2018年,我开始玩单片机。正好爸想着改造一下家里花园的浇水系统,就趁机将其智能化。所以购买了一个 ESP8266 开发板,电磁阀和继电器。希望能实现在手机或者电脑上远程遥控浇水的功能。

当时用 Flask 当作后端,用 Angular 作为前端,用 Arduino 为单片机编程。项目地址在 这里。实现了对电磁阀的远程控制,和展示阀门的实时状态。

后面因为自己的学业,间断着修补了一些 bug 之后就没有在开发。

最近,因为之前疫情的原因,利用 DjangoFlutter 开发了一个应用后。便想着把之前的物联网项目也整合进这个应用里,这样便可以在同一个应用中使用,不再需要进入不同网页,并且还要登录不同的账号。同时如果能加入一些新功能就更好。


想着既然要重写相关的代码,不如研究一下比之前更好的架构。之前服务器和客户端,单片机利用 SocketIO 进行通讯,可以实现实时的数据更新。现在我使用的服务器是使用的 GraphQL,同样它也拥有一个 Subscription 可以实现实时通讯。单片机上我准备换回 MQTT 协议,因为这个协议更适合物联网设备。

MQTT

此时遇到了第一个问题,Python 上的 MQTT 客户端不方便与 Django 进行整合。

正如这个 回答 提到

If you need Django running in multiple threads then to publish messages from your Django app you can use helper functions from Publish module of Paho - https://eclipse.org/paho/clients/python/docs/#id17 You don't need to create an instance of mqtt client and start a loop in this case. And to subscribe to some topic consider running mqtt client as a standalone script and import there needed modules of your Django app (and don't forget to setup the Django environment in the script).

多线程模式下运行 Django,如果此时整合了 MQTT 客户端,会出现接受多次消息的问题。所以需要一个独立的脚本来实现消息的订阅。

这个时候我发现了一个 MQTT 消息服务器 EMQX。它提供了 WebHook 功能,可以将各种事件上报给服务器,其中就包括了消息发布和设备上下线。这样我就不需要自己来整合 MQTT 客户端到服务器中。并且需要发布消息时,它提供了 HTTP API,可以通过发送 HTTP 请求来发布消息。这样 Django 便可以接受和发布 MQTT 消息,同时不会受到多线程模式的影响。

Subscription

Graphene 推荐 了三个库,我在一番尝试选择了 graphene-subscriptions。它可以实现在特定的模型创建时推送数据,正好符合我的需求。

不过在 Flutter 客户端订阅时,我遇到了问题。我在 Flutter 上使用的 graphql-flutter 库来实现客户端和服务器的通讯。但是我却无法在客户端上和服务器建立连接,会一直尝试连接然后断开连接。

并且认证相关的问题,我还没有理清楚。这个库也正在升级 v4 版本 的过程中。

所以我暂时放弃了实时更新数据的想法,准备利用轮询来实现数据的更新。

Celery

这次重新实现物联网功能,我加上了最近发现的,叫做任务队列的东西。

维基的介绍
The execution units, called tasks, are executed concurrently on one or more worker nodes using multiprocessing, eventlet or gevent. Tasks can execute asynchronously (in the background) or synchronously (wait until ready). Celery is used in production systems, for instance Instagram, to process millions of tasks every day.

利用这个,我可以实现自由添加各种任务,不用担心执行过程中将网络请求给卡住。等任务完成之后,再来请求执行结果就行。

并且其中有一个配套的组件 celery beat,通过它可以实现定时触发任务。这个任务可以是控制物联网设备,比如定时开关阀门,从而实现自动浇水。也可以是执行脚本,比如 定时清除过期的令牌

架构图

整个项目的架构如下图:

smart-home.png

计划

接下来等各种库都完成更新之后,尝试实现实时传输数据的功能。

根据各种反馈持续完善,把我们家打造成一个智慧家庭。😊

标签: 智慧家庭, 物联网