基于Python+MySQL实现物联网引论课程一个火警报警及应急处理系统
物联网引论课程大作业设计报告
一、选题、内容及功能说明
我们大作业选择的是题目三:一个火警报警及应急处理系统。
主要需要实现四个功能:
- 感知环境温度,当环境温度超过阈值,自动触发报警:终端 led 以固定频率闪烁,终端上电机转动
- 基础功能指令实现,可以远程设置阈值
- 报警状态下,按下按钮可以现场解除报警
- 通过网页查询温湿度,显示温湿度曲线,远程关闭或打开报警
为了实现上述功能,我们兵分四路,分别处理传感器端、LwM2M端、Django 服务器端和客户端,通过确定接口,调用api、订阅信息,完成一系列的工作流程。最终我们完全实现了题目三的要求内容,并颇具亮点。 并且,我们还完成了对于传感器端的完全掌握,客户端、服务器端也都留出了相应的接口方便以后的拓展,对于基础IOT开发,其工作流程以及工程方面的拓展性,都有了较深的认识。
二、设计方案与设计思路
传感器端:
传感器端设计分为平台通信和功能实现两部分,具体设计方案和思路如下:
平台通信
- 在电信平台进行实名认证并开通使能服务
- 添加产品和物模型
- 修改代码服务ID与平台一致并将代码加载到开发板上
- 接通电源、通信
功能实现
- 电机控制,0表示关闭,1表示开启
- 温湿度上报控制,0表示关闭上报,1表示开始上报
- 上报周期控制,输入整数改变上报周期
- Led闪烁,0表示关闭闪烁,1表示开启闪烁。仿照原有服务新增一个服务,仿照温湿度上传函数实现周期闪烁。
- 按键关闭报警,按下key2时同时停止电机转动和led灯闪烁。可以在服务线程中检查按钮状态,若按下则停止led灯闪烁并关闭电机
服务器端:
可以看出服务器端向南连通LwM2M服务器和向北连通客户端,起桥梁作用,其主要工作可以分为两块:
向LwM2M服务器请求服务:
- 启动/关闭电机
- 启动/关闭LED
- 启动/关闭数据上报
- 温湿度数据自动推送
- 请求最新的温湿度数据
- 启动/关闭规则
- 修改规则
为客户端提供服务:
- 启动/关闭电机
- 启动/关闭LED
- 启动/关闭报警状态(电机、LED灯同时工作)
- 启动/关闭数据上报
- 请求最新的温湿度数据
- 请求历史温湿度数据
- 更改规则阈值(包括温湿度)
设计方案:
我们打算通过Django框架进行服务器端的开发,向LwM2M服务器端请求服务的具体方式为使用天翼CTWing提供的Python SDK,除了温湿度数据自动推送的所有功能依照API手册调用相关接口即可,而设备温湿度数据的自动推送则通过 LwM2M 服务器端提供的订阅服务解决,由于没有公网 IP,我们打算采用内网穿透的方法实现订阅功能。
对于客户端需要请求的服务,提供一组后端函数供其调用,当后端函数被调用后,大部分函数会转向LwM2M服务器请求服务,因此对客户端提供的服务和向LwM2M服务器端请求的服务基本是一一对应和的。
通过文档了解发现,更改规则阈值的的服务需要包含三个操作:停止规则,更改规则,启动规则,否则无法更改规则内容。另外,对于订阅服务,提供一个后端函数供LwM2M服务器调用,此函数能接收LwM2M服务器推送的温湿度数据,并写入Django客户端本地的MySQL数据库,当客户端请求相关历史温湿度数据时便予以返回。
服务器端与LwM2M服务器端、客户端的之间的通信均基于http协议
客户端:
客户端设计的重点主要是UI界面设计与客户端、服务端之间的交互。
由于Vue框架已经集成了非常完备的功能,我们选择了vue作为客户端的主体开发框架。为了提供良好的用户体验,我们选择做一个单页 web,所有功能在用户视角下一览无遗,同时也省去了页面的切换时间。客户端分为五大功能模块,分别为电机控制、LED 控制、警报控制、温湿度管理、阈值设置,每个模块设置若干按钮来实现相应功能。
客户端与服务端之间的通信采用vue中内嵌的axios库,客户端向服务端发送一个HTTP请求,服务端进行功能调用,将结果返回给客户端,显示在 web页面上。
三、开发工作介绍
传感器端:
基础指令对接:
可以看到在在下面的核心函数中,每一个指令都会被解析成为一个 CmdStruct 类型的结构体,其中包含关键指令信息。指令则会进一步完成相应的判断、识别、和利用现有函数对传感器的控制。
温湿度上报:
我们找到了关键的温湿度上报函数和控制其等频率运作的 timer函数,学习其运作机理对我们实现led等频率闪烁作用极大。
报警机制处理:
我们在服务器端便把报警功能直接拆分成为了马达转动和 led 闪烁两个部分,分别向传感器端发送指令。识别指令类似于基础指令的识别:
而灯的等频率闪烁我们则是效仿了温湿度的等频率上报,设计了自己的 flag标识,写了与原timer的类似的temp_timer,完成了led的等频率闪烁,并且与温湿度上报并不冲突。
而按钮停止报警的实现则较为简单,只需要我们在主线程函数中进行对于按钮状态的特判,进一步操作原有函数控制led,马达即可。
服务器端:
后端代码详见附录
数据流图
配置表
MySQL配置
新建 iot 数据库,device_data 表
CREATE SCHEMA `iot` ;
CREATE TABLE `device_data` (`time` varchar(50) NOT NULL,`humidity_data` varchar(50) NOT NULL,`temperature_data` varchar(50) NOT NULL,PRIMARY KEY (`time`)
)
Python SDK只需要导入我们需要使用的接口函数
具体包括四个.py文件:
- aep_device_command.py
- aep_device_status.py
- aep_rule_engine.py
- AepSdkRequestSend.py
Django支持跨域设置
内网穿透
利用ngrok进行内网穿透,在命令行中运行:
.\ding -config=.\ding.cfg -subdomain=iot 8080 即可
客户端:
我们以获取最新温湿度这一功能为例,来展示客户端与服务端的通信过程。
温湿度曲线表:三个参数分别是时间,湿度和温度
在get里面配置指定图标的数据
利用axios从后端获取数据
四、系统成果展示
传感器端:
由于电机、温湿度上传等功能图片不便展示,仅展示led闪烁,其余用视频展示。
视频说明(见附录):
- 电机展示:下发开始指令后电机转动,下发关闭指令后电机停止转动。
- Led展示:下发开始指令后led开始闪烁,下发关闭指令后led停止闪烁。
- 温湿度上报展示:下发开始指令后开始上报,下发关闭指令后上报停止。
服务器端:
启动电机:
关闭电机:
开启LED:
关闭LED:
获取最新温度:
开启/关闭报警:
报警就是同时开启/关闭电机和LED,因此省略服务器端运行结果的展示接收温湿度推送:
修改规则:
客户端:
客户端主页面效果如下所示:
在温湿度管理模块中,点击左下角的获取最新温湿度按钮,客户端会将从服务端获取的温湿度信息以Notice窗口的形式显示在页面左下角,该窗口可由用户手动关闭。
点击历史温湿度曲线按钮,页面会跳转到温湿度曲线图,如下图所示。温湿度曲线通过echarts功能组件绘制。用户可通过左右拖动x轴游标来自由选择时间范围。
点击历史温湿度曲线按钮,页面会跳转到温湿度曲线图,如下图所示。温湿度曲线通过echarts功能组件绘制。用户可通过左右拖动x轴游标来自由选择时间范围。并且两条曲线在同一屏显示,方便用户进行比对。
五、设计亮点
传感器端实现
led等频闪烁不与其他任何服务冲突,且很容易调节频率(在源代码中更改一个数字即可)。如有需要还可以增加一个调节频率的服务。
前后端分离
前端采用了Vue进行开发,后端采用Django进行开发,采用前后端分离的做法,好处是开发效率较高,整个开发过程中前后端开发可同步进行,且很少遇到bug。
此外,前后端可以部署在不同的服务器上,甚至可以使用多个后端服务器,通过 Nginx 进行反向代理,防止某一个后端服务器宕机导致系统整体失效,增加了系统可靠性,是投入生产的保证(虽然实验中不明显)
数据库的使用
如果不采用数据库进行温湿度的存储,那么系统永远只能知道此时此刻的温湿度数据,将温湿度数据写入 MySQL 能够获取任意开发板历史时间节点的温湿度数据
订阅机制的使用
如果采用轮询的方法获取温湿度数据,如果开发板某一时间段的温湿度数据没有发生任何变化,将带来大量的冗余数据;如果采用订阅机制,只在开发板温湿度发生变化时对相关数据实现推送,将不会产生此问题
规则的使用
一般的做法为:在Django服务器端进行条件判断,并根据相应逻辑判断,执行相应的动作,但是这种方法耦合性太大,数据链路太长,由架构图可知贯穿三端:设备端,LwM2M 服务器端和 Django 服务器端,并且一旦 Django服务器端宕机,监视功能将完全失效(本实验为温湿度一旦超过阈值需要开启报警状态);因此我们选择通过LwM2M服务器端实现监视功能,具体通过规则引擎实现,主要原理和通过Django服务器端实现基本相同,优点是安全性更高,Django服务器端的宕机不会直接导致监视功能的失效,耦合性较小,此外数据链路较短,理论上延迟更小(只有两端进行http协议交互)
采用 echarts 组件画曲线图
用户可根据自己的需求选择时间范围,而且温度与湿度可以同时显示在一张图上,用户可以清晰地比较两条曲线的变化趋势。
六、大作业总结
在研发过程中遇到了哪些问题?是如何解决的?
传感器端:
- 实名认证后平台仍然没有“产品中心”
需要开通使能服务才能添加设备 - 按照指导说明添加设备和服务后,进行相关指令下发后无响应。
自带源代码中服务ID不正确,与平台的服务ID不吻合,改为相同的服务ID可以正常实现功能。 - 服务ID正确后平台没有显示温湿度数据上报
没有下发指令让温湿度上报打开。下发指令成功实现温湿度数据上报。 - 想通过主线程的闪烁函数实现 led 闪烁功能,但线程间无法传递变量
闪烁相关的函数要写在同一个线程里。 - 创建了 temp_timer_cb 等但是把灯的开启关闭写在了线程循环中,灯的闪烁频率会受温湿度上报影响
仅使用Temp_timer_cb可以完成闪烁任务,不需要将闪烁另写在线程循环里,会受其他循环的服务冲突。 - 把灯的闪烁写在了温湿度上报的 nb_timer_cb 里,试图让灯和上报频率相等,但实际并不可行。
需要新写的专门为灯闪烁使用的Temp_timer_cb完成闪烁任务。
服务器端:
跨域
前后端分离最大的问题就是会带来跨域问题,我们利用Django框架支持跨域,具体方法见配置表
订阅功能需要公网IP
订阅功能的实现需要公网 IP,但是我们小组没有服务器,没有公网 IP,所以采用ngrok进行内网穿透,具体使用方法见配置表
规则的权限问题
最开始手动在网站上配置了规则,但始终无法通过api开启/关闭规则和更改规则内容,通过向技术支持人员了解发现,通过api创建的规则和手动创建的规则存在操作权限不同的问题,即手动创建的规则只能手动更改、开启/暂停,api创建的规则同理只能通过api操作
request的返回信息为十六进制表示
调用api后返回信息为十六进制,无法阅读利用Python的函数进行解析
临时突然更新接口
某次检查时发现原本正常的功能,在运行时会出奇怪的bug,后来发现是api进行了更新(查询设备温湿度,之前返回的信息和后来返回的信息的数据结构存在细微区别)
接口调用时无法关闭Print开关,调试困难
只要调用api就会输出大量的无用信息,且不能关闭,调试困难自行添加Print输出更多更明显的信息辅助调试