虎年第一次推送 | esp8266搭建轻量智能家居平台
今天的内容其实是在农历春节前就完成的,但是由于临近放假那几天稍微有点忙,春节放假期间只想好好休息,所以也就没发出来。今天是我复工的第一天,把它发出来算是2022
年内容创作的开始和起点,新的一年,我要不断提升自己,努力创作出更多内容,同时也希望能够真正帮到各位小伙伴,好了下面让我们开始今天的正文:
前言
截止到今天,我已经居家办公一个月多,期间小台灯突然就坏了,更不幸的是,在修台灯的时候,烙铁还坏了,由于疫情影响,物流也停了,所以买是没法买的,于是我决定用之前把玩过几次的esp8266
翻出来,让它发挥下真正的价值,于是经过昨天一天的捣鼓,我的智能家居管理平台完美诞生,虽然它现在就只能控制小台灯,但是它确确实实解决我关灯难的问题(这么冷的天,睡前还要取关灯,想想都觉得冷),下面我就来分享下我的小成果。
轻量智能家居管理平台
硬件部分
本次项目示例需要用到三个硬件:esp8266
开发板、继电器装置和一个LED
灯。这里的LED
灯可以换成任何设备,因为抛开LED
灯,剩下的设备其实起的作用就是一个开关。
esp8266
关于8266
这款硬件,这里就不赘述了,之前我也分享过一些小demo
,感兴趣的小伙伴可以去看下:
这款开发板的价格很亲民,10
块钱就可以拿下,关键是可玩性还是很高的:
首先确保本地环境没有问题,驱动安装正常:
继电器
继电器是很早之前就到手了,就是这种双路光耦继电器,价格¥3.5
,其中NO
表示常开,NC
表示常闭,COM
就是公共端子。从这个图片上可以很清楚地看到我用的是常开,所以在后面的代码中我在一开始要把LED
引脚设置成HEIGH
,否则LED
从一开始就是亮的,感兴趣的小伙伴可以自己试下,当然你也可以直接用NC
端,这样就不存在这个问题了:
另外,从继电器上给出的参数可以看出,这个继电器其实可以支持到10A 250V
的功率,说明用在普通家用电器上也是可以的。这里我就接了一个3.7V
的小台灯,确实有点大材小用了。
被控制对象
这里就是一个功率特别小的台灯,就是通过8266
和继电器来实现远程控制,后面会有视频演示哦。
代码部分
arduino
先是arduino
部分,这块的代码很简单,也没有复杂的逻辑,主要是基于c++
的硬件操作。
首先打开我们的arduino IDE
,然后安装依赖库
今天的项目主要涉及websocket
的一些功能,所以我们安装ArduinoWebsockets
这个包就行了,这个包的作用就是让我们的8266
能够构建一个简易的websocket
服务器,能够处理一些简单的请求即可,我本地安装的是0.5.2
:
另外我们还需要ESP8266WiFi
的相关依赖,这个库就是8266
的核心库,其中wifi
配网需要用到:
由于,我还有加了OLED
,加这个小屏幕的作用主要是为了方便查看8266
的ip
,同时能够通过它调试代码,类似于日志控制台,所以还需要通过添加它的库,也就是上面图中的SSD1306
库。
以上工作完成后,我们开始编写arduino
代码:
#include <ArduinoWebsockets.h>
#include <ESP8266WiFi.h>
#include <SPI.h>; // 加载SPI库
#include <Wire.h>; // 加载Wire库
#include <Adafruit_GFX.h>; // 加载Adafruit_GFX库
#include <Adafruit_SSD1306.h>; // 加载Adafruit_SSD1306库
// 定义 OLED屏幕的分辨率
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
// WiFi parameters
const char* ssid = "wifi名称";
const char* password = "wifi密码";
String ip = "";
int LED=16;//GPIO16--D0
using namespace websockets;
WebsocketsServer server;
void setup() {
Serial.begin(115200);
// 设置OLED的I2C地址
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// 清空屏幕
display.clearDisplay();
// 设置字体大小
display.setTextSize(1);
// 设置字体颜色
display.setTextColor(SSD1306_WHITE);
// 设置开始显示文字的坐标
display.setCursor(0, 0);
// Connect to wifi
WiFi.begin(ssid, password);
// Wait some time to connect to wifi
for (int i = 0; i < 15 && WiFi.status() != WL_CONNECTED; i++) {
Serial.print(".");
delay(1000);
}
ip = WiFi.localIP().toString();
// 输出的字符
display.println("IP: " + ip);
// 输出的字符
display.println("webSocket Server");
// 使更改的显示生效
display.display();
// 创建websocket服务器
server.listen(80);
//设置对应引脚为输出模式
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
}
void loop() {
display.clearDisplay(); // 清空屏幕
display.setCursor(0, 0); // 设置开始显示文字的坐标
auto client = server.accept();
if (client.available()) {
auto msg = client.readBlocking();
// return echo
client.send("Echo: " + msg.data());
// close the connection
client.close();
String ipInfo = "IP: " + ip;
// 将ip信息输出到屏幕上
printText(ipInfo);
String data = msg.data();
int status =digitalRead(LED);
if(data.equals("taggleLed")) {
if (status == LOW) {
digitalWrite(LED,HIGH);
printText("ligth close!");
} else {
digitalWrite(LED,LOW);
printText("ligth open!");
}
}
printText("message: " + data); // 输出的字符
}
delay(1000);
}
// 向屏幕输出字符串
void printText(String text) {
display.setTextSize(1); // 设置字体大小
display.setTextColor(SSD1306_WHITE); // 设置字体颜色
display.println(text); // 输出的字符
// 使更改的显示生效
display.display();
}
代码虽然看着很长,很复杂,其实内部逻辑很简单:
首先是配网,这块需要指定 wifi
名称和密码;配网完成后,会在小屏幕上显示 8266
的ip
地址;接着会启动 websocket
服务,端口用的是80
;然后就是 LED
的相关操作:这里我们把LED
(也就是台灯)的引脚(这里用的是GPIO16
,对应8266
的D0
针脚)设置为输出模式,同时将引脚电平设置为高电平(HIGH
)。
注意: 因为我用到的是继电器的常开端,所以我设置为HEIGH
,如果你用的是常闭端,你可以设置为低电平LOW
,这块前面在继电器部分也说过了。
关于8266
的详细引脚图可以参考下面这个图:
在loop
代码中,我们监听客户端的wesocket
请求,如果请求内容为taggleLed
,我们就去获取LED
引脚的电平,根据LED
引脚的电平值设置它新的电平值:
如果电平为高电平(关闭状态,仅在当前示例中),则将引脚电平设置为LOW
,即开灯操作,否则将电平设置为高电平,也就是关灯操作。
至此我们arduino
部分的代码就完成了,下面看下接线图:
图画的太累了,效果貌似还不怎么好,后面找找合适的软件,不过参照图上的连线是没有问题的。
后端部分
最开始想的是前端发送http
请求,然后后端再调用arduino
的websocket
服务,后来才想起来,前端可以直接通过js
发送websocket
请求,于是项目就变成了一个纯前端项目,但是为了让手机端也能够访问,于是我就索性把它变成一个后端项目,虽然只有一个页面,页面效果如下(就是找素材有点费时间,关于后端部分我已经分享过了,也就是我年前分享的python
项目):
这块最核心的代码就主要是js
发送websocket
请求部分:
function taggleCmd() {
var ws = new WebSocket("ws://192.168.0.101:80");
//申请一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,WebSocket协议的u rl使用ws://开头,另外安全的WebSocket协议使用wss://开头
ws.onopen = function(){
//当WebSocket创建成功时,触发onopen事件
console.log("open");
ws.send("taggleLed"); //将消息发送到服务端
}
ws.onmessage = function(e){
//当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据
console.log(e.data);
}
ws.onclose = function(e){
//当客户端收到服务端发送的关闭连接请求时,触发onclose事件
console.log("close");
}
ws.onerror = function(e){
//如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
console.log(error);
}
}
也就是点击对应的按钮时,调用taggleCmd
方法发送taggleLed
消息即可,这样arduino
在收到响应的请求时就可以触发相应的操作。
这里配置的192.168.0.101:80
,就是我们8266
的ip
和websocket
的服务端口,下面我们通过一个视频来看下操作效果:
为了便于运行和编辑,后端我用的是python
的flask
框架,目前只有一个页面,后续考虑增加设备管理(增删改查)、操作注册等页面。
另外,这里再放上一个webscoket
客户端的python
脚本,方便各位小伙伴测试:
from websocket import create_connection
ws = create_connection("ws://192.168.0.101:80")
print("Sending 'Hello, World'...")
ws.send("taggleLed")
print("Sent")
print("Receiving...")
result = ws.recv()
print("Received '%s'" % result)
ws.close()
结语
本次这个项目,比预想的要简单很多,反而前端页面成了最耗时间的操作,但从实际达成的效果来说,我还是很满意的,毕竟现在躺在床上就可以关灯开灯,它不香吗?
单个esp8266
有10
个数据引脚,也就是说它可以控制10
个用电设备,从这一点上说,一个esp8266
开发板就可以满足我们大部分家电的控制需求,价格简直不要太友好。
当然今天我们算是提供了一种家庭智能设备控制的一种解决方案,有了这套解决方案的加持,我们不仅可以实现手机端、pc
端对设备的控制,还可以实现设备的定时启停,甚至是根据日出日落进行相关这样的复制控制操作,这里的esp8266
+继电器充当的只是执行器,而真正的智能是外部的逻辑运算。