公司业务需要开发IOT从硬件到软件的全部工作,由于一开始来的硬件工程师选择了基于TCP直接进行终端与控制中心交互,自己设计报文内容与格式,所以远程控制也需要自己实现。还是自己太年轻,放着好好的现成的MQTT协议不用,自己瞎折腾。

硬件终端与服务器的通讯模块采用的是普通的2G卡,这样才能与自己的服务器直接通信(电信的物联网卡只能连接华为云,移动的物联网卡只能连接Oneconnect云平台,然后再对接自己的业务系统)。为了节省终端电池电量,终端5分钟唤醒一次连接服务器上报数据,也就是在这个时候,需要服务器查询控制任务队列,下发给下位机。所以,这里有下面几个工作需要完成:

  • 前端用户界面操作,发送任务给后端服务器(React + Django),随后等待得到控制结果状态
  • 后端创建任务(写Redis)
  • 下位机每5分钟连接一次上位机,上位机(Twisted)查询任务队列(Redis),将对应的任务下发给下位机,下位机获取控制报执行相应操作后,返回控制结果给上位机
  • 上位机返回控制结果给web后端(Redis 发布),后端监听服务(订阅 Redis)返回给前端(WebSocket)
  • 前端拿到结果,UI反馈给用户

其中,不是必须通过Web后端才可以给硬件的上位机发送任务(这里是Twisted进程),比如本身就可以使用autobahn-python直接搭建一个WAMP,其运行在Twisted上,就可以省去一步交互了。由于在这个项目中涉及到权限验证、开关抽象(一个下位机有多个开关)等工作,所以还把这层放在Django中,反而省去很多开发。

另外需要说明一下为什么web前后端之间用WebSocket,因为这里的任务相当于异步任务,前后端都不知道下位机执行任务的准确时间,除了前端轮询的解决方案,最好的就是建立一个双工长连接,这样当web后端一旦知道任务结果,就可以主动发送给前端,因此WebSocket是最合适的方案。当然,Django本身不支持长连接,幸得有大牛开发了channels,使得我们可以基于Django开发WebSocet服务,并且还支持异步!

以上的过程画成图是这样的!

iot-remote-control-sequence

补充:

  • 任务队列是写Redis
  • 注意任务队列消费过后,要删除(即此次任务已执行,不论结果成功与否)
  • Django Channels需要建立一个后台监听服务(Channel layers using outside of consumer),第一时间通知给web前端