Explorar el Código

Merge pull request #43 from sidoh/held_commands

Trickle whether a button is held in UDP to RF packets
Chris Mullins hace 8 años
padre
commit
f348bcfd94

+ 9 - 6
lib/MiLight/CctPacketFormatter.cpp

@@ -3,7 +3,7 @@
 
 void CctPacketFormatter::initializePacket(uint8_t* packet) {
   size_t packetPtr = 0;
-  
+
   packet[packetPtr++] = CCT;
   packet[packetPtr++] = deviceId >> 8;
   packet[packetPtr++] = deviceId & 0xFF;
@@ -30,16 +30,19 @@ void CctPacketFormatter::updateTemperature(uint8_t value) {
     value / CCT_INTERVALS
   );
 }
-  
+
 void CctPacketFormatter::command(uint8_t command, uint8_t arg) {
   pushPacket();
+  if (held) {
+    command |= 0x80;
+  }
   currentPacket[CCT_COMMAND_INDEX] = command;
 }
 
 void CctPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) {
   command(getCctStatusButton(groupId, status), 0);
 }
-  
+
 void CctPacketFormatter::increaseTemperature() {
   command(CCT_TEMPERATURE_UP, 0);
 }
@@ -58,7 +61,7 @@ void CctPacketFormatter::decreaseBrightness() {
 
 uint8_t CctPacketFormatter::getCctStatusButton(uint8_t groupId, MiLightStatus status) {
   uint8_t button = 0;
-  
+
   if (status == ON) {
     switch(groupId) {
       case 1:
@@ -90,10 +93,10 @@ uint8_t CctPacketFormatter::getCctStatusButton(uint8_t groupId, MiLightStatus st
         break;
     }
   }
-  
+
   return button;
 }
 
 void CctPacketFormatter::format(uint8_t const* packet, char* buffer) {
   PacketFormatter::formatV1Packet(packet, buffer);
-}
+}

+ 4 - 0
lib/MiLight/MiLightClient.cpp

@@ -23,6 +23,10 @@ void MiLightClient::begin() {
   }
 }
 
+void MiLightClient::setHeld(bool held) {
+  formatter->setHeld(held);
+}
+
 MiLightRadio* MiLightClient::switchRadio(const MiLightRadioType type) {
   MiLightRadio* radio = NULL;
 

+ 2 - 0
lib/MiLight/MiLightClient.h

@@ -27,6 +27,8 @@ public:
   void read(uint8_t packet[]);
   void write(uint8_t packet[]);
 
+  void setHeld(bool held);
+
   // Common methods
   void updateStatus(MiLightStatus status);
   void updateStatus(MiLightStatus status, uint8_t groupId);

+ 24 - 18
lib/MiLight/PacketFormatter.cpp

@@ -7,8 +7,8 @@ PacketStream::PacketStream()
       numPackets(0),
       packetLength(0),
       currentPacket(0)
-  { }
-  
+{ }
+
 bool PacketStream::hasNext() {
   return currentPacket < numPackets;
 }
@@ -22,18 +22,23 @@ uint8_t* PacketStream::next() {
 PacketFormatter::PacketFormatter(const size_t packetLength, const size_t maxPackets)
   : packetLength(packetLength),
     numPackets(0),
-    currentPacket(NULL)
-{ 
+    currentPacket(NULL),
+    held(false)
+{
   packetStream.packetLength = packetLength;
   packetStream.packetStream = PACKET_BUFFER;
 }
-  
+
 void PacketFormatter::finalizePacket(uint8_t* packet) { }
-  
-void PacketFormatter::updateStatus(MiLightStatus status) { 
+
+void PacketFormatter::updateStatus(MiLightStatus status) {
   updateStatus(status, groupId);
 }
 
+void PacketFormatter::setHeld(bool held) {
+  this->held = held;
+}
+
 void PacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) { }
 void PacketFormatter::updateBrightness(uint8_t value) { }
 void PacketFormatter::updateMode(uint8_t value) { }
@@ -54,33 +59,33 @@ void PacketFormatter::decreaseBrightness() { }
 
 void PacketFormatter::updateTemperature(uint8_t value) { }
 void PacketFormatter::updateSaturation(uint8_t value) { }
-  
-void PacketFormatter::pair() { 
+
+void PacketFormatter::pair() {
   for (size_t i = 0; i < 5; i++) {
     updateStatus(ON);
   }
 }
 
-void PacketFormatter::unpair() { 
+void PacketFormatter::unpair() {
   pair();
 }
-  
+
 PacketStream& PacketFormatter::buildPackets() {
   if (numPackets > 0) {
     finalizePacket(currentPacket);
   }
-  
+
   packetStream.numPackets = numPackets;
   packetStream.currentPacket = 0;
-  
+
   return packetStream;
 }
-  
+
 void PacketFormatter::valueByStepFunction(StepFunction increase, StepFunction decrease, uint8_t numSteps, uint8_t value) {
   for (size_t i = 0; i < numSteps; i++) {
     (this->*decrease)();
   }
-  
+
   for (size_t i = 0; i < value; i++) {
     (this->*increase)();
   }
@@ -95,13 +100,14 @@ void PacketFormatter::prepare(uint16_t deviceId, uint8_t groupId) {
 void PacketFormatter::reset() {
   this->numPackets = 0;
   this->currentPacket = currentPacket;
+  this->held = false;
 }
 
 void PacketFormatter::pushPacket() {
   if (numPackets > 0) {
     finalizePacket(currentPacket);
   }
-  
+
   currentPacket = PACKET_BUFFER + (numPackets * packetLength);
   numPackets++;
   initializePacket(currentPacket);
@@ -123,7 +129,7 @@ void PacketFormatter::formatV1Packet(uint8_t const* packet, char* buffer) {
   buffer += sprintf_P(buffer, "b3            : %02X\n", packet[5]);
   buffer += sprintf_P(buffer, "Sequence Num. : %02X", packet[6]);
 }
-  
+
 size_t PacketFormatter::getPacketLength() const {
   return packetLength;
-}
+}

+ 23 - 20
lib/MiLight/PacketFormatter.h

@@ -6,14 +6,14 @@
 #define PACKET_FORMATTER_BUFFER_SIZE 48
 
 #ifndef _PACKET_FORMATTER_H
-#define _PACKET_FORMATTER_H 
+#define _PACKET_FORMATTER_H
 
 struct PacketStream {
   PacketStream();
-  
+
   uint8_t* next();
   bool hasNext();
-  
+
   uint8_t* packetStream;
   size_t numPackets;
   size_t packetLength;
@@ -23,69 +23,72 @@ struct PacketStream {
 class PacketFormatter {
 public:
   PacketFormatter(const size_t packetLength, const size_t maxPackets = 1);
-  
+
   typedef void (PacketFormatter::*StepFunction)();
-  
+
   void updateStatus(MiLightStatus status);
   virtual void updateStatus(MiLightStatus status, uint8_t groupId);
   virtual void command(uint8_t command, uint8_t arg);
-  
+
+  virtual void setHeld(bool held);
+
   // Mode
   virtual void updateMode(uint8_t value);
   virtual void modeSpeedDown();
   virtual void modeSpeedUp();
   virtual void nextMode();
   virtual void previousMode();
-  
+
   virtual void pair();
   virtual void unpair();
-  
+
   // Color
   virtual void updateHue(uint16_t value);
   virtual void updateColorRaw(uint8_t value);
   virtual void updateColorWhite();
-  
+
   // White temperature
   virtual void increaseTemperature();
   virtual void decreaseTemperature();
   virtual void updateTemperature(uint8_t value);
-  
+
   // Brightness
   virtual void updateBrightness(uint8_t value);
   virtual void increaseBrightness();
   virtual void decreaseBrightness();
-  
+
   virtual void updateSaturation(uint8_t value);
-  
+
   virtual void reset();
-  
+
   virtual PacketStream& buildPackets();
   virtual void prepare(uint16_t deviceId, uint8_t groupId);
   virtual void format(uint8_t const* packet, char* buffer);
-  
+
   static void formatV1Packet(uint8_t const* packet, char* buffer);
-  
+
   template <typename T>
   static T rescale(T value, uint8_t newMax, float oldMax = 255.0) {
     return round(value * (newMax / oldMax));
   }
-  
+
   size_t getPacketLength() const;
-  
+
 protected:
   static uint8_t* PACKET_BUFFER;
-  
+
   uint8_t* currentPacket;
   size_t packetLength;
   uint16_t deviceId;
   uint8_t groupId;
   uint8_t sequenceNum;
   size_t numPackets;
+  bool held;
   PacketStream packetStream;
-  
+
   void pushPacket();
   void valueByStepFunction(StepFunction increase, StepFunction decrease, uint8_t numSteps, uint8_t value);
-  
+
   virtual void initializePacket(uint8_t* packetStart) = 0;
   virtual void finalizePacket(uint8_t* packet);
 };

+ 20 - 17
lib/MiLight/RgbCctPacketFormatter.cpp

@@ -19,10 +19,10 @@ uint8_t const RgbCctPacketFormatter::V2_OFFSETS[][4] = {
 
 void RgbCctPacketFormatter::initializePacket(uint8_t* packet) {
   size_t packetPtr = 0;
-  
+
   // Always encode with 0x00 key. No utility in varying it.
   packet[packetPtr++] = 0x00;
-  
+
   packet[packetPtr++] = 0x20;
   packet[packetPtr++] = deviceId >> 8;
   packet[packetPtr++] = deviceId & 0xFF;
@@ -33,14 +33,17 @@ void RgbCctPacketFormatter::initializePacket(uint8_t* packet) {
   packet[packetPtr++] = 0;
 }
 
-void RgbCctPacketFormatter::unpair() { 
+void RgbCctPacketFormatter::unpair() {
   for (size_t i = 0; i < 5; i++) {
     updateStatus(ON, 0);
   }
 }
-  
+
 void RgbCctPacketFormatter::command(uint8_t command, uint8_t arg) {
   pushPacket();
+  if (held) {
+    command |= 0x80;
+  }
   currentPacket[RGB_CCT_COMMAND_INDEX] = command;
   currentPacket[RGB_CCT_ARGUMENT_INDEX] = arg;
 }
@@ -48,7 +51,7 @@ void RgbCctPacketFormatter::command(uint8_t command, uint8_t arg) {
 void RgbCctPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) {
   command(RGB_CCT_ON, groupId + (status == OFF ? 5 : 0));
 }
-  
+
 void RgbCctPacketFormatter::modeSpeedDown() {
   command(RGB_CCT_ON, RGB_CCT_MODE_SPEED_DOWN);
 }
@@ -73,7 +76,7 @@ void RgbCctPacketFormatter::previousMode() {
 void RgbCctPacketFormatter::updateBrightness(uint8_t brightness) {
   command(RGB_CCT_BRIGHTNESS, 0x8F + brightness);
 }
-  
+
 void RgbCctPacketFormatter::updateHue(uint16_t value) {
   uint8_t remapped = rescale(value, 255, 360);
   updateColorRaw(remapped);
@@ -82,7 +85,7 @@ void RgbCctPacketFormatter::updateHue(uint16_t value) {
 void RgbCctPacketFormatter::updateColorRaw(uint8_t value) {
   command(RGB_CCT_COLOR, 0x5F + value);
 }
-  
+
 void RgbCctPacketFormatter::updateTemperature(uint8_t value) {
   command(RGB_CCT_KELVIN, 0x94 - (value*2));
 }
@@ -91,11 +94,11 @@ void RgbCctPacketFormatter::updateSaturation(uint8_t value) {
   uint8_t remapped = value + 0xD;
   command(RGB_CCT_SATURATION, remapped);
 }
-  
+
 void RgbCctPacketFormatter::updateColorWhite() {
   updateTemperature(0);
 }
-  
+
 void RgbCctPacketFormatter::finalizePacket(uint8_t* packet) {
   encodeV2Packet(packet);
 }
@@ -116,7 +119,7 @@ uint8_t RgbCctPacketFormatter::decodeByte(uint8_t byte, uint8_t s1, uint8_t xorK
   uint8_t value = byte - s2;
   value = value ^ xorKey;
   value = value - s1;
-  
+
   return value;
 }
 
@@ -124,13 +127,13 @@ uint8_t RgbCctPacketFormatter::encodeByte(uint8_t byte, uint8_t s1, uint8_t xorK
   uint8_t value = byte + s1;
   value = value ^ xorKey;
   value = value + s2;
-  
+
   return value;
 }
 
 void RgbCctPacketFormatter::decodeV2Packet(uint8_t *packet) {
   uint8_t key = xorKey(packet[0]);
-  
+
   for (size_t i = 1; i <= 8; i++) {
     packet[i] = decodeByte(packet[i], 0, key, V2_OFFSET(i, packet[0], V2_OFFSET_JUMP_START));
   }
@@ -139,12 +142,12 @@ void RgbCctPacketFormatter::decodeV2Packet(uint8_t *packet) {
 void RgbCctPacketFormatter::encodeV2Packet(uint8_t *packet) {
   uint8_t key = xorKey(packet[0]);
   uint8_t sum = key;
-  
+
   for (size_t i = 1; i <= 7; i++) {
     sum += packet[i];
     packet[i] = encodeByte(packet[i], 0, key, V2_OFFSET(i, packet[0], V2_OFFSET_JUMP_START));
   }
-  
+
   packet[8] = encodeByte(sum, 2, key, V2_OFFSET(8, packet[0], 0));
 }
 
@@ -153,12 +156,12 @@ void RgbCctPacketFormatter::format(uint8_t const* packet, char* buffer) {
   for (int i = 0; i < packetLength; i++) {
     buffer += sprintf_P(buffer, PSTR("%02X "), packet[i]);
   }
-  
+
   uint8_t decodedPacket[packetLength];
   memcpy(decodedPacket, packet, packetLength);
-  
+
   decodeV2Packet(decodedPacket);
-  
+
   buffer += sprintf_P(buffer, PSTR("\n\nDecoded:\n"));
   buffer += sprintf_P(buffer, PSTR("Key      : %02X\n"), decodedPacket[0]);
   buffer += sprintf_P(buffer, PSTR("b1       : %02X\n"), decodedPacket[1]);

+ 10 - 7
lib/MiLight/RgbPacketFormatter.cpp

@@ -2,7 +2,7 @@
 
 void RgbPacketFormatter::initializePacket(uint8_t *packet) {
   size_t packetPtr = 0;
-  
+
   packet[packetPtr++] = RGB;
   packet[packetPtr++] = deviceId >> 8;
   packet[packetPtr++] = deviceId & 0xFF;
@@ -11,13 +11,13 @@ void RgbPacketFormatter::initializePacket(uint8_t *packet) {
   packet[packetPtr++] = sequenceNum++;
 }
 
-void RgbPacketFormatter::pair() { 
+void RgbPacketFormatter::pair() {
   for (size_t i = 0; i < 5; i++) {
     command(RGB_SPEED_UP, 0);
   }
 }
 
-void RgbPacketFormatter::unpair() { 
+void RgbPacketFormatter::unpair() {
   for (size_t i = 0; i < 5; i++) {
     command(RGB_SPEED_UP | 0x10, 0);
   }
@@ -29,9 +29,12 @@ void RgbPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) {
 
 void RgbPacketFormatter::command(uint8_t command, uint8_t arg) {
   pushPacket();
+  if (held) {
+    command |= 0x80;
+  }
   currentPacket[RGB_COMMAND_INDEX] = command;
 }
-  
+
 void RgbPacketFormatter::updateHue(uint16_t value) {
   const int16_t remappedColor = (value + 40) % 360;
   updateColorRaw(rescale(remappedColor, 255, 360));
@@ -58,11 +61,11 @@ void RgbPacketFormatter::increaseBrightness() {
 void RgbPacketFormatter::decreaseBrightness() {
   command(RGB_BRIGHTNESS_DOWN, 0);
 }
-  
+
 void RgbPacketFormatter::modeSpeedDown() {
   command(RGB_SPEED_DOWN, 0);
 }
- 
+
 void RgbPacketFormatter::modeSpeedUp() {
   command(RGB_SPEED_UP, 0);
 }
@@ -81,4 +84,4 @@ void RgbPacketFormatter::format(uint8_t const* packet, char* buffer) {
   buffer += sprintf_P(buffer, "Color    : %02X\n", packet[3]);
   buffer += sprintf_P(buffer, "Command  : %02X\n", packet[4]);
   buffer += sprintf_P(buffer, "Sequence : %02X\n", packet[5]);
-}
+}

+ 10 - 7
lib/MiLight/RgbwPacketFormatter.cpp

@@ -3,7 +3,7 @@
 
 void RgbwPacketFormatter::initializePacket(uint8_t* packet) {
   size_t packetPtr = 0;
-  
+
   packet[packetPtr++] = RGBW;
   packet[packetPtr++] = deviceId >> 8;
   packet[packetPtr++] = deviceId & 0xFF;
@@ -13,11 +13,11 @@ void RgbwPacketFormatter::initializePacket(uint8_t* packet) {
   packet[packetPtr++] = sequenceNum++;
 }
 
-void RgbwPacketFormatter::unpair() { 
+void RgbwPacketFormatter::unpair() {
   PacketFormatter::updateStatus(ON);
   updateColorWhite();
 }
-  
+
 void RgbwPacketFormatter::modeSpeedDown() {
   command(RGBW_SPEED_DOWN, 0);
 }
@@ -39,7 +39,7 @@ void RgbwPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) {
   uint8_t button = RGBW_GROUP_1_ON + ((groupId - 1)*2) + status;
   command(button, 0);
 }
-  
+
 void RgbwPacketFormatter::updateBrightness(uint8_t value) {
   // Expect an input value in [0, 100]. Map it down to [0, 25].
   const uint8_t adjustedBrightness = rescale(value, 25, 100);
@@ -49,16 +49,19 @@ void RgbwPacketFormatter::updateBrightness(uint8_t value) {
   const uint8_t packetBrightnessValue = (
     ((31 - adjustedBrightness) + 17) % 32
   );
-  
+
   command(RGBW_BRIGHTNESS, 0);
   currentPacket[RGBW_BRIGHTNESS_GROUP_INDEX] |= (packetBrightnessValue << 3);
 }
 
 void RgbwPacketFormatter::command(uint8_t command, uint8_t arg) {
   pushPacket();
+  if (held) {
+    command |= 0x80;
+  }
   currentPacket[RGBW_COMMAND_INDEX] = command;
 }
-  
+
 void RgbwPacketFormatter::updateHue(uint16_t value) {
   const int16_t remappedColor = (value + 40) % 360;
   updateColorRaw(rescale(remappedColor, 255, 360));
@@ -76,4 +79,4 @@ void RgbwPacketFormatter::updateColorWhite() {
 
 void RgbwPacketFormatter::format(uint8_t const* packet, char* buffer) {
   PacketFormatter::formatV1Packet(packet, buffer);
-}
+}

+ 3 - 1
lib/Udp/V6CctCommandHandler.cpp

@@ -13,9 +13,11 @@ bool V6CctCommandHandler::handleCommand(
     uint32_t command,
     uint32_t commandArg)
 {
-  const uint8_t cmd = command & 0xFF;
+  const uint8_t cmd = command & 0x7F;
   const uint8_t arg = commandArg >> 24;
 
+  client->setHeld((command & 0x80) == 0x80);
+
   if (cmd == V2_CCT_COMMAND_PREFIX) {
     switch (arg) {
       case V2_CCT_ON:

+ 3 - 1
lib/Udp/V6RgbCctCommandHandler.cpp

@@ -31,9 +31,11 @@ bool V6RgbCctCommandHandler::handleCommand(
     uint32_t command,
     uint32_t commandArg)
 {
-  const uint8_t cmd = command & 0xFF;
+  const uint8_t cmd = command & 0x7F;
   const uint8_t arg = commandArg >> 24;
 
+  client->setHeld((command & 0x80) == 0x80);
+
   if (cmd == V2_STATUS) {
     switch (arg) {
       case V2_RGB_CCT_ON:

+ 3 - 1
lib/Udp/V6RgbCommandHandler.cpp

@@ -12,9 +12,11 @@ bool V6RgbCommandHandler::handleCommand(
     uint32_t command,
     uint32_t commandArg)
 {
-  const uint8_t cmd = command & 0xFF;
+  const uint8_t cmd = command & 0x7F;
   const uint8_t arg = commandArg >> 24;
 
+  client->setHeld((command & 0x80) == 0x80);
+
   if (cmd == V2_RGB_COMMAND_PREFIX) {
     switch (arg) {
       case V2_RGB_ON:

+ 3 - 1
lib/Udp/V6RgbwCommandHandler.cpp

@@ -23,9 +23,11 @@ bool V6RgbwCommandHandler::handleCommand(
     uint32_t command,
     uint32_t commandArg)
 {
-  const uint8_t cmd = command & 0xFF;
+  const uint8_t cmd = command & 0x7F;
   const uint8_t arg = commandArg >> 24;
 
+  client->setHeld((command & 0x80) == 0x80);
+
   if (cmd == V2_RGBW_COMMAND_PREFIX) {
     switch (arg) {
       case V2_RGBW_ON: