当前位置: 首页 > news >正文

《ESP32 物联网全栈实战-11》小程序进阶

第 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 插座,从硬件到小程序全链路

http://www.jsqmd.com/news/1336154/

相关文章:

  • 天津管道疏通公司口碑**:2026年本地正规品牌综合对比与推荐 - 园子一号
  • 寂静猎人:每天问一遍AI,看看AI的观点
  • 全星研发项目管理APQP软件系统——让研发合规与效率一步到位
  • 合肥管道疏通公司口碑**:2026年本地正规品牌综合对比与推荐 - 园子一号
  • WinCC组合框控件:实现PLC变量安全赋值与模式选择
  • AI Agent学习:上下文工程(Context Engineering)心得总结(李博杰《深入理解 AI Agent》2.1,2.2观后总结)
  • 在功率半导体(如 IGBT 或 SiC MOSFET)的驱动电路与测试中,栅电阻(Gate Resistor)用于控制功率器件开通和关断的速度,抑制寄生振荡
  • Flutter应用版本逆向分析:从APK/IPA中提取Flutter SDK版本号的实战指南
  • 厦门各区小学上学期期中语文、数学、英语试卷及答案解析
  • 什么是减振器吊环连杆凸焊机?一篇读懂其定义、价值与实现路径 - 全域品牌推荐
  • PHP Composer依赖管理机制与优化实战
  • 智谱清言转 word 工具推荐:首选「AI 导出鸭」平板版,专治智谱清言输出乱码,一键无损导出 Word,完美还原公式表格与代码流程图。
  • 游戏抽奖概率模型解析:从独立事件到保底机制的策略规划
  • 开封管道疏通公司口碑**:2026年本地正规品牌综合对比与推荐 - 园子一号
  • 2026年企业培训考核选型指南:为何它能成为在线考试平台首选?
  • 【语音增强】组稀疏信号去噪:非凸正则化,凸优化研究附Matlab代码
  • 兄弟,IPA 又传不上去了
  • 嵌入式开发IO口扩展实战:I2C总线驱动PCF8574与MCP23017芯片详解
  • 【仅限首批内测者】扣子v2.3.1表单触发器Beta API提前解锁:支持条件分支+异步队列+失败重试(附迁移清单)
  • 企业做GEO很关心的10个问题,尤其第3个
  • IDEA中fastjson依赖配置与ClassNotFoundException排查指南
  • 四款主流AI知识库工具横向评测:功能定位与场景适配分析
  • Markdown与Typora:提升写作效率的轻量级标记语言与编辑器指南
  • HarmonyOS7 VideoPictureInPicture 教程:画中画模式为什么特别适合边看边做事
  • 【MCP】Notion MCP 智能体案例讲解
  • ArcGIS JS 基础教程(24):VectorTileLayer 矢量切片图层
  • Chrome 80+ Cookie加密机制解析与Python实战解密
  • VR粒子特效性能调优:Cocos Creator实战指南
  • 惠州管道疏通公司口碑**:2026年本地正规品牌综合对比与推荐 - 园子一号
  • 三分钟免费接入DeepSeek:Codex本地客户端配置与AI编程实战