一、前期准备
1、首先家里得有wifi信号覆盖
2、eps8266芯片
3、红外编解码芯片
4、云服务器
二、基础知识
1、c语言链表
2、红外编解码芯片的使用
3、linux网络编程
三、如何实现跨网控制
3.1、云服务器直接运行基于mqtt等物联网协议的服务端程序
3.2、接入现成的各大物联网平台
3.3、自己写一个物联网平台(本文做法)
四、参考mqtt协议写一个物联网平台程序(超级简化版mqtt)
4.1、mqtt核心(发布/ 订阅模型)
发布/ 订阅模型将发送消息的客户端(发布者)与接收消息的客户端(订阅者)分离。发布者和订阅者从不彼此直接联系。实际上,他们甚至不知道另一个存在。它们之间的连接由第三个组件(代理)处理。
4.2、订阅者
接收消息的客户端
4.2.1、用链表管理接入服务器的订阅者
将订阅者客户端的套接字描述符和订阅者name存储在一个结构体,发布者发布消息到订阅者时,可通过name查找到对应的fd。
4.2.2、注册一个用户(订阅者)
向链表添加一个新的结点
int addUser(User *userHead,User *user);
服务端收到客户端信息 adduser xxxx,会执行如下代码,此处允许重命名,先删除之前的结点,再添加一个结点。
deleteUser(&userList, user);
user = (User *)malloc(sizeof(User));
user->clientFd = clientFd;
strcpy(user->name, splitBuf[1]);
user->next = NULL;
ret = addUser(&userList, user);
4.2.3、注销一个用户(订阅者)
链表里面删除对应的结点
int deleteUser(User *userHead,User *user);
订阅者客户端退出时会执行
deleteUser(&userList, user);
printf("client exit\n");
close(clientFd);
break ;
4.3、发布者
4.3.1、往订阅者发一个消息
通过name从用户链表找到对应结点,然后往发消息。
服务端收到 send abc xxxx会执行sendMsgToOtherUser函数,将xxx发给abc。转发的数据格式 xxx [from] 方括号表示内容不一定会有。
int sendMsgToOtherUser(User *userHead,User *fromUser, char *name, char *msg);
能找到服务端就将发布者的消息转发给订阅者,不能找到就结束这次查找
while(p != NULL){
if(strcmp(p->name, name) == 0){
write(p->clientFd, writeBuf, strlen(writeBuf));
return 1;
}
p = p->next;
}
如上面发布/ 订阅模型,发布者和订阅者从不彼此直接联系。实际上,他们甚至不知道另一个存在。它们之间的连接由第三个组件(代理)处理。
五、搭建订阅者客户端(空调)
使用搭载ESP8266的wemos D1开发板
5.1、客户端初始化,并注册用户名air
#define IP "公网服务器IP"
#define PORT 9100
char* ssid = "wifi名";
char* passwd = "wifi密码";
WiFiClient client;
void initClient()
{
WiFi.mode(WIFI_STA); // 设置STA模式
WiFi.begin(ssid, passwd); //连接网络
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
if (!client.connect(IP, PORT)) {
Serial.println("connection failed");
return;
}else{
Serial.println("connection success");
}
client.write("adduser air", strlen("adduser air"));
}
5.2、接收服务端信息
uint8_t readBuf[64] = {0};
if(client.available() > 0){
client.read(readBuf, sizeof(readBuf));
//Serial.write(readBuf, sizeof(readBuf));
// Serial.println();
}
5.3、根据收到的信息进行相应处理
char *p = strtok((char *)readBuf, " ");
if(p != NULL){
if(strcmp(p, "open") == 0){
Serial.write(open_air, sizeof(open_air));
}else if(strcmp(p, "close") == 0){
Serial.write(close_air, sizeof(close_air));
}
}
5.4、串口发送红外编码
5.4.1、串口初始化
Serial.begin(9600);
5.4.2、用串口助手接收红外编解码的破解码,程序里面用数组保存
unsigned char close_air[] = {};
unsigned char open_air[] = {};
5.4.3、wemos D1的串口发编码到红外编解码模块
Serial.write(open_air, sizeof(open_air));
Serial.write(close_air, sizeof(close_air));
六、效果图
6.1、云服务器运行服务端程序,9100端口进行监听
6.2、空调客户端连接,并新建用户air
6.3、发消息给空调客户端
6.4、服务端收到来自发布者的指令
6.5、空调客户端接收消息
wemos D1 收到匿名用户发来的信息,并执行open操作。串口助手收到空调开编码,模拟红外编解码收到串口信息