MiLightClient.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #include <MiLightClient.h>
  2. uint8_t MiLightClient::nextSequenceNum() {
  3. return sequenceNum++;
  4. }
  5. bool MiLightClient::available() {
  6. return radio.available();
  7. }
  8. void MiLightClient::read(MiLightPacket& packet) {
  9. uint8_t *packetBytes = reinterpret_cast<uint8_t*>(&packet);
  10. size_t length = sizeof(packet);
  11. radio.read(packetBytes, length);
  12. }
  13. void MiLightClient::write(MiLightPacket& packet, const unsigned int resendCount) {
  14. uint8_t *packetBytes = reinterpret_cast<uint8_t*>(&packet);
  15. Serial.print("Packet bytes (");
  16. Serial.print(sizeof(packet));
  17. Serial.print(" bytes): ");
  18. for (int i = 0; i < sizeof(packet); i++) {
  19. Serial.print(packetBytes[i], HEX);
  20. Serial.print(" ");
  21. }
  22. Serial.println();
  23. for (int i = 0; i < resendCount; i++) {
  24. Serial.print(".");
  25. radio.write(packetBytes, sizeof(packet));
  26. }
  27. Serial.println();
  28. }
  29. void MiLightClient::write(
  30. const uint16_t deviceId,
  31. const uint16_t color,
  32. const uint8_t brightness,
  33. const uint8_t groupId,
  34. const MiLightButton button) {
  35. // Expect an input value in [0, 255]. Map it down to [0, 25].
  36. const uint8_t adjustedBrightness = round(brightness * (25 / 255.0));
  37. // The actual protocol uses a bizarre range where min is 16, max is 23:
  38. // [16, 15, ..., 0, 31, ..., 23]
  39. const uint8_t packetBrightnessValue = (
  40. ((31 - adjustedBrightness) + 17) % 32
  41. );
  42. // Map color as a Hue value in [0, 359] to [0, 255]. The protocol also has
  43. // 0 being roughly magenta (#FF00FF)
  44. const int16_t remappedColor = (color + 40) % 360;
  45. const uint8_t adjustedColor = round(remappedColor * (255 / 359.0));
  46. MiLightPacket packet;
  47. packet.deviceType = MiLightDeviceType::RGBW;
  48. packet.deviceId = deviceId;
  49. packet.color = adjustedColor;
  50. packet.brightnessGroupId = (packetBrightnessValue << 3) | groupId;
  51. packet.button = button;
  52. packet.sequenceNum = nextSequenceNum();
  53. write(packet);
  54. }
  55. void MiLightClient::updateColor(const uint16_t deviceId, const uint8_t groupId, const uint16_t hue) {
  56. write(deviceId, hue, 0, groupId, COLOR);
  57. }
  58. void MiLightClient::updateBrightness(const uint16_t deviceId, const uint8_t groupId, const uint8_t brightness) {
  59. write(deviceId, 0, brightness, groupId, BRIGHTNESS);
  60. }
  61. void MiLightClient::updateStatus(const uint16_t deviceId, const uint8_t groupId, MiLightStatus status) {
  62. uint8_t button = MiLightButton::GROUP_1_ON + ((groupId - 1)*2) + status;
  63. write(deviceId, 0, 0, 0, static_cast<MiLightButton>(button));
  64. }
  65. void MiLightClient::updateColorWhite(const uint16_t deviceId, const uint8_t groupId) {
  66. write(deviceId, 0, 0, groupId, COLOR_WHITE);
  67. }
  68. void MiLightClient::allOn(const uint16_t deviceId) {
  69. write(deviceId, 0, 0, 0, ALL_ON);
  70. }
  71. void MiLightClient::allOff(const uint16_t deviceId) {
  72. write(deviceId, 0, 0, 0, ALL_OFF);
  73. }