点灯APP、小爱同学、MQTT同时控制开关-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 3450|回复: 3

[分享] 点灯APP、小爱同学、MQTT同时控制开关

[复制链接]
发表于 2021-5-24 21:47 | 显示全部楼层 |阅读模式
前段时间一直在玩mqtt,感觉很方便、透明。最近又迷上了点灯科技,特别是它和小爱之间的关联,让我这样的懒人更有了动口不动手的理由。
虽然小爱好使唤,但我还是想把它集成到MQTT中,通过其他平台统一控制。可是找了好多帖子,没有找到使用MQTT的例子,只好自己研究了。
我买了个220V转5V模块,连接到一个继电器插座上,在上面插上esp8266-01。
8微信截图_20210524213242.png
2微信截图_20210524213258.png
大部分是示例中的语句,只不过是把mqtt示例和插座示例合起来了。

下面是我的源码,MQTT在主题homeassistant/zhuwodeng/kaiguan下,发布消息,内容为ON,即是控制开关打开,OFF为关闭。
每个操作执行后,均向状态主题homeassistant/zhuwodeng/zhuangtai发布开关状态消息。
HA平台收到消息后处理开关状态。


  1. #define BLINKER_WIFI
  2. #define BLINKER_MIOT_OUTLET

  3. #include <Blinker.h>

  4. int GPIO = 0; //定义继电器输入引脚为GPIO/0
  5. //下面这3行一定要改为自己的
  6. char auth[] = "888888888888";
  7. char ssid[] = "ChinaNet-****";
  8. char pswd[] = "1234567890";
  9. bool oState = true;

  10. /************************* Adafruit.io Setup *********************************/
  11. #define AIO_SERVER      "192.168.2.100"
  12. #define AIO_SERVERPORT  1883                   // use 8883 for SSL
  13. #define AIO_USERNAME    "test"
  14. #define AIO_KEY         "test2020"
  15. Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
  16. //下面定义了2个主题,1个是灯状态,1个是控制开关
  17. Adafruit_MQTT_Publish zhuangtai = Adafruit_MQTT_Publish(&mqtt, "homeassistant/zhuwodeng/zhuangtai");
  18. Adafruit_MQTT_Subscribe kaiguan = Adafruit_MQTT_Subscribe(&mqtt, "homeassistant/zhuwodeng/kaiguan");


  19. // 新建组件对象(在点灯APP里的开关的名字)
  20. BlinkerButton Button1("btn-abc");

  21. // 按下按键即会执行该函数,在APP中按下按钮执行的程序

  22. void button1_callback(const String & state)
  23. {
  24.     //digitalWrite(GPIO, !digitalRead(GPIO));
  25.     BLINKER_LOG("get button state: ", state);
  26.    
  27.     if (state == BLINKER_CMD_ON) {
  28.       oState = true;
  29.     }
  30.     else if (state == BLINKER_CMD_OFF) {
  31.       oState = false;
  32.     }
  33.     turnonoff();//调用开关函数
  34.     Blinker.vibrate();
  35. }
  36. //小爱控制
  37. void miotPowerState(const String & state)
  38. {
  39.     BLINKER_LOG("need set power state: ", state);

  40.     if (state == BLINKER_CMD_ON) {
  41.         oState = true;
  42.     }
  43.     else if (state == BLINKER_CMD_OFF) {
  44.         oState = false;
  45.     }
  46.     turnonoff();
  47. }
  48. //小爱查询状态
  49. void miotQuery(int32_t queryCode)
  50. {
  51.     BLINKER_LOG("MIOT Query codes: ", queryCode);
  52.     BlinkerMIOT.powerState(oState ? "on" : "off");
  53.     BlinkerMIOT.print();
  54. }


  55. void setup()
  56. {
  57.     Serial.begin(115200);
  58.     BLINKER_DEBUG.stream(Serial);
  59.     pinMode(GPIO, OUTPUT);
  60.     digitalWrite(GPIO, LOW);
  61.     Blinker.begin(auth, ssid, pswd);
  62.     Button1.attach(button1_callback);
  63.     BlinkerMIOT.attachPowerState(miotPowerState);
  64.     BlinkerMIOT.attachQuery(miotQuery);
  65.     mqtt.subscribe(&kaiguan);
  66. }

  67. void loop()
  68. {
  69.     Blinker.run();
  70.     MQTT_connect();
  71.   Adafruit_MQTT_Subscribe *subscription;
  72.   subscription = mqtt.readSubscription();
  73.     // Check if its the onoff button feed
  74.     if (subscription == &kaiguan) {
  75.       Serial.print(F("On-Off button: "));
  76.       Serial.println((char *)kaiguan.lastread);
  77.       if (strcmp((char *)kaiguan.lastread, "ON") == 0) {
  78.         oState = true;
  79.       }
  80.       if (strcmp((char *)kaiguan.lastread, "OFF") == 0) {
  81.         oState = false;
  82.       }
  83.       turnonoff();
  84.     }
  85. }

  86. void MQTT_connect() {
  87.   int8_t ret;

  88.   // Stop if already connected.
  89.   if (mqtt.connected()) {
  90.     return;
  91.   }

  92.   Serial.print("Connecting to MQTT... ");

  93.   uint8_t retries = 5;
  94.   ret = mqtt.connect();
  95.   while (ret != 0) { // connect will return 0 for connected
  96.        Serial.println(mqtt.connectErrorString(ret));
  97.        Serial.println("Retrying MQTT connection in 10 seconds...");
  98.        mqtt.disconnect();
  99.        delay(10000);  // wait 5 seconds
  100.        retries--;
  101.        ret = mqtt.connect();
  102.        if (retries == 0) {
  103.          // basically die and wait for WDT to reset me
  104.          while (1);
  105.        }
  106.   }
  107.   Serial.println("MQTT Connected!");
  108.   turnonoff();
  109. }
  110. //这是自己增加的一个统一控制开关的函数,不管通过哪种方式控制设备,都在这里执行。
  111. void turnonoff(){
  112.   if (oState){
  113.         digitalWrite(GPIO, LOW);
  114.         Button1.color("#f7dc05");
  115.         Button1.print("on");
  116.         Serial.println("kaiguan is set to ON");
  117.         BlinkerMIOT.powerState("on");
  118.         BlinkerMIOT.print();
  119.         zhuangtai.publish("ON");
  120.   }
  121.   else{
  122.         digitalWrite(GPIO, HIGH);
  123.         Button1.color("#000000");
  124.         Button1.print("off");
  125.         Serial.println("kaiguan is set to OFF");
  126.         BlinkerMIOT.powerState("off");
  127.         BlinkerMIOT.print();
  128.         zhuangtai.publish("OFF");
  129.   }
  130. }
复制代码
附:源文件 zhuwodeng.zip (2.48 KB, 下载次数: 63)



发表于 2021-6-3 21:18 | 显示全部楼层
老哥可以加个好友交流一下不 想知道可不可以接入物理开关并同步 wx: ohwmf666
 楼主| 发表于 2021-6-4 20:01 | 显示全部楼层
mafeikeji 发表于 2021-6-3 21:18
老哥可以加个好友交流一下不 想知道可不可以接入物理开关并同步 wx: ohwmf666 ...

在官方一个AP配网的示例中发现了使用物理按钮的方法,需要引用一个库OneButton,地址https://github.com/mathertel/OneButton。
这里的按钮是会反弹的那种只能点按的开关,不是我们家里一般装修用的上下按键的翘板开关。可以这么说——不是switch,是button。
在上贴第6行处,插入下列2句。
#include "OneButton.h"  //引用此库文件
#define BLINKER_BUTTON_PIN 2 //这里是8266的GPIO2引脚,我的NodeMcu是D4。

在上贴第13行处插入下1句
OneButton button(BLINKER_BUTTON_PIN, true); //按钮按下,输入低电平时此按钮触发,所以把GPIO2与GND之间用一个按钮连接起来。

在上贴第27行处插入以下函数
void buttonswitch(){
  oState = !oState; //按钮按下执行开关命令,把控制灯状态的变量置为相反状态。
  turnonoff();
}

在上贴第76行后插入下1句
button.attachClick(buttonswitch); //物理按钮单击时调用此函数
在上贴第96行后插入下1句button.tick(); //时刻关注是否按下按钮

就这样,当短按GPIO2上的按钮再松开时,就会触发灯的开关状态。
根据OneButton的说明文档,按钮还有双击、长按等事件。
关于翘板开关的使用,等找时间再试试。
发表于 2021-6-9 09:34 | 显示全部楼层
本帖最后由 mafeikeji 于 2021-6-11 13:59 编辑

射射大佬,我发现在安装函数段有写    digitalWrite(GPIO, LOW);  但是上电还是高电平这个有办法解决么
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-1 07:20 , Processed in 0.168361 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表