第 11 篇:小程序进阶——ECharts 图表 + 历史查询 + 告警推送
上篇做了一个能看能控的基础版。这篇加上三个进阶功能:温度曲线(ECharts)、历史数据查询(HTTP API + InfluxDB)、阈值告警推送。
1. 集成 ECharts 温度曲线
微信小程序用echarts-for-weixin组件。这是 ECharts 官方适配的小程序版。
安装:
# 项目根目录npminstallec-canvas# 然后:开发者工具 → 工具 → 构建 npm页面中引入:
pages/history/history.json
{"usingComponents":{"ec-canvas":"../../ec-canvas/ec-canvas"},"navigationBarTitleText":"温度历史"}pages/history/history.wxml
<viewclass="container"><viewclass="chart-box"><ec-canvasid="tempChart"canvas-id="tempChart"ec="{{ec}}"></ec-canvas></view><viewclass="time-tabs"><buttonsize="mini"bindtap="loadHistory"data-range="1h">近1小时</button><buttonsize="mini"bindtap="loadHistory"data-range="6h">近6小时</button><buttonsize="mini"bindtap="loadHistory"data-range="24h">近24小时</button></view></view>pages/history/history.js
import*asechartsfrom'../../ec-canvas/echarts';Page({data:{ec:{// 懒加载:canvas 渲染完成后才初始化 EChartslazyLoad:true,},tempData:[],humiData:[],},onLoad(){// 获取 ec-canvas 组件实例this.ecComponent=this.selectComponent('#tempChart');this.initChart();this.loadHistory('1h');},initChart(){this.ecComponent.init((canvas,width,height,dpr)=>{constchart=echarts.init(canvas,null,{width:width,height:height,devicePixelRatio:dpr,});chart.setOption(this.getChartOption());this.chart=chart;returnchart;});},getChartOption(){return{color:['#ff6b6b','#48dbfb'],legend:{data:['温度','湿度'],bottom:0},grid:{top:20,bottom:40,left:50,right:20},xAxis:{type:'time',axisLabel:{fontSize:10}},yAxis:[{type:'value',name:'°C',min:0,max:50},{type:'value',name:'%',min:0,max:100},],tooltip:{trigger:'axis'},series:[{name:'温度',type:'line',smooth:true,data:[],yAxisIndex:0,},{name:'湿度',type:'line',smooth:true,data:[],yAxisIndex:1,},],};},asyncloadHistory(range){wx.showLoading({title:'加载中...'});try{constres=awaitwx.request({url:`https://api.your-server.com/history?range=${range}`,method:'GET',});consttempData=res.data.temp.map(d=>[newDate(d.time),d.value]);consthumiData=res.data.humi.map(d=>[newDate(d.time),d.value]);this.chart.setOption({series:[{data:tempData},{data:humiData},],});}catch(err){wx.showToast({title:'加载失败',icon:'error'});}finally{wx.hideLoading();}},});2. 后端 API——从 InfluxDB 查历史数据
小程序不能直接连数据库,需要一个中间 API 服务。最简单的方案:用 Node.js/Express 写一个轻量 API,跑在服务器上。
// api-server.js (Node.js + Express)constexpress=require('express');const{InfluxDB}=require('@influxdata/influxdb-client');constapp=express();constinflux=newInfluxDB({url:'http://localhost:8086',token:'my-super-secret-token',});app.get('/history',async(req,res)=>{constrange=req.query.range||'1h';// 1h / 6h / 24hconstqueryApi=influx.getQueryApi('iot-org');constquery=`from(bucket: "sensor-data") |> range(start: -${range}) |> filter(fn: (r) => r._measurement == "mqtt_consumer") |> filter(fn: (r) => r._field == "temp" or r._field == "humi") |> aggregateWindow(every:${range==='1h'?'30s':'5m'}, fn: mean)`;consttemp=[],humi=[];forawait(const{values,row}ofqueryApi.iterateRows(query)){constpoint={time:row[2],value:row[5]};if(row[4]==='temp')temp.push(point);elsehumi.push(point);}res.json({temp,humi});});app.listen(3000,()=>console.log('API Server on :3000'));3. 阈值告警推送
方案 A:小程序内告警
// 在 MQTT message 回调中this.client.on('message',(topic,payload)=>{constdata=JSON.parse(payload.toString());if(data.temp>40){wx.showModal({title:'⚠️ 高温警告',content:`当前温度${data.temp}°C,超过阈值 40°C!`,showCancel:false,});// 播放提示音(小程序支持)wx.vibrateLong();}this.setData({temperature:data.temp.toFixed(1),humidity:data.humi.toFixed(1),});});方案 B:微信服务通知(需要订阅消息)
流程: 1. 用户点击"订阅告警"按钮 → 调用 wx.requestSubscribeMessage 2. 用户同意 → 拿到一次推送权限 3. 后端检测到温度超标 → 调用微信 API 推送模板消息// 小程序端:订阅wx.requestSubscribeMessage({tmplIds:['模板ID_高温告警'],success(res){if(res['模板ID_高温告警']==='accept'){// 保存用户 openid → 后端用于推送}},});4. 增加刷新与重连机制
IoT 小程序最大的痛点是"不知道数据为什么不更新了"。增强健壮性:
Page({data:{connected:false,lastUpdate:''},onLoad(){this.connectMQTT();// 每 30 秒检查一次 MQTT 心跳this.heartbeatTimer=setInterval(()=>{if(!this.data.connected){console.log('重连中...');this.connectMQTT();}},30000);},// 记录最后更新时间updateLastTime(){constnow=newDate();this.setData({lastUpdate:`${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`,});},// 手动刷新refreshData(){this.client.publish('device/refresh/cmd','1');},onUnload(){clearInterval(this.heartbeatTimer);if(this.client)this.client.end();},});5. 调试技巧
| 问题 | 排查方法 |
|---|---|
| MQTT 连不上 | 检查wss://域名是否已配置到白名单 |
| 数据不更新 | 打开开发者工具 → Console → 看有没有message日志 |
| ECharts 白屏 | 检查ec-canvas组件路径是否正确 |
| API 请求失败 | 检查服务器域名白名单(request合法域名) |
| 真机不显示 | 预览时勾选"不校验合法域名"仅开发有效,真机必须配置 |
下一篇:完整项目——智能 WiFi 插座,从硬件到小程序全链路