yeelight灯泡wifi控制器-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2695|回复: 0

yeelight灯泡wifi控制器

[复制链接]
发表于 2020-7-1 10:53 | 显示全部楼层 |阅读模式
本帖最后由 vany5921 于 2020-7-1 10:54 编辑

      一个简单的Yeelight灯泡无线M5控制器,可替代手机进行操作,如果手机连接Yeelight时设置了自动光线补偿,那么会对控制器的调光产生一定影响。控制器闲置3秒自动休眠,按B键唤醒,通过陀螺仪调整灯泡亮度,C键开关灯控制。开机黑屏,接入wifi后屏幕会显示内容。   
  1. #define M5STACK_MPU6886
  2. #include <ArduinoJson.h>
  3. #include <M5Stack.h>
  4. #include <WiFi.h>

  5. #include "yeelight.h"

  6. #define SSID "SSID"
  7. #define WIFI_PWD "PASSWORD"
  8. #define SLEEP_WAIT 3000
  9. #define ACCEL_THRESHOLD 200
  10. #define MAX_DIMMER_VALUE 50000
  11. #define DIMMER_TO_PERCENT(param) ((100 * (param)) / MAX_DIMMER_VALUE)

  12. void angleDimmer(void* xParam);
  13. void sleepWait(void* xParam);

  14. void waitForWiFi();
  15. void lightPowerToggle();

  16. void lightAdjustBrightness();

  17. void power_on_rutine();

  18. TaskHandle_t sleepTaskHandle;
  19. TaskHandle_t angleTaskHandle;
  20. Yeelight* yeelight;

  21. bool initialized = false;
  22. bool inactive = false;

  23. time_t last_activity = millis();
  24. int32_t dimmer_value = 0;
  25. int current_bright = 1;
  26. int toggle_counter = 1;

  27. String brightness_params;

  28. void setup() {
  29.   M5.begin();

  30.   M5.Power.begin();
  31.   M5.Power.setWakeupButton(BUTTON_B_PIN);
  32.   M5.IMU.Init();

  33.   WiFi.begin(SSID, WIFI_PWD);

  34.   waitForWiFi();

  35.   M5.Lcd.fillScreen(BLACK);
  36.   M5.Lcd.setTextColor(GREEN, BLACK);
  37.   M5.Lcd.setTextSize(2);

  38.   yeelight = new Yeelight();
  39.   yeelight->lookup();
  40. }

  41. void loop() {
  42.   M5.update();

  43.   if (!initialized) {
  44.     power_on_rutine();
  45.     initialized = true;
  46.     inactive = false;
  47.   }

  48.   if (M5.BtnC.wasPressed()) {
  49.     lightPowerToggle();
  50.   }

  51.   Serial.println(current_bright);

  52.   lightAdjustBrightness();

  53.   if (inactive) {
  54.     vTaskDelete(angleTaskHandle);
  55.     vTaskDelete(sleepTaskHandle);
  56.     initialized = false;
  57.     M5.Power.lightSleep();
  58.   }
  59.   delay(100);
  60. }

  61. void lightPowerToggle() {
  62.   last_activity = millis();

  63.   M5.Lcd.setCursor(0, 60);
  64.   M5.Lcd.print("Sending power toggle ");
  65.   M5.Lcd.println(toggle_counter++);
  66.   yeelight->sendCommand("toggle", "[]");
  67. }

  68. void lightAdjustBrightness() {
  69.   int new_bright = (int)(dimmer_value / (MAX_DIMMER_VALUE / 100));
  70.   String brightness_params;

  71.   if (new_bright < 1) {
  72.     new_bright = 1;
  73.   }

  74.   if (new_bright != current_bright) {
  75.     current_bright = new_bright;
  76.     brightness_params = String("[") + new_bright + ", "smooth", 500]";

  77.     Serial.println(yeelight->sendCommand("set_bright", brightness_params));
  78.   }
  79. }

  80. void power_on_rutine() {
  81.   M5.Lcd.fillScreen(BLACK);

  82.   last_activity = millis();
  83.   xTaskCreate(angleDimmer, "angleDimmer", 4096, NULL, 10, &angleTaskHandle);
  84.   xTaskCreate(sleepWait, "sleepWait", XT_STACK_MIN_SIZE, NULL, 9,
  85.               &sleepTaskHandle);

  86.   waitForWiFi();
  87.   M5.Lcd.setCursor(0, 0);
  88.   M5.Lcd.println("Connected to Wifi");

  89.   while (!yeelight->feedback()) {
  90.     yeelight->lookup();
  91.     delay(50);
  92.   }
  93.   M5.Lcd.setCursor(0, 20);
  94.   M5.Lcd.println("Light detected");
  95. }

  96. void waitForWiFi() {
  97.   while (WiFi.status() != WL_CONNECTED) {
  98.     delay(100);
  99.     Serial.print(F("."));
  100.   }
  101. }

  102. void angleDimmer(void* xParam) {
  103.   int16_t gx, gy, gz;

  104.   while (1) {
  105.     M5.IMU.getGyroAdc(&gx, &gy, &gz);

  106.     if (gz >= ACCEL_THRESHOLD || gz <= -ACCEL_THRESHOLD) {
  107.       dimmer_value -= gz;  // I want right turns to increment the brightness
  108.       last_activity = millis();
  109.     }

  110.     if (dimmer_value >= MAX_DIMMER_VALUE) {
  111.       dimmer_value = MAX_DIMMER_VALUE;
  112.     } else if (dimmer_value <= 0) {
  113.       dimmer_value = 0;
  114.     }
  115.     vTaskDelay(100 * portTICK_PERIOD_MS);
  116.   }
  117. }

  118. void sleepWait(void* xParam) {
  119.   while (1) {
  120.     if (millis() > last_activity + SLEEP_WAIT) {
  121.       inactive = true;
  122.     }
  123.     M5.Lcd.setCursor(0, 100);
  124.     M5.Lcd.print("Brightness:    %");
  125.     M5.Lcd.setCursor(140, 100);
  126.     M5.Lcd.println(current_bright);
  127.     vTaskDelay(500 * portTICK_PERIOD_MS);
  128.   }
  129. }
复制代码

yeelight.cpp

  1. #ifdef ESP32
  2. #include <WiFi.h>
  3. #else
  4. #include <ESP8266WiFi.h>
  5. #endif

  6. #include <WiFiUdp.h>

  7. #include "yeelight.h"

  8. WiFiUDP _udp;
  9. WiFiClient _client;
  10. IPAddress _ipMulti(239, 255, 255, 250);
  11. char _packetBuffer[550];

  12. String _location, _support;
  13. bool _powered;
  14. char _server[15];

  15. uint16_t _cmdid = 0, _port = 0;

  16. Yeelight::Yeelight() {}

  17. Yeelight::~Yeelight() { _udp.stop(); }

  18. void Yeelight::lookup() {
  19. #ifdef ESP32
  20.   _udp.beginMulticast(_ipMulti, 1982);
  21.   _udp.beginMulticastPacket();
  22. #else
  23.   _udp.beginMulticast(WiFi.localIP(), _ipMulti, 1982);
  24.   _udp.beginPacketMulticast(_ipMulti, 1982, WiFi.localIP());
  25. #endif
  26.   _udp.print(
  27.       "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1982\r\nMAN: "
  28.       ""ssdp:discover"\r\nST: wifi_bulb");
  29.   _udp.endPacket();
  30.   _udp.begin(1982);
  31. }

  32. int Yeelight::feedback() {
  33.   int packetSize = _udp.parsePacket();
  34.   if (packetSize) {
  35.     int len = _udp.read(_packetBuffer, 550);
  36.     if (len > 0) {
  37.       _packetBuffer[len] = 0;
  38.     }
  39.     parseFeedback(_packetBuffer, len);
  40.   }
  41.   return packetSize;
  42. }

  43. void Yeelight::parseFeedback(char* buffer, size_t len) {
  44.   int i = 0, _i = 0;
  45.   char _b[255];
  46.   while (i < len) {
  47.     if (buffer[i] == '\r' && i + 1 <= len && buffer[i + 1] == '\n') {
  48.       _b[_i] = 0;

  49.       // ----
  50.       String _str = String(_b);
  51.       if (_str.startsWith("Location: yeelight://")) {
  52.         int colon = _str.indexOf(':', 21) + 1;
  53.         _location = _str.substring(10);
  54.         _str.substring(21, colon).toCharArray(_server, colon - 21);
  55.         _port = _str.substring(colon).toInt();
  56.       }
  57.       if (_str.startsWith("support: ")) {
  58.         _support = _str.substring(9);
  59.       }
  60.       if (_str.startsWith("power: ")) {
  61.         _powered = _str.substring(7) == "on";
  62.       }
  63.       // ----

  64.       i = i + 2;
  65.       _i = 0;
  66.     } else {
  67.       _b[_i] = buffer[i];
  68.       i++;
  69.       _i++;
  70.     }
  71.   }
  72. }

  73. String Yeelight::sendCommand(String method, String params) {
  74.   if (_client.connect(_server, _port)) {
  75.     String payload = String("") + "{"id":" + (++_cmdid) + ","method":"" +
  76.                      method + "","params":" + params + "}";
  77.     _client.println(payload);
  78.   }

  79.   String result = "";
  80.   while (_client.connected()) {
  81.     result = _client.readStringUntil('\r');
  82.     _client.stop();
  83.   }
  84.   return result;
  85. }

  86. bool Yeelight::isPowered() { return _powered; }

  87. String Yeelight::getSupport() { return _support; }

  88. String Yeelight::getLocation() { return _location; }
复制代码


yeelight.h

  1. #ifndef Yeelight_h
  2. #define Yeelight_h

  3. class Yeelight {
  4. public:
  5.   Yeelight();
  6.   ~Yeelight();
  7.   void lookup();
  8.   int feedback();
  9.   String getLocation();
  10.   String getSupport();
  11.   bool isPowered();
  12.   String sendCommand(String method, String params);

  13. private:
  14.   void parseFeedback(char* buffer, size_t len);
  15. };

  16. #endif
复制代码



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-11-28 02:43 , Processed in 0.144987 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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