1.1 安装 IRremoteESP8266 库
1.2 把ESP8266红外接收的实例,上传到NodeMCU中.
1.3 读取遥控器红外键值
把红外接收模块的信号线连接到GPIO14(Node MCU 对应D5引脚)
红外接收模块接线图,型号:VS/HX1838B
打开Arduino 调试串口监视器,选择波特率为115200
空调遥控器对准红外接收管,按下需要的按键,串口监视器会打印出对应的键值,复制到记事本留着后面步骤用。
代码参考 太极创客
// 引入对应的头文件
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
// 声明对象
Ticker ticker;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
const char* mqttServer = "***.***.***.***"; //常量, mqtt服务器地址
int count; // Ticker计数用的变量
String messageString = "off"; //发布消息的变量,默认是关闭状态
//定义红外发射的管脚
const uint16_t kIrLed = 5; // ESP8266 GPIO pin to use. Recommended: 5 (D1).
IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message.
//空调开,根据遥控器解码后的数据修改 [] 和 {} 里面的数值
uint16_t power_on[227] = {3080, 1608, 472, 1108, 472, 1110, 472, 318, 498, 318, 498, 318, 498, 1108, 472, 320, 496, 318, 498, 1108, 472, 1108, 472, 316, 500, 1108, 472, 322, 494, 320, 496, 1108, 472, 1108, 472, 316, 500, 1108, 472, 1108, 472, 316, 522, 286, 506, 1108, 494, 282, 510, 318, 498, 1108, 496, 284, 508, 316, 524, 280, 514, 316, 522, 280, 536, 278, 512, 318, 498, 318, 518, 280, 536, 280, 534, 282, 526, 302, 522, 282, 534, 280, 534, 282, 512, 316, 522, 280, 536, 1062, 518, 282, 510, 316, 500, 1084, 496, 316, 498, 318, 510, 1072, 498, 1082, 520, 282, 538, 274, 542, 274, 542, 276, 540, 274, 542, 274, 542, 1056, 524, 274, 540, 1056, 524, 276, 540, 276, 540, 276, 542, 274, 540, 276, 542, 274, 542, 1056, 522, 274, 542, 274, 542, 274, 540, 276, 540, 276, 540, 276, 540, 276, 540, 274, 540, 276, 540, 276, 540, 276, 540, 274, 542, 274, 540, 276, 540, 274, 542, 274, 542, 274, 542, 274, 542, 274, 542, 274, 540, 276, 538, 280, 512, 316, 498, 318, 498, 316, 500, 316, 524, 280, 534, 282, 510, 318, 498, 316, 498, 318, 498, 318, 498, 318, 496, 318, 496, 320, 496, 320, 494, 320, 496, 1086, 492, 1088, 492, 1088, 492, 324, 492, 324, 492, 324, 492, 326, 490, 1110, 468, 1112, 468}; // TCL112AC
//空调关
uint16_t power_off[227] = {3078, 1610, 470, 1110, 470, 1112, 468, 346, 468, 348, 466, 350, 466, 1110, 470, 348, 470, 346, 468, 1112, 468, 1090, 492, 346, 468, 1112, 468, 348, 466, 348, 468, 1114, 468, 1112, 470, 324, 492, 1088, 492, 1088, 492, 320, 496, 322, 494, 1084, 496, 318, 498, 316, 502, 1080, 500, 314, 502, 314, 526, 272, 544, 272, 542, 274, 542, 274, 542, 274, 540, 274, 542, 274, 540, 276, 542, 274, 540, 274, 540, 276, 540, 274, 540, 274, 542, 274, 542, 274, 542, 274, 540, 276, 540, 274, 540, 1056, 498, 316, 500, 316, 498, 1084, 496, 1082, 500, 314, 524, 278, 538, 278, 512, 316, 498, 318, 498, 318, 498, 1084, 496, 318, 498, 1084, 496, 318, 496, 320, 496, 320, 496, 322, 496, 320, 494, 320, 494, 1086, 492, 322, 492, 324, 492, 346, 470, 346, 470, 346, 468, 348, 468, 348, 468, 348, 466, 350, 466, 350, 466, 350, 466, 350, 464, 352, 464, 352, 462, 354, 460, 356, 460, 356, 460, 356, 460, 356, 458, 356, 458, 358, 458, 358, 458, 356, 458, 358, 458, 356, 458, 358, 458, 356, 460, 356, 458, 358, 458, 356, 460, 356, 458, 356, 458, 358, 458, 356, 458, 358, 458, 358, 458, 358, 458, 1122, 456, 1124, 456, 1146, 436, 1144, 434, 1146, 434, 1146, 434, 1146, 434, 382, 434, 1146, 434}; // TCL112AC
//计数
void tickerCount(){
count++;
}
// 连接MQTT服务器
void connectMQTTServer(){
// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)
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());
// 建立发布信息,当前D1引脚状态
// String messageString;
// if(digitalRead(D1)){
// messageString = "off";
// } else {
// messageString = "on";
// }
// 建立发布信息:设备的状态
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
// 实现ESP8266向主题发布信息,并在串口监视器显示出来
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') { // 如果收到的信息以“1”为开始
//digitalWrite(LED_BUILTIN, LOW); // 点亮LED。
irsend.sendRaw(power_on, 279, 38); //发送红外指令-开机 (表示发送power_off数组, 数组长度为279, 38kHz的频率)
messageString = "on"; //更新设备状态
pubMQTTmsg(); //调用函数发布消息
} else {
//digitalWrite(LED_BUILTIN, HIGH); // 熄灭LED。
irsend.sendRaw(power_off, 279, 38); //发送红外指令-关机
messageString = "off"; //更新设备状态
pubMQTTmsg(); //调用函数发布消息
}
}
//程序入口
void setup() {
//开启串口通讯
Serial.begin(9600);
// 建立WiFiManager对象
WiFiManager wifiManager;
//设置输出信号的引脚,此处是板载的LED
//pinMode(LED_BUILTIN, OUTPUT);
//红外初始化
irsend.begin();
// 如果您希望该WiFi添加密码,可以使用以下语句,第二个参数是密码
// wifiManager.autoConnect("AutoConnectAP", "12345678");
// 自动连接WiFi。以下语句的参数是连接ESP8266时的WiFi名称
wifiManager.autoConnect("AutoConnectAP");
// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println("");
Serial.print("ESP8266 Connected to ");
Serial.println(WiFi.SSID()); // WiFi名称
Serial.print("IP address:\t");
Serial.println(WiFi.localIP()); // IP
// 设置MQTT服务器和端口号
mqttClient.setServer(mqttServer, 1883);
// 收到信息后的回调函数
mqttClient.setCallback(receiveCallback);
// 连接MQTT服务器
connectMQTTServer();
// Ticker定时对象
ticker.attach(1, tickerCount);
}
//循环执行
void loop() {
if (mqttClient.connected()) { // 如果开发板成功连接服务器
// 每隔10秒钟发布一次信息
if (count >= 10){
pubMQTTmsg();
count = 0;
}
// 保持心跳
mqttClient.loop();
} else { // 如果开发板未能成功连接服务器
connectMQTTServer(); // 则尝试连接服务器
}
}
硬件接线图
带放大电路的接线图,遥控距离5米左右。
型号:5mm白色发射二极管 ,2N2222三极管。
<template>
<view class="content">
<!-- <image class="logo" src="/static/logo.png" ></image> -->
<image class="logo" :src="state=='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') //引入mqtt库
var ntime = 0 //计时初始值
export default {
data() {
return {
title: '设备离线',
state:'off', //改变图标状态
imgurloff:'/static/off.png',
imgurlon:'/static/on.png',
timer: null,
//app端和小程序端必须用【 wx:// 或者 wxs:// 】
urls: 'wx://43.***.***.46:3000/mqtt',
client: null,
//MQTT连接的配置
options: {
clientId: '',
clean: false,
password: 'admin',
username: 'public',
keepalive: 0, //心跳时间
}
}
},
onLoad() {
// 多设备登录的时候 clientId 不能重复,否则消息订阅会有冲突,此处以时间戳作为clientId
this.options.clientId = 'App' + Math.round(new Date() / 1000)
//延迟一秒再调用方法,作用是等待赋值给clientId
setTimeout( ()=> {
this.mqttconnect()
},1000)
},
onShow() {
// esp8266每10秒发布一次消息,num清零一次,如果30秒后变量num还没有清零,判断设备离线了
//建立定时器10秒运行一次
this.timer = setInterval( () => {
ntime = ntime + 10
if(ntime >= 30 ){
this.title = '设备离线 XXX'
this.state = 'off'
}
}, 10000)
},
onHide() {
// 清除定时器
if(this.timer) {
clearInterval(this.timer);
this.timer = null;
}
},
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 = '设备在线'
this.state = msg
console.log('收到来自'+ topic + '的消息:' + message.toString())
ntime = 0
})
},
btnon() {
//发布开灯指令
this.client.publish('test/esp8266/sub', '1', (err) => {
console.log(err || '发送信息成功')
})
this.state = 'on'
},
btnoff() {
//发布关灯指令
this.client.publish('test/esp8266/sub', '0', (err) => {
console.log(err || '发送信息成功')
})
this.state = '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>
请看另一篇文章:nodejs + uniapp 联合开发MQTT服务端与移动端app