





1. 宦娟,吴帆,曹伟建等.基于窄带物联网的养殖塘水质监测系统研制[J].农业工程学报,2019,35(08):252-261.
2. Sajal Saha, Rakibul Hasan Rajib et al. “IoT Based Automated Fish Farm Aquaculture Monitoring System.” 2018 International Conference on Innovations in Science, Engineering and Technology (ICISET) (2018). 201-206.
3. K. Preetham, B. Mallikarjun et al. “Aquaculture monitoring and control system: An IoT based approach.” (2019). 1167-1170.
4. Nikitha Rosaline and Dr. S. Sathyalakshimi. “IoT Based Aquaculture Monitoring and Control System.” Journal of Physics: Conference Series (2019).
5. Rodolfo W. L. Coutinho and A. Boukerche. “Towards a Novel Architectural Design for IoT-Based Smart Marine Aquaculture.” IEEE Internet of Things Magazine (2022). 174-179.
6. 彭琛,陈伟平,曾昱.物联网技术在智能水产养殖系统中的应用[J].湖南文理学院学报(自然科学版),2021,33(04):37-41+87.
7. 杨金明,余情,朱红飞等.基于物联网技术的水产养殖智能管理系统设计[J].湖北农业科学,2016,55(16):4276-4279.
8. 冼锂东,龙祖连.基于物联网技术智慧水产养殖系统的研究设计[J].物联网技术,2022,12(02):65-68.
9. 徐晓姗.基于物联网和3G技术的智能水产养殖环境监测系统的设计与应用[J].网络安全技术与应用,2014,No.165(09):235-236.
10. 刘星桥,骆波,朱成云.基于物联网和GIS的水产养殖测控系统平台设计[J].渔业现代化,2016,43(06):16-20.
11. 李新成,林德峰,王胜涛等.基于物联网的水产养殖池塘智能管控系统设计[J].水产学杂志,2020,33(01):81-86.
12. 杨轶霞.基于物联网技术的智能水产养殖监控系统应用[J].电子技术,2021,50(05):178-179.
13. B. Paul, Shubham Agnihotri et al. “Sustainable Smart Aquaponics Farming Using IoT and Data Analytics.” Journal of Information Technology Research (2022). 1-27.
14. 林永铖,林超洋,梁志锋等.基于物联网技术的淡水养殖监控系统[J].电气技术,2015,No.192(10):59-62.
15. 基于物联网的智慧水产系统开发 [2021-08-05]
16. 吴小峰.基于物联网技术的智能水产养殖管理系统设计[J].襄阳职业技术学院学报,2015,14(06):15-18.
17. R. Ismail, K. Shafinah et al. “A Proposed Model of Fishpond Water Quality Measurement and Monitoring System based on Internet of Things (IoT).” IOP Conference Series: Earth and Environment (2020).
18. 王韵琪,尤文杰,李呈祥等.基于物联网的水产智能养殖环境监控系统设计[J].科技风,2022,No.510(34):66-68.
19. 潘春霖.基于物联网技术的智能渔业监控系统设计[J].天津农业科学,2017,23(12):26-30.
20. 汤朝婧.基于物联网技术的水产养殖系统设计[J].物联网技术,2024,14(02):82-85+89.
21. 基于物联网的水产养殖环境智能监控系统 [2014-02-20]
22. 胡琼.基于物联网的智慧水产养殖系统模型设计[J].无线互联科技,2019,16(02):33-34.
23. 李卓然.基于嵌入式Linux的水产养殖物联网监测系统设计[J].农机化研究,2019,41(11):229-233.
24. 王英杰. 基于物联网的水产养殖测控系统的设计与实现[D].江苏大学,2017.
25. 黄劲斐.物联网水产监测系统的设计[J].科技视界,2020,No.318(24):24-25.
26. 杨宁生,袁永明,孙英泽.物联网技术在我国水产养殖上的应用发展对策[J].中国工程科学,2016,18(03):57-61.
27. 陈浩成,袁永明,马晓飞等.基于物联网的水产养殖水质监控集成技术[J].现代农业科技,2013,No.608(18):324-326.
28. M. Lafont, Samuel Dupont et al. “Back to the future: IoT to improve aquaculture : Real-time monitoring and algorithmic prediction of water parameters for aquaculture needs.” Global Internet of Things Summit (2019). 1-6.
29. U. Acar, Frank Kane et al. “Designing An IoT Cloud Solution for Aquaculture.” Global Internet of Things Summit (2019). 1-6.
30. 顾丽敏.基于物联网的数字化渔业养殖监测系统设计[J].信息系统工程,2021,No.325(01):74-75.


步进电机28BYJ-48名称含义:
28:表示步进电机的有效最大外径为28毫米
B: 表示步进电机“步”字汉语拼音首字母
Y: 表示永磁式“永”字汉语拼音首字母
J: 表示减速型“减”字汉语拼音首字母
BYJ: 组合即为永磁式减速步进电机
48:表示四相八拍
5V:表示额定电压为5V,且为直流电压
步进角:5.625度,就是1个脉冲信号转5.625度,64个信号转360度。
减速比:1/64,电机壳里边的电机转64圈,电机壳外边的部分转1圈。
四相:ABCD四相(电机定子上有8个齿,相对的2个齿是1相),
八拍:(A-AB-B-BC-C-CD-D-DA-A)。
一拍就是一个脉冲信号,完成一个循环用8个脉冲信号。
当通电状态的改变完成一个循环时,转子转过一个齿距。转8个齿距就是一圈,8×8=64
64拍,64个脉冲信号转一圈360度。


TDS (Total Dissolved Solids)、中文名总溶解固体、又称溶解性固体、又称溶解性固体总量、表明1升水肿容有多少毫克溶解性固体、一般来说、TDS值越高、表示水中含有溶解物越多、水就越不洁净、虽然在特定情况下TDS并不能有效反映水质的情况、但作为一种可快速检测的参数、TDS目前还可以作为有效的在水质情况反映参数来作为参考。常用的TDS检测设备为TDS笔、虽然价格低廉、简单易用、但不能把数据传给控制系统、做长时间的在线监测、并做水质状况分析、使用专门的仪器、虽然能传数据、精度也高、但价格很贵、为此这款TDS传感器模块、即插即用、使用简单方便、测量用的激励源采用交流信号、可有效防止探头极化、延长探头寿命的同时、也增加了输出信号的稳定性、TDS探头为防水探头、可长期侵入水中测量、该产品可以应用于生活用水、水培等领域的水质检测、有了这个传感器、可轻松DIY--套TDS检测仪了、轻松检测水的洁净程度。
打开官网,搜索物联网,就能快速找到 设备接入IoTDA。



点击立即创建。





开通之后,点击总览,也能查看接入信息。 我们当前设备准备采用MQTT协议接入华为云平台,这里可以看到MQTT协议的地址和端口号等信息。

端口号: MQTT (1883)| MQTTS (8883)
接入地址:
C:Users11266>ping
正在 Ping [117.78.5.125] 具有 32 字节的数据:
来自 117.78.5.125 的回复: 字节=32 时间=42ms TTL=94
来自 117.78.5.125 的回复: 字节=32 时间=42ms TTL=94
来自 117.78.5.125 的回复: 字节=32 时间=42ms TTL=94
来自 117.78.5.125 的回复: 字节=32 时间=43ms TTL=94
117.78.5.125 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 42ms,最长 = 43ms,平均 = 42ms
C:Users11266>





上传到华为云IOT平台的属性:
PH值检测 PH 整型
浑浊度检测 water_quality 整型
温度检测 DS18B20 浮点数
换水电机 water_motor BOOL类型
充氧电机 oxygen_motor BOOL类型
定时充氧 oxygen_motor_time 整型
水温阀值 DS18B20_MAX 整型
换水电机-出水 clean_motor BOOL类型
照明灯 lighting_led BOOL类型
水位检测 water_monitor 整型

















{
"device_id": "65dd4fc72ccc1a583879a7e1_dev1",
"secret": "12345678"
}






以当前设备为例,最终订阅主题的格式如下:
$oc/devices/{device_id}/sys/messages/down
最终的格式:
$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/messages/down

发布的主题格式:
$oc/devices/{device_id}/sys/properties/report
最终的格式:
$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/report
发布主题时,需要上传数据,这个数据格式是JSON格式。
上传的JSON数据格式如下:
{
"services": [
{
"service_id": <填服务ID>,
"properties": {
"<填属性名称1>": <填属性值>,
"<填属性名称2>": <填属性值>,
..........
}
}
]
}
根据JSON格式,一次可以上传多个属性字段。 这个JSON格式里的,服务ID,属性字段名称,属性值类型,在前面创建产品的时候就已经介绍了,不记得可以翻到前面去查看。
根据这个格式,组合一次上传的属性数据:
{"services": [{"service_id": "stm32","properties":{"PH":20,"water_quality":60,"DS18B20":14.1,"oxygen_motor_time":10,"DS18B20_MAX":15,"water_monitor":10,"clean_motor":1,"lighting_led":1,"water_motor":1,"oxygen_motor":1}}]}

华为云的MQTT服务器地址:117.78.5.125
华为云的MQTT端口号:1883


ClientId 65dd4fc72ccc1a583879a7e1_dev1_0_0_2024022705
Username 65dd4fc72ccc1a583879a7e1_dev1
Password 91c783515515d883c533df05ef0e15ed526e583cfb141de54e9ba1545fba0513





华为云的MQTT服务器地址:117.78.5.125
华为云的MQTT端口号:1883
ClientId 65dd4fc72ccc1a583879a7e1_dev1_0_0_2024022705
Username 65dd4fc72ccc1a583879a7e1_dev1
Password 91c783515515d883c533df05ef0e15ed526e583cfb141de54e9ba1545fba0513
订阅主题: $oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/messages/down
发布主题: $oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/report
发布的数据:
{"services": [{"service_id": "stm32","properties":{"PH":20,"water_quality":60,"DS18B20":14.1,"oxygen_motor_time":10,"DS18B20_MAX":15,"water_monitor":10,"clean_motor":1,"lighting_led":1,"water_motor":1,"oxygen_motor":1}}]}
Qt的中文官网: https://www.qt.io/zh-cn/


qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details
安装的时候,第一个复选框里勾选一个mingw 32编译器即可,其他的不管默认就行,直接点击下一步继续安装。


【1】获取项目凭证 点击左上角用户名,选择下拉菜单里的我的凭证

756f8211ec6847c3a5ee4061b37d4ddb
鼠标放在左上角头像上,在下拉菜单里选择统一身份认证。

点击左上角创建用户。






主用户名 hid_x13ruy5yb1ruano
IAM用户 ds_abc
密码 DS12345678
设备影子是一个用于存储和检索设备当前状态信息的JSON文档。
每个设备有且只有一个设备影子,由设备ID唯一标识
设备影子仅保存最近一次设备的上报数据和预期数据
无论该设备是否在线,都可以通过该影子获取和设置设备的属性

{
"device_id": "65dd4fc72ccc1a583879a7e1_dev1",
"shadow": [
{
"service_id": "stm32",
"desired": {
"properties": null,
"event_time": null
},
"reported": {
"properties": {
"PH": 20,
"water_quality": 60,
"DS18B20": 14.1,
"oxygen_motor_time": 10,
"DS18B20_MAX": 15,
"water_monitor": 10,
"clean_motor": 1,
"lighting_led": 1,
"water_motor": 1,
"oxygen_motor": 1
},
"event_time": "20240227T052838Z"
},
"version": 0
}
]
}

设备的产品模型中定义了物联网平台可向设备下发的属性,应用服务器可调用此接口向指定设备下发属性。平台负责将属性以同步方式发送给设备,并将设备执行属性结果同步返回。


{"services":{"oxygen_motor":1}}













在工程文件下方,增加当前软件的图标配置,图标需要是ICO格式,将图标放在工程同级路径下,在工程配置文件里指定好图标名称。


/*
功能: 获取token
*/
void Widget::GetToken()
,"name": "%2","password": "%3"}}},"
""scope":{"project":{"name":"%4"}}}}")
.arg(MAIN_USER)
.arg(IAM_USER)
.arg(IAM_PASSWORD)
.arg(SERVER_ID);
//发送请求
manager->post(request, text.toUtf8());
}
void Widget::on_pushButton_rtc_clicked()
}").arg(str);
//发送请求
manager->put(request, post_param.toUtf8());
}
//查询设备属性
void Widget::Get_device_properties()
//解析反馈结果
void Widget::replyFinished(QNetworkReply *reply)
}
QMessageBox::information(this,"提示",displayInfo,QMessageBox::Ok,QMessageBox::Ok);
return;
}
//判断状态码
if(200 != statusCode)
if(obj.contains("error_msg"))
{
error_str+="错误消息:";
error_str+=obj.take("error_msg").toString();
error_str+="
";
}
//显示错误代码
QMessageBox::information(this,"提示",error_str,QMessageBox::Ok,QMessageBox::Ok);
}
}
return;
}
//设置属性
if(function_select==12 || function_select==13)
if(obj1.contains("result_desc"))
{
success=obj1.take("result_desc").toString();
}
if(val==0 && success =="success")
{
//显示状态
QMessageBox::information(this,"提示","远程命令操作完成.",QMessageBox::Ok,QMessageBox::Ok);
return;
}
else
{
//显示状态
QMessageBox::information(this,"提示","设备未正确回应.请检查设备网络.",QMessageBox::Ok,QMessageBox::Ok);
return;
}
}
}
}
}
//查询设备属性
if(function_select==0)
}
}
}
}
}
return;
}
}
/// 像设备端发送命令
/// brief Widget::MQTT_Cmd_Send
/// param cmd
///
void Widget::MQTT_Cmd_Send(QString cmd)
}").arg(cmd);
//发送请求
manager->put(request, post_param.toUtf8());
}











成功之后,在目录下可以看到生成的apk文件,也就是Android手机的安装包,电脑端使用QQ发送给手机QQ,手机登录QQ接收,就能直接安装。
生成的apk的目录在哪里呢?

D:linux-share-dirQTbuild-Smarts_Fishbowl_HuaWeiYunIot-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Releaseandroid-buildbuildoutputsapkdebug

len:140,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=17f9bd7d-d81a-493c-94fa-5d7fc4d637a3{"services":{"lighting_led":1}}
len:139,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=bc1d53f6-dd28-48f6-a39c-fea3f1c7c45c{"services":{"clean_motor":0}}
len:140,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=2fb1619b-9d48-4bc2-9d07-054895275005{"services":{"oxygen_motor":1}}
len:139,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=9b2b0c35-12ea-4c6a-a43d-496d229b1783{"services":{"water_motor":1}}
len:145,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=f27f9be3-4e78-483b-82ae-d145ba78ce60{"services":{"oxygen_motor_time":1}}
len:136,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=09f0831e-6e9b-4220-a3d0-25912c67b48e{"services":{"temp_max":1}}
len:149,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=696f8046-fcf7-4307-b9a5-9604d31c8b94{"services":{"rtc_time":20240227162845}}

1. ESP8266 WIFI接线
ATK-ESP8266串口WIFI模块与STM32的串口2相连接。
PA2(TX)--RXD 模块接收脚
PA3(RX)--TXD 模块发送脚
GND---GND 地
VCC---VCC 3.3V
2. TFT 1.44 寸彩屏接线
GND 电源地
VCC 3.3v电源
SCL 接PC8(SCL)
SDA 接PC9(SDA)
RST 接PC10
DC 接PB7
CS 接PB8
BL 接PB11
3. DS18B20温度传感器
VCC--3.3v
GND---GND
OUT---PB3
4. SG90舵机-模拟鱼缸换水-出水
VCC--->5V
OUT--->PA7
GND--->GND
5. 水质传感器(ADC通道1)
VCC--->5V
GND--->GND
OUT--->PA1
6. SG90舵机-模拟鱼缸换水-进水
OUT----PB5
GND---GND 地
VCC---5v
7. 鱼缸水温加热--继电器控制
GND----GND
VCC---3.3V
OUT---PB4
8. 增氧泵--继电器控制
GND----GND
VCC---5V
OUT---PC11
9. PH值检测
VCC--->3.3V
GND--->GND
OUT--->PA4
10. 照明灯开关
VCC--->3.3V
GND--->GND
OUT--->PA6
11. 水位检测
VCC--->3.3V
GND--->GND
OUT--->PA5
13. 板载LED灯接线(这个不用接,这是开发板本身的)
LED1---PA8
LED2---PD2
14. 板载按键接线(这个不用接,这是开发板本身的)
K0---PA0
K1---PC5
K2---PA15


//如果WIFI已经连接到网络
if(esp8266_connect)
{
//组合JSON报文数据
sprintf(data_buff,"{"services": [{"service_id": "stm32","properties":{"PH":%d,"water_quality":%d,"DS18B20":%.1f,"oxygen_motor_time":%d,"DS18B20_MAX":%d,"water_monitor":%d,"clean_motor":%d,"lighting_led":%d,"water_motor":%d,"oxygen_motor":%d}}]}",
PH,percentage,DS18B20,oxygen_motor_time,DS18B20_MAX,water_monitor,clean_motor,lighting_led,water_motor,oxygen_motor);
//上传数据
MQTT_PublishData(POST_TOPIC,data_buff,0);
printf("更新一次数据.
");
}
len:140,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=17f9bd7d-d81a-493c-94fa-5d7fc4d637a3{"services":{"lighting_led":1}}
len:139,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=bc1d53f6-dd28-48f6-a39c-fea3f1c7c45c{"services":{"clean_motor":0}}
len:140,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=2fb1619b-9d48-4bc2-9d07-054895275005{"services":{"oxygen_motor":1}}
len:139,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=9b2b0c35-12ea-4c6a-a43d-496d229b1783{"services":{"water_motor":1}}
len:145,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=f27f9be3-4e78-483b-82ae-d145ba78ce60{"services":{"oxygen_motor_time":1}}
len:136,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=09f0831e-6e9b-4220-a3d0-25912c67b48e{"services":{"temp_max":1}}
len:149,Data:l$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/request_id=696f8046-fcf7-4307-b9a5-9604d31c8b94{"services":{"rtc_time":20240227162845}}
开发板自带了4个按键,其中第2是个RST 是复位键、另外3个按键是可编程的独立按键。

key=KEY_Scan();
if(key)printf("key=%d
",key);
//按下按键1进行翻页
if(key==1)
else
{
page_2();
}
}
//按下按键2控制照明灯打开
else if(key==2)
{
lighting_led=!lighting_led;
}
//按下按键3控制 控制
else if(key==3)
{
//清洗3次
open_clean_motor();
close_clean_motor();
delay_ms(1000);
open_clean_motor();
close_clean_motor();
delay_ms(1000);
open_clean_motor();
close_clean_motor();
}
//轮询时间到达
if(time_cnt>20)
//水质太差 就启动换水
if(percentage>80)
{
//正转 换水电机
open_water_motor();
}
else
{
//--反转 换水电机
close_water_motor();
}
//显示页面1
if(page==0)
{
//实时时间与日期
Gui_DrawFont_GBK16(16*1,16*6+2,WHITE,0,(u8*)date_buff);
Gui_DrawFont_GBK16(16*1+8,16*7+2,WHITE,0,(u8*)time_buff);
//显示温度
sprintf(mqtt_message,"%4.1fC",DS18B20);
Gui_DrawFont_GBK16(72,16*0+2,WHITE,0,(u8*)mqtt_message);
// printf("%s
",mqtt_message);
//显示水质
sprintf(mqtt_message,"%4d%%",percentage);
Gui_DrawFont_GBK16(72,16*1+2,WHITE,0,(u8*)mqtt_message);
//PH值
sprintf(mqtt_message,"%4d",PH);
Gui_DrawFont_GBK16(72,16*2+2,WHITE,0,(u8*)mqtt_message);
//充氧间隔
sprintf(mqtt_message,"%4dm",oxygen_motor_time);
Gui_DrawFont_GBK16(72,16*3+2,WHITE,0,(u8*)mqtt_message);
//恒温温度
sprintf(mqtt_message,"%4dC",DS18B20_MAX);
Gui_DrawFont_GBK16(72,16*4+2,WHITE,0,(u8*)mqtt_message);
//水位距离
sprintf(mqtt_message,"%4d%%",water_monitor);
Gui_DrawFont_GBK16(72,16*5+2,WHITE,0,(u8*)mqtt_message);
}
else if(page==1)
{
//实时时间与日期
Gui_DrawFont_GBK16(16*0,16*2+2,WHITE,0,(u8*)date_buff);
Gui_DrawFont_GBK16(16*0+8,16*3+2,WHITE,0,(u8*)time_buff);
char *p=format_time(oxygen_food_sec);
Gui_DrawFont_GBK16(0,16*5+2,WHITE,0,(u8*)p);
}
//恒温判断. 如果小于温度阀值
if(DS18B20<DS18B20_MAX)
{
temp_heat=1; //开启加热
}
else
{
temp_heat=0; //停止加热
}
//如果WIFI已经连接到网络
if(esp8266_connect)
{
//组合JSON报文数据
sprintf(data_buff,"{"services": [{"service_id": "stm32","properties":{"PH":%d,"water_quality":%d,"DS18B20":%.1f,"oxygen_motor_time":%d,"DS18B20_MAX":%d,"water_monitor":%d,"clean_motor":%d,"lighting_led":%d,"water_motor":%d,"oxygen_motor":%d}}]}",
PH,percentage,DS18B20,oxygen_motor_time,DS18B20_MAX,water_monitor,clean_motor,lighting_led,water_motor,oxygen_motor);
//上传数据
MQTT_PublishData(POST_TOPIC,data_buff,0);
printf("更新一次数据.
");
}
}
// 接收WIFI返回的数据
if(USART2_RX_FLAG)
{
USART2_RX_BUFFER[USART2_RX_CNT]='0';
printf("WIFI收到数据:
");
//向串口打印服务器返回的数据
for(i=0;i<USART2_RX_CNT;i++)
{
printf("%c",USART2_RX_BUFFER[i]);
}
#if 0
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=8401c98b-268e-4382-82fd-b69d78275020{"services":{"motor_food":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=22e6e1ff-3e5c-4a25-bbbf-fd4e8f314a68{"services":{"led_sw":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=a15b8f8d-06cf-4597-8cd9-f92e3e0a7b4f{"services":{"motor_oxygen":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=c5b708d8-7c58-43c8-9943-64e25fe6f4df{"services":{"motor_water":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=852659ce-183c-42bf-b896-f9c1e960f405{"services":{"time_food":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=e401d20d-8c10-453d-b1cf-ba7c97a66f7d{"services":{"oxygen_food":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=dd10158b-3da0-45a2-be68-27ddb14a797c{"services":{"temp_max":15}}
#endif
if(USART2_RX_CNT>5)
//关 照明灯
else if(strstr((char*)&USART2_RX_BUFFER[5],""lighting_led":0"))
{
lighting_led=0;
}
//开 换水电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""water_motor":1"))
{
//--反转 换水电机
close_water_motor();
}
//关 换水电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""water_motor":0"))
{
//正转 换水电机
open_water_motor();
}
//开 充氧电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""oxygen_motor":1"))
{
oxygen_motor=1;
}
//关 充氧电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""oxygen_motor":0"))
{
oxygen_motor=0;
}
//开 换水电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""clean_motor":1"))
{
//--反转 换水电机-出水
close_clean_motor();
}
//关 换水电机-出水
else if(strstr((char*)&USART2_RX_BUFFER[5],""clean_motor":0"))
{
//正转 换水电机-出水
open_clean_motor();
}
//充氧时间间隔
else if(strstr((char*)&USART2_RX_BUFFER[5],""oxygen_motor_time":"))
{
char *p=strstr((char*)&USART2_RX_BUFFER[5],""oxygen_motor_time":");
oxygen_motor_time=atoi(p+20);
oxygen_food_sec = oxygen_motor_time*60; //转为秒单位
printf("oxygen_motor_time=%d
",oxygen_motor_time);
}
//加热温度上限阀值
else if(strstr((char*)&USART2_RX_BUFFER[5],""temp_max":"))
{
char *p=strstr((char*)&USART2_RX_BUFFER[5],""temp_max":");
DS18B20_MAX=atoi(p+11);
printf("DS18B20_MAX=%d
",DS18B20_MAX);
}
else if(strstr((char*)&USART2_RX_BUFFER[5],""rtc_time":"))
{
char *p=strstr((char*)&USART2_RX_BUFFER[5],""rtc_time":");
p+=11; //向后偏移,指向正确的时间
char *time=p;
int tm_sec; //秒
int tm_min; //分
int tm_hour; //时
int tm_mday; //日
int tm_mon; //月
int tm_year; //年
tm_year=(time[0]-48)*1000+(time[1]-48)*100+(time[2]-48)*10+(time[3]-48)*1;
tm_mnotallow=(time[4]-48)*10+(time[5]-48)*1;
tm_mday=(time[6]-48)*10+(time[7]-48)*1;
tm_hour=(time[8]-48)*10+(time[9]-48)*1;
tm_min=(time[10]-48)*10+(time[11]-48)*1;
tm_sec=(time[12]-48)*10+(time[13]-48)*1;
SetRtcTime(tm_year,tm_mon,tm_mday,tm_hour,tm_min,tm_sec);
printf("RTC时间设置成功:%d-%d-%d %d:%d:%d
",tm_year,tm_mon,tm_mday,tm_hour,tm_min,tm_sec);
}
//下发指令请求回应给服务器
if(strstr((char*)&USART2_RX_BUFFER[5],"properties/set/request_id"))
strncpy(request_id,p,47);
}
//上报数据
sprintf(mqtt_message,"{"result_code": 0,"result_desc": "success"}");
sprintf(data_buff,"$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/response/%s",
request_id);
MQTT_PublishData(data_buff,mqtt_message,0);
printf("发布主题:%s
",data_buff);
printf("发布数据:%s
",mqtt_message);
}
}
USART2_RX_CNT=0;
USART2_RX_FLAG=0;
}





WIFI模式:STA+TCP客户端
Connect_WIFI热点名称:abc
Connect_WIFI热点密码:12345678
TCP服务器端口号:1883
TCP服务器IP地址:117.78.5.125
ESP8266成功连接上热点...
准备连接MQTT服务器...
0x20 0x2 0 0 服务器连接成功.


#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include "esp8266.h"
#include "oled.h"
#include "adc.h"
#include <string.h>
#include <stdlib.h>
#include "font.h"
#include "mqtt.h"
#include "ds18b20.h"
#include "rtc.h"
#include "hardware.h"
//物联网服务器的设备信息
#define MQTT_ClientID "65dd4fc72ccc1a583879a7e1_dev1_0_0_2024022705"
#define MQTT_UserName "65dd4fc72ccc1a583879a7e1_dev1"
#define MQTT_PassWord "91c783515515d883c533df05ef0e15ed526e583cfb141de54e9ba1545fba0513"
//订阅与发布的主题
#define SET_TOPIC "$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/messages/down" //订阅
#define POST_TOPIC "$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/report" //发布
//设置连接的路由器信息
#define CONNECT_WIFI "abc" //将要连接的路由器名称 --不要出现中文、空格等特殊字符
#define CONNECT_PASS "12345678" //将要连接的路由器密码
#define CONNECT_SERVER_IP "117.78.5.125" //服务器IP地址
#define CONNECT_SERVER_PORT 1883 //服务器端口号
//JTAG模式设置,用于设置JTAG的模式
//mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;
#define JTAG_SWD_DISABLE 0X02
#define SWD_ENABLE 0X01
#define JTAG_SWD_ENABLE 0X00
void JTAG_Set(u8 mode)
{
u32 temp;
temp=mode;
temp<<=25;
RCC->APB2ENR|=1<<0; //开启辅助时钟
AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]
AFIO->MAPR|=temp; //设置jtag模式
}
char request_id[100];
char mqtt_message[100];
//WIFI发送数据存储区域
char data_buff[300];
char time_buff[50];
char date_buff[50];
double DS18B20;// 环境温度
int DS18B20_int;// 环境温度
int DS18B20_MAX=15; //加热温度上限阀值: DS18B20_MAX;
int oxygen_motor_time=5; //充氧时间间隔: oxygen_motor_time
int oxygen_food_sec=300; // 充氧时间间隔 秒
int water_quality=0; //浑浊度检测 水质状态: 浑浊度检测;
int led_sw=0; //氛围灯开关
int ledNumber=1; //LED灯的编号
int percentage=0; //水质
int water_monitor; //水位检测
u32 SecCnt=0;
int PH; //PH值检测
/*
函数功能: 定时器1的更新中断服务函数 模拟RTC
*/
void TIM1_UP_IRQHandler(void)
TIM1->SR=0;
}
/*
这个函数接受一个整数参数(秒数),并返回一个指向固定长度字符串的指针。
使用 sprintf 函数将小时、分钟和秒格式化为 HH:MM:SS 的字符串,并将其存储在 result 数组中,最后将其作为返回值返回。
在主函数中,程序要求用户输入秒数,调用 format_time 函数将其转换为格式化后的时分秒字符串,并将其打印输出。
注意,这个程序假设用户输入的秒数不超过一天(86400秒)。如果需要处理更长的时间单位,需要修改 format_time 函数的实现。
*/
char* format_time(int seconds)
{
static char result[9]; // 存储结果的字符串,固定长度为8(HH:MM:SS0)
int minutes = seconds / 60;
seconds = seconds % 60;
int hours = minutes / 60;
minutes = minutes % 60;
sprintf(result, "%02d:%02d:%02d", hours, minutes, seconds);
// printf("seconds:%d
",seconds);
return result;
}
/*
实时水温水质浊度投喂间隔充氧间隔恒温温度下次投喂时间下次充氧时间水位距离
*/
//页面1
void page_1()
{
//实时水温
LCD_ShowChineseFont(0,0+2,16,HZ_FONT_16[0],RED,0);
LCD_ShowChineseFont(16*1,0+2,16,HZ_FONT_16[1],RED,0);
LCD_ShowChineseFont(16*2,0+2,16,HZ_FONT_16[2],RED,0);
LCD_ShowChineseFont(16*3,0+2,16,HZ_FONT_16[3],RED,0);
//水质浊度
LCD_ShowChineseFont(0,16*1+2,16,HZ_FONT_16[4],RED,0);
LCD_ShowChineseFont(16*1,16*1+2,16,HZ_FONT_16[5],RED,0);
LCD_ShowChineseFont(16*2,16*1+2,16,HZ_FONT_16[6],RED,0);
LCD_ShowChineseFont(16*3,16*1+2,16,HZ_FONT_16[7],RED,0);
//PH值
Gui_DrawFont_GBK16(0,16*2+2,RED,0,(u8*)"PH");
//充氧间隔
LCD_ShowChineseFont(0,16*3+2,16,HZ_FONT_16[12],RED,0);
LCD_ShowChineseFont(16*1,16*3+2,16,HZ_FONT_16[13],RED,0);
LCD_ShowChineseFont(16*2,16*3+2,16,HZ_FONT_16[14],RED,0);
LCD_ShowChineseFont(16*3,16*3+2,16,HZ_FONT_16[15],RED,0);
//恒温温度
LCD_ShowChineseFont(0,16*4+2,16,HZ_FONT_16[16],RED,0);
LCD_ShowChineseFont(16*1,16*4+2,16,HZ_FONT_16[17],RED,0);
LCD_ShowChineseFont(16*2,16*4+2,16,HZ_FONT_16[18],RED,0);
LCD_ShowChineseFont(16*3,16*4+2,16,HZ_FONT_16[19],RED,0);
//鱼缸水位
LCD_ShowChineseFont(0,16*5+2,16,HZ_FONT_16[22],RED,0);
LCD_ShowChineseFont(16*1,16*5+2,16,HZ_FONT_16[23],RED,0);
LCD_ShowChineseFont(16*2,16*5+2,16,HZ_FONT_16[32],RED,0);
LCD_ShowChineseFont(16*3,16*5+2,16,HZ_FONT_16[33],RED,0);
}
//页面2
void page_2()
{
//当前实时时间
LCD_ShowChineseFont(0,16*1+2,16,HZ_FONT_16[20],RED,0);
LCD_ShowChineseFont(16*1,16*1+2,16,HZ_FONT_16[21],RED,0);
LCD_ShowChineseFont(16*2,16*1+2,16,HZ_FONT_16[22],RED,0);
LCD_ShowChineseFont(16*3,16*1+2,16,HZ_FONT_16[23],RED,0);
LCD_ShowChineseFont(16*4,16*1+2,16,HZ_FONT_16[24],RED,0);
LCD_ShowChineseFont(16*5,16*1+2,16,HZ_FONT_16[25],RED,0);
//下次充氧时间
LCD_ShowChineseFont(0,16*4+2,16,HZ_FONT_16[26],RED,0);
LCD_ShowChineseFont(16*1,16*4+2,16,HZ_FONT_16[27],RED,0);
LCD_ShowChineseFont(16*2,16*4+2,16,HZ_FONT_16[28],RED,0);
LCD_ShowChineseFont(16*3,16*4+2,16,HZ_FONT_16[29],RED,0);
LCD_ShowChineseFont(16*4,16*4+2,16,HZ_FONT_16[30],RED,0);
LCD_ShowChineseFont(16*5,16*4+2,16,HZ_FONT_16[31],RED,0);
}
int main()
else
{
Gui_DrawFont_GBK16(0,16*0+2,WHITE,0,(u8*)"WIFI ERROR...");
run_state=0;
printf("ESP8266硬件检测错误.
");
}
}
//如果初始化成功。就去连接指定的热点。
if(run_state)
Gui_DrawFont_GBK16(0,16*4+2,WHITE,0,(u8*)"Connect Success");
printf("ESP8266成功连接上热点...
");
printf("准备连接MQTT服务器...
");
//清屏为黑色
Lcd_Clear(0);
Gui_DrawFont_GBK16(0,16*1+2,WHITE,0,(u8*)" ");
Gui_DrawFont_GBK16(0,16*0+2,WHITE,0,(u8*)"Connect IOT MQTT");
//2. MQTT协议初始化
MQTT_Init();
//3. 连接服务器
for(i=0;i<5;i++)
run_state=0;
Gui_DrawFont_GBK16(0,16*1+2,WHITE,0,(u8*)" ");
Gui_DrawFont_GBK16(0,16*1+2,WHITE,0,(u8*)"Connect Error");
printf("服务器连接失败,正在重试...
");
delay_ms(500);
}
//如果服务器已连接
if(esp8266_connect)
else
{
Gui_DrawFont_GBK16(0,16*2+2,WHITE,0,(u8*)" ");
Gui_DrawFont_GBK16(0,16*2+2,WHITE,0,(u8*)"TOPIC Sub OK.");
printf("主题订阅成功.
");
//表示WIFI连接成功
esp8266_cnotallow=1;
}
}
else
{
printf("服务器连接失败.请保证WIFI能够连接互联网.
");
Gui_DrawFont_GBK16(0,16*1+2,WHITE,0,(u8*)" ");
Gui_DrawFont_GBK16(0,16*1+2,WHITE,0,(u8*)"Connect ERROR");
Gui_DrawFont_GBK16(0,16*2+2,WHITE,0,(u8*)"NET ERROR");
//视觉停留
delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);
}
}
#endif
SetRtcTime(2023,03,22,22,22,10); //设置时间
//定时器初始化。1秒中断一次,为了方便计时
TIMER1_Init(7200,15000); //1000000us 1000000us
//清屏为黑色
Lcd_Clear(0);
//复位 正转 换水电机-出水
open_clean_motor();
//复位 正转 换水电机
open_water_motor();
//默认显示页面1
page_1();
while(1)
else
{
page_2();
}
}
//按下按键2控制照明灯打开
else if(key==2)
{
lighting_led=!lighting_led;
}
//按下按键3控制 控制鱼缸清洗
else if(key==3)
{
//清洗3次
open_clean_motor();
close_clean_motor();
delay_ms(1000);
open_clean_motor();
close_clean_motor();
delay_ms(1000);
open_clean_motor();
close_clean_motor();
}
//轮询时间到达
if(time_cnt>20)
//水质太差 就启动换水
if(percentage>80)
{
//正转 换水电机
open_water_motor();
}
else
{
//--反转 换水电机
close_water_motor();
}
//显示页面1
if(page==0)
{
//实时时间与日期
Gui_DrawFont_GBK16(16*1,16*6+2,WHITE,0,(u8*)date_buff);
Gui_DrawFont_GBK16(16*1+8,16*7+2,WHITE,0,(u8*)time_buff);
//显示温度
sprintf(mqtt_message,"%4.1fC",DS18B20);
Gui_DrawFont_GBK16(72,16*0+2,WHITE,0,(u8*)mqtt_message);
// printf("%s
",mqtt_message);
//显示水质
sprintf(mqtt_message,"%4d%%",percentage);
Gui_DrawFont_GBK16(72,16*1+2,WHITE,0,(u8*)mqtt_message);
//PH值
sprintf(mqtt_message,"%4d",PH);
Gui_DrawFont_GBK16(72,16*2+2,WHITE,0,(u8*)mqtt_message);
//充氧间隔
sprintf(mqtt_message,"%4dm",oxygen_motor_time);
Gui_DrawFont_GBK16(72,16*3+2,WHITE,0,(u8*)mqtt_message);
//恒温温度
sprintf(mqtt_message,"%4dC",DS18B20_MAX);
Gui_DrawFont_GBK16(72,16*4+2,WHITE,0,(u8*)mqtt_message);
//水位距离
sprintf(mqtt_message,"%4d%%",water_monitor);
Gui_DrawFont_GBK16(72,16*5+2,WHITE,0,(u8*)mqtt_message);
}
else if(page==1)
{
//实时时间与日期
Gui_DrawFont_GBK16(16*0,16*2+2,WHITE,0,(u8*)date_buff);
Gui_DrawFont_GBK16(16*0+8,16*3+2,WHITE,0,(u8*)time_buff);
char *p=format_time(oxygen_food_sec);
Gui_DrawFont_GBK16(0,16*5+2,WHITE,0,(u8*)p);
}
//恒温判断. 如果小于温度阀值
if(DS18B20<DS18B20_MAX)
{
temp_heat=1; //开启加热
}
else
{
temp_heat=0; //停止加热
}
//如果WIFI已经连接到网络
if(esp8266_connect)
{
//组合JSON报文数据
sprintf(data_buff,"{"services": [{"service_id": "stm32","properties":{"PH":%d,"water_quality":%d,"DS18B20":%.1f,"oxygen_motor_time":%d,"DS18B20_MAX":%d,"water_monitor":%d,"clean_motor":%d,"lighting_led":%d,"water_motor":%d,"oxygen_motor":%d}}]}",
PH,percentage,DS18B20,oxygen_motor_time,DS18B20_MAX,water_monitor,clean_motor,lighting_led,water_motor,oxygen_motor);
//上传数据
MQTT_PublishData(POST_TOPIC,data_buff,0);
printf("更新一次数据.
");
}
}
// 接收WIFI返回的数据
if(USART2_RX_FLAG)
{
USART2_RX_BUFFER[USART2_RX_CNT]='0';
printf("WIFI收到数据:
");
//向串口打印服务器返回的数据
for(i=0;i<USART2_RX_CNT;i++)
{
printf("%c",USART2_RX_BUFFER[i]);
}
#if 0
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=8401c98b-268e-4382-82fd-b69d78275020{"services":{"motor_food":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=22e6e1ff-3e5c-4a25-bbbf-fd4e8f314a68{"services":{"led_sw":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=a15b8f8d-06cf-4597-8cd9-f92e3e0a7b4f{"services":{"motor_oxygen":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=c5b708d8-7c58-43c8-9943-64e25fe6f4df{"services":{"motor_water":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=852659ce-183c-42bf-b896-f9c1e960f405{"services":{"time_food":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=e401d20d-8c10-453d-b1cf-ba7c97a66f7d{"services":{"oxygen_food":1}}
$oc/devices/640ee9ee40773741f9fb55cb_dev1/sys/properties/set/request_id=dd10158b-3da0-45a2-be68-27ddb14a797c{"services":{"temp_max":15}}
#endif
if(USART2_RX_CNT>5)
//关 照明灯
else if(strstr((char*)&USART2_RX_BUFFER[5],""lighting_led":0"))
{
lighting_led=0;
}
//开 换水电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""water_motor":1"))
{
//--反转 换水电机
close_water_motor();
}
//关 换水电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""water_motor":0"))
{
//正转 换水电机
open_water_motor();
}
//开 充氧电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""oxygen_motor":1"))
{
oxygen_motor=1;
}
//关 充氧电机
else if(strstr((char*)&USART2_RX_BUFFER[5],""oxygen_motor":0"))
{
oxygen_motor=0;
}
//开 换水电机-出水
else if(strstr((char*)&USART2_RX_BUFFER[5],""clean_motor":1"))
{
//--反转 换水电机-出水
close_clean_motor();
}
//关 换水电机-出水
else if(strstr((char*)&USART2_RX_BUFFER[5],""clean_motor":0"))
{
//正转 换水电机-出水
open_clean_motor();
}
//充氧时间间隔
else if(strstr((char*)&USART2_RX_BUFFER[5],""oxygen_motor_time":"))
{
char *p=strstr((char*)&USART2_RX_BUFFER[5],""oxygen_motor_time":");
oxygen_motor_time=atoi(p+20);
oxygen_food_sec = oxygen_motor_time*60; //转为秒单位
printf("oxygen_motor_time=%d
",oxygen_motor_time);
}
//加热温度上限阀值
else if(strstr((char*)&USART2_RX_BUFFER[5],""temp_max":"))
{
char *p=strstr((char*)&USART2_RX_BUFFER[5],""temp_max":");
DS18B20_MAX=atoi(p+11);
printf("DS18B20_MAX=%d
",DS18B20_MAX);
}
else if(strstr((char*)&USART2_RX_BUFFER[5],""rtc_time":"))
{
char *p=strstr((char*)&USART2_RX_BUFFER[5],""rtc_time":");
p+=11; //向后偏移,指向正确的时间
char *time=p;
int tm_sec; //秒
int tm_min; //分
int tm_hour; //时
int tm_mday; //日
int tm_mon; //月
int tm_year; //年
tm_year=(time[0]-48)*1000+(time[1]-48)*100+(time[2]-48)*10+(time[3]-48)*1;
tm_mnotallow=(time[4]-48)*10+(time[5]-48)*1;
tm_mday=(time[6]-48)*10+(time[7]-48)*1;
tm_hour=(time[8]-48)*10+(time[9]-48)*1;
tm_min=(time[10]-48)*10+(time[11]-48)*1;
tm_sec=(time[12]-48)*10+(time[13]-48)*1;
SetRtcTime(tm_year,tm_mon,tm_mday,tm_hour,tm_min,tm_sec);
printf("RTC时间设置成功:%d-%d-%d %d:%d:%d
",tm_year,tm_mon,tm_mday,tm_hour,tm_min,tm_sec);
}
//下发指令请求回应给服务器
if(strstr((char*)&USART2_RX_BUFFER[5],"properties/set/request_id"))
strncpy(request_id,p,47);
}
//上报数据
sprintf(mqtt_message,"{"result_code": 0,"result_desc": "success"}");
sprintf(data_buff,"$oc/devices/65dd4fc72ccc1a583879a7e1_dev1/sys/properties/set/response/%s",
request_id);
MQTT_PublishData(data_buff,mqtt_message,0);
printf("发布主题:%s
",data_buff);
printf("发布数据:%s
",mqtt_message);
}
}
USART2_RX_CNT=0;
USART2_RX_FLAG=0;
}
DelayMs(10);
time_cnt++;
timer_hour_cnt++;
}
}