CC2530/ESP32 传感器 ZigBee MQTT MYSQL Springboot Vue Echarts老年卫生间自动报警系统防坠落
- 写在前言
-
- 显示运行效果
- 一代版本
-
- ESP32 MQTT读取红外传感器
- ESP32 MQTT读取触控传感器
- ESP32 MQTT读取温湿度传感器
- python订阅MQTT保存数据到MySQL
- Springboot后端读取MySQL
- Vue Axios Echarts js大屏幕可视化显示
- 二代版本
-
- CC2530读取红外传感器
- CC2530读取汽车跟踪传感器
- CC2530读激光测距传感器
- CC2530读取温湿度传感器
- python订阅MQTT保存数据到MySQL
- Springboot后端读取MySQL
- Vue Axios Echarts js大屏幕可视化显示
- 总结
写在前言
这是我第一次发布,也是我第一次制作。分为两个版本,一个是esp以红外、触摸、温湿度、蜂鸣器等为开发板获取数据。通过MQTT发送和使用数据python接收并保存mysql后端在数据库中使用Springboot,前端使用vue结合echarts制作可视化大屏幕。使用另一个版本CC以激光测距传感器、红外传感器、温湿度传感器、光敏传感器湿度传感器、光敏传感器等获取数据zigbee协议组网,将整个感知层分为四个节点和一个协调器,每个节点负责数据采集和使用zigbee通过协调器将数据传输到协调器esp8266使用mqtt发送数据。数据获取、保存、前后端显示和esp32模块相同。下面分为一代和二代。内容很长,希望大家能看完。
显示运行效果
废话不多说,先看操作效果。演示视频录得有点草率,请多包容,将就一下。 演示视频
一代版本
使用了三个一代版本ESP32开发板分别获取卫生间、卫生间和淋浴的信息。整体架构图如下:
ESP32 MQTT读取红外传感器
先用红外传感器判断老人是否使用卫生间。引脚连接图如下:
代码如下:
#include <WiFi.h> #include <PubSubClient.h> // WiFi名及密码 const char* ssid = ""; //WiFi名 const char* password = ""; //WiFi密码 const char* mqtt_server = "broker.emqx.io"; //mqtt服务器ip地址 const int buzzpin = 16; //定义蜂鸣器16号引脚 const int ledpin = 2;///红外引脚 int infrared_value = 0;///红外传感器值 int infrared_hight = 0;///红外高电平 int infrared_low = 0;///红外低电平 int flag = 0; boolean infrared_flag = false;////红外检测卫生间使用状态false表示无人、true表示有人 char attributes[1000];
#
define
LED_BUILTIN
13
//灯 13引脚 WiFiClient espClient
;
// 定义wifiClient实例 PubSubClient
client
(espClient
)
;
// 定义PubSubClient的实例
void
setup_wifi
(
)
{
//初始化WiFi
delay
(
10
)
;
// 板子通电后要启动,稍微等待一下让板子点亮 Serial
.
println
(
)
;
// 准备连接WiFi Serial
.
print
(
"连接: "
)
; Serial
.
println
(ssid
)
;
//输出连接WiFi名 WiFi
.
mode
(WIFI_STA
)
; WiFi
.
begin
(ssid
, password
)
;
while
(WiFi
.
status
(
)
!= WL_CONNECTED
)
{
delay
(
500
)
; Serial
.
print
(
"."
)
;
}
randomSeed
(
micros
(
)
)
; Serial
.
println
(
""
)
; Serial
.
println
(
"WiFi连接成功!"
)
; Serial
.
println
(
"IP address: "
)
; Serial
.
println
(WiFi
.
localIP
(
)
)
;
}
void
callback
(
char
* topic
, byte
* payload
,
unsigned
int length
)
{
Serial
.
print
(
"消息来自: ["
)
; Serial
.
print
(topic
)
;
// 打印主题信息 Serial
.
print
(
"] 主题,内容:"
)
;
char str
[
100
]
;
for
(
int i
=
0
; i
< length
; i
++
)
{
Serial
.
print
(
(
char
)payload
[i
]
)
;
// 打印主题内容 str
[i
]
=
(
char
)payload
[i
]
;
} Serial
.
println
(
)
;
if
(
strcmp
(topic
,
"light_linfeng"
)
==
0
)
{
//判读信息来源主题
if
(
strcmp
(str
,
"开灯"
)
==
0
)
{
//判断命令
digitalWrite
(LED_BUILTIN
, HIGH
)
;
// 开灯
}
else
if
(
strcmp
(str
,
"关灯"
)
==
0
)
{
digitalWrite
(LED_BUILTIN
, LOW
)
;
// 关灯
}
}
else
if
(
strcmp
(topic
,
"alarm_linfeng"
)
==
0
)
{
//判读信息来源主题
if
(
strcmp
(str
,
"开始"
)
==
0
)
{
digitalWrite
(buzzpin
, HIGH
)
;
// 开始报警
}
else
if
(
strcmp
(str
,
"关闭"
)
==
0
)
{
digitalWrite
(buzzpin
, LOW
)
;
// 关闭报警
}
}
}
void
reconnect
(
)
{
while
(
!client
.
connected
(
)
)
{
// 保持连接mqtt Serial
.
print
(
"尝试MQTT连接…"
)
; String clientId
=
"ESP8266Client-"
;
// 创建随机的客户端ID clientId
+=
String
(
random
(
0xffff
)
, HEX
)
;
if
(client
.
connect
(clientId
.
c_str
(
)
)
)
{
// 尝试连接 Serial
.
println
(
"连接成功!"
)
; client
.
subscribe
(
"linfeng_data"
)
;
//订阅消息 client
.
subscribe
(
"light_linfeng"
)
;
//订阅消息 client
.
subscribe
(
"alarm_linfeng"
)
;
//订阅消息
}
else
{
//连接失败 Serial
.
print
(
"failed, rc="
)
; Serial
.
print
(client
.
state
(
)
)
; Serial
.
println
(
" try again in 5 seconds"
)
;
delay
(
5000
)
;
}
}
}
void
setup
(
)
{
pinMode
(LED_BUILTIN
, OUTPUT
)
;
// 初始化BUILTIN_LED引脚作为输出
pinMode
(buzzpin
, OUTPUT
)
;
// 初始化buzzpin引脚作为输出 Serial
.
begin
(
115200
)
;
// 串口波特率
setup_wifi
(
)
;
//执行Wifi初始化,下文有具体描述 client
.
setServer
(mqtt_server
,
1883
)
;
//设定MQTT服务器与使用的端口,1883是默认的MQTT端口 client
.
setCallback
(callback
)
;
//设定回调方式,当ESP8266收到订阅消息时会调用此方法
}
void
loop
(
)
{
if
(
!client
.
connected
(
)
)
{
reconnect
(
)
;
} client
.
loop
(
)
; infrared_value
=
digitalRead
(ledpin
)
;
//读取红外传感器
if
(infrared_value
== HIGH
&& flag
==
0
)
//如果它的值为高电平,即检测到有人通过
{
flag
=
1
; infrared_hight
=
1
;
}
else
if
(infrared_value
== LOW
)
{
flag
=
0
;
}
if
(infrared_hight
==
1
)
{
infrared_hight
=
0
;
if
(infrared_flag
)
{
Serial
.
println
(
"离开卫生间!"
)
; String payload
=
"{"
; payload
+=
"\"place\":"
; payload
+=
"\"wc\","
; payload
+=
"\"IsWc\":"
; payload
+= false
; payload
+=
"}"
; payload
.
toCharArray
( attributes
,
1000
)
; client
.
publish
(
"linfeng_data"
, attributes
)
;
//MQTT发布消息 client
.
publish
(
"wc_linfeng"
,
"不行"
)
;
//向马桶、淋浴发送指令表示不可以发布信息
}
else
if
(
!infrared_flag
)
{
Serial
.
println
(
"进入卫生间!"
)
; String payload
=
"{"
; payload
+=
"\"place\":"
; payload
+=
"\"wc\","
; payload
+=
"\"IsWc\":"
; payload
+= true
; payload
+=
"}"
; payload
.
toCharArray
( attributes
,
1000
)
; client
.
publish
(
"linfeng_data"
, attributes
)
;
//MQTT发布消息 client
.
publish
(
"wc_linfeng"
,
"可以"
)
;
//向马桶、淋浴发送指令表示可以发布信息
} infrared_flag
=
!infrared_flag
; infrared_hight
=
0
;
}
delay
(
200
)
;
}
使用串口调试助手可查看信息的收发,结果如下:
ESP32+MQTT读取触控传感器
使用触控传感器采集老人使用马桶的数据,引脚连接图如下: 关键代码如下:
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
if (wc_flag == 1) {
touch_value = digitalRead(TOUCH_PIN); //如果进入卫生间则读取触控传感器
}
if (touch_value == HIGH) //如果它的值为高电平,即检测到有人通过
{
touch_hight = 1;
delay(100);
}
else
{
if (touch_hight == 1) {
touch_low = 1;
}
delay(100);
}
if (touch_hight == 1 && touch_low == 1) {
if (touch_flag) {
String payload = "{";
payload += "\"place\":"; payload += "\"toilet\",";
payload += "\"IsToilet\":"; payload += false;
payload += "}";
payload.toCharArray( attributes, 1000 );
client.publish("linfeng_data", attributes); //MQTT发布消息
Serial.println("离开马桶!");
} else if (!touch_flag) {
String payload = "{";
payload += "\"place\":"; payload += "\"toilet\",";
payload += "\"IsToilet\":"; payload += true;
payload += "}";
payload.toCharArray( attributes, 1000 );
client.publish("linfeng_data", attributes); //MQTT发布消息
Serial.println("使用马桶!");
}
touch_flag = !touch_flag;
touch_hight = 0;
touch_low = 0;
}
delay(200);
}
使用串口调试助手可查看信息的收发,结果如下:
ESP32+MQTT读取温湿度传感器
前两个传感器采集了卫生间和马桶的信息。此处就采集淋浴的使用情况,淋浴的使用和马桶一样,通过触控传感器来采集,此处多了一个温湿度的采集。温湿度引脚连接图如下: 关键代码如下:
void getAndSendTemperatureAndHumidityData()
{
// 大概1s读取一次
delay(200);
byte hum;
byte tem;
int err = SimpleDHTErrSuccess;
if ((err = dht11.read(&tem, &hum, NULL)) != SimpleDHTErrSuccess) {
Serial.print("读取数据失败, err="); Serial.println(err);delay(1000);
return;
}
// 查看是否读取温湿度失败的
if (isnan(hum) || isnan(tem)) {
Serial.println("从DHT传感器读取失败!");
return;
}
String temperature = String(tem);
String humidity = String(hum);
// 构建一个 JSON 格式的payload的字符串
String payload = "{";
payload += "\"temperature\":"; payload += temperature; payload += ",";
payload += "\"humidity\":"; payload += humidity;
payload += "}";
payload.toCharArray( attributes, 100 );
client.publish( "Tem_hum", attributes );
}
使用淋浴结果如下:
python订阅MQTT保存数据到MySQL
感知层的数据获取完成后,接下来就是数据的存储。使用python订阅感知层发送的MQTT主题,接收这些主题的信息,并将其保存到MySQL数据库中。关键代码如下:
# -*- encoding: utf-8 -*-
""" @File : 老人卫生间防摔倒自动报警系统.py @Time : 2022/5/22 16:32 @Author : 林枫 @Software: PyCharm """
import time
import paho.mqtt.client as mqtt
import pymysql
broker = 'broker.emqx.io'
port = 1883
def saveMysql(tableName, data):
conn = pymysql.connect(host='localhost', # 调用MySQL 并命名为 conn
user='root', # 输入用户名
password='', # 输入初始密码
db='oldman', # 调用数据库
charset='utf8') # 定义格式
cursor = conn.cursor() # 创建游标 模拟鼠标
if tableName == 'toilet':
sql = """ insert into toilet( in_time, out_time ) values(%s, %s) """
# sql语句向表名为林的表中插入值 这里的%s是占位符 等待匹配对应值
cursor.execute(sql, (data[0], data[1])) # 向占位符中输入对应值
conn.commit()
conn.rollback()
time.sleep(1) # 延时0.1秒,免得CPU出问题
..............
print("保存成功!")
conn.close() # 关闭 数据库
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("连接成功!")
client.subscribe(topic='linfeng_data')
else:
print("Failed to connect, return code %dn", rc)
def on_message(client, userdata, msg):
global wcs_time, toilet_times, showers_time
message = []
data = eval(msg.payload.decode())
if data["place"] == "wc":
if data["IsWc"] == 1:
wcs_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # 规整本地时间的格式
print(wcs_time)
message.clear()
message = [1, 0, 0, wcs_time]
print("开始保存数据到state中......................")
saveMysql("state", message)
if data["IsWc"] == 0:
wc_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # 规整本地时间的格式
print(wc_time)
message.clear()
message.append(wcs_time)
message.append(wc_time)
print("开始保存数据到wc中......................")
saveMysql("wc", message)
message.clear<