RgbCctPacketFormatter.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include <RgbCctPacketFormatter.h>
  2. #define V2_OFFSET(byte, key) ( V2_OFFSETS[byte-1][key%4] )
  3. uint8_t const RgbCctPacketFormatter::V2_OFFSETS[][4] = {
  4. { 0x45, 0x1F, 0x14, 0x5C },
  5. { 0xAB, 0x49, 0x63, 0x91 },
  6. { 0x2D, 0x1F, 0x4A, 0xEB },
  7. { 0xAF, 0x03, 0x1D, 0xF3 },
  8. { 0x5A, 0x22, 0x30, 0x11 },
  9. { 0x04, 0xD8, 0x71, 0x42 },
  10. { 0xAF, 0x04, 0xDD, 0x07 },
  11. { 0xE1, 0x93, 0xB8, 0xE4 }
  12. };
  13. void RgbCctPacketFormatter::reset() {
  14. size_t packetPtr = 0;
  15. packet[packetPtr++] = 0x00;
  16. packet[packetPtr++] = 0x20;
  17. packet[packetPtr++] = deviceId >> 8;
  18. packet[packetPtr++] = deviceId & 0xFF;
  19. packet[packetPtr++] = 0;
  20. packet[packetPtr++] = 0;
  21. packet[packetPtr++] = sequenceNum++;
  22. packet[packetPtr++] = groupId;
  23. packet[packetPtr++] = 0;
  24. }
  25. void RgbCctPacketFormatter::command(uint8_t command, uint8_t arg) {
  26. packet[RGB_CCT_COMMAND_INDEX] = command;
  27. packet[RGB_CCT_ARGUMENT_INDEX] = arg;
  28. }
  29. void RgbCctPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) {
  30. command(RGB_CCT_ON, 0xC0 + groupId + (status == OFF ? 5 : 0));
  31. }
  32. void RgbCctPacketFormatter::updateBrightness(uint8_t brightness) {
  33. command(RGB_CCT_BRIGHTNESS, 0x4F + brightness);
  34. }
  35. void RgbCctPacketFormatter::updateHue(uint16_t value) {
  36. const int16_t remappedColor = (value + 20) % 360;
  37. updateColorRaw(rescale(remappedColor, 255, 360));
  38. }
  39. void RgbCctPacketFormatter::updateColorRaw(uint8_t value) {
  40. command(RGB_CCT_COLOR, 0x15 + value);
  41. }
  42. void RgbCctPacketFormatter::updateTemperature(uint8_t value) {
  43. command(RGB_CCT_KELVIN, (0x4C + value)*2);
  44. }
  45. void RgbCctPacketFormatter::updateSaturation(uint8_t value) {
  46. command(RGB_CCT_SATURATION, value - 0x33);
  47. }
  48. void RgbCctPacketFormatter::updateColorWhite() {
  49. updateTemperature(0);
  50. }
  51. uint8_t* RgbCctPacketFormatter::buildPacket() {
  52. encodeV2Packet(packet);
  53. return packet;
  54. }
  55. uint8_t RgbCctPacketFormatter::xorKey(uint8_t key) {
  56. // Generate most significant nibble
  57. const uint8_t shift = (key & 0x0F) < 0x04 ? 0 : 1;
  58. const uint8_t x = (((key & 0xF0) >> 4) + shift + 6) % 8;
  59. const uint8_t msn = (((4 + x) ^ 1) & 0x0F) << 4;
  60. // Generate least significant nibble
  61. const uint8_t lsn = ((((key & 0xF) + 4)^2) & 0x0F);
  62. return ( msn | lsn );
  63. }
  64. uint8_t RgbCctPacketFormatter::encodeByte(uint8_t byte, uint8_t s1, uint8_t xorKey, uint8_t s2) {
  65. uint8_t value = (byte + s1) % 0x100;
  66. value = value ^ xorKey;
  67. value = (value + s2) % 0x100;
  68. return value;
  69. }
  70. void RgbCctPacketFormatter::encodeV2Packet(uint8_t *packet) {
  71. uint8_t key = xorKey(packet[0]);
  72. uint8_t sum = key;
  73. printf("Packet: ");
  74. for (size_t i = 0; i < 9; i++) {
  75. printf("%02X ", packet[i]);
  76. }
  77. printf("\n");
  78. for (size_t i = 1; i <= 7; i++) {
  79. sum += packet[i];
  80. packet[i] = encodeByte(packet[i], 0, key, V2_OFFSET(i, packet[0]));
  81. }
  82. packet[8] = encodeByte(sum, 2, key, V2_OFFSET(8, packet[0]));
  83. }