1. 功能介绍
随着全球气候变化和人类活动的增加,森林火灾成为了一个严重的环境问题。及早发现和迅速响应火灾事件对于减少火灾的损失至关重要。为了实现对森林火灾的快速预警和联动控制,决定利用华为云IoT物联网平台来搭建一个高效的系统模型。
该系统模型的目标是在检测到森林火灾后,能够快速将火灾信息上报到云平台,并与指定的服务器进行数据报告的交互。同时,系统还能自动向抽水泵发送指令,打开开关以进行抽水灭火操作。通过这样的联动控制系统,可以实现快速响应和减少火灾对森林和生态环境的破坏。
该系统模型的核心是华为云IoT物联网平台,它提供了丰富的功能和服务,包括设备接入、数据采集、消息通信、云端数据存储和分析等。我们可以利用该平台的能力来接收来自火灾检测设备的数据,并通过云端的数据分析和处理来实现火灾预警和联动控制。
当火灾检测设备检测到火灾时,会通过无线通信将火灾信息发送到华为云IoT物联网平台。云平台接收到信息后,会立即进行处理并将火灾报告发送给指定的服务器。服务器可以根据报告中的信息采取相应的措施,如调度抽水泵进行灭火操作。
通过这个系统模型,可以实现对森林火灾的快速预警和联动控制,大大提高了火灾应对的效率和准确性。同时,利用华为云IoT物联网平台的强大功能,可以灵活地扩展和定制系统,以适应不同规模和需求的森林火灾防控工作。
硬件平台介绍:
MCU: STM32F103ZET6
物联网云平台: 华为IOT云平台
气体检测传感器: MQ2-烟雾传感器、MQ135-空气质量检测传感器
火焰检测: 采用火焰检测传感器
抽水机: 采用直流电机模拟水泵,打开开关抽水喷水灭火
上网网卡: 采用GSM模块SIM800C,使用的是物联网专用卡,包年只能上网这种。
与云端服务器的通信协议: 终端设备采用MQTT3.1.1协议与华为云服务器进行登录连接。
温湿度检测传感器: DHT11
供电方式: 电池+太阳能供电
为了演示联动控制,火警(烟雾)检测装置和灭火(直流电机)装置分为两个独立的设备,分别连接上云端。
火警检测装置连接上物联网服务器之后,可以在服务器上配置数据处理规则,如果烟雾浓度超标,可以自动向灭火装置发送指令,进行灭火操作。服务器收到火警检测装置上传的烟雾浓度、空气质量等数据后,可以向自己的私有服务器转发数据,方便自己服务器收到数据后做分析存储处理,比如: 向指定邮箱发送邮件、手机APP推送通知栏、向指定用户推送短消息提示等等。
2. 创建产品(火警预警装置)
打开官网链接: www.huaweicloud.com/s/JeeJqeiBl…
(1)选择设备接入IotTDA选项。
(2)选择免费试用。
(3)在产品页面选择创建新的产品。
(4)填入产品信息,创建产品
(5)选择自己刚才创建的产品,创建数据模型,点击自定义模型
(6)选择添加属性
这个添加的属性就是设备端上报的数据类型。 比如: MQ2烟雾传感器检测的烟雾数据值类型。
在这个页面上还有一个添加命令的功能,这是用于云端下发指令给设备端使用的。当前这个设备是火警检测装置,只需要上报数据给服务器,不需要下发指令,这里就只需要添加属性就行了。
根据自己的设备的具体情况填写即可,如果上报的数据有多种类型就创建多个属性。
3. 创建产品(灭火装置)
创建的流程和上面一样,这是多增加了一个命令下发的功能,方便云端远程控制电机开启和关闭,实现灭火功能。
(1)创建产品
(2)产品创建完毕之后,添加服务器ID
(3)添加属性,电机属性是可以读可以写的,范围设置为0和1,只能开关
(4)添加命令,这个命令用于云端远程向设备下发指令,设备收到指令后可以做出相应的逻辑处理
接着选择新增输入参数:
最后点击确定即可。
现在产品已经创建完毕。
4. 创建设备(火警预警装置)
(1)在设备页面,选择注册设备,选择自己的对应的产品,设备标识码一般填自己设备的硬件标号。
(2)设备创建成功之后会弹出弹窗,点击保存并关闭,会自动弹出下载窗口,是个文本文件,存放了密匙信息
{
"device_id": "61bacdc02b2aa20288c5a094_QQ1126626497",
"secret": "1126626497"
}
5. 创建设备(灭火装置)
流程与上面火警预警装置设备一样的。
{
"device_id": "61bad0564d9b020287193be2_QQ1126626497",
"secret": "1126626497"
}
6. 生成MQTT协议登录ID和密匙
设备创建完成接来下生成MQTT登录账号、密匙,方便设备登录云端平台。
官网工具地址: iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
填入刚才创建设备时,保存下载文件里的信息,对着弹窗填入,最后生成了ID、用户名、密码参数,用于MQTT协议登录使用。
(1)火警预警装置生成登录参数
ClientId 61bacdc02b2aa20288c5a094_QQ1126626497_0_0_2021121605
Username 61bacdc02b2aa20288c5a094_QQ1126626497
Password 43ed43bcbddc48772694fc2b18ec1112170f4d6cc52fbf1e01401c2ea1748475
(2)灭火装置
ClientId 61bad0564d9b020287193be2_QQ1126626497_0_0_2021121605
Username 61bad0564d9b020287193be2_QQ1126626497
Password 43ed43bcbddc48772694fc2b18ec1112170f4d6cc52fbf1e01401c2ea1748475
7. 上报属性格式与主题订阅格式
产品设备、MQTT登录参数都到位了,接下来需要了解设备向服务器上报数据时,如何上报,格式是怎么样的。
(1)第一个问题是:华为云IoT物联网服务器的IP和端口号是多少?
在总览选项页面,点击多协议接入选项,就能看到了。
如果选择MQTT协议接入:
域名是: a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
如果你的设备不能解析域名,也可以直接填IP地址 121.36.42.100
端口号: 1883
(2)第二个问题是:发布数据的主题和订阅数据的主题怎么填?
在产品页面,选择自己的产品,进去之后就能看到主题的格式介绍页面了。
为了方便后续复制粘贴,这里总结下格式:
火警预警装置:
格式: $oc/devices/{device_id}/sys/messages/down
//订阅主题: 平台下发消息给设备
$oc/devices/61bacdc02b2aa20288c5a094_QQ1126626497/sys/messages/down
格式: $oc/devices/{device_id}/sys/properties/report
//设备上报数据
$oc/devices/61bacdc02b2aa20288c5a094_QQ1126626497/sys/properties/report
灭火装置:
格式: $oc/devices/{device_id}/sys/messages/down
//订阅主题: 平台下发消息给设备
$oc/devices/61bad0564d9b020287193be2_QQ1126626497/sys/messages/down
格式: $oc/devices/{device_id}/sys/properties/report
//设备上报数据
$oc/devices/61bad0564d9b020287193be2_QQ1126626497/sys/properties/report
(3)第三个问题是:上报属性时,数据格式是什么?
官方文档介绍: support.huaweicloud.com/devg-iothub…
总结下格式: 上报的数据就是JSON格式,一次性可以上传多个属性数据,JSON数组里按照顺序增加即可。
重要的字段含义解释:这两个字段后面的数据需要自己根据自己的设备产品去填充的。
service_id 示设备服务的ID。
properties 是设备服务的属性列表,具体字段在设备关联的产品模型中定义。
火警预警装置上传的数据:
{"services": [{"service_id": "MQ2","properties":{"MQ2":100}}]}
灭火装置上传的数据:
{"services": [{"service_id": "motor","properties":{"motor":1}}]}
8. 使用MQTT客户端模拟设备测试
(1)登录火警预警装置
(2)灭火装置登录
可以看到,设备已经成功登录服务器,完成了数据上报。这也证明服务器端设备创建已经全部OK,正常。
9. 配置设备联动
(1)创建规则
(2)填写规则信息
(3)添加触发条件,选择需要处理数据的设备,设置条件:当烟雾浓度大于等于100就触发
(4)添加执行动作,当烟雾浓度超过100就下发指令给灭火装置
(3)最后点击创建规则,生效规则
(4)测试效果
使用两个MQTT客户端分别模拟火警预警装置和灭火装置,当烟雾浓度超过100时,查看灭火装置是否收到云端下发的指令。
10. 数据转发
如果数据需要转发到其他地方,可以自己创建规则配置。
11. 硬件设备测试
设备端采用GSM模块SIM800C完成上网功能,主控MCU采用STM32F103ZET6。
任意只要能上网的设备都可以使用当前代码连接服务器,因为当前模拟的是户外设备,只能采用GSM模块上网。
如果是智能家居,屋里小区的设备,有WIFI的可以采用ESP8266这些无线网卡。
项目工程源码: download.csdn.net/download/xi…
1. SIM800C.c
这是SIM800C的配置代码
#include "sim800c.h"
/*
函数功能:向SIM800C模块发送指令
函数参数:
char *cmd 发送的命令
char *check_data 检测返回的数据
返回值: 0表示成功 1表示失败
*/
u8 SIM800C_SendCmd(char *cmd,char *check_data)
{
u16 i,j;
for(i=0;i< 5;i++) //测试的总次数
{
USART2_RX_FLAG=0;
USART2_RX_CNT=0;
memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));
USART_X_SendString(USART2,cmd); //发送指令
for(j=0;j"))return 1; //设置发送的手机号
USART_X_SendData(USART2,text,len); //发送短信内容
send_buf[0] = 0x1a;
send_buf[1] = '\0';
if(SIM800C_SendCmd(send_buf,"+CMGS"))return 2; //发送结束符号
return 0;
}
/*
函数功能:NTP网络同步时间
*/
void SIM800C_NtpUpdate(void)
{
SIM800C_SendCmd("AT+SAPBR=3,1,"Contype","GPRS"\r\n","OK");//配置承载场景1
SIM800C_SendCmd("AT+SAPBR=3,1,"APN","CMNET"\r\n","OK");
SIM800C_SendCmd("AT+SAPBR=1,1\r\n","OK"); //激活一个GPRS上下文
DelayMs(5);
SIM800C_SendCmd("AT+CNTPCID=1\r\n","OK"); //设置CNTP使用的CID
SIM800C_SendCmd("AT+CNTP="202.120.2.101",32\r\n","OK"); //设置NTP服务器和本地时区(32时区 时间最准确)
SIM800C_SendCmd("AT+CNTP\r\n","+CNTP: 1"); //同步网络时间
printf("同步网络时间:%s\r\n",USART2_RX_BUFF);
}
/*
函数功能:GPRS数据通信初始化
返 回 值: 0表示成功
*/
u8 SIM800C_GPRS_Init(void)
{
SIM800C_SendCmd("AT+CIPCLOSE=1\r\n","CLOSE OK"); //关闭连接
SIM800C_SendCmd("AT+CIPSHUT\r\n","SHUT OK"); //关闭移动场景
if(SIM800C_SendCmd("AT+CGCLASS="B"\r\n","OK"))return 1; //设置GPRS移动台类别为B,支持包交换和数据交换
if(SIM800C_SendCmd("AT+CGDCONT=1,"IP","CMNET"\r\n","OK"))return 2;//设置PDP上下文,互联网接协议,接入点等信息
if(SIM800C_SendCmd("AT+CGATT=1\r\n","OK"))return 3; //附着GPRS业务
if(SIM800C_SendCmd("AT+CIPCSGP=1,"CMNET"\r\n","OK"))return 4; //设置为GPRS连接模式
if(SIM800C_SendCmd("AT+CIPHEAD=1\r\n","OK"))return 5; //设置接收数据显示IP头(方便判断数据来源)
return 0;
}
/*
函数功能: 连接TCP服务器
函数参数:
ipaddr:ip地址
port:端口
返 回 值: 0表示成功,其他值表示失败
*/
u8 SIM800C_Connect_TCP_Server(char *ipaddr,char *port)
{
char cmd_buff[100];
SIM800C_SendCmd("AT+CIPCLOSE=1\r\n","CLOSE OK"); //关闭连接
SIM800C_SendCmd("AT+CIPSHUT\r\n","SHUT OK"); //关闭移动场景
sprintf(cmd_buff,"AT+CIPSTART="TCP","%s","%s"\r\n",ipaddr,port);
if(SIM800C_SendCmd(cmd_buff,"OK"))return 1; //发起连接
return 0;
}
/*
函数功能: TCP客户端模式下发送数据
返 回 值: 0表示成功,其他值表示失败
*/
u8 SIIM800C_TCP_SendData(u8 *data,u32 len)
{
char send_buf[2];
//准备发送数据
if(SIM800C_SendCmd("AT+CIPSEND\r\n"," >")==0)
{
//发送数据
USART_X_SendData(USART2,data,len);
//发送结束符号
DelayMs(50);
send_buf[0] = 0x1a;
send_buf[1] = '\0';
if(SIM800C_SendCmd(send_buf,"SEND OK"))return 2;
else return 0;
}
return 1;
}
2. adc.c
这是烟雾传感器的ADC通道配置代码。
//////////////////////////////////////////////////////////////////////////////////
// 功能描述 : 智能环境检测系统
// 时间 : 20190605
// 版本 : v3.3
// 版权所有,盗版必究。
//Copyright(C) DS小龙哥 2016 - 2020
///////////////////////////////////////////////////////////////////////////////////
#include "adc.h"
/*
函数功能: ADC1的初始化
规则通道方式
*/
void ADC1_Init(void)
{
/*1. 配置ADC采集输入的IO口*/
RCC- >APB2ENR |= 1 < CRL &= 0xFFFFFFF0;
GPIOB- >CRL |= 0x00000000;//配置PB0为模拟输入模式
/*2.配置ADC1时钟*/
RCC- >APB2ENR|=1< APB2RSTR|=1< APB2RSTR&=~(1< CFGR&=~(0x3< CFGR|=0x2< CR1&=~(0xF< CR2|=1< CR2|=1< CR2|=1< CR2|=0x7< CR2&=~(1< CR2&=~(1< SQR1&=~(0xF< SMPR2|=0x7< SMPR1|=0x7< CR2|=1< CR2|=1< CR2|=1< CR2&1SQR3|=ch< CR2|=1< SR&1< DR; //返回接收到的数据值
}
3. DHT11.c
这是温湿度检测代码。
//////////////////////////////////////////////////////////////////////////////////
// 功能描述 : 智能环境检测系统
// 时间 : 20190605
// 版本 : v3.3
// 版权所有,盗版必究。
//Copyright(C) DS小龙哥 2016 - 2020
///////////////////////////////////////////////////////////////////////////////////
#include "dht11.h"
#include "delay.h"
/*
复位DHT1
*/
void DHT11_Rst(void)
{
DHT11_IO_OUT(); //SET OUTPUT
DHT11_DQ_OUT=0; //拉低DQ
delay_ms(20); //拉低至少18ms
DHT11_DQ_OUT=1; //DQ=1
delay_us(30); //主机拉高20~40us
}
/*
等待DHT11的回应
返回1:未检测到DHT11的存在
返回0:存在
*/
u8 DHT11_Check(void)
{
u8 retry=0;
DHT11_IO_IN();//SET INPUT
while (DHT11_DQ_IN&&retry=100)return 1;
else retry=0;
while (!DHT11_DQ_IN&&retry=100)return 1;
return 0;
}
/*
从DHT11读取一个位
返回值:1/0
*/
u8 DHT11_Read_Bit(void)
{
u8 retry=0;
while(DHT11_DQ_IN&&retry< 100)//等待变为低电平
{
retry++;
delay_us(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry< 100)//等待变高电平
{
retry++;
delay_us(1);
}
delay_us(40);//等待40us
if(DHT11_DQ_IN)return 1;
else return 0;
}
/*
从DHT11读取一个字节
返回值:读到的数据
*/
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;
for(i=0;i< 8;i++)
{
dat< APB2ENR|=1CRL|=0X00300000;
GPIOA- >ODR|=1<