本文实现的目标是用手机远程控制 esp8266 板载 LED 熄灭。 效果图:
1. 自有服务器搭建MQTT服务端,用的是nodejs平台
server.js
const mosca = require("mosca");
const mqttSetting = {
interfaces:[
{ type: "mqtt", port: 1883 },
{ type: "http", port: 3000, bundle: true }
]
}
const MqttServer = new mosca.Server(mqttSetting)
MqttServer.on("ready", function() {
console.log("mqtt is running...");
});
MqttServer.on("clientConnected", function(client) {
console.log("client connected", client.id);
});
MqttServer.on("published", function(packet, client) {
var topic = packet.topic;
switch (topic) {
case "test_topic":
console.log('message', packet.payload.toString());
break;
case "other":
console.log("message_other", packet.payload.toString());
break;
}
});
运行服务:
node server.js
第一次运行会报错,解决方法点这里
2. Arduino 编写程序上传到 ESP8266-NodeMCU
NodeMCU模块第一次通电会打开wifi等待连接配网,网络配置好之后每次通电都会自动连接到 mqtt 服务器订阅、发布消息。 代码来源 太极创客
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
#include <Ticker.h>
const char* mqttServer = "48.128.128.88";
int count;
Ticker ticker;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
void setup() {
Serial.begin(9600);
WiFiManager wifiManager;
pinMode(LED_BUILTIN, OUTPUT);
wifiManager.autoConnect("AutoConnectAP");
Serial.println("");
Serial.print("ESP8266 Connected to ");
Serial.println(WiFi.SSID());
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
mqttClient.setServer(mqttServer, 1883);
mqttClient.setCallback(receiveCallback);
connectMQTTServer();
ticker.attach(1, tickerCount);
}
void loop() {
if (mqttClient.connected()) {
if (count >= 5){
pubMQTTmsg();
count = 0;
}
mqttClient.loop();
} else {
connectMQTTServer();
}
}
void tickerCount(){
count++;
}
void connectMQTTServer(){
String clientId = "esp8266-" + WiFi.macAddress();
if (mqttClient.connect(clientId.c_str())) {
Serial.println("MQTT Server Connected.");
Serial.println("Server Address: ");
Serial.println(mqttServer);
Serial.println("ClientId:");
Serial.println(clientId);
subscribeTopic();
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(3000);
}
}
void pubMQTTmsg(){
String topicString = "test/esp8266/pub" ;
char publishTopic[topicString.length() + 1];
strcpy(publishTopic, topicString.c_str());
String messageString;
if(digitalRead(LED_BUILTIN)){
messageString = "off";
} else {
messageString = "on";
}
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
if(mqttClient.publish(publishTopic, publishMsg)){
Serial.println("Publish Topic:");Serial.println(publishTopic);
Serial.println("Publish message:");Serial.println(publishMsg);
} else {
Serial.println("Message Publish Failed.");
}
}
void subscribeTopic(){
String topicString = "test/esp8266/sub" ;
char subTopic[topicString.length() + 1];
strcpy(subTopic, topicString.c_str());
if(mqttClient.subscribe(subTopic)){
Serial.println("Subscribe Topic:");
Serial.println(subTopic);
} else {
Serial.print("Subscribe Fail...");
}
}
void receiveCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message Received [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println("");
Serial.print("Message Length(Bytes) ");
Serial.println(length);
if ((char)payload[0] == '1') {
digitalWrite(LED_BUILTIN, LOW);
} else {
digitalWrite(LED_BUILTIN, HIGH);
}
}
3. uniapp 编写移动端操作开关灯
<template>
<view class="content">
<!-- <image class="logo" src="/static/logo.png" ></image> -->
<image class="logo" :src="title=='on' ? imgurlon : imgurloff"></image>
<view class="text-area">
<view class="title">{{title}}</view>
</view>
<view class="btn">
<button type="default" @click="btnon()">开</button>
<button type="default" @click="btnoff()">关</button>
</view>
</view>
</template>
<script>
var mqtt = require('../../mqtt.min.js')
export default {
data() {
return {
title: 'Hello',
imgurloff:'/static/off.png',
imgurlon:'/static/on.png',
urls: 'wx://48.128.128.88:3000/mqtt',
client: null,
options: {
clientId: '',
clean: false,
password: 'admin',
username: 'public',
keepalive: 0,
}
}
},
onLoad() {
this.options.clientId = 'App' + Math.round(new Date() / 1000)
setTimeout( ()=> {
this.mqttconnect()
},1000)
},
methods: {
mqttconnect() {
this.client = mqtt.connect(this.urls,this.options)
this.client.on('connect', () => {
this.client.subscribe('test/esp8266/pub', (err) => {
console.log(err || '订阅默认主题成功')
})
this.client.publish('test/esp8266/pub', 'testmsg', (err) => {
console.log(err || '发送信息成功')
})
})
this.client.on('message', (topic, message) => {
let msg = message.toString();
this.title = msg
console.log('收到来自'+ topic + '的消息:' + message.toString());
})
},
btnon() {
this.client.publish('test/esp8266/sub', '1', (err) => {
console.log(err || '发送信息成功')
})
this.title = 'on'
},
btnoff() {
this.client.publish('test/esp8266/sub', '0', (err) => {
console.log(err || '发送信息成功')
})
this.title = 'off'
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
.btn{
display: flex;
flex-direction: row;
margin: 20rpx;
}
button{
margin: 20rpx;
border-radius: 5rpx;
color: #0055ff;
background-color: #909090;
}
</style>
|