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.

144 lines
3.5 KiB

  1. /*
  2. LED MODULE
  3. Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. // -----------------------------------------------------------------------------
  6. // LED
  7. // -----------------------------------------------------------------------------
  8. typedef struct {
  9. unsigned char pin;
  10. bool reverse;
  11. } led_t;
  12. std::vector<led_t> _leds;
  13. bool ledAuto;
  14. bool ledStatus(unsigned char id) {
  15. if (id >= _leds.size()) return false;
  16. bool status = digitalRead(_leds[id].pin);
  17. return _leds[id].reverse ? !status : status;
  18. }
  19. bool ledStatus(unsigned char id, bool status) {
  20. if (id >= _leds.size()) return false;
  21. bool s = _leds[id].reverse ? !status : status;
  22. digitalWrite(_leds[id].pin, _leds[id].reverse ? !status : status);
  23. return status;
  24. }
  25. bool ledToggle(unsigned char id) {
  26. if (id >= _leds.size()) return false;
  27. return ledStatus(id, !ledStatus(id));
  28. }
  29. void ledBlink(unsigned char id, unsigned long delayOff, unsigned long delayOn) {
  30. if (id >= _leds.size()) return;
  31. static unsigned long next = millis();
  32. if (next < millis()) {
  33. next += (ledToggle(id) ? delayOn : delayOff);
  34. }
  35. }
  36. #if LED_WIFI
  37. void showStatus() {
  38. if (wifiConnected()) {
  39. if (WiFi.getMode() == WIFI_AP) {
  40. ledBlink(LED_WIFI - 1, 2500, 2500);
  41. } else {
  42. ledBlink(LED_WIFI - 1, 4900, 100);
  43. }
  44. } else {
  45. ledBlink(LED_WIFI - 1, 500, 500);
  46. }
  47. }
  48. #endif
  49. void ledMQTTCallback(unsigned int type, const char * topic, const char * payload) {
  50. static bool isFirstMessage = true;
  51. if (type == MQTT_CONNECT_EVENT) {
  52. char buffer[strlen(MQTT_TOPIC_LED) + 3];
  53. sprintf_P(buffer, PSTR("%s/+"), MQTT_TOPIC_LED);
  54. mqttSubscribe(buffer);
  55. }
  56. if (type == MQTT_MESSAGE_EVENT) {
  57. // Match topic
  58. String t = mqttSubtopic((char *) topic);
  59. if (!t.startsWith(MQTT_TOPIC_LED)) return;
  60. // Get led ID
  61. unsigned int ledID = t.substring(strlen(MQTT_TOPIC_LED)+1).toInt();
  62. if (ledID >= ledCount()) {
  63. DEBUG_MSG_P(PSTR("[LED] Wrong ledID (%d)\n"), ledID);
  64. return;
  65. }
  66. // get value
  67. unsigned int value = (char)payload[0] - '0';
  68. bool bitAuto = (value & 0x02) > 0;
  69. bool bitState = (value & 0x01) > 0;
  70. // Check ledAuto
  71. if (ledID == 0) {
  72. ledAuto = bitAuto ? bitState : false;
  73. setSetting("ledAuto", String() + (ledAuto ? "1" : "0"));
  74. if (bitAuto) return;
  75. }
  76. // Action to perform
  77. ledStatus(ledID, bitState);
  78. }
  79. }
  80. unsigned char ledCount() {
  81. return _leds.size();
  82. }
  83. void ledConfigure() {
  84. ledAuto = getSetting("ledAuto", String() + LED_AUTO).toInt() == 1;
  85. }
  86. void ledSetup() {
  87. #ifdef LED1_PIN
  88. _leds.push_back((led_t) { LED1_PIN, LED1_PIN_INVERSE });
  89. #endif
  90. #ifdef LED2_PIN
  91. _leds.push_back((led_t) { LED2_PIN, LED2_PIN_INVERSE });
  92. #endif
  93. #ifdef LED3_PIN
  94. _leds.push_back((led_t) { LED3_PIN, LED3_PIN_INVERSE });
  95. #endif
  96. #ifdef LED4_PIN
  97. _leds.push_back((led_t) { LED4_PIN, LED4_PIN_INVERSE });
  98. #endif
  99. for (unsigned int i=0; i < _leds.size(); i++) {
  100. pinMode(_leds[i].pin, OUTPUT);
  101. ledStatus(i, false);
  102. }
  103. ledConfigure();
  104. mqttRegister(ledMQTTCallback);
  105. DEBUG_MSG_P(PSTR("[LED] Number of leds: %d\n"), _leds.size());
  106. DEBUG_MSG_P(PSTR("[LED] Led auto indicator is %s\n"), ledAuto ? "ON" : "OFF" );
  107. }
  108. void ledLoop() {
  109. #if LED_WIFI
  110. if (ledAuto) showStatus();
  111. #endif
  112. }