Bandeau de LEDs contrôlable (puissance, couleur, effet) au travers de Home Assistant
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.

227 lines
5.4 KiB

3 years ago
  1. #include "mqttfastledmenu_local.h"
  2. #include "mqttfastledmenu.h"
  3. #include <FastLED.h>
  4. #include <ESP8266WiFi.h>
  5. #include <PubSubClient.h>
  6. // LED
  7. int brightness = LED_BRIGHTNESS_DEFAULT;
  8. int color = LED_COLOR_DEFAULT;
  9. int speed = LED_SPEED_DEFAULT;
  10. CRGB leds[LED_NUM];
  11. int ledEffect = LED_EFFECT_OFF;
  12. // WIFI
  13. WiFiClient espClient;
  14. // MQTT
  15. char message_buff[100];
  16. PubSubClient client(espClient);
  17. void setup() {
  18. Serial.begin(115200);
  19. Serial.println("\nresetting");
  20. // WIFI
  21. setupWifi();
  22. // MQTT
  23. client.setServer(MQTT_SERVER, MQTT_PORT);
  24. client.setCallback(callbackMQTT);
  25. testConnectMQTT();
  26. client.subscribe(MQTT_LED_EFFECT);
  27. client.subscribe(MQTT_LED_BRIGHTNESS);
  28. client.subscribe(MQTT_LED_COLOR);
  29. client.subscribe(MQTT_LED_SPEED);
  30. // LED
  31. LEDS.addLeds<LED_CHIPSET,LED_PIN, LED_COLOR_ORDER>(leds, LED_NUM).setCorrection(TypicalSMD5050);
  32. FastLED.setBrightness(brightness);
  33. ledBlackAll();
  34. }
  35. // WIFI
  36. void setupWifi() {
  37. Serial.print("Connexion a ");
  38. Serial.print(WIFI_SSID);
  39. WiFi.mode(WIFI_STA);
  40. WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  41. while (WiFi.status() != WL_CONNECTED) {
  42. delay(500);
  43. Serial.print(".");
  44. }
  45. Serial.println();
  46. Serial.print("IP : ");
  47. Serial.println(WiFi.localIP());
  48. }
  49. // MQTT
  50. void testConnectMQTT() {
  51. while (!client.connected()) {
  52. Serial.print("Connexion au serveur MQTT... ");
  53. if (client.connect("ESP8266Client", MQTT_USER, MQTT_PASS)) {
  54. // TODO : doit-on se reconnecter aux topics ?
  55. Serial.println("OK");
  56. } else {
  57. Serial.print("KO, erreur : ");
  58. Serial.print(client.state());
  59. Serial.println(", on attend 5 secondes avant de recommencer");
  60. delay(5000);
  61. }
  62. }
  63. }
  64. // Déclenche les actions à la réception d'un message
  65. void callbackMQTT(char* topic, byte* payload, unsigned int length) {
  66. if (String(topic) == MQTT_LED_EFFECT) {
  67. Serial.print("Received [" + String(topic) + "] : ");
  68. Serial.print(payload[0]);
  69. Serial.print(" ~ ");
  70. Serial.print(payload[0] - '0');
  71. ledEffect = payload[0] - '0';
  72. Serial.print("[");
  73. Serial.print(ledEffect);
  74. Serial.println("]");
  75. // Si on ne repasse pas tout à noir, cela peut faire des effets surprenants
  76. ledBlackAll();
  77. } else if (String(topic) == MQTT_LED_BRIGHTNESS) {
  78. unsigned int i = 0;
  79. for(i = 0; i < length; i++) {
  80. message_buff[i] = payload[i];
  81. }
  82. message_buff[i] = '\0';
  83. // TODO : il est surement possible de faire plus propre
  84. String msgString = String(message_buff);
  85. brightness = msgString.toInt();
  86. FastLED.setBrightness(brightness);
  87. Serial.print("Received [" + String(topic) + "] : ");
  88. Serial.println(msgString);
  89. } else if (String(topic) == MQTT_LED_COLOR) {
  90. unsigned int i = 0;
  91. for(i = 0; i < length; i++) {
  92. message_buff[i] = payload[i];
  93. }
  94. message_buff[i] = '\0';
  95. String msgString = String(message_buff);
  96. color = msgString.toInt();
  97. Serial.print("Received [" + String(topic) + "] : ");
  98. Serial.println(msgString);
  99. } else if (String(topic) == MQTT_LED_SPEED) {
  100. unsigned int i = 0;
  101. for(i = 0; i < length; i++) {
  102. message_buff[i] = payload[i];
  103. }
  104. message_buff[i] = '\0';
  105. String msgString = String(message_buff);
  106. speed = msgString.toInt();
  107. Serial.print("Received [" + String(topic) + "] : ");
  108. Serial.println(msgString);
  109. }
  110. }
  111. // LED
  112. void ledBlackAll()
  113. {
  114. FastLED.clear();
  115. FastLED.show();
  116. FastLED.delay(1000 / speed);
  117. }
  118. void ledCylon()
  119. {
  120. // Effet cylon : on allume une led, on attends, on eteinds, on passe à la suivante
  121. // TODO : trop d'attente entre les clients.loop !!!!
  122. for(int i = 0; i < LED_NUM; i++) {
  123. if ((i % 10) == 0) {
  124. client.loop();
  125. if (ledEffect != LED_EFFECT_CYLON) {
  126. return;
  127. }
  128. }
  129. leds[i] = color;
  130. FastLED.show();
  131. FastLED.delay(1000 / speed);
  132. leds[i] = CRGB::Black;
  133. FastLED.show();
  134. FastLED.delay(1000 / speed);
  135. }
  136. for(int i = LED_NUM - 1; i > 0; i--) {
  137. if ((i % 10) == 0) {
  138. client.loop();
  139. if (ledEffect != LED_EFFECT_CYLON) {
  140. return;
  141. }
  142. }
  143. leds[i] = color;
  144. FastLED.show();
  145. FastLED.delay(1000 / speed);
  146. leds[i] = CRGB::Black;
  147. FastLED.show();
  148. }
  149. FastLED.delay(1000 / speed);
  150. }
  151. void ledError()
  152. {
  153. for(int i = 0; i < LED_NUM; i++) {
  154. if ((i % 2) == 0) {
  155. leds[i] = CRGB::Black;
  156. } else {
  157. leds[i] = color;
  158. }
  159. }
  160. FastLED.show();
  161. FastLED.delay(1000 / speed);
  162. }
  163. // TODO : ne doit pas rester à terme, ça ne sert à rien de garder une fonction comme ça
  164. void ledFullRed()
  165. {
  166. fill_solid(leds, LED_NUM, color);
  167. FastLED.show();
  168. FastLED.delay(1000 / speed);
  169. }
  170. void loop() {
  171. // MQTT
  172. testConnectMQTT();
  173. client.loop();
  174. EVERY_N_SECONDS(180) {
  175. Serial.print("MQTT Subscribe refresh");
  176. client.subscribe(MQTT_LED_EFFECT);
  177. client.subscribe(MQTT_LED_BRIGHTNESS);
  178. client.subscribe(MQTT_LED_COLOR);
  179. client.subscribe(MQTT_LED_SPEED);
  180. Serial.println(" done");
  181. }
  182. // LED
  183. switch(ledEffect)
  184. {
  185. case LED_EFFECT_OFF:
  186. ledBlackAll();
  187. break;
  188. case LED_EFFECT_CYLON:
  189. ledCylon();
  190. break;
  191. case LED_EFFECT_FULLRED:
  192. ledFullRed();
  193. break;
  194. default:
  195. ledError();
  196. break;
  197. }
  198. }
  199. // TODO : regrouper input et select en un seul group, l'input enverrait directement Off et les effets ne seraient que effets