Advertisement
gempir

D1 Mini

Jul 6th, 2018
284
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.57 KB | None | 0 0
  1. /*
  2.  * ESP8266 MQTT Lights for Home Assistant.
  3.  * See https://github.com/corbanmailloux/esp-mqtt-rgb-led
  4.  */
  5.  
  6. // https://github.com/bblanchon/ArduinoJson
  7. #include <ArduinoJson.h>
  8.  
  9. #include <ESP8266WiFi.h>
  10.  
  11. // http://pubsubclient.knolleary.net/
  12. #include <PubSubClient.h>
  13.  
  14. // https://github.com/FastLED/FastLED
  15. #include <FastLED.h>
  16.  
  17. const char* ssid = "Taris";
  18. const char* password = "****";
  19.  
  20. const char* mqtt_server = "192.168.178.23";
  21. const char* mqtt_username = "gempir";
  22. const char* mqtt_password = "****";
  23. //Port not needed if you are using your own, you can change this if you are using a service like cloudmqtt
  24. const int mqtt_port = 1883;
  25.  
  26. const char* client_id = "falcon"; // Must be unique on the MQTT network
  27.  
  28. // Topics
  29. const char* light_state_topic = "home/falcon";
  30. const char* light_set_topic = "home/falcon/set";
  31.  
  32. const char* on_cmd = "ON";
  33. const char* off_cmd = "OFF";
  34.  
  35. const int BUFFER_SIZE = JSON_OBJECT_SIZE(10);
  36.  
  37. // Maintained state for reporting to HA
  38. byte red = 255;
  39. byte green = 255;
  40. byte blue = 255;
  41. byte brightness = 255;
  42.  
  43. //Your amount of LEDs to be wrote, and their configuration for FastLED
  44. //
  45. #define NUM_LEDS    5
  46. #define DATA_PIN    2
  47. //#define CLOCK_PIN 5
  48. #define CHIPSET     WS2812B
  49. #define COLOR_ORDER GRB
  50.  
  51. // Real values to write to the LEDs (ex. including brightness and state)
  52. byte realRed = 0;
  53. byte realGreen = 0;
  54. byte realBlue = 0;
  55.  
  56. bool stateOn = false;
  57.  
  58. // Globals for fade/transitions
  59. bool startFade = false;
  60. unsigned long lastLoop = 0;
  61. int transitionTime = 0;
  62. bool inFade = false;
  63. int loopCount = 0;
  64. int stepR, stepG, stepB;
  65. int redVal, grnVal, bluVal;
  66.  
  67. // Globals for flash
  68. bool flash = false;
  69. bool startFlash = false;
  70. int flashLength = 0;
  71. unsigned long flashStartTime = 0;
  72. byte flashRed = red;
  73. byte flashGreen = green;
  74. byte flashBlue = blue;
  75. byte flashBrightness = brightness;
  76.  
  77. WiFiClient espClient;
  78. PubSubClient client(espClient);
  79. CRGB leds[NUM_LEDS];
  80.  
  81. void setup() {
  82. //  pinMode(LED_BUILTIN, OUTPUT); This doesn't work for some reason?
  83. //  digitalWrite(LED_BUILTIN, LOW);
  84.  
  85.   FastLED.addLeds<CHIPSET, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  86.   Serial.begin(115200);
  87.   setup_wifi();
  88.   client.setServer(mqtt_server, mqtt_port);
  89.   client.setCallback(callback);
  90. }
  91.  
  92. void setup_wifi() {
  93.  
  94.   delay(10);
  95.   // We start by connecting to a WiFi network
  96.   Serial.println();
  97.   Serial.print("Connecting to ");
  98.   Serial.println(ssid);
  99.  
  100.   WiFi.begin(ssid, password);
  101.  
  102.   while (WiFi.status() != WL_CONNECTED) {
  103.     delay(500);
  104.     Serial.print(".");
  105.   }
  106.  
  107.   Serial.println("");
  108.   Serial.println("WiFi connected");
  109.   Serial.println("IP address: ");
  110.   Serial.println(WiFi.localIP());
  111. }
  112.  
  113.   /*
  114.   SAMPLE PAYLOAD:
  115.     {
  116.       "brightness": 120,
  117.       "color": {
  118.         "r": 255,
  119.         "g": 100,
  120.         "b": 100
  121.       },
  122.       "flash": 2,
  123.       "transition": 5,
  124.       "state": "ON"
  125.     }
  126.   */
  127. void callback(char* topic, byte* payload, unsigned int length) {
  128.   Serial.print("Message arrived [");
  129.   Serial.print(topic);
  130.   Serial.print("] ");
  131.  
  132.   char message[length + 1];
  133.   for (int i = 0; i < length; i++) {
  134.     message[i] = (char)payload[i];
  135.   }
  136.   message[length] = '\0';
  137.   Serial.println(message);
  138.  
  139.   if (!processJson(message)) {
  140.     return;
  141.   }
  142.  
  143.   if (stateOn) {
  144.     // Update lights
  145.     realRed = map(red, 0, 255, 0, brightness);
  146.     realGreen = map(green, 0, 255, 0, brightness);
  147.     realBlue = map(blue, 0, 255, 0, brightness);
  148.   }
  149.   else {
  150.     realRed = 0;
  151.     realGreen = 0;
  152.     realBlue = 0;
  153.   }
  154.  
  155.   startFade = true;
  156.   inFade = false; // Kill the current fade
  157.  
  158.   sendState();
  159. }
  160.  
  161. bool processJson(char* message) {
  162.   StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
  163.  
  164.   JsonObject& root = jsonBuffer.parseObject(message);
  165.  
  166.   if (!root.success()) {
  167.     Serial.println("parseObject() failed");
  168.     return false;
  169.   }
  170.  
  171.   if (root.containsKey("state")) {
  172.     if (strcmp(root["state"], on_cmd) == 0) {
  173.       stateOn = true;
  174.     }
  175.     else if (strcmp(root["state"], off_cmd) == 0) {
  176.       stateOn = false;
  177.     }
  178.   }
  179.  
  180.   // If "flash" is included, treat RGB and brightness differently
  181.   if (root.containsKey("flash")) {
  182.     flashLength = (int)root["flash"] * 1000;
  183.  
  184.     if (root.containsKey("brightness")) {
  185.       flashBrightness = root["brightness"];
  186.     }
  187.     else {
  188.       flashBrightness = brightness;
  189.     }
  190.  
  191.     if (root.containsKey("color")) {
  192.       flashRed = root["color"]["r"];
  193.       flashGreen = root["color"]["g"];
  194.       flashBlue = root["color"]["b"];
  195.     }
  196.     else {
  197.       flashRed = red;
  198.       flashGreen = green;
  199.       flashBlue = blue;
  200.     }
  201.  
  202.     flashRed = map(flashRed, 0, 255, 0, flashBrightness);
  203.     flashGreen = map(flashGreen, 0, 255, 0, flashBrightness);
  204.     flashBlue = map(flashBlue, 0, 255, 0, flashBrightness);
  205.  
  206.     flash = true;
  207.     startFlash = true;
  208.   }
  209.   else { // Not flashing
  210.     flash = false;
  211.  
  212.     if (root.containsKey("color")) {
  213.       red = root["color"]["r"];
  214.       green = root["color"]["g"];
  215.       blue = root["color"]["b"];
  216.     }
  217.  
  218.     if (root.containsKey("brightness")) {
  219.       brightness = root["brightness"];
  220.     }
  221.  
  222.     if (root.containsKey("transition")) {
  223.       transitionTime = root["transition"];
  224.     }
  225.     else {
  226.       transitionTime = 0;
  227.     }
  228.   }
  229.  
  230.   return true;
  231. }
  232.  
  233. void sendState() {
  234.   StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
  235.  
  236.   JsonObject& root = jsonBuffer.createObject();
  237.  
  238.   root["state"] = (stateOn) ? on_cmd : off_cmd;
  239.   JsonObject& color = root.createNestedObject("color");
  240.   color["r"] = red;
  241.   color["g"] = green;
  242.   color["b"] = blue;
  243.  
  244.   root["brightness"] = brightness;
  245.  
  246.   char buffer[root.measureLength() + 1];
  247.   root.printTo(buffer, sizeof(buffer));
  248.  
  249.   client.publish(light_state_topic, buffer, true);
  250. }
  251.  
  252. void reconnect() {
  253.   // Loop until we're reconnected
  254.   while (!client.connected()) {
  255.     Serial.print("Attempting MQTT connection...");
  256.     // Attempt to connect
  257.     if (client.connect(client_id, mqtt_username, mqtt_password)) {
  258.       Serial.println("connected");
  259.       client.subscribe(light_set_topic);
  260.     } else {
  261.       Serial.print("failed, rc=");
  262.       Serial.print(client.state());
  263.       Serial.println(" try again in 5 seconds");
  264.       // Wait 5 seconds before retrying
  265.       delay(5000);
  266.     }
  267.   }
  268. }
  269.  
  270. void setColor(int inR, int inG, int inB) {
  271.   for(int i = 0; i < NUM_LEDS; i++) {
  272.         leds[i].red   = inR;
  273.         leds[i].green = inG;
  274.         leds[i].blue  = inB;
  275.   }
  276.   FastLED.show();
  277.  
  278.   Serial.println("Setting LEDs:");
  279.   Serial.print("r: ");
  280.   Serial.print(inR);
  281.   Serial.print(", g: ");
  282.   Serial.print(inG);
  283.   Serial.print(", b: ");
  284.   Serial.println(inB);
  285. }
  286.  
  287. void loop() {
  288.  
  289.   if (!client.connected()) {
  290.     reconnect();
  291.   }
  292.   client.loop();
  293.  
  294.   if (flash) {
  295.     if (startFlash) {
  296.       startFlash = false;
  297.       flashStartTime = millis();
  298.     }
  299.  
  300.     if ((millis() - flashStartTime) <= flashLength) {
  301.       if ((millis() - flashStartTime) % 1000 <= 500) {
  302.         setColor(flashRed, flashGreen, flashBlue);
  303.       }
  304.       else {
  305.         setColor(0, 0, 0);
  306.         // If you'd prefer the flashing to happen "on top of"
  307.         // the current color, uncomment the next line.
  308.         // setColor(realRed, realGreen, realBlue);
  309.       }
  310.     }
  311.     else {
  312.       flash = false;
  313.       setColor(realRed, realGreen, realBlue);
  314.     }
  315.   }
  316.  
  317.   if (startFade) {
  318.     // If we don't want to fade, skip it.
  319.     if (transitionTime == 0) {
  320.       setColor(realRed, realGreen, realBlue);
  321.  
  322.       redVal = realRed;
  323.       grnVal = realGreen;
  324.       bluVal = realBlue;
  325.  
  326.       startFade = false;
  327.     }
  328.     else {
  329.       loopCount = 0;
  330.       stepR = calculateStep(redVal, realRed);
  331.       stepG = calculateStep(grnVal, realGreen);
  332.       stepB = calculateStep(bluVal, realBlue);
  333.  
  334.       inFade = true;
  335.     }
  336.   }
  337.  
  338.   if (inFade) {
  339.     startFade = false;
  340.     unsigned long now = millis();
  341.     if (now - lastLoop > transitionTime) {
  342.       if (loopCount <= 1020) {
  343.         lastLoop = now;
  344.        
  345.         redVal = calculateVal(stepR, redVal, loopCount);
  346.         grnVal = calculateVal(stepG, grnVal, loopCount);
  347.         bluVal = calculateVal(stepB, bluVal, loopCount);
  348.        
  349.         setColor(redVal, grnVal, bluVal); // Write current values to LED pins
  350.  
  351.         Serial.print("Loop count: ");
  352.         Serial.println(loopCount);
  353.         loopCount++;
  354.       }
  355.       else {
  356.         inFade = false;
  357.       }
  358.     }
  359.   }
  360. }
  361.  
  362. // From https://www.arduino.cc/en/Tutorial/ColorCrossfader
  363. /* BELOW THIS LINE IS THE MATH -- YOU SHOULDN'T NEED TO CHANGE THIS FOR THE BASICS
  364. *
  365. * The program works like this:
  366. * Imagine a crossfade that moves the red LED from 0-10,
  367. *   the green from 0-5, and the blue from 10 to 7, in
  368. *   ten steps.
  369. *   We'd want to count the 10 steps and increase or
  370. *   decrease color values in evenly stepped increments.
  371. *   Imagine a + indicates raising a value by 1, and a -
  372. *   equals lowering it. Our 10 step fade would look like:
  373. *
  374. *   1 2 3 4 5 6 7 8 9 10
  375. * R + + + + + + + + + +
  376. * G   +   +   +   +   +
  377. * B     -     -     -
  378. *
  379. * The red rises from 0 to 10 in ten steps, the green from
  380. * 0-5 in 5 steps, and the blue falls from 10 to 7 in three steps.
  381. *
  382. * In the real program, the color percentages are converted to
  383. * 0-255 values, and there are 1020 steps (255*4).
  384. *
  385. * To figure out how big a step there should be between one up- or
  386. * down-tick of one of the LED values, we call calculateStep(),
  387. * which calculates the absolute gap between the start and end values,
  388. * and then divides that gap by 1020 to determine the size of the step  
  389. * between adjustments in the value.
  390. */
  391. int calculateStep(int prevValue, int endValue) {
  392.     int step = endValue - prevValue; // What's the overall gap?
  393.     if (step) {                      // If its non-zero,
  394.         step = 1020/step;            //   divide by 1020
  395.     }
  396.    
  397.     return step;
  398. }
  399.  
  400. /* The next function is calculateVal. When the loop value, i,
  401. *  reaches the step size appropriate for one of the
  402. *  colors, it increases or decreases the value of that color by 1.
  403. *  (R, G, and B are each calculated separately.)
  404. */
  405. int calculateVal(int step, int val, int i) {
  406.     if ((step) && i % step == 0) { // If step is non-zero and its time to change a value,
  407.         if (step > 0) {              //   increment the value if step is positive...
  408.             val += 1;
  409.         }
  410.         else if (step < 0) {         //   ...or decrement it if step is negative
  411.             val -= 1;
  412.         }
  413.     }
  414.    
  415.     // Defensive driving: make sure val stays in the range 0-255
  416.     if (val > 255) {
  417.         val = 255;
  418.     }
  419.     else if (val < 0) {
  420.         val = 0;
  421.     }
  422.    
  423.     return val;
  424. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement