CctPacketFormatter.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include <CctPacketFormatter.h>
  2. static const uint8_t CCT_PROTOCOL_ID = 0x5A;
  3. bool CctPacketFormatter::canHandle(const uint8_t *packet, const size_t len) {
  4. return len == packetLength && packet[0] == CCT_PROTOCOL_ID;
  5. }
  6. void CctPacketFormatter::initializePacket(uint8_t* packet) {
  7. size_t packetPtr = 0;
  8. // Byte 0: Packet length = 7 bytes
  9. // Byte 1: CCT protocol
  10. packet[packetPtr++] = CCT_PROTOCOL_ID;
  11. // Byte 2 and 3: Device ID
  12. packet[packetPtr++] = deviceId >> 8;
  13. packet[packetPtr++] = deviceId & 0xFF;
  14. // Byte 4: Zone
  15. packet[packetPtr++] = groupId;
  16. // Byte 5: Bulb command, filled in later
  17. packet[packetPtr++] = 0;
  18. // Byte 6: Packet sequence number 0..255
  19. packet[packetPtr++] = sequenceNum++;
  20. // Byte 7: Checksum over previous bytes, including packet length = 7
  21. // The checksum will be calculated when setting the command field
  22. packet[packetPtr++] = 0;
  23. // Byte 8: CRC LSB
  24. // Byte 9: CRC MSB
  25. }
  26. void CctPacketFormatter::finalizePacket(uint8_t* packet) {
  27. uint8_t checksum;
  28. // Calculate checksum over packet length .. sequenceNum
  29. checksum = 7; // Packet length is not part of packet
  30. for (uint8_t i = 0; i < 6; i++) {
  31. checksum += currentPacket[i];
  32. }
  33. // Store the checksum in the sixth byte
  34. currentPacket[6] = checksum;
  35. }
  36. void CctPacketFormatter::updateBrightness(uint8_t value) {
  37. valueByStepFunction(
  38. &PacketFormatter::increaseBrightness,
  39. &PacketFormatter::decreaseBrightness,
  40. CCT_INTERVALS,
  41. value / CCT_INTERVALS
  42. );
  43. }
  44. void CctPacketFormatter::updateTemperature(uint8_t value) {
  45. valueByStepFunction(
  46. &PacketFormatter::increaseTemperature,
  47. &PacketFormatter::decreaseTemperature,
  48. CCT_INTERVALS,
  49. value / CCT_INTERVALS
  50. );
  51. }
  52. void CctPacketFormatter::command(uint8_t command, uint8_t arg) {
  53. pushPacket();
  54. if (held) {
  55. command |= 0x80;
  56. }
  57. currentPacket[CCT_COMMAND_INDEX] = command;
  58. }
  59. void CctPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) {
  60. command(getCctStatusButton(groupId, status), 0);
  61. }
  62. void CctPacketFormatter::increaseTemperature() {
  63. command(CCT_TEMPERATURE_UP, 0);
  64. }
  65. void CctPacketFormatter::decreaseTemperature() {
  66. command(CCT_TEMPERATURE_DOWN, 0);
  67. }
  68. void CctPacketFormatter::increaseBrightness() {
  69. command(CCT_BRIGHTNESS_UP, 0);
  70. }
  71. void CctPacketFormatter::decreaseBrightness() {
  72. command(CCT_BRIGHTNESS_DOWN, 0);
  73. }
  74. void CctPacketFormatter::enableNightMode() {
  75. command(getCctStatusButton(groupId, OFF) | 0x10, 0);
  76. }
  77. uint8_t CctPacketFormatter::getCctStatusButton(uint8_t groupId, MiLightStatus status) {
  78. uint8_t button = 0;
  79. if (status == ON) {
  80. switch(groupId) {
  81. case 0:
  82. button = CCT_ALL_ON;
  83. break;
  84. case 1:
  85. button = CCT_GROUP_1_ON;
  86. break;
  87. case 2:
  88. button = CCT_GROUP_2_ON;
  89. break;
  90. case 3:
  91. button = CCT_GROUP_3_ON;
  92. break;
  93. case 4:
  94. button = CCT_GROUP_4_ON;
  95. break;
  96. }
  97. } else {
  98. switch(groupId) {
  99. case 0:
  100. button = CCT_ALL_OFF;
  101. break;
  102. case 1:
  103. button = CCT_GROUP_1_OFF;
  104. break;
  105. case 2:
  106. button = CCT_GROUP_2_OFF;
  107. break;
  108. case 3:
  109. button = CCT_GROUP_3_OFF;
  110. break;
  111. case 4:
  112. button = CCT_GROUP_4_OFF;
  113. break;
  114. }
  115. }
  116. return button;
  117. }
  118. uint8_t CctPacketFormatter::cctCommandIdToGroup(uint8_t command) {
  119. switch (command & 0xF) {
  120. case CCT_GROUP_1_ON:
  121. case CCT_GROUP_1_OFF:
  122. return 1;
  123. case CCT_GROUP_2_ON:
  124. case CCT_GROUP_2_OFF:
  125. return 2;
  126. case CCT_GROUP_3_ON:
  127. case CCT_GROUP_3_OFF:
  128. return 3;
  129. case CCT_GROUP_4_ON:
  130. case CCT_GROUP_4_OFF:
  131. return 4;
  132. case CCT_ALL_ON:
  133. case CCT_ALL_OFF:
  134. return 0;
  135. }
  136. return 255;
  137. }
  138. MiLightStatus CctPacketFormatter::cctCommandToStatus(uint8_t command) {
  139. switch (command & 0xF) {
  140. case CCT_GROUP_1_ON:
  141. case CCT_GROUP_2_ON:
  142. case CCT_GROUP_3_ON:
  143. case CCT_GROUP_4_ON:
  144. case CCT_ALL_ON:
  145. return ON;
  146. case CCT_GROUP_1_OFF:
  147. case CCT_GROUP_2_OFF:
  148. case CCT_GROUP_3_OFF:
  149. case CCT_GROUP_4_OFF:
  150. case CCT_ALL_OFF:
  151. return OFF;
  152. }
  153. }
  154. BulbId CctPacketFormatter::parsePacket(const uint8_t* packet, JsonObject& result, GroupStateStore* stateStore) {
  155. uint8_t command = packet[CCT_COMMAND_INDEX] & 0x7F;
  156. BulbId bulbId(
  157. (packet[1] << 8) | packet[2],
  158. packet[3],
  159. REMOTE_TYPE_CCT
  160. );
  161. uint8_t onOffGroupId = cctCommandIdToGroup(command);
  162. if (onOffGroupId < 255) {
  163. result["state"] = cctCommandToStatus(command) == ON ? "ON" : "OFF";
  164. } else if (command == CCT_BRIGHTNESS_DOWN) {
  165. result["command"] = "brightness_down";
  166. } else if (command == CCT_BRIGHTNESS_UP) {
  167. result["command"] = "brightness_up";
  168. } else if (command == CCT_TEMPERATURE_DOWN) {
  169. result["command"] = "temperature_down";
  170. } else if (command == CCT_TEMPERATURE_UP) {
  171. result["command"] = "temperature_up";
  172. } else {
  173. result["button_id"] = command;
  174. }
  175. return bulbId;
  176. }
  177. void CctPacketFormatter::format(uint8_t const* packet, char* buffer) {
  178. PacketFormatter::formatV1Packet(packet, buffer);
  179. }