改造家里的开关成为智能开关,保留原有开关控制,零火版

改造家里的开关成为智能开关,保留原有开关控制,零火版

亮点

  1. 成本不超20块,这可能是目前能找到的最便宜方案了吧。
  2. 体积较小,可以塞入86开关面板内。
  3. 手机app+智能音箱+物理开关控制,状态能同步。
  4. 接入点灯科技平台,支持wifi配网,包括blinker 设备密钥。
  5. 入手门槛大大降低,有电工基础,会接入线就行。

过程1,下载固件和wifi配置网

过程2,接线

过程3,改造过程

过程4,最后效果

点动式物理开关演示

器材

需要的器件如下,
在这里插入图片描述
在这里插入图片描述

接线

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

手机app端,Blinker设置

1,下载客户端

https://diandeng.tech/doc/app-download, 下载其app, 按注册blinker账号,获取密钥authkey,iOS 在app store 搜索blinker 安装

在这里插入图片描述

2,注册账号

在这里插入图片描述

3,创建设备

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
到这一步,我们拿到设备的密钥,请记录下来,后面要用!!!!

为设备增加一个按钮, 按键设置如下图
在这里插入图片描述

在这里插入图片描述

固件下载

1,下载网盘工具包

链接:https://pan.baidu.com/s/1LU4XkcYnH83GNsA61ywFqw 提取码:681i 复制这段内容后打开百度网盘手机App,操作更方便哦

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2,烧写固件

把esp8266插在烧写器上,然后插入电脑的usb口,如下
在这里插入图片描述
运行NdoeMcu-pyFlasher-4.0-xx.exe开始下载固件到esp8266
在这里插入图片描述

配置wifi上网

1, 重启esp-01
在这里插入图片描述
在这里插入图片描述
用手机连接到esp8266的wifi热点,热点名不是根据型号会不一样,多半以esp-xxx开头

在这里插入图片描述
在这里插入图片描述
在电脑的浏览器打开http://192.168.4.1
在这里插入图片描述
选择要配置的wifi,点击
在这里插入图片描述
2,输入密码和点灯科技创建的设备ID
在这里插入图片描述
3,点确定开始配网
在这里插入图片描述
成功后

在这里插入图片描述
手机端
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

接入小爱同学配置

1、在手机上安装米家,小米音箱app.
2、在米家APP上添加点灯科技的扩展。

在这里插入图片描述
3,从小爱音箱APP上查看有没有找到设备
在这里插入图片描述

1、如果发现在设备,就说明配置成功了,我这里设备名叫“新的设备”,现在可以对小爱说 “打开新的设备”
2、你还可以添加小爱学习
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

接入小度配置

代码已经支持,作者还没来得及测试,参考小爱同学配置一下

接入天猫精灵配置

代码已经支持,作者还没来得及测试,参考小爱同学配置一下

接入siri配置

1,安装“快捷指令”app,点击打开

在这里插入图片描述
在这里插入图片描述
点运行按钮测试一下开关,passwd是123456

出现下图结果,说明接口调用成功了。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
现在对着siri说,“打开台灯”“关闭台灯”

代码

/*
NodeMcu或esp-01/01s控制1路继电器,集成blinker平台,
用手机app控制1路继电器开关,添加一路物理开关控制,继电器用常开(NO)模式
 
v1.0
Created 2021
by 阳阳学编程
www.sooncore.com
抖音号:yyxbc2010
微信号:yyxbc2010

固件有网页配网功能,固件烧写工具:
链接:https://pan.baidu.com/s/1WsE_2gERyjaUZFbwgJnsOw 提取码:56r8 

说明:

1,继电器高电平触发时,YYXBC_HIGH = 1,YYXBC_LOW  = 0
继电器低电平触发时,YYXBC_HIGH = 0,YYXBC_LOW  = 1
const int YYXBC_HIGH = 0 ;
const int YYXBC_LOW  = 1 ;

2,用esp-01时,物理开关接在vcc 和gpio2上,继电器接在gpio0上
用nodeMcu时,物理开关接在vcc 和D4上,继电器接在D3上,下面的宏
定义只能同时有一个生效

//NodeMCU 继电器接D3,物理开关接D4
#define LED_BUILTIN_LIGHT 0
#define LED_BUILTIN_K2 2

//Esp-01/01s,继电器接GPIO0,物理开关接GPIO2
//#define LED_BUILTIN_LIGHT D3
//#define LED_BUILTIN_K2 D4

3,YYXBC_BUTTON_TYPE = 1时表示物理开关为点动模式,0时表示自锁模式
const int YYXBC_BUTTON_TYPE = 1;

获得具体连接电路图和更多资源,请参阅阳阳学编程网站 www.sooncore.com。
   
This example code is in the public domain.
*/

#define BLINKER_PRINT Serial
#define BLINKER_WIFI
#define BLINKER_MIOT_OUTLET              // 设置小爱灯类库
#define BLINKER_DUEROS_OUTLET            // 设置小度灯类库
#define BLINKER_ALIGENIE_OUTLET          // 设置天猫灯类库

#define BLINKER_WITHOUT_SSL              //使用这个宏,表示不用SSL加密,可以得到更多内存

//
如果要使用apconfig配网模式,打开注释掉,加让这行代码生效
//#define BLINKER_APCONFIG

如果要使用smartconfig配网模式,打开注释掉,加让这行代码生效
//#define BLINKER_ESP_SMARTCONFIG

#include <Blinker.h>
#include <ESP8266WebServer.h>

char auth[] = "a7a437131912";
char ssid[] = "panzujiMi10";
char pswd[] = "moto1984";

String version  = "1.0.3";

//NodeMCU 继电器接D3,物理开关接D4
#define LED_BUILTIN_LIGHT 0
#define LED_BUILTIN_K2 2

//Esp-01/01s,继电器接GPIO0,物理开关接GPIO2
//#define LED_BUILTIN_LIGHT D3
//#define LED_BUILTIN_K2 D4

/***
 * 继电器高电平触发时,YYXBC_HIGH = 1,YYXBC_LOW  = 0
 * 继电器低电平触发时,YYXBC_HIGH = 0,YYXBC_LOW  = 1
 */
const int YYXBC_HIGH = 0 ;
const int YYXBC_LOW  = 1 ;

/***
 * 物理开关点动模式1,自锁模式0
 */
const int YYXBC_BUTTON_TYPE = 0;

//http接口请求密码
String httppswd = "123456";

bool oDuerState = YYXBC_LOW;
bool oMioState = YYXBC_LOW;
bool oAligenieState = YYXBC_LOW;

// 新建组件对象
BlinkerButton Button1("btn-abc");

//webserver for siri
static ESP8266WebServer esp8266_server(80);

//心跳回调
void heartbeat()
{
    
    
   BLINKER_LOG("heartbeat,state: ", digitalRead(LED_BUILTIN));

    //较正app的按钮状态
    if(YYXBC_HIGH == digitalRead(LED_BUILTIN_LIGHT) ){
    
    
        Button1.print("on");
    }else{
    
    
       Button1.print("off");
    }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*******如果是手机app 有对设备进行操作就执行下面

void button1_callback(const String & state)
{
    
    
    BLINKER_LOG("button1_callback get button state: ", state);

    if (state == BLINKER_CMD_ON) {
    
    
        BLINKER_LOG("Toggle on!");
        Button1.print("on");
        digitalWrite(LED_BUILTIN_LIGHT, YYXBC_HIGH);
        oDuerState = YYXBC_HIGH;
        oMioState =YYXBC_HIGH;
        oAligenieState = YYXBC_HIGH;
    }
    else if (state == BLINKER_CMD_OFF) {
    
    
        BLINKER_LOG("Toggle off!");
        Button1.print("off");
        digitalWrite(LED_BUILTIN_LIGHT, YYXBC_LOW);
        oDuerState = YYXBC_LOW;
        oMioState = YYXBC_LOW;
        oAligenieState = YYXBC_LOW;
    }
    BlinkerDuerOS.powerState(oDuerState == YYXBC_HIGH ? "on" : "off");
    BlinkerDuerOS.report();
    BlinkerMIOT.powerState(oMioState == YYXBC_HIGH ? "on" : "off");
    BlinkerMIOT.print();
    BlinkerAliGenie.powerState(oAligenieState == YYXBC_HIGH ? "on" : "off");
    BlinkerAliGenie.print(); 
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*******如果小度 有对设备进行操作就执行下面
void duerPowerState(const String & state)
{
    
    
    BLINKER_LOG("duerPowerState need set power state: ", state);

    if (state == BLINKER_CMD_ON) {
    
    
       button1_callback(BLINKER_CMD_ON);
    }
    else if (state == BLINKER_CMD_OFF) {
    
    
      button1_callback(BLINKER_CMD_OFF);
    }
}

void duerQuery(int32_t queryCode)
{
    
    
    BLINKER_LOG("DuerOS Query codes: ", queryCode);

    switch (queryCode)
    {
    
    
        case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :        
            BLINKER_LOG("DuerOS Query power state");
            BlinkerDuerOS.powerState(oDuerState == YYXBC_HIGH? "on" : "off");
            BlinkerDuerOS.print();
            break;
        case BLINKER_CMD_QUERY_TIME_NUMBER :
            BLINKER_LOG("DuerOS Query time");
            BlinkerDuerOS.time(millis());
            BlinkerDuerOS.print();
            break;
        default :
            BlinkerDuerOS.powerState(oDuerState == YYXBC_HIGH? "on" : "off");
            BlinkerDuerOS.print();
            break;
    }
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*******如果小爱有对设备进行操作就执行下面
void miotPowerState(const String & state)
{
    
    
    BLINKER_LOG("miotPowerState need set power state: ", state);

    if (state == BLINKER_CMD_ON) {
    
    
       button1_callback(BLINKER_CMD_ON);
    }
    else if (state == BLINKER_CMD_OFF) {
    
    
      button1_callback(BLINKER_CMD_OFF);
    }
}

void miotQuery(int32_t queryCode)
{
    
    
    BLINKER_LOG("MIOT Query codes: ", queryCode);

    switch (queryCode)
    {
    
    
      case BLINKER_CMD_QUERY_ALL_NUMBER :
          BLINKER_LOG("MIOT Query All");
          BlinkerMIOT.powerState(oMioState == YYXBC_HIGH? "on" : "off");
          BlinkerMIOT.print();
          break;
      case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
          BLINKER_LOG("MIOT Query Power State");
          BlinkerMIOT.powerState(oMioState ==YYXBC_HIGH ? "on" : "off");
          BlinkerMIOT.print();
          break;
      default :
          BlinkerMIOT.powerState(oMioState ==YYXBC_HIGH ? "on" : "off");
          BlinkerMIOT.print();
          break;
    }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*******如果天猫精灵有对设备进行操作就执行下面
void aligeniePowerState(const String & state)
{
    
    
    BLINKER_LOG("aligeniePowerState need set power state: ", state);

    if (state == BLINKER_CMD_ON) {
    
    
       button1_callback(BLINKER_CMD_ON);
    }
    else if (state == BLINKER_CMD_OFF) {
    
    
      button1_callback(BLINKER_CMD_OFF);
    }
}

void aligenieQuery(int32_t queryCode)
{
    
    
    BLINKER_LOG("AliGenie Query codes: ", queryCode);

    switch (queryCode)
    {
    
    
      case BLINKER_CMD_QUERY_ALL_NUMBER :
          BLINKER_LOG("AliGenie Query All");
          BlinkerAliGenie.powerState(oAligenieState == YYXBC_HIGH? "on" : "off");
          BlinkerAliGenie.print();
          break;
      case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
          BLINKER_LOG("AliGenie Query Power State");
          BlinkerAliGenie.powerState(oAligenieState == YYXBC_HIGH? "on" : "off");
          BlinkerAliGenie.print();
          break;
      default :
          BlinkerAliGenie.powerState(oAligenieState == YYXBC_HIGH ? "on" : "off");
          BlinkerAliGenie.print();
          break;
    }
}

void dataRead(const String & data){
    
    
  BLINKER_LOG("Blinker readString: ", data);

  Blinker.vibrate();
  
  uint32_t BlinkerTime = millis();
  
  Blinker.print("millis", BlinkerTime);

}

void setup() {
    
    
    // 初始化串口
    Serial.begin(115200);

    #if defined(BLINKER_PRINT)
        BLINKER_DEBUG.stream(BLINKER_PRINT);
    #endif

//        //debug 命令
//    BLINKER_DEBUG.stream(BLINKER_PRINT);
//    BLINKER_DEBUG.debugAll();

    // 初始化有LED的IO
    pinMode(LED_BUILTIN_LIGHT, OUTPUT);
    digitalWrite(LED_BUILTIN_LIGHT, YYXBC_LOW);
    
    pinMode(LED_BUILTIN_K2, OUTPUT);
//    digitalWrite(LED_BUILTIN_K2, LOW);
    
 #if (defined(BLINKER_APCONFIG)) || (defined(BLINKER_ESP_SMARTCONFIG))
     //启动配网模式用这行代码
    Blinker.begin(auth);
 #else 
    Blinker.begin(auth, ssid, pswd);
 #endif
 
    Blinker.attachData(dataRead);

    BlinkerDuerOS.attachPowerState(duerPowerState); //小度语音操作注册函数
    BlinkerDuerOS.attachQuery(duerQuery);

    BlinkerMIOT.attachPowerState(miotPowerState);//小爱语音操作注册函数
    BlinkerMIOT.attachQuery(miotQuery);

    BlinkerAliGenie.attachPowerState(aligeniePowerState);//天猫语音操作注册函数
    BlinkerAliGenie.attachQuery(aligenieQuery);     
  
    Button1.attach(button1_callback);
    //注册回调函数
    Blinker.attachHeartbeat(heartbeat);
    
    //启动webserver ,提供接口给siri用
    esp8266_server.on("/", handleRoot); 
    esp8266_server.on("/post", handleSetConfig);           
    esp8266_server.onNotFound(handleNotFound);  
    esp8266_server.begin();                  
      
    Serial.println("HTTP esp8266_server started");
}

void loop() {
    
    

    static int lastms = 0;
    if (millis()-lastms > 10000) {
    
    
      lastms = millis();
      Serial.printf(PSTR("Running (%s),state(%s),version %s for %d Free mem=%d\n"),
          WiFi.localIP().toString().c_str(),
          oAligenieState == YYXBC_HIGH  ? "YYXBC_HIGH" : "CLOES",
          version.c_str(), lastms/1000, ESP.getFreeHeap());
    }
    
    Blinker.run();//运行Blinker
    esp8266_server.handleClient();// 处理http服务器访问
    
    //检查物理开关状态
    if(YYXBC_BUTTON_TYPE == 1){
    
    
       btnHandler1();
    }else{
    
    
       btnHandler2();
    }
   
}


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*******如果iOS的siri有对设备进行操作就执行下面
                                                                  
void handleRoot() {
    
       //处理网站根目录“/”的访问请求 
   String data = "<html>";
      data += "<head><title>设置</title></head>";
      data += "<body>";
      data +=" <p>ESP8266 智能开关,技术支持 微信:yyxbc2010</p><hr>";
      data +=" <p>SSID:"+ WiFi.SSID() + "</p><hr>";
      data +=" <p>PSW:"+ WiFi.psk() + "</p><hr>";
      data += "</body>";
      data += "</html>";  
      
    esp8266_server.send(200, "text/html; charset=utf-8", data);  
} 


void handleSetConfig() {
    
       //处理来自siri的访问请求 
  if (esp8266_server.method() != HTTP_POST) {
    
    
    esp8266_server.send(405, "text/plain", "Method Not Allowed");
  } else {
    
    
//    String message = "POST form was:\n";
    String btnName,btnState,btnPswd;
    for (uint8_t i = 0; i < esp8266_server.args(); i++) {
    
    
       String name = esp8266_server.argName(i);
       if(name == "btn") {
    
    
           btnName = esp8266_server.arg(i);
       }
       else if (name == "state"){
    
    
           btnState = esp8266_server.arg(i);
       } 
       else if (name == "passwd"){
    
    
           btnPswd = esp8266_server.arg(i);
       }     
    }
    if(btnPswd != httppswd){
    
    
      String message = "{\"errcode\":0,\"msg\":\"password error\"}";  
      esp8266_server.send(200, "text/html; charset=utf-8", message);  
      return;
    }
    if(btnName.length() >0 && btnState.length() >0) {
    
    
        //开关btn-abc
        if(btnName == "btn-1"){
    
    
          if(btnState == "on"){
    
    
             button1_callback( BLINKER_CMD_ON);
          }else if (btnState == "off"){
    
    
             button1_callback( BLINKER_CMD_OFF);
          }
        }
    
    }
    String message = "{\"errcode\":0,\"msg\":\" ok\"}";  
    esp8266_server.send(200, "text/html; charset=utf-8", message); 
  }
}

// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){
    
       
//  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += esp8266_server.uri();
  message += "\nMethod: ";
  message += (esp8266_server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += esp8266_server.args();
  message += "\n";
  for (uint8_t i = 0; i < esp8266_server.args(); i++) {
    
    
    message += " " + esp8266_server.argName(i) + ": " + esp8266_server.arg(i) + "\n";
  }
  esp8266_server.send(404, "text/plain", message);

}

//点动模式按钮,监听按钮状态,执行相应处理
void btnHandler1()
{
    
    
  static bool oButtonState = false;
  int state1 =  digitalRead(LED_BUILTIN_K2); //按钮状态
  int state2 =  digitalRead(LED_BUILTIN_LIGHT); //灯的状态
  if(state1 == HIGH )
  {
    
    
    if(oButtonState ){
    
    
      if(state2 == YYXBC_HIGH )
      {
    
     
        button1_callback(BLINKER_CMD_OFF);
        Serial.println("按钮对灯已执行关闭");
      }else{
    
    
        button1_callback(BLINKER_CMD_ON);
        Serial.println("按钮对灯已执行打开");
      }
      oButtonState = false;
    }
  }else{
    
    
    oButtonState = true;
  }
}



//自锁模式按钮,监听按钮状态,执行相应处理
void btnHandler2()
{
    
    
 static bool is_btn = false;//按钮的标志位,用来逻辑处理对比,判断按钮有没有改变状态
  bool is = digitalRead(LED_BUILTIN_K2);   //按钮状态
  if ( is != is_btn)
  {
    
    
    bool is_led = digitalRead(LED_BUILTIN_LIGHT);
    digitalWrite(LED_BUILTIN_LIGHT, !is_led);
    if (is_led == YYXBC_HIGH)
    {
    
    
      button1_callback(BLINKER_CMD_OFF);
      Serial.println("按钮对灯已执行关闭");
    }
    else
    {
    
    
      button1_callback(BLINKER_CMD_ON);
      Serial.println("按钮对灯已执行打开");
    }
    is_btn = digitalRead(LED_BUILTIN_K2);  //更新按钮状态
  }
}

资源下载

本文章相关资源链接:https://pan.baidu.com/s/1LU4XkcYnH83GNsA61ywFqw 提取码:681i 复制这段内容后打开百度网盘手机App,操作更方便哦

关注阳阳学编程抖音号

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/panpanloveruth/article/details/113977715