FUT089PacketFormatter.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include <FUT089PacketFormatter.h>
  2. #include <V2RFEncoding.h>
  3. #include <Units.h>
  4. void FUT089PacketFormatter::modeSpeedDown() {
  5. command(FUT089_ON, FUT089_MODE_SPEED_DOWN);
  6. }
  7. void FUT089PacketFormatter::modeSpeedUp() {
  8. command(FUT089_ON, FUT089_MODE_SPEED_UP);
  9. }
  10. void FUT089PacketFormatter::updateMode(uint8_t mode) {
  11. command(FUT089_MODE, mode);
  12. }
  13. void FUT089PacketFormatter::updateBrightness(uint8_t brightness) {
  14. command(FUT089_BRIGHTNESS, brightness);
  15. }
  16. // change the hue (which may also change to color mode).
  17. void FUT089PacketFormatter::updateHue(uint16_t value) {
  18. uint8_t remapped = Units::rescale(value, 255, 360);
  19. updateColorRaw(remapped);
  20. }
  21. void FUT089PacketFormatter::updateColorRaw(uint8_t value) {
  22. command(FUT089_COLOR, FUT089_COLOR_OFFSET + value);
  23. }
  24. // change the temperature (kelvin). Note that temperature and saturation share the same command
  25. // number (7), and they change which they do based on the mode of the lamp (white vs. color mode).
  26. // To make this command work, we need to switch to white mode, make the change, and then flip
  27. // back to the original mode.
  28. void FUT089PacketFormatter::updateTemperature(uint8_t value) {
  29. // look up our current mode
  30. const GroupState* ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_FUT089);
  31. BulbMode originalBulbMode;
  32. if (ourState != NULL) {
  33. originalBulbMode = ourState->getBulbMode();
  34. // are we already in white? If not, change to white
  35. if (originalBulbMode != BulbMode::BULB_MODE_WHITE) {
  36. updateColorWhite();
  37. }
  38. }
  39. // now make the temperature change
  40. command(FUT089_KELVIN, 100 - value);
  41. // and return to our original mode
  42. if (ourState != NULL && (settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_WHITE)) {
  43. switchMode(*ourState, originalBulbMode);
  44. }
  45. }
  46. // change the saturation. Note that temperature and saturation share the same command
  47. // number (7), and they change which they do based on the mode of the lamp (white vs. color mode).
  48. // Therefore, if we are not in color mode, we need to switch to color mode, make the change,
  49. // and switch back to the original mode.
  50. void FUT089PacketFormatter::updateSaturation(uint8_t value) {
  51. // look up our current mode
  52. const GroupState* ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_FUT089);
  53. BulbMode originalBulbMode = BulbMode::BULB_MODE_WHITE;
  54. if (ourState != NULL) {
  55. originalBulbMode = ourState->getBulbMode();
  56. }
  57. // are we already in color? If not, we need to flip modes
  58. if (ourState != NULL && (settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_COLOR)) {
  59. updateHue(ourState->getHue());
  60. }
  61. // now make the saturation change
  62. command(FUT089_SATURATION, 100 - value);
  63. // and revert back if necessary
  64. if (ourState != NULL && (settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_COLOR)) {
  65. switchMode(*ourState, originalBulbMode);
  66. }
  67. }
  68. void FUT089PacketFormatter::updateColorWhite() {
  69. command(FUT089_ON, FUT089_WHITE_MODE);
  70. }
  71. void FUT089PacketFormatter::enableNightMode() {
  72. uint8_t arg = groupCommandArg(OFF, groupId);
  73. command(FUT089_ON | 0x80, arg);
  74. }
  75. BulbId FUT089PacketFormatter::parsePacket(const uint8_t *packet, JsonObject result) {
  76. if (stateStore == NULL) {
  77. Serial.println(F("ERROR: stateStore not set. Prepare was not called! **THIS IS A BUG**"));
  78. BulbId fakeId(0, 0, REMOTE_TYPE_FUT089);
  79. return fakeId;
  80. }
  81. uint8_t packetCopy[V2_PACKET_LEN];
  82. memcpy(packetCopy, packet, V2_PACKET_LEN);
  83. V2RFEncoding::decodeV2Packet(packetCopy);
  84. BulbId bulbId(
  85. (packetCopy[2] << 8) | packetCopy[3],
  86. packetCopy[7],
  87. REMOTE_TYPE_FUT089
  88. );
  89. uint8_t command = (packetCopy[V2_COMMAND_INDEX] & 0x7F);
  90. uint8_t arg = packetCopy[V2_ARGUMENT_INDEX];
  91. if (command == FUT089_ON) {
  92. if ((packetCopy[V2_COMMAND_INDEX] & 0x80) == 0x80) {
  93. result["command"] = "night_mode";
  94. } else if (arg == FUT089_MODE_SPEED_DOWN) {
  95. result["command"] = "mode_speed_down";
  96. } else if (arg == FUT089_MODE_SPEED_UP) {
  97. result["command"] = "mode_speed_up";
  98. } else if (arg == FUT089_WHITE_MODE) {
  99. result["command"] = "set_white";
  100. } else if (arg <= 8) { // Group is not reliably encoded in group byte. Extract from arg byte
  101. result["state"] = "ON";
  102. bulbId.groupId = arg;
  103. } else if (arg >= 9 && arg <= 17) {
  104. result["state"] = "OFF";
  105. bulbId.groupId = arg-9;
  106. }
  107. } else if (command == FUT089_COLOR) {
  108. uint8_t rescaledColor = (arg - FUT089_COLOR_OFFSET) % 0x100;
  109. uint16_t hue = Units::rescale<uint16_t, uint16_t>(rescaledColor, 360, 255.0);
  110. result["hue"] = hue;
  111. } else if (command == FUT089_BRIGHTNESS) {
  112. uint8_t level = constrain(arg, 0, 100);
  113. result["brightness"] = Units::rescale<uint8_t, uint8_t>(level, 255, 100);
  114. // saturation == kelvin. arg ranges are the same, so can't distinguish
  115. // without using state
  116. } else if (command == FUT089_SATURATION) {
  117. const GroupState* state = stateStore->get(bulbId);
  118. if (state != NULL && state->getBulbMode() == BULB_MODE_COLOR) {
  119. result["saturation"] = 100 - constrain(arg, 0, 100);
  120. } else {
  121. result["color_temp"] = Units::whiteValToMireds(100 - arg, 100);
  122. }
  123. } else if (command == FUT089_MODE) {
  124. result["mode"] = arg;
  125. } else {
  126. result["button_id"] = command;
  127. result["argument"] = arg;
  128. }
  129. return bulbId;
  130. }