2020年,在B站上初识ESP8266,被ESP8266的低门槛、高性价比深深吸引,2020年6月20日,买下我的第一块ESP8266开发板,开始入坑。打小就喜欢鼓捣电子设备,现在的工作也涉猎智能家居相关的产品,所以一直想把自己的家里弄得科技感强一点,于是开始一边学习,一边开始用ESP8266来实现一些智能控制的小功能,由于是我的第一个Arduino程序,所以代码比较乱,各位请见谅,不过,不得不说,Arduino的确很好上手,blinker也帮我解决了手机程序的问题。
目前主要实现了如下几项功能:
1、通过红外发射管,可控制客厅的灯光、电视机等家电;
2、通过温湿度传感器,可获取室内的温湿度数据;
3、通过光敏电阻,可获取室内的亮度信息;
4、通过WIFI接入物业的门控、梯控系统,可以解锁楼下单元门、呼叫电梯到指定的楼层;
5、配置了一块0.96吋的OLED小屏幕可显示天气信息;
6、通过点灯科技接入小度音箱,可通过小度音箱控制灯光、家电、单元门、电梯等。
模块让我塞到墙壁盒里了,先看一下手机端的截图和配套的OLED图吧。
- #define BLINKER_P RINT Serial
- #define BLINKER_WIFI
- #define BLINKER_DUEROS_LIGHT
- #define BLINKER_WITHOUT_SSL
- #include <WiFiUdp.h>
- #include <Blinker.h>
- #include <IRremoteESP8266.h>
- #include <IRsend.h>
- #include "DHTesp.h"
- #include "OneButton.h"
- #include <ESP8266HTTPClient.h>
- #include <U8g2lib.h>
- #ifdef U8X8_HAVE_HW_SPI
- #include <SPI.h>
- #endif
- #ifdef U8X8_HAVE_HW_I2C
- #include <Wire.h>
- #endif
- //定义128X64四针OLED模块连接管脚
- U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0 , /* clock=*/ 5, /* data=*/ 4, /* reset=*/ U8X8_PIN_NONE);
- int flag = 0;
- boolean _up = false;
- int incomingByte = 0;//读取串口
- //定义GPIO
- #define IRPIN 14 //红外发射管 GPIO14
- #define K1PIN 13 //按键1 GPIO13
- #define K2PIN 12 //按键2 GPIO12
- #define K3PIN 16 //按键3 GPIO16
- #define K4PIN 0 //按键4 GPIO0
- #define DHTPIN 2 //温湿度传感器 GPIO2
- #define DHTTYPE DHT11
- OneButton button1(K1PIN, true);
- OneButton button2(K2PIN, true);
- //OneButton button3(K3PIN, true);
- OneButton button4(K4PIN, true);
- //定义WIFI密码、设备密码
- char auth[] = "***";
- char ssid[] = "***";
- char pswd[] = "***";
- //定义全局变量
- int lightbright = 100; //灯光初始亮度
- String lightstate = "off"; //灯光初始状态
- int count = 0; //循环计数器
- float humi_read = 0, temp_read = 0; //温湿度
- float bright ; //光敏电阻
- //初始化各模块
- WiFiUDP udp; //初始化UDP
- IRsend irsend(IRPIN); //初始化IR发射管
- DHTesp dht; //初始化温湿度传感器
- //初始化APP组件
- BlinkerButton BtnLightPwr("btn-light-pwr");
- BlinkerButton BtnLightMode("btn-light-mode");
- BlinkerNumber NumTemp("num-temp");
- BlinkerNumber NumHumi("num-humi");
- BlinkerNumber NumBright("num-bright");
- BlinkerSlider Slider1("ran-bright");
- BlinkerButton BtnTvPwr("btn-tv-pwr");
- BlinkerButton BtnTvMode("btn-tv-mode");
- BlinkerButton BtnTvVolp("btn-tv-volp");
- BlinkerButton BtnTvVolm("btn-tv-volm");
- BlinkerButton BtnDoor0502("btn-door-0502");
- BlinkerButton BtnLift1004("btn-lift-1004");
- BlinkerButton BtnDoor0401("btn-door-0401");
- BlinkerButton BtnLift0302("btn-lift-0302");
- void dataRead(const String & data)
- {
- BLINKER_LOG("Blinker readString: ", data);
- Blinker.vibrate();
- uint32_t BlinkerTime = millis();
- Blinker.print("millis", BlinkerTime);
- if (data.length() == 9) {
- doorOpen(data);
- }
- }
- //心跳包
- void heartbeat()
- {
- BtnLightPwr.print(lightstate);
- Slider1.print(lightbright);
- NumTemp.print(temp_read);
- NumHumi.print(humi_read);
- NumBright.print(bright);
- }
- //图表数据
- void dataStorage()
- {
- Blinker.dataStorage("temp", temp_read);
- Blinker.dataStorage("humi", humi_read);
- Blinker.dataStorage("bright", bright);
- }
- // app 端按下按键即会执行该函数 回调函数
- void BtnLightPwr_callback(const String & state) {
- BLINKER_LOG("灯光开关按钮被按下: ", state);
- if (state == "on") {
- irsend.sendNEC(0x1FE7887);
- } else if (state == "off") {
- irsend.sendNEC(0x1FE48B7);
- }
- lightstate = state;
- BlinkerDuerOS.powerState(lightstate);
- BlinkerDuerOS.report();
- BtnLightPwr.print(lightstate);
- }
- void BtnLightMode_callback(const String & state) {
- BLINKER_LOG("灯光模式切换按钮被按下");
- irsend.sendNEC(0x1FE609F);
- lightbright = 100;
- }
- void BtnTvPwr_callback(const String & state) {
- BLINKER_LOG("电视开关按钮被按下");
- irsend.sendSony(0xa90, 12);
- }
- void BtnTvMode_callback(const String & state) {
- BLINKER_LOG("电视信源切换按钮被按下");
- irsend.sendSony(0xA50, 12);
- }
- void BtnTvVolp_callback(const String & state) {
- BLINKER_LOG("电视音量加按钮被按下");
- irsend.sendSony(0x490, 12);
- }
- void BtnTvVolm_callback(const String & state) {
- BLINKER_LOG("电视音量减按钮被按下");
- irsend.sendSony(0xc90, 12);
- }
- void Slider1_callback(int32_t value)
- {
- BLINKER_LOG("灯光亮度调整为: ", value);
- int temp = 0;
- temp = value - lightbright;
- if ( temp > 0 ) {
- for (int counter = 1; counter <= temp * 0.63; counter++) {
- irsend.sendNEC(0x1FEF807);
- Blinker.delay(50);
- }
- if (lightbright > 100) lightbright = 100;
- }
- else {
- for (int counter = 1; counter <= -temp * 0.63; counter++) {
- irsend.sendNEC(0x1FE50AF);
- Blinker.delay(50);
- }
- if ( lightbright < 1) lightbright = 1;
- }
- lightbright = value;
- BlinkerDuerOS.brightness(lightbright);
- BlinkerDuerOS.report();
- }
- void BtnDoor0502_callback(const String & state) {
- doorOpen("050210990");
- Blinker.vibrate();
- }
- void BtnLift1004_callback(const String & state) {
- doorOpen("050210991");
- Blinker.vibrate();
- }
- void BtnDoor0401_callback(const String & state) {
- doorOpen("040103020");
- Blinker.vibrate();
- }
- void BtnLift0302_callback(const String & state) {
- doorOpen("040103021");
- Blinker.vibrate();
- }
- //小度电源类回调
- void duerPowerState(const String & state)
- {
- BLINKER_LOG("小度设置灯光开关: ", state);
- if (state == BLINKER_CMD_ON) {
- lightstate = "on";
- irsend.sendNEC(0x1FE7887);
- }
- else if (state == BLINKER_CMD_OFF) {
- lightstate = "off";
- irsend.sendNEC(0x1FE48B7);
- }
- BtnLightPwr.print(lightstate);
- BlinkerDuerOS.powerState(lightstate);
- BlinkerDuerOS.print();
- }
- //用户自定义亮度控制的回调函数:
- void duerBright(const String & duBright)
- {
- BLINKER_LOG("(不生效)小度设置灯光亮度: ", duBright);
- BlinkerDuerOS.brightness(100);
- BlinkerDuerOS.print();
- if (duBright == "99") {//开门
- doorOpen("050210990");
- }
- else if (duBright == "98") {//叫梯
- doorOpen("050210991");
- }
- }
- //用户步长设置亮度的回调函数
- void duerRelativeBright(int32_t duBright)
- {
- BLINKER_LOG("小度调整灯光亮度: ", duBright);
- lightbright += duBright;
- BlinkerDuerOS.brightness(lightbright);
- BlinkerDuerOS.print();
- if ( duBright > 0 ) {
- for (int counter = 1; counter <= duBright * 0.63; counter++) {
- irsend.sendNEC(0x1FEF807);
- Blinker.delay(50);
- }
- if (lightbright > 100) lightbright = 100;
- }
- else {
- for (int counter = 1; counter <= -duBright * 0.63; counter++) {
- irsend.sendNEC(0x1FE50AF);
- Blinker.delay(50);
- }
- if ( lightbright < 1) lightbright = 1;
- }
- Slider1.print(lightbright);
- }
- //小度模式的设置接口
- void duerMode(const String & mode)
- {
- BLINKER_LOG("小度设置灯光模式: ", mode);
- BlinkerDuerOS.mode(mode);
- BlinkerDuerOS.print();
- if (mode == "None") {
- // 切换冷暖光
- irsend.sendNEC(0x1FE609F);
- }
- else if (mode == "SLEEP" or mode == "NIGHT") {
- irsend.sendNEC(0x1FEA05F);
- BtnLightPwr.print("on");
- lightstate = "on";
- }
- else if (mode == "ENERGY_SAVING") {
- // 辅助灯
- irsend.sendNEC(0x1FE48B7);
- Blinker.delay(50);
- irsend.sendNEC(0x1FE20DF);
- BtnLightPwr.print("on");
- lightstate = "on";
- }
- else if (mode == "TV" or mode == "VIDEO") {
- // 电视遥控器
- }
- //wsMode = mode;
- }
- void click1() {
- Serial.println("Button 1 click.");
- if (lightstate == "on") {
- irsend.sendNEC(0x1FE48B7);
- lightstate = "off";
- u8g2.setPowerSave(0);
- u8g2.setCursor(24, 40);
- u8g2.print("关闭客厅灯");
- u8g2.sendBuffer();
- Blinker.delay(2000);
- u8g2.clearBuffer();
- u8g2.setPowerSave(1);
- } else if (lightstate == "off") {
- irsend.sendNEC(0x1FE7887);
- lightstate = "on";
- u8g2.setPowerSave(0);
- u8g2.setCursor(24, 36);
- u8g2.print("打开客厅灯");
- u8g2.sendBuffer();
- Blinker.delay(2000);
- u8g2.clearBuffer();
- u8g2.setPowerSave(1);
- }
- BlinkerDuerOS.powerState(lightstate);
- BlinkerDuerOS.report();
- BtnLightPwr.print(lightstate);
- }
- void click2() {
- Serial.println("Button 2 click.");
- time_t run_time = Blinker.runTime();
- int run_d = run_time / 86400;
- int run_h = (run_time - run_d * 86400) / 3600;
- int run_m = (run_time - run_d * 86400 - run_h * 3600) / 60;
- int run_s = run_time - run_d * 86400 - run_h * 3600 - run_m * 60;
- String run_str = String(run_d) + "-" + String(run_h) + ":" + String(run_m) + ":" + String(run_s);
-
- u8g2.setPowerSave(0);
- u8g2.setCursor(0, 15);
- u8g2.print("运行时间:" + run_str);
- u8g2.setCursor(0, 31);
- u8g2.print("室内温度:" + String(temp_read) + " ℃");
- u8g2.setCursor(0, 47);
- u8g2.print("室内湿度:" + String(humi_read) + " %");
- u8g2.setCursor(0, 63);
- u8g2.print("室内亮度:" + String(bright));
- u8g2.sendBuffer();
- Serial.println("显示室内温度");
- WiFiClient client;
- HTTPClient http;
- Serial.print("[HTTP] begin...\n");
- if (http.begin(client, "http://api.help.bj.cn/apis/weather/?id=101060101")) { // HTTP
- Serial.print("[HTTP] GET...\n");
- // start connection and send HTTP header
- int httpCode = http.GET();
- // httpCode will be negative on error
- if (httpCode > 0) {
- // HTTP header has been send and Server response header has been handled
- Serial.printf("[HTTP] GET... code: %d\n", httpCode);
- // file found at server
- if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
- String payload = http.getString();
- Serial.println(payload);
- DynamicJsonDocument doc(1000);
- DeserializationError error = deserializeJson(doc, payload);
- JsonObject obj = doc.as<JsonObject>();
- String w_weather = doc["weather"].as<char*>(); //晴
- String w_temp = doc["temp"].as<char*>(); //10
- String w_humidity = doc["humidity"].as<char*>();//24%
- String w_wd = doc["wd"].as<char*>(); //西南风
- String w_wdforce = doc["wdforce"].as<char*>(); //4级
- String w_aqi = doc["aqi"].as<char*>(); //156
- String w_pm25 = doc["pm25"].as<char*>(); //156
- Blinker.delay(6000);
- u8g2.clearBuffer();
- u8g2.setCursor(0, 15);
- u8g2.print("室外天气:" + w_weather);
- u8g2.setCursor(0, 31);
- u8g2.print("空气质量:" + w_aqi);
- u8g2.setCursor(0, 47);
- u8g2.print("温度:" + String(w_temp) + "℃ 湿度:" + String(w_humidity));
- u8g2.setCursor(0, 63);
- u8g2.print("风力:" + w_wd + w_wdforce);
- u8g2.sendBuffer();
- Serial.println("显示室外天气");
- Blinker.delay(6000);
- u8g2.clearBuffer();
- u8g2.setPowerSave(1);
- Serial.println("关闭屏幕");
- }
- } else {
- Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
- }
- http.end();
- } else {
- Serial.printf("[HTTP} Unable to connect\n");
- }
- }
- void click3() {
- Serial.println("Button 3 click.");
- doorOpen("050210990");
- u8g2.setPowerSave(0);
- u8g2.setCursor(24, 36);
- u8g2.print("打开单元门");
- u8g2.sendBuffer();
- Blinker.delay(2000);
- u8g2.clearBuffer();
- u8g2.setPowerSave(1);
- }
- void click4() {
- Serial.println("Button 4 click.");
- doorOpen("050210991");
- u8g2.setPowerSave(0);
- u8g2.setCursor(32, 36);
- u8g2.print("呼叫电梯");
- u8g2.sendBuffer();
- Blinker.delay(2000);
- u8g2.clearBuffer();
- u8g2.setPowerSave(1);
- }
- //新方法,发送给进行转发
- void doorOpen(const String & doorNum)
- {
- IPAddress NewWIFIIP(192, 168, 99, 1);
- String lift[] = {"0101", "0102", "0103", "0201", "0202", "0401", "0402", "0501", "0502", "0503", "0601", "0602", "0701", "0702", "0801", "0802", "0901", "0902", "1001", "1002", "1101", "1102", "1103", "1201", "1202", "1301", "1302"};
- String unitNum = doorNum.substring(0, 4);
- int ip = 0;
- for (ip = 0; ip <= 24; ip++) {
- if (unitNum == lift[ip])break;
- }
- String ipstr = String(ip+1);
- if (ipstr.length() == 1)
- {
- ipstr = "0" + ipstr;
- }
- Serial.println(ipstr);
- char door[9] ;
- strcpy(door, (ipstr + doorNum).c_str());
- udp.beginPacket(NewWIFIIP, 20625);
- udp.write(door, 11);
- udp.endPacket();
- }
- void setup() {
- // 初始化串口,并开启调试信息
- Serial.begin(9600);
- BLINKER_DEBUG.stream(Serial); //串口打印调试信息
- // BLINKER_DEBUG.debugAll();
- // 初始化有LED的IO
- pinMode(LED_BUILTIN, OUTPUT); //LED_BUILTIN 宏就是开发板指示灯的io口
- digitalWrite(LED_BUILTIN, HIGH);
- // 初始化blinker
- Blinker.begin(auth, ssid, pswd);
- //Blinker.begin(auth);
- Blinker.attachData(dataRead);
- Blinker.attachHeartbeat(heartbeat);
- Blinker.attachDataStorage(dataStorage);
- BtnLightPwr.attach(BtnLightPwr_callback); //绑定按键执行回调函数
- BtnLightMode.attach(BtnLightMode_callback);
- BtnTvPwr.attach(BtnTvPwr_callback);
- BtnTvMode.attach(BtnTvMode_callback);
- BtnTvVolp.attach(BtnTvVolp_callback);
- BtnTvVolm.attach(BtnTvVolm_callback);
- BtnDoor0502.attach(BtnDoor0502_callback);
- BtnLift1004.attach(BtnLift1004_callback);
- BtnDoor0401.attach(BtnDoor0401_callback);
- BtnLift0302.attach(BtnLift0302_callback);
- Slider1.attach(Slider1_callback);
- Slider1.print(lightbright);
- BlinkerDuerOS.attachPowerState(duerPowerState); //小度语音操作注册函数
- BlinkerDuerOS.attachRelativeBrightness(duerRelativeBright);
- BlinkerDuerOS.attachBrightness(duerBright);
- BlinkerDuerOS.attachMode(duerMode);
- //红外模块初始化
- irsend.begin();
- //温湿度传感器初始化
- dht.setup(DHTPIN, DHTesp::DHTTYPE);
- button1.attachClick(click1);
- button2.attachClick(click2);
- //button3.attachClick(click3);
- button4.attachClick(click4);
- //初始化OLED
- u8g2.enableUTF8Print();//必须否则中文不显示。
- u8g2.begin();
- u8g2.setFont(u8g2_font_wqy14_t_gb2312);
- pinMode(K3PIN, INPUT);
- //设备启动后需要的一些操作
- Blinker.wechat("家庭网关上线", "家庭网关上线", "家庭网关上线"); //发送微信
- irsend.sendNEC(0x1FE7887); //关灯
- }
- void loop() {
- Blinker.run(); /*每次运行都会将设备收到的数据进行一次解析。
- 在使用WiFi接入时,该语句也负责保持网络连接*/
- if (Serial.available() > 0)
- {
- incomingByte = Serial.read();
- BLINKER_LOG("读到:", incomingByte);
- switch (incomingByte) {
- case 1:
- BLINKER_LOG("开灯");
- BtnLightPwr_callback("on");
- break;
- case 2:
- BLINKER_LOG("关灯");
- BtnLightPwr_callback("off");
- break;
- case 3:
- BLINKER_LOG("灯光切换模式");
- irsend.sendNEC(0x1FE609F);
- lightbright = 100;
- break;
- case 4:
- BLINKER_LOG("灯亮一点");
- duerRelativeBright(20);
- break;
- case 5:
- BLINKER_LOG("灯暗一点");
- duerRelativeBright(-20);
- break;
- case 6:
- BLINKER_LOG("灯睡眠模式");
- duerMode("SLEEP");
- break;
- case 7:
- BLINKER_LOG("灯节能模式");
- duerMode("ENERGY_SAVING");
- break;
- case 8:
- BLINKER_LOG("灯冷暖光切换");
- irsend.sendNEC(0x1FE609F);
- break;
- case 9:
- BLINKER_LOG("打开/关闭电视");
- irsend.sendSony(0xa90, 12);
- break;
- case 10:
- BLINKER_LOG("电视信源切换");
- irsend.sendSony(0xA50, 12);
- break;
- case 11:
- BLINKER_LOG("电视大点声");
- irsend.sendSony(0x490, 12);
- break;
- case 12:
- BLINKER_LOG("电视小点声");
- irsend.sendSony(0xc90, 12);
- break;
- case 13:
- BLINKER_LOG("开门");
- doorOpen("050210990");
- break;
- case 14:
- BLINKER_LOG("呼叫电梯");
- doorOpen("050210991");
- break;
- case 15:
- BLINKER_LOG("激活电梯");
- doorOpen("050210992");
- break;
- default:
- Serial.println("default");
- }
- }
- count = count + 1;
- button1.tick();
- button2.tick();
- //button3.tick();
- button4.tick();
- if (digitalRead(K3PIN) == LOW)
- flag = 1;
- if ((digitalRead(K3PIN) == HIGH) && (flag == 1))
- {
- _up = true; flag = 0;
- }
- if (_up)
- {
- _up = false;
- click3();
- }
- if (count % 1000 == 0) {
- float h = dht.getHumidity();
- float t = dht.getTemperature();
- if (dht.getStatusString() != "OK")
- {
- BLINKER_LOG("Failed to read from DHT sensor!");
- }
- else
- {
- BLINKER_LOG("湿度:", h, " %");
- BLINKER_LOG("温度:", t, " ℃");
- humi_read = h;
- temp_read = t;
- }
- bright = analogRead(0);
- BLINKER_LOG("亮度:", bright);
- }
- else if (count > 180000) {
- count = 0;
- }
- Blinker.delay(10);
- }
复制代码
|