RgbCctPacketFormatter.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include <RgbCctPacketFormatter.h>
  2. #include <Units.h>
  3. #include <V2RFEncoding.h>
  4. #define GROUP_COMMAND_ARG(status, groupId) ( groupId + (status == OFF ? 5 : 0) )
  5. void RgbCctPacketFormatter::initializePacket(uint8_t* packet) {
  6. size_t packetPtr = 0;
  7. // Always encode with 0x00 key. No utility in varying it.
  8. packet[packetPtr++] = 0x00;
  9. packet[packetPtr++] = 0x20;
  10. packet[packetPtr++] = deviceId >> 8;
  11. packet[packetPtr++] = deviceId & 0xFF;
  12. packet[packetPtr++] = 0;
  13. packet[packetPtr++] = 0;
  14. packet[packetPtr++] = sequenceNum++;
  15. packet[packetPtr++] = groupId;
  16. packet[packetPtr++] = 0;
  17. }
  18. void RgbCctPacketFormatter::unpair() {
  19. for (size_t i = 0; i < 5; i++) {
  20. updateStatus(ON, 0);
  21. }
  22. }
  23. void RgbCctPacketFormatter::command(uint8_t command, uint8_t arg) {
  24. pushPacket();
  25. if (held) {
  26. command |= 0x80;
  27. }
  28. currentPacket[RGB_CCT_COMMAND_INDEX] = command;
  29. currentPacket[RGB_CCT_ARGUMENT_INDEX] = arg;
  30. }
  31. void RgbCctPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) {
  32. command(RGB_CCT_ON, GROUP_COMMAND_ARG(status, groupId));
  33. }
  34. void RgbCctPacketFormatter::modeSpeedDown() {
  35. command(RGB_CCT_ON, RGB_CCT_MODE_SPEED_DOWN);
  36. }
  37. void RgbCctPacketFormatter::modeSpeedUp() {
  38. command(RGB_CCT_ON, RGB_CCT_MODE_SPEED_UP);
  39. }
  40. void RgbCctPacketFormatter::updateMode(uint8_t mode) {
  41. lastMode = mode;
  42. command(RGB_CCT_MODE, mode);
  43. }
  44. void RgbCctPacketFormatter::nextMode() {
  45. updateMode((lastMode+1)%RGB_CCT_NUM_MODES);
  46. }
  47. void RgbCctPacketFormatter::previousMode() {
  48. updateMode((lastMode-1)%RGB_CCT_NUM_MODES);
  49. }
  50. void RgbCctPacketFormatter::updateBrightness(uint8_t brightness) {
  51. command(RGB_CCT_BRIGHTNESS, RGB_CCT_BRIGHTNESS_OFFSET + brightness);
  52. }
  53. void RgbCctPacketFormatter::updateHue(uint16_t value) {
  54. uint8_t remapped = Units::rescale(value, 255, 360);
  55. updateColorRaw(remapped);
  56. }
  57. void RgbCctPacketFormatter::updateColorRaw(uint8_t value) {
  58. command(RGB_CCT_COLOR, RGB_CCT_COLOR_OFFSET + value);
  59. }
  60. void RgbCctPacketFormatter::updateTemperature(uint8_t value) {
  61. command(RGB_CCT_KELVIN, RGB_CCT_KELVIN_OFFSET - (value*2));
  62. }
  63. void RgbCctPacketFormatter::updateSaturation(uint8_t value) {
  64. uint8_t remapped = value + RGB_CCT_SATURATION_OFFSET;
  65. command(RGB_CCT_SATURATION, remapped);
  66. }
  67. void RgbCctPacketFormatter::updateColorWhite() {
  68. updateTemperature(0);
  69. }
  70. void RgbCctPacketFormatter::enableNightMode() {
  71. uint8_t arg = GROUP_COMMAND_ARG(OFF, groupId);
  72. command(RGB_CCT_ON | 0x80, arg);
  73. }
  74. void RgbCctPacketFormatter::finalizePacket(uint8_t* packet) {
  75. V2RFEncoding::encodeV2Packet(packet);
  76. }
  77. void RgbCctPacketFormatter::parsePacket(const uint8_t *packet, JsonObject& result) {
  78. uint8_t packetCopy[RGB_CCT_PACKET_LEN];
  79. memcpy(packetCopy, packet, RGB_CCT_PACKET_LEN);
  80. V2RFEncoding::decodeV2Packet(packetCopy);
  81. result["device_id"] = (packetCopy[2] << 8) | packetCopy[3];
  82. result["group_id"] = packetCopy[7];
  83. result["device_type"] = "rgb_cct";
  84. uint8_t command = (packetCopy[RGB_CCT_COMMAND_INDEX] & 0x7F);
  85. uint8_t arg = packetCopy[RGB_CCT_ARGUMENT_INDEX];
  86. if (command == RGB_CCT_ON) {
  87. if (arg == RGB_CCT_MODE_SPEED_DOWN) {
  88. result["command"] = "mode_speed_down";
  89. } else if (arg == RGB_CCT_MODE_SPEED_UP) {
  90. result["command"] = "mode_speed_up";
  91. } else if (arg < 5) { // Group is not reliably encoded in group byte. Extract from arg byte
  92. result["state"] = "ON";
  93. result["group_id"] = arg;
  94. } else {
  95. result["state"] = "OFF";
  96. result["group_id"] = arg-5;
  97. }
  98. } else if (command == RGB_CCT_COLOR) {
  99. uint8_t rescaledColor = (arg - RGB_CCT_COLOR_OFFSET) % 0x100;
  100. uint16_t hue = Units::rescale<uint16_t, uint16_t>(rescaledColor, 360, 255.0);
  101. result["hue"] = hue;
  102. } else if (command == RGB_CCT_KELVIN) {
  103. uint8_t temperature =
  104. static_cast<uint8_t>(
  105. // Range in packets is 180 - 220 or something like that. Shift to
  106. // 0..224. Then strip out values out of range [0..24), and (224..255]
  107. constrain(
  108. static_cast<uint8_t>(arg + RGB_CCT_KELVIN_REMOTE_OFFSET),
  109. 24,
  110. 224
  111. )
  112. +
  113. // Shift 24 down to 0
  114. RGB_CCT_KELVIN_REMOTE_START
  115. )/2; // values are in increments of 2
  116. result["color_temp"] = Units::whiteValToMireds(temperature, 100);
  117. // brightness == saturation
  118. } else if (command == RGB_CCT_BRIGHTNESS && arg >= (RGB_CCT_BRIGHTNESS_OFFSET - 15)) {
  119. uint8_t level = constrain(arg - RGB_CCT_BRIGHTNESS_OFFSET, 0, 100);
  120. result["brightness"] = Units::rescale<uint8_t, uint8_t>(level, 255, 100);
  121. } else if (command == RGB_CCT_SATURATION) {
  122. result["saturation"] = constrain(arg - RGB_CCT_SATURATION_OFFSET, 0, 100);
  123. } else if (command == RGB_CCT_MODE) {
  124. result["mode"] = arg;
  125. } else {
  126. result["button_id"] = command;
  127. result["argument"] = arg;
  128. }
  129. if (! result.containsKey("state")) {
  130. result["state"] = "ON";
  131. }
  132. }
  133. void RgbCctPacketFormatter::format(uint8_t const* packet, char* buffer) {
  134. buffer += sprintf_P(buffer, PSTR("Raw packet: "));
  135. for (int i = 0; i < packetLength; i++) {
  136. buffer += sprintf_P(buffer, PSTR("%02X "), packet[i]);
  137. }
  138. uint8_t decodedPacket[packetLength];
  139. memcpy(decodedPacket, packet, packetLength);
  140. V2RFEncoding::decodeV2Packet(decodedPacket);
  141. buffer += sprintf_P(buffer, PSTR("\n\nDecoded:\n"));
  142. buffer += sprintf_P(buffer, PSTR("Key : %02X\n"), decodedPacket[0]);
  143. buffer += sprintf_P(buffer, PSTR("b1 : %02X\n"), decodedPacket[1]);
  144. buffer += sprintf_P(buffer, PSTR("ID : %02X%02X\n"), decodedPacket[2], decodedPacket[3]);
  145. buffer += sprintf_P(buffer, PSTR("Command : %02X\n"), decodedPacket[4]);
  146. buffer += sprintf_P(buffer, PSTR("Argument : %02X\n"), decodedPacket[5]);
  147. buffer += sprintf_P(buffer, PSTR("Sequence : %02X\n"), decodedPacket[6]);
  148. buffer += sprintf_P(buffer, PSTR("Group : %02X\n"), decodedPacket[7]);
  149. buffer += sprintf_P(buffer, PSTR("Checksum : %02X"), decodedPacket[8]);
  150. }