#include <DHT.h>
#include <WiFi.h>
#include <PubSubClient.h>
// 引脚定义
#define DHTPIN 4 // DHT11数据引脚
#define MQ2PIN 34 // MQ-2模拟输入
#define BUZZER_PIN 25 // 蜂鸣器控制
#define RELAY_PIN 26 // 继电器控制
// 传感器类型
#define DHTTYPE DHT11
// 安全配置
const char* mqttUser = "smart_home_user"; // MQTT用户名
const char* mqttPass = "secure_password123"; // MQTT密码
const char encryptionKey = 0x55; // 简易加密密钥
// 继电器触发模式
#define RELAY_TRIGGER_MODE HIGH // LOW=低电平触发,HIGH=高电平触发
// 报警阈值
const int GAS_THRESHOLD = 3650; // 气体检测阈值
// WiFi和MQTT配置
const char* ssid = "Wokwi-GUEST"; // Wokwi专用WiFi
const char* password = "";
const char* mqttServer = "44.232.241.40"; // 公共MQTT服务器
const int mqttPort = 1883;
const char* mqttTopic = "fjjxu/2025/4/selfmsg";
const char* mqttControlTopic = "fjjxu/2025/4/control"; // 新增控制主题
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
// 全局变量
bool alarmState = false;
bool ledState = false;
unsigned long lastBeepTime = 0;
const int beepInterval = 500; // 蜂鸣器间歇时间(ms)
// 简易加密/解密函数(异或加密)
String simpleEncrypt(String input, char key) {
String output = "";
for (int i = 0; i < input.length(); i++) {
output += (char)(input[i] ^ key);
}
return output;
}
void setup() {
Serial.begin(115200);
// 初始化引脚
pinMode(BUZZER_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(RELAY_PIN, (RELAY_TRIGGER_MODE == LOW) ? HIGH : LOW);
// 初始化传感器
dht.begin();
// 连接WiFi
connectWiFi();
// 设置MQTT
client.setServer(mqttServer, mqttPort);
client.setCallback(mqttCallback);
}
// 连接WiFi函数
void connectWiFi() {
WiFi.begin(ssid, password);
Serial.print("正在连接WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi已连接");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
}
// MQTT回调函数
void mqttCallback(char* topic, byte* payload, unsigned int length) {
// 将payload转换为字符串并解密
String encryptedMessage;
for (int i = 0; i < length; i++) {
encryptedMessage += (char)payload[i];
}
String message = simpleEncrypt(encryptedMessage, encryptionKey);
Serial.print("收到消息 [");
Serial.print(topic);
Serial.print("]: ");
Serial.println(message);
// 处理控制命令
if (String(topic) == mqttControlTopic) {
if (message.indexOf("\"led\":1") != -1 || message.indexOf("\"led\":true") != -1) {
setLedState(true);
} else if (message.indexOf("\"led\":0") != -1 || message.indexOf("\"led\":false") != -1) {
setLedState(false);
}
}
}
// 设置LED状态函数
void setLedState(bool state) {
ledState = state;
digitalWrite(RELAY_PIN, (RELAY_TRIGGER_MODE == LOW) ? !state : state);
Serial.print("LED状态已更新: ");
Serial.println(ledState ? "ON" : "OFF");
}
// MQTT重连函数
void reconnect() {
while (!client.connected()) {
Serial.print("尝试MQTT连接...");
if (client.connect("WokwiClient", mqttUser, mqttPass)) {
Serial.println("已连接");
client.subscribe(mqttControlTopic);
Serial.print("已订阅主题: ");
Serial.println(mqttControlTopic);
} else {
Serial.print("失败, rc=");
Serial.print(client.state());
Serial.println(" 5秒后重试...");
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// 定时读取传感器数据
static unsigned long previousMillis = 0;
const long interval = 2000;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
readSensors();
}
// 串口控制测试
if (Serial.available()) {
char cmd = Serial.read();
if (cmd == '1') setLedState(true);
else if (cmd == '0') setLedState(false);
}
}
// 读取传感器数据函数
void readSensors() {
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
int gasValue = analogRead(MQ2PIN);
// 添加随机波动并约束范围
humidity = constrain(humidity + random(-2, 3), 0, 100);
temperature = constrain(temperature + random(-2, 3) / 10.0, -10, 50);
gasValue = constrain(gasValue + random(-50, 60), 0, 5000);
// 打印传感器数据
Serial.print("温度: "); Serial.print(temperature); Serial.print("°C");
Serial.print(" 湿度: "); Serial.print(humidity); Serial.print("%");
Serial.print(" 气体值: "); Serial.print(gasValue);
Serial.print(" LED状态: "); Serial.println(ledState ? "ON" : "OFF");
// 创建并发送MQTT消息
String payload = "{\"temperature\":" + String(temperature) +
",\"humidity\":" + String(humidity) +
",\"gasValue\":" + String(gasValue) +
",\"alarm\":" + String(alarmState ? "true" : "false") +
",\"led\":" + String(ledState ? "1" : "0") + "}";
client.publish(mqttTopic, simpleEncrypt(payload, encryptionKey).c_str());
// 火灾检测
if (gasValue > GAS_THRESHOLD) {
triggerAlarm(true);
} else {
triggerAlarm(false);
}
}
// 触发警报函数
void triggerAlarm(bool active) {
alarmState = active;
if (active) {
if (millis() - lastBeepTime >= beepInterval) {
tone(BUZZER_PIN, 1000, 500);
lastBeepTime = millis();
Serial.println("⚠️ 警报触发!");
}
} else {
noTone(BUZZER_PIN);
Serial.println("✅ 警报停止");
}
}