|
本帖最后由 vany5921 于 2020-7-1 10:54 编辑
一个简单的Yeelight灯泡无线M5控制器,可替代手机进行操作,如果手机连接Yeelight时设置了自动光线补偿,那么会对控制器的调光产生一定影响。控制器闲置3秒自动休眠,按B键唤醒,通过陀螺仪调整灯泡亮度,C键开关灯控制。开机黑屏,接入wifi后屏幕会显示内容。 - #define M5STACK_MPU6886
- #include <ArduinoJson.h>
- #include <M5Stack.h>
- #include <WiFi.h>
- #include "yeelight.h"
- #define SSID "SSID"
- #define WIFI_PWD "PASSWORD"
- #define SLEEP_WAIT 3000
- #define ACCEL_THRESHOLD 200
- #define MAX_DIMMER_VALUE 50000
- #define DIMMER_TO_PERCENT(param) ((100 * (param)) / MAX_DIMMER_VALUE)
- void angleDimmer(void* xParam);
- void sleepWait(void* xParam);
- void waitForWiFi();
- void lightPowerToggle();
- void lightAdjustBrightness();
- void power_on_rutine();
- TaskHandle_t sleepTaskHandle;
- TaskHandle_t angleTaskHandle;
- Yeelight* yeelight;
- bool initialized = false;
- bool inactive = false;
- time_t last_activity = millis();
- int32_t dimmer_value = 0;
- int current_bright = 1;
- int toggle_counter = 1;
- String brightness_params;
- void setup() {
- M5.begin();
- M5.Power.begin();
- M5.Power.setWakeupButton(BUTTON_B_PIN);
- M5.IMU.Init();
- WiFi.begin(SSID, WIFI_PWD);
- waitForWiFi();
- M5.Lcd.fillScreen(BLACK);
- M5.Lcd.setTextColor(GREEN, BLACK);
- M5.Lcd.setTextSize(2);
- yeelight = new Yeelight();
- yeelight->lookup();
- }
- void loop() {
- M5.update();
- if (!initialized) {
- power_on_rutine();
- initialized = true;
- inactive = false;
- }
- if (M5.BtnC.wasPressed()) {
- lightPowerToggle();
- }
- Serial.println(current_bright);
- lightAdjustBrightness();
- if (inactive) {
- vTaskDelete(angleTaskHandle);
- vTaskDelete(sleepTaskHandle);
- initialized = false;
- M5.Power.lightSleep();
- }
- delay(100);
- }
- void lightPowerToggle() {
- last_activity = millis();
- M5.Lcd.setCursor(0, 60);
- M5.Lcd.print("Sending power toggle ");
- M5.Lcd.println(toggle_counter++);
- yeelight->sendCommand("toggle", "[]");
- }
- void lightAdjustBrightness() {
- int new_bright = (int)(dimmer_value / (MAX_DIMMER_VALUE / 100));
- String brightness_params;
- if (new_bright < 1) {
- new_bright = 1;
- }
- if (new_bright != current_bright) {
- current_bright = new_bright;
- brightness_params = String("[") + new_bright + ", "smooth", 500]";
- Serial.println(yeelight->sendCommand("set_bright", brightness_params));
- }
- }
- void power_on_rutine() {
- M5.Lcd.fillScreen(BLACK);
- last_activity = millis();
- xTaskCreate(angleDimmer, "angleDimmer", 4096, NULL, 10, &angleTaskHandle);
- xTaskCreate(sleepWait, "sleepWait", XT_STACK_MIN_SIZE, NULL, 9,
- &sleepTaskHandle);
- waitForWiFi();
- M5.Lcd.setCursor(0, 0);
- M5.Lcd.println("Connected to Wifi");
- while (!yeelight->feedback()) {
- yeelight->lookup();
- delay(50);
- }
- M5.Lcd.setCursor(0, 20);
- M5.Lcd.println("Light detected");
- }
- void waitForWiFi() {
- while (WiFi.status() != WL_CONNECTED) {
- delay(100);
- Serial.print(F("."));
- }
- }
- void angleDimmer(void* xParam) {
- int16_t gx, gy, gz;
- while (1) {
- M5.IMU.getGyroAdc(&gx, &gy, &gz);
- if (gz >= ACCEL_THRESHOLD || gz <= -ACCEL_THRESHOLD) {
- dimmer_value -= gz; // I want right turns to increment the brightness
- last_activity = millis();
- }
- if (dimmer_value >= MAX_DIMMER_VALUE) {
- dimmer_value = MAX_DIMMER_VALUE;
- } else if (dimmer_value <= 0) {
- dimmer_value = 0;
- }
- vTaskDelay(100 * portTICK_PERIOD_MS);
- }
- }
- void sleepWait(void* xParam) {
- while (1) {
- if (millis() > last_activity + SLEEP_WAIT) {
- inactive = true;
- }
- M5.Lcd.setCursor(0, 100);
- M5.Lcd.print("Brightness: %");
- M5.Lcd.setCursor(140, 100);
- M5.Lcd.println(current_bright);
- vTaskDelay(500 * portTICK_PERIOD_MS);
- }
- }
复制代码
yeelight.cpp
- #ifdef ESP32
- #include <WiFi.h>
- #else
- #include <ESP8266WiFi.h>
- #endif
- #include <WiFiUdp.h>
- #include "yeelight.h"
- WiFiUDP _udp;
- WiFiClient _client;
- IPAddress _ipMulti(239, 255, 255, 250);
- char _packetBuffer[550];
- String _location, _support;
- bool _powered;
- char _server[15];
- uint16_t _cmdid = 0, _port = 0;
- Yeelight::Yeelight() {}
- Yeelight::~Yeelight() { _udp.stop(); }
- void Yeelight::lookup() {
- #ifdef ESP32
- _udp.beginMulticast(_ipMulti, 1982);
- _udp.beginMulticastPacket();
- #else
- _udp.beginMulticast(WiFi.localIP(), _ipMulti, 1982);
- _udp.beginPacketMulticast(_ipMulti, 1982, WiFi.localIP());
- #endif
- _udp.print(
- "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1982\r\nMAN: "
- ""ssdp:discover"\r\nST: wifi_bulb");
- _udp.endPacket();
- _udp.begin(1982);
- }
- int Yeelight::feedback() {
- int packetSize = _udp.parsePacket();
- if (packetSize) {
- int len = _udp.read(_packetBuffer, 550);
- if (len > 0) {
- _packetBuffer[len] = 0;
- }
- parseFeedback(_packetBuffer, len);
- }
- return packetSize;
- }
- void Yeelight::parseFeedback(char* buffer, size_t len) {
- int i = 0, _i = 0;
- char _b[255];
- while (i < len) {
- if (buffer[i] == '\r' && i + 1 <= len && buffer[i + 1] == '\n') {
- _b[_i] = 0;
- // ----
- String _str = String(_b);
- if (_str.startsWith("Location: yeelight://")) {
- int colon = _str.indexOf(':', 21) + 1;
- _location = _str.substring(10);
- _str.substring(21, colon).toCharArray(_server, colon - 21);
- _port = _str.substring(colon).toInt();
- }
- if (_str.startsWith("support: ")) {
- _support = _str.substring(9);
- }
- if (_str.startsWith("power: ")) {
- _powered = _str.substring(7) == "on";
- }
- // ----
- i = i + 2;
- _i = 0;
- } else {
- _b[_i] = buffer[i];
- i++;
- _i++;
- }
- }
- }
- String Yeelight::sendCommand(String method, String params) {
- if (_client.connect(_server, _port)) {
- String payload = String("") + "{"id":" + (++_cmdid) + ","method":"" +
- method + "","params":" + params + "}";
- _client.println(payload);
- }
- String result = "";
- while (_client.connected()) {
- result = _client.readStringUntil('\r');
- _client.stop();
- }
- return result;
- }
- bool Yeelight::isPowered() { return _powered; }
- String Yeelight::getSupport() { return _support; }
- String Yeelight::getLocation() { return _location; }
复制代码
yeelight.h
- #ifndef Yeelight_h
- #define Yeelight_h
- class Yeelight {
- public:
- Yeelight();
- ~Yeelight();
- void lookup();
- int feedback();
- String getLocation();
- String getSupport();
- bool isPowered();
- String sendCommand(String method, String params);
- private:
- void parseFeedback(char* buffer, size_t len);
- };
- #endif
复制代码
|
|