Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
4.8 KiB

  1. /*
  2. LIGHT MODULE
  3. Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
  6. #include <Ticker.h>
  7. #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY9192
  8. #include <my9291.h>
  9. my9291 * _my9291;
  10. Ticker colorTicker;
  11. bool _mqttSkipColor = false;
  12. #endif
  13. // -----------------------------------------------------------------------------
  14. // UTILS
  15. // -----------------------------------------------------------------------------
  16. void color_rgb2array(const char * rgb, unsigned int * array) {
  17. char * p = (char *) rgb;
  18. if (p[0] == '#') ++p;
  19. unsigned long value = strtol(p, NULL, 16);
  20. array[0] = (value >> 16) & 0xFF;
  21. array[1] = (value >> 8) & 0xFF;
  22. array[2] = (value) & 0xFF;
  23. }
  24. void color_array2rgb(unsigned int * array, char * rgb) {
  25. unsigned long value = array[0];
  26. value = (value << 8) + array[1];
  27. value = (value << 8) + array[2];
  28. sprintf(rgb, "#%06X", value);
  29. }
  30. // -----------------------------------------------------------------------------
  31. // LIGHT MANAGEMENT
  32. // -----------------------------------------------------------------------------
  33. void lightColor(const char * rgb, bool save) {
  34. #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY9192
  35. unsigned int array[4] = {0};
  36. color_rgb2array(rgb, array);
  37. // If all set to the same value use white instead
  38. if ((array[0] == array[1]) && (array[1] == array[2])) {
  39. array[3] = array[0];
  40. array[0] = array[1] = array[2] = 0;
  41. }
  42. // Set new color (if light is open it will automatically change)
  43. _my9291->setColor((my9291_color_t) { array[0], array[1], array[2], array[3] });
  44. #endif
  45. // Delay saving to EEPROM 5 seconds to avoid wearing it out unnecessarily
  46. if (save) {
  47. colorTicker.once(LIGHT_SAVE_DELAY, lightColorSave);
  48. }
  49. // Report color to MQTT broker
  50. _mqttSkipColor = true;
  51. mqttSend(MQTT_COLOR_TOPIC, rgb);
  52. // Report color to WS clients
  53. char message[20];
  54. sprintf(message, "{\"color\": \"%s\"}", rgb);
  55. wsSend(message);
  56. }
  57. void lightColor(const char * rgb) {
  58. lightColor(rgb, true);
  59. }
  60. String lightColor() {
  61. String response;
  62. #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY9192
  63. my9291_color_t color = _my9291->getColor();
  64. unsigned int array[3];
  65. if (color.white > 0) {
  66. array[0] = array[1] = array[2] = color.white;
  67. } else {
  68. array[0] = color.red;
  69. array[1] = color.green;
  70. array[2] = color.blue;
  71. }
  72. char rgb[8];
  73. color_array2rgb(array, rgb);
  74. response = String(rgb);
  75. #endif
  76. return response;
  77. }
  78. void lightState(bool state) {
  79. #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY9192
  80. _my9291->setState(state);
  81. #endif
  82. }
  83. bool lightState() {
  84. bool response = false;
  85. #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY9192
  86. response = _my9291->getState();
  87. #endif
  88. return response;
  89. }
  90. // -----------------------------------------------------------------------------
  91. // PERSISTANCE
  92. // -----------------------------------------------------------------------------
  93. void lightColorSave() {
  94. setSetting("color", lightColor());
  95. saveSettings();
  96. }
  97. void lightColorRetrieve() {
  98. lightColor(getSetting("color", LIGHT_DEFAULT_COLOR).c_str(), false);
  99. }
  100. // -----------------------------------------------------------------------------
  101. // MQTT
  102. // -----------------------------------------------------------------------------
  103. void lightMQTTCallback(unsigned int type, const char * topic, const char * payload) {
  104. String mqttSetter = getSetting("mqttSetter", MQTT_USE_SETTER);
  105. String mqttGetter = getSetting("mqttGetter", MQTT_USE_GETTER);
  106. bool sameSetGet = mqttGetter.compareTo(mqttSetter) == 0;
  107. if (type == MQTT_CONNECT_EVENT) {
  108. char buffer[strlen(MQTT_COLOR_TOPIC) + mqttSetter.length() + 20];
  109. sprintf(buffer, "%s%s", MQTT_COLOR_TOPIC, mqttSetter.c_str());
  110. mqttSubscribe(buffer);
  111. }
  112. if (type == MQTT_MESSAGE_EVENT) {
  113. // Match topic
  114. char * t = mqttSubtopic((char *) topic);
  115. int len = mqttSetter.length();
  116. if (strncmp(t + strlen(t) - len, mqttSetter.c_str(), len) != 0) return;
  117. if (strncmp(t, MQTT_COLOR_TOPIC, strlen(MQTT_COLOR_TOPIC)) == 0) {
  118. if (_mqttSkipColor) {
  119. _mqttSkipColor = false;
  120. } else {
  121. lightColor(payload, true);
  122. }
  123. return;
  124. }
  125. }
  126. }
  127. // -----------------------------------------------------------------------------
  128. // SETUP
  129. // -----------------------------------------------------------------------------
  130. void lightSetup() {
  131. #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY9192
  132. _my9291 = new my9291(MY9291_DI_PIN, MY9291_DCKI_PIN, MY9291_COMMAND);
  133. #endif
  134. lightColorRetrieve();
  135. mqttRegister(lightMQTTCallback);
  136. }
  137. #endif // LIGHT_PROVIDER != LIGHT_PROVIDER_NONE