ESP8266连接自建MQTT服务远程遥控空调

1. 解码空调红外键值

1.1 安装 IRremoteESP8266 库
在这里插入图片描述
1.2 把ESP8266红外接收的实例,上传到NodeMCU中.
在这里插入图片描述
在这里插入图片描述

1.3 读取遥控器红外键值
把红外接收模块的信号线连接到GPIO14(Node MCU 对应D5引脚)
在这里插入图片描述
红外接收模块接线图,型号:VS/HX1838B
在这里插入图片描述
打开Arduino 调试串口监视器,选择波特率为115200
在这里插入图片描述
空调遥控器对准红外接收管,按下需要的按键,串口监视器会打印出对应的键值,复制到记事本留着后面步骤用。
在这里插入图片描述

2. Arduino程序的编写,并上传到NodeMCU中

代码参考 太极创客

// 引入对应的头文件
#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三极管。
在这里插入图片描述
在这里插入图片描述

3. 使用uniapp 编写移动端程序

<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>

运行效果图
在这里插入图片描述

4. MQTT服务器搭建

请看另一篇文章:nodejs + uniapp 联合开发MQTT服务端与移动端app

猜你喜欢

转载自blog.csdn.net/weixin_38946164/article/details/120039195