Browse Source

preliminary UDP support

Chris Mullins 8 years ago
parent
commit
1ce6d4b9f4

+ 13 - 9
lib/MiLight/MiLightClient.cpp

@@ -56,7 +56,7 @@ void MiLightClient::write(MiLightPacket& packet, const unsigned int resendCount)
 
 void MiLightClient::write(
   const uint16_t deviceId,
-  const uint16_t color,
+  const uint8_t color,
   const uint8_t brightness,
   const uint8_t groupId,
   const MiLightButton button) {
@@ -70,15 +70,10 @@ void MiLightClient::write(
     ((31 - adjustedBrightness) + 17) % 32
   );
   
-  // Map color as a Hue value in [0, 359] to [0, 255]. The protocol also has
-  // 0 being roughly magenta (#FF00FF)
-  const int16_t remappedColor = (color + 40) % 360;
-  const uint8_t adjustedColor = round(remappedColor * (255 / 359.0));
-  
   MiLightPacket packet;
   packet.deviceType = MiLightDeviceType::RGBW;
   packet.deviceId = deviceId;
-  packet.color = adjustedColor;
+  packet.color = color;
   packet.brightness = packetBrightnessValue;
   packet.groupId = groupId;
   packet.button = button;
@@ -87,8 +82,17 @@ void MiLightClient::write(
   write(packet);
 }
     
-void MiLightClient::updateColor(const uint16_t deviceId, const uint8_t groupId, const uint16_t hue) {
-  write(deviceId, hue, 0, groupId, COLOR);
+void MiLightClient::updateColorRaw(const uint16_t deviceId, const uint8_t groupId, const uint16_t color) {
+  write(deviceId, color, 0, groupId, COLOR);
+}
+
+void MiLightClient::updateHue(const uint16_t deviceId, const uint8_t groupId, const uint16_t hue) {
+  // Map color as a Hue value in [0, 359] to [0, 255]. The protocol also has
+  // 0 being roughly magenta (#FF00FF)
+  const int16_t remappedColor = (hue + 40) % 360;
+  const uint8_t adjustedColor = round(remappedColor * (255 / 359.0));
+  
+  write(deviceId, adjustedColor, 0, groupId, COLOR);
 }
 
 void MiLightClient::updateBrightness(const uint16_t deviceId, const uint8_t groupId, const uint8_t brightness) {

+ 4 - 2
lib/MiLight/MiLightClient.h

@@ -81,13 +81,15 @@ class MiLightClient {
     
     void write(
       const uint16_t deviceId,
-      const uint16_t color,
+      const uint8_t color,
       const uint8_t brightness,
       const uint8_t groupId,
       const MiLightButton button
     );
     
-    void updateColor(const uint16_t deviceId, const uint8_t groupId, const uint16_t hue);
+    void updateColorRaw(const uint16_t deviceId, const uint8_t groupId, const uint16_t color);
+    
+    void updateHue(const uint16_t deviceId, const uint8_t groupId, const uint16_t hue);
     void updateBrightness(const uint16_t deviceId, const uint8_t groupId, const uint8_t brightness);
     void updateStatus(const uint16_t deviceId, const uint8_t groupId, MiLightStatus status);
     void updateColorWhite(const uint16_t deviceId, const uint8_t groupId);

+ 85 - 0
lib/MiLight/MiLightUdpServer.cpp

@@ -0,0 +1,85 @@
+#include <MiLightUdpServer.h>
+
+MiLightUdpServer::MiLightUdpServer(MiLightClient*& client, uint16_t port, uint16_t deviceId)
+  : client(client), 
+    port(port),
+    deviceId(deviceId),
+    lastGroup(0)
+{ }
+
+void MiLightUdpServer::begin() {
+  socket.begin(this->port);
+}
+
+void MiLightUdpServer::handleClient() {
+  const size_t packetSize = socket.parsePacket();
+  
+  if (packetSize) {
+    if (packetSize == 3) {
+      socket.read(packetBuffer, packetSize);
+      handleCommand(packetBuffer[0], packetBuffer[1]);
+    } else {
+      Serial.print("Error, unexpected packet length (should always be 3, was: ");
+      Serial.println(packetSize);
+    }
+  }
+}
+
+void MiLightUdpServer::handleCommand(uint8_t command, uint8_t commandArg) {
+  if (command >= UDP_GROUP_1_ON && command <= UDP_GROUP_4_OFF) {
+    const MiLightStatus status = (command % 2) == 1 ? ON : OFF;
+    const uint8_t groupId = (command - UDP_GROUP_1_ON + 2)/2;
+    
+    client->updateStatus(deviceId, groupId, status);
+    
+    this->lastGroup = groupId;
+  } else if (command >= UDP_GROUP_ALL_WHITE && command <= UDP_GROUP_4_WHITE) {
+    const uint8_t groupId = (command - UDP_GROUP_ALL_WHITE)/2;
+    client->updateColorWhite(deviceId, groupId);
+    this->lastGroup = groupId;
+  } else {
+    // Group on/off
+    switch (command) {
+      case UDP_ALL_ON:
+        client->allOn(deviceId);
+        break;
+      
+      case UDP_ALL_OFF:
+        client->allOff(deviceId);
+        break;
+      
+      case UDP_COLOR:
+        client->updateColorRaw(deviceId, this->lastGroup, commandArg);
+        break;
+        
+      case UDP_DISCO_MODE:
+        pressButton(this->lastGroup, DISCO_MODE);
+        break;
+        
+      case UDP_SPEED_DOWN:
+        pressButton(this->lastGroup, SPEED_DOWN);
+        break;
+        
+      case UDP_SPEED_UP:
+        pressButton(this->lastGroup, SPEED_UP);
+        break;
+        
+      case UDP_BRIGHTNESS:
+        // map [2, 27] --> [0, 100]
+        client->updateBrightness(
+          deviceId, 
+          this->lastGroup, 
+          round(((commandArg - 2) / 25.0)*100)
+        );
+        break;
+        
+      default:
+        Serial.print("MiLightUdpServer - Unhandled command: ");
+        Serial.println(command);
+    }
+  }
+}
+
+void MiLightUdpServer::pressButton(uint8_t group, MiLightButton button) {
+  client->write(deviceId, 0, 0, group, button);
+}  

+ 58 - 0
lib/MiLight/MiLightUdpServer.h

@@ -0,0 +1,58 @@
+#include <Arduino.h>
+#include <MiLightClient.h>
+#include <WiFiUdp.h>
+
+#define MILIGHT_PACKET_BUFFER_SIZE 10
+
+#ifndef _MILIGHT_UDP_SERVER
+#define _MILIGHT_UDP_SERVER 
+
+// These are mostly a remapping of MiLightButton
+enum MiLightUdpCommands {
+  UDP_ALL_ON            = 0x41,
+  UDP_ALL_OFF           = 0x42,
+  
+  UDP_SPEED_UP          = 0x43, 
+  UDP_SPEED_DOWN        = 0x44, 
+  
+  UDP_GROUP_1_ON        = 0x45,
+  UDP_GROUP_1_OFF       = 0x46,
+  UDP_GROUP_2_ON        = 0x47,
+  UDP_GROUP_2_OFF       = 0x48,
+  UDP_GROUP_3_ON        = 0x49,
+  UDP_GROUP_3_OFF       = 0x4A,
+  UDP_GROUP_4_ON        = 0x4B,
+  UDP_GROUP_4_OFF       = 0x4C,
+  
+  UDP_DISCO_MODE        = 0x4D,
+  
+  UDP_GROUP_ALL_WHITE   = 0xC2,
+  UDP_GROUP_1_WHITE     = 0xC5,
+  UDP_GROUP_2_WHITE     = 0xC7,
+  UDP_GROUP_3_WHITE     = 0xC9,
+  UDP_GROUP_4_WHITE     = 0xCB,
+  
+  UDP_BRIGHTNESS        = 0x4E,
+  UDP_COLOR             = 0x40
+};
+
+class MiLightUdpServer {
+public:
+  MiLightUdpServer(MiLightClient*& client, uint16_t port, uint16_t deviceId);
+    
+  void begin();
+  void handleClient();
+    
+protected:
+  WiFiUDP socket;
+  MiLightClient*& client;
+  uint16_t port;
+  uint16_t deviceId;
+  uint8_t lastGroup;
+  char packetBuffer[MILIGHT_PACKET_BUFFER_SIZE];
+  
+  void handleCommand(uint8_t command, uint8_t commandArg);
+  void pressButton(uint8_t group, MiLightButton button);
+};
+
+#endif

+ 2 - 2
src/main.cpp

@@ -7,9 +7,9 @@
 #include <WebServer.h>
 #include <IntParsing.h>
 #include <Settings.h>
+#include <MiLightUdpServer.h>
 
 MiLightClient* milightClient;
-
 WiFiManager wifiManager;
 WebServer *server = new WebServer(80);
 File updateFile;
@@ -51,7 +51,7 @@ void handleUpdateGroup(const UrlTokenBindings* urlBindings) {
   }
   
   if (request.containsKey("hue")) {
-    milightClient->updateColor(deviceId, groupId, request["hue"]);
+    milightClient->updateHue(deviceId, groupId, request["hue"]);
   }
   
   if (request.containsKey("level")) {