这里写自定义目录标题
- 案例成果
- 1.Ardino写入部分
- 2.微信小程序JS部分
- 3.微信小程序xml部分
- 4. 微信小程序CSS部分
案例成果
1.Ardino写入部分
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
const char *ssid = "601B";
const char *password = "12345678";
const char* mqtt_server = "bemfa.com";
const int mqtt_server_port = 9501;
#define ID_MQTT "0c876e1774cc3bd27de1d5d1bfc61c90"
WiFiClient espClient;
PubSubClient client(espClient);
#define ledpin 2
#define eqpin 3
#define beeppin 18
#define flapin 5
#define dhtpin 15
#define DHTTYPE DHT11
#define airpin 34
DHT dht(dhtpin, DHTTYPE);
bool val1 = 0;
bool val2 = 0;
const char* mqtt_switch_topic = "switch";
const char* mqtt_temper_topic = "temper";
const char* mqtt_humid_topic = "humid";
const char* mqtt_air_topic = "air";
const char* mqtt_earthquake_topic = "earthquake";
const char* mqtt_flame_topic = "flame";
const char* mqtt_beep_topic = "beep";
void setup_wifi() {delay(10);Serial.println();Serial.print("Connecting to ");Serial.println(ssid);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}Serial.println("");Serial.println("WiFi connected");Serial.print("IP address: ");Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {Serial.print("订阅的信息为 [");Serial.print(topic);Serial.print("] ");String message;for (int i = 0; i < length; i++) {message += (char)payload[i];}Serial.println(message);if (strcmp(topic, mqtt_switch_topic) == 0) {if (message == "on") {digitalWrite(ledpin, HIGH);Serial.println("打开 LED 灯");} else if (message == "off") {digitalWrite(ledpin, LOW);Serial.println("关闭 LED 灯");}}
}
void reconnect() {while (!client.connected()) {Serial.print("尝试连接MQTT...");if (client.connect(ID_MQTT)) {Serial.println("connected");client.subscribe(mqtt_switch_topic);Serial.print("已订阅主题: ");Serial.println(mqtt_switch_topic);} else {Serial.print("failed, rc=");Serial.print(client.state());Serial.println(" try again in 5 seconds");delay(5000);}}
}
void setup() {Serial.begin(115200);Serial.println("初始化系统...");dht.begin();pinMode(ledpin, OUTPUT);digitalWrite(ledpin, LOW);pinMode(eqpin, INPUT);pinMode(flapin, INPUT);pinMode(beeppin, OUTPUT);pinMode(airpin, INPUT); setup_wifi();client.setServer(mqtt_server, mqtt_server_port);client.setCallback(callback);reconnect();Serial.println("系统初始化完成!");
}void loop() {if (!client.connected()) {reconnect(); }client.loop();float h = dht.readHumidity();float t = dht.readTemperature();if (isnan(h) || isnan(t)) {Serial.println("Failed to read from DHT sensor!");} else {Serial.print("湿度: ");Serial.print(h);Serial.print("%, 温度: ");Serial.print(t);Serial.println("°C");String tempMsg = String(t);String humidMsg = String(h);client.publish(mqtt_temper_topic, tempMsg.c_str());client.publish(mqtt_humid_topic, humidMsg.c_str());}int airval = analogRead(airpin);Serial.print("空气质量: ");Serial.println(airval);String airMsg = String(airval);client.publish(mqtt_air_topic, airMsg.c_str());val1 = digitalRead(eqpin);if (val1 == 0) {client.publish(mqtt_earthquake_topic, "off");Serial.println("无震感");client.publish(mqtt_beep_topic, "off"); }else {client.publish(mqtt_earthquake_topic, "on");Serial.println("有震感");client.publish(mqtt_beep_topic, "on"); }val2 = digitalRead(flapin);Serial.print("火灾传感器状态: ");Serial.println(val2);if (val2 == 1) {client.publish(mqtt_flame_topic, "off");Serial.println("无火灾");digitalWrite(beeppin, HIGH);}else {client.publish(mqtt_flame_topic, "on");Serial.println("有火灾");digitalWrite(beeppin, LOW);}delay(100);
}
2.微信小程序JS部分
const app = getApp()
import mqtt from '../../utils/mqtt.min'Page({data: {ledtopic: "switch", eqtopic: "earthquake", fhtopic: "flame", wdtopic: "temper", sdtopic: "humid", kqtopic: "air", beeptopic: "beep", uid: "0c876e1774cc3bd27de1d5d1bfc61c90", qustatus: "无震感", flastatus: "无火灾", wdval: "未知", sdval: "未知", airval: "未知", beepstatus: "关闭", isThemeOn: false, device_status: "离线", client: null },mqttConnect() {var that = this;var options = {keepalive: 60, clean: true, protocolVersion: 4, clientId: that.data.uid };that.data.client = mqtt.connect('wxs://bemfa.com:9504/wss', options);that.data.client.on('connect', function() {console.log("连接服务器成功");that.setData({device_status: "在线"});that.data.client.subscribe(that.data.eqtopic, function(err) {if(err) console.log(err);});that.data.client.subscribe(that.data.fhtopic, function(err) {if(err) console.log(err);});that.data.client.subscribe(that.data.wdtopic, function(err) {if(err) console.log(err);});that.data.client.subscribe(that.data.sdtopic, function(err) {if(err) console.log(err);});that.data.client.subscribe(that.data.kqtopic, function(err) {if(err) console.log(err);});that.data.client.subscribe(that.data.beeptopic, function(err) {if(err) console.log(err);});});that.data.client.on('message', function(topic, message) {var msg = message.toString();if(topic === that.data.eqtopic) {that.setData({qustatus: msg === 'on' ? '有地震' : '无地震'});}else if(topic === that.data.fhtopic) {that.setData({flastatus: msg === 'on' ? '有火灾' : '无火灾'});}else if(topic === that.data.wdtopic) {that.setData({wdval: msg});}else if(topic === that.data.sdtopic) {that.setData({sdval: msg});}else if(topic === that.data.kqtopic) {that.setData({airval: msg});}else if(topic === that.data.beeptopic) {that.setData({beepstatus: msg === 'on' ? '开启' : '关闭'});}});that.data.client.on('reconnect', function() {console.log("重新连接");that.setData({device_status: "连接中"});});that.data.client.on('error', function(error) {console.log("连接失败", error);that.setData({device_status: "离线"});});},onLoad() {this.mqttConnect()},onThemeSwitchTap: function() {if(this.data.client && this.data.client.connected) {const message = this.data.isThemeOn ? 'off' : 'on';this.data.client.publish(this.data.ledtopic, message);this.setData({isThemeOn: !this.data.isThemeOn});} else {console.log("MQTT未连接");}}
})
3.微信小程序xml部分
<!--pages/znjj/znjj.wxml-->
<view class="imag4_src"></view>
<image class="imag4" src="/img/znjj.png"></image>
<view class="spacer"></view><view class="container1"><view class="view1"><view class="img_wd"><view class="content-row"><image class="img1" src="/img/wd.png"></image><text>温度</text></view><view class="loading-container"><!-- 修改:绑定温度数据 --><text class="loading-text">{{wdval}}</text></view></view></view><view class="view2"><view class="img_wd"><view class="content-row"><image class="img1" src="/img/sd.png"></image><text>湿度</text></view><view class="loading-container"><!-- 修改:绑定湿度数据 --><text class="loading-text">{{sdval}}</text></view></view></view><view class="view3"><view class="img_wd"><view class="content-row"><image class="img1" src="/img/PM2.5.png"></image><text>空气</text></view><view class="loading-container"><!-- 修改:绑定空气质量数据 --><text class="loading-text">{{airval}}</text></view></view></view>
</view><view class="spacer"></view><view class="container2"><view class="view4"><view class="img_wd"><view class="content-row"><image class="img1" src="/img/hy.png"></image><text>防火</text></view><view class="loading-container"><!-- 修改:绑定火灾状态 --><text class="loading-text">{{flastatus}}</text></view></view></view><view class="view5"><view class="img_wd"><view class="content-row"><image class="img1" src="/img/dz.png"></image><text>地震</text></view><view class="loading-container"><text class="loading-text">{{qustatus}}</text></view></view></view><view class="view6"><view class="img_wd"><view class="content-row"><image class="img1" src="/img/kt.png"></image><text>空调</text></view><view class="switch-container"><button class="theme-switch-button" bindtap="onThemeSwitchTap">{{isThemeOn ? 'on' : 'off'}}</button></view></view></view>
</view><view class="spacer"></view><view class="container3"><view class="view7"><view class="img_wd"><view class="content-text"><text>设备状态</text><text class="module">{{device_status}}</text></view></view></view><view class="view8"><view class="img_wd"><view class="content-text"><text>火灾告警</text><view wx:if="{{flastatus == '有火灾'}}"><image class="img5" src="/img/hz_on.png"></image></view><view wx:else><image class="img5" src="/img/hz_off.png"></image></view></view></view></view><view class="view9"><view class="img_wd"><view class="content-text"><text>地震告警</text><!-- 修改:使用qustatus而不是eqstatus --><view wx:if="{{qustatus == '有地震'}}"><image class="img5" src="/img/dz_on.png"></image></view><view wx:else><image class="img5" src="/img/dz_off.png"></image></view></view></view></view>
</view>
4. 微信小程序CSS部分
.imag4_src{display: block; width: 100%; }.imag4{width: 350px; height: 200px; justify-content: center; border: 1px solid #000; border-radius: 10px; margin: 20px; box-shadow: 5px 5px 15px rgba(0,0,0,0.3); transition: transform 0.3s ease; }.imag4:hover{transform: scale(1.05); }.spacer{height: 10px; }.container1,.container2{display: flex; flex-direction: row; justify-content: center; }.container1 .view1,.container1 .view2,.container1 .view3,.container2 .view4,.container2 .view5,.container2 .view6{width: 90px; height: 100px; margin: 20px; position: relative; background-color: transparent; display: flex; align-items: lsft; justify-content: center; border: 2px solid rgb(291,214,214); box-shadow: 0 0 10px rgba(37,37,37,0.5); }.container1 .view1 { background-color: #e3ece2; } .container1 .view2 { background-color: #ccd4cb; } .container1 .view3 { background-color: #e5f3ee; } .container2 .view4 { background-color: #f7e7e9; } .container2 .view5 { background-color: #d7eef7; } .container2 .view6 { background-color: #e3e4f1; } .img_wd{justify-content: flex-start; align-items: flex-start; width: 100px; height: 100px; position: relative; }.content-row{margin-top: 1px; display: flex; align-items: center; margin-left: 3px; }.img1{width: 30px; height: 30px; border: 1px solid rgb(211,209,209); border-radius: 10px; margin: 3px; box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3); transition: transform 0.3s ease; margin-right: 5px; }.loading-container{margin-top: 20px; display: flex; justify-content: center; align-items: center; }.loading-text{justify-content: center; align-items: center; font-size: 16px; color: #333; height: 20px; }.container3{display: flex; flex-direction: row; justify-content: center; }.container3 .view7,.container3 .view8,.container3 .view9{width: 90px; height: 100px; margin: 20px; position: relative; background-color: transparent; display: flex; align-items: left; justify-content: center; border: 2px solid rgb(219, 214, 214); box-shadow: 0 0 10px rgba(37, 37, 37, 0.5); border-radius: 60px; }.container3 .view7 { background-color: #f1ecec; } .container3 .view8 { background-color: #f3f8f6; } .container3 .view9 { background-color: #ece6f5; } .switch-container {width: 60px; height: 30px; display: flex; justify-content: center; align-items: center; margin-top: 20px; margin-left: auto; margin-right: auto; }.theme-switch-button {height: 30px; line-height: 30px; background-color: rgb(146, 198, 247); color: rgb(13, 13, 14); border: none; border-radius: 20px; text-align: center; font-size: 13px; border: 1px solid rgb(241, 234, 234); box-shadow: 0 0 10px rgba(2, 8, 27, 0.5); padding: 0; }.content-text {display: flex; flex-direction: column; align-items: center; justify-content: flex-start; margin-top: 15px; width: 100%; box-sizing: border-box; }.module {margin-top: 10px; color: #f74d4d; font-weight: bold; }.img5{margin-top: 5px; width: 50px; height: 40px; }