2025年11月

        实现了消息发布订阅和数据存储,接下来就是怎么用数据了。数据展示就是可视化,可以用的软件很多,Grafana是开源软件中用得最多的(吧?)。由于用的人多,教程也多,所以只要注意以下几点就行了:

  • 安装包去官网找,安装过程很详细,只是要记得一定要选择和自己主机的CPU和操作系统对应的安装包,否则安装不成功。
  • 打开端口。
  • 新建仪表盘时,如果SQL语句写了后可视化窗口里却空空如也,那八成是没有指定数据库,引用的表要写成XXX.YYY,其中XXX是数据库名,YYY是表名。

        二十多年前,似乎还在用着33.6K的modem时,MP3刚刚发明出来,在网上慢吞吞地下载了很多歌曲和乐曲,很多很喜欢的歌曲和乐曲就是那时候发现的。只是那时候网上的搜索引擎功能还很弱,网上的信息也很少,即使觉得一首歌很好听,也找不到有关这首歌的太多的信息,尤其有时候歌名都不完整,就比如这首小号曲,下载下来的名字叫wonderland,在用上apple music后就用这个名字搜,无奈同名的太多,都不是这一首。直到前天在微信的视频号中发现有人发这首,才知道了这首曲子的全名,用这个名字果然也在apple music中搜寻到了。嗯,果然对于音乐来说,微信视频号比小红书强多了。

        EMQX接受到消息后,存储到TDengine数据库的方法就是设定规则,方法如下:

  • 建立规则,用SQL语句把需要存储的消息及相应字段筛选出来(有可能接收到的是发布端的心跳包,这个是不需要存储的):SELECT XXXX,payload.XXX,XXXXX,XXX,XXX FROM "XXX/XXX/XXXX" WHERE is_null(payload.XXX)=false
  • 在规则的动作输出中选择TDengine,写一条在数据库中插入数据的SQL语句:insert into XXXXX using XXX tags('XXX','XXX') values (${XXX},'${XXX}', ${XXX}, ${payload.XXX}, '${XXX}'),第一个字段记得永远要用时间戳,字段是int或者float的,不需要加''。
  • 在规则建立页面有调试功能,可以在设定规则后,用MQTT.fx发布数据,然后观察是否成功存储到TDengine中,以此来判断和排除语法错误。
  • TDengine是时序型数据库,规范建表的方法是先建超级表stable,需要存储的字段都在超级表中事先确定,然后每个设备用一个新表table存储数据,表会继承超级表的字段,不需要再次定义,但也意味着不能随意修改增减,所以超级表设计时一定要考虑周全,否则只能逐个增加超级表的字段。
  • 规则的动作输出也可以选择为消息再输出,把筛选出来的消息以另外一个主题重新发布出去。
  • 同理,当规则的SQL语句中增加了数据的比较和筛选功能(如数值大于或小于某个设定值时),再设定一个消息再输出,就实现了报警功能,这样做的好处是规则的设定完全是在服务器端,前端硬件设备不需要做任何设定,这样灵活性无疑大了很多。筛选出来的数据同时也可以存储到TDengine中,实现报警数据的记录。

        Arduino调试过程中,会出现一些匪夷所思的问题,表面上看来是闹鬼,其实都各有原因,只不过原因隐藏得比较隐秘。比如:

  • 用UNO调试一个电路,当单独挂载一个SSD1306的IIC屏时,使用例程和自己的程序都正常,但一旦放到一个有三个IIC器件的系统中就始终无法编译通过,想过可能是地址的问题,但查下来地址都不重复,最后发现是通常用的SSD1306库文件消耗内存太大,UNO这样的内存有限的MCU当只运行这个库时没有问题,一旦加载的库多了,内存就不够分,体现在在编译显示分配失败。解决办法是找一个内存消耗小的库,或者换成MEGA2560,显然前者更有可行性。
  • 一个串口屏的应用,接收到信息后报警,用一个按钮中止报警修改报警背景颜色,结果程序编译完成后其他功能都正常,唯独串口屏无法显示设定的初始界面,总是一晃就变成空数据界面,怎么调整程序都不行,最后发现是按钮对应的IO口异常,虽然软件做了上拉,但高电平时只有2V,造成进入LOOP循环后程序认为按钮已经被按下,串口屏自动显示报警中止后设定的画面,此时又没有数据,只能显示一个空数据画面,换一个IO口就一切正常了。
  • Arduino里将时间戳转换为正常的日期和时间格式,网上的Arduino time库现在的IDE用不了,试验了安装time库可以进行转换,然而转换出来的日期和时间始终不对,最后发现这个库的转换功能只能用于转换10位的时间戳,如果你用的是13位的时间戳,那必然不对,需要先将13位的时间戳截取为10位,才能正确转换。