Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Adafruit_NeoPixel.h>
- #include <ESP8266WiFi.h>
- #include <ESP8266HTTPClient.h>
- #include "Adafruit_MQTT.h"
- #include "Adafruit_MQTT_Client.h"
- /* ---- Constants ---- */
- /* ---- WiFi ---- */
- #define WIFI_SSID "xxxxx"
- #define WIFI_PASSWORD "xxxxx"
- const int WIFI_GRACE_PERIOD = 15000;
- // Create an ESP8266 WiFiClient class to connect to the MQTT server.
- WiFiClient client;
- // or... use WiFiFlientSecure for SSL
- //WiFiClientSecure client;
- /* ---- Home Assistant ---- */
- const int API_INTERVAL = 15000;
- unsigned long API_last_hello = 0;
- String API_HELLO = "http://xxxxx:8123/api/";
- bool API_never_been_up = true;
- const String API_AUTHORIZATION = "Bearer xxxxxx";
- //const String API_AUTHORIZATION = "Bearer test";
- const String API_CONTENT_TYPE = "application/json";
- String API_GET_STATE = "http://xxxxx:8123/api/states/";
- String API_SET_STATE = "http://xxxxx:8123/api/services/";
- /* ---- WS2812B ---- */
- const byte LED_PIN = 0;
- const byte LED_COUNT = 4;
- byte current_color = 0;
- const byte MAX_COLOR = 120;
- const byte LED_PHASE1 = 0;
- const byte LED_PHASE2 = 3;
- const byte LED_PHASE3 = 2;
- const byte LED_PHASE4 = 1;
- const byte UP_R = 0; // Green is for online/on
- const byte UP_G = MAX_COLOR;
- const byte UP_B = 0;
- const byte DOWN_R = MAX_COLOR; // Red is for offline/off
- const byte DOWN_G = 0;
- const byte DOWN_B = 0;
- const byte HOT_R = 0; // Blue is for cooling 3D Printer
- const byte HOT_G = 0;
- const byte HOT_B = MAX_COLOR;
- const byte PRINTING_R = MAX_COLOR; // Purple is for printing
- const byte PRINTING_G = 0;
- const byte PRINTING_B = MAX_COLOR;
- const byte UNKNOWN_R = MAX_COLOR; // Orange is for unknown
- const byte UNKNOWN_G = (int)MAX_COLOR/2;
- const byte UNKNOWN_B = 0;
- const byte PENDING_R = 0; // Black is for pending
- const byte PENDING_G = 0;
- const byte PENDING_B = 0;
- Adafruit_NeoPixel led_strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
- /* ---- Global ---- */
- const byte MATRIX_COMMON_PIN = 5;
- const int COMPONENTS_INTERVAL = 500;
- const int BUTTONS_READ_INTERVAL = 50;
- const byte DEBUG_LEVEL = 1;
- unsigned long uptime = millis();
- unsigned long buttons_read_last = 0;
- const byte STATE_COOL = 2;
- const byte STATE_DOWN = 3;
- const byte STATE_HOT = 5;
- const byte STATE_OFF = 3;
- const byte STATE_ON = 2;
- const byte STATE_PENDING = 1;
- const byte STATE_UNKNOWN = 0;
- const byte STATE_UP = 2;
- const byte STATE_PRINTING = 6;
- /* ---- 3D Printer ---- */
- const byte ENDER3_BUTTON_PIN = 14;
- const byte ENDER3_LED = 2;
- String ENDER3_API_STATE = "sensor.ender_3_current_state";
- String ENDER3_API_CURRENT_BED_TEMP = "sensor.ender_3_actual_bed_temp";
- String ENDER3_API_CURRENT_E0_TEMP = "sensor.ender_3_actual_tool0_temp";
- String ENDER3_API_POWER = "switch.power_ender_3";
- String ENDER3_API_PRINTING = "binary_sensor.ender_3_printing";
- int ENDER3_COOL_BED = 35;
- int ENDER3_COOL_EXTRUDER = 35;
- byte Ender3_last_known_state = 0;
- bool Ender3_requested_change = false;
- bool Ender3_button_last_known_state = false;
- bool Ender3_was_printing = false;
- /* ---- PC ---- */
- const byte PC_BUTTON_PIN = 4;
- const byte PC_LED = 3;
- String PC_API = "switch.power_pc";
- byte PC_last_known_state = 0;
- bool PC_requested_change = false;
- bool PC_button_last_known_state = false;
- /* ---- Screens ---- */
- const byte SCREENS_BUTTON_PIN = 13;
- const byte SCREENS_LED = 0;
- String SCREENS_API = "switch.power_screens";
- byte screens_last_known_state = 0;
- bool screens_requested_change = false;
- bool screens_button_last_known_state = false;
- /* ---- Soldering Iron ---- */
- const byte SOLDERING_IRON_BUTTON_PIN = 12;
- const byte SOLDERING_IRON_LED = 1;
- String SOLDERING_IRON_API = "switch.soldering_iron";
- byte soldering_iron_last_known_state = 0;
- bool soldering_iron_requested_change = false;
- bool soldering_iron_button_last_known_state = false;
- /* ---- Functions ---- */
- /* ---- WiFi ---- */
- void connectWiFi() {
- Serial.println();
- Serial.println();
- Serial.print("Connecting to ");
- Serial.println(WIFI_SSID);
- WiFi.mode(WIFI_STA);
- WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- }
- Serial.println("");
- Serial.println("WiFi connected");
- Serial.println("IP address: ");
- Serial.println(WiFi.localIP());
- }
- void disconnectWiFi() {
- API_never_been_up = true;
- WiFi.disconnect();
- }
- void checkWiFi() {
- if (WiFi.status() != WL_CONNECTED) {
- // Reconnect WiFi
- showPhase1();
- API_never_been_up = true;
- connectWiFi();
- delay(COMPONENTS_INTERVAL);
- // Check API
- checkAPI();
- }
- }
- /* ---- Home Assistant ---- */
- void prepareHTTPRequest(HTTPClient &http, String url) {
- http.begin (url);
- http.addHeader("Authorization", API_AUTHORIZATION);
- http.addHeader("Content-Type", API_CONTENT_TYPE);
- }
- void checkAPI() {
- HTTPClient http;
- prepareHTTPRequest(http, API_HELLO);
- int httpCode = http.GET();
- http.end();
- if (httpCode <= 0) {
- Serial.print ("HTTP hello failed (" + (String) httpCode + "). ");
- if (uptime > WIFI_GRACE_PERIOD) {
- Serial.println ("Trying to reconnect to WiFi");
- showPhase1();
- disconnectWiFi();
- } else {
- showPhase3();
- Serial.println ("Still in grace period.");
- }
- } else {
- Serial.print ("HTTP hello succeeded (" + (String) httpCode + "). ");
- API_never_been_up = false;
- showPhase4();
- delay(COMPONENTS_INTERVAL);
- }
- }
- String simpleJSONExtract(String data, String key) {
- // Adding the surrounding quotes to avoid partial match
- if (key.indexOf("\"") == -1)
- key = "\"" + key + "\"";
- // Adding color to avoid matching a value
- if (key.indexOf(":") == -1)
- key = key + ":";
- // Starting by truncating after: "key":
- int next_idx = data.indexOf(key);
- if (next_idx == -1)
- return "";
- String value = data.substring(next_idx + 1 + key.length());
- debugLog3("1: " + value);
- // Then cutting to the first "
- next_idx = value.indexOf("\"");
- if (next_idx == -1)
- return "";
- value = value.substring(next_idx + 1);
- debugLog3("2: " + value);
- // Then cutting until the next "
- next_idx = value.indexOf("\"");
- if (next_idx == -1)
- return "";
- value = value.substring(0, next_idx);
- debugLog3("3: " + value);
- return value;
- }
- int queryAndDisplayState(String API_id, byte LED_id, byte &last_known_state) {
- HTTPClient http;
- prepareHTTPRequest(http, API_GET_STATE + API_id);
- int httpCode = http.GET();
- byte current_state;
- if (httpCode != 200) {
- debugLog("Query " + API_id + ": HTTP " + (String)httpCode);
- current_state = STATE_UNKNOWN;
- displayState (LED_id, STATE_UNKNOWN);
- } else {
- String payload = http.getString();
- debugLog3(payload);
- String value = simpleJSONExtract(payload, "state");
- debugLog2(value);
- if (value == "on") {
- current_state = STATE_UP;
- displayState (LED_id, STATE_UP);
- } else if (value == "off") {
- current_state = STATE_DOWN;
- displayState (LED_id, STATE_DOWN);
- } else {
- current_state = STATE_UNKNOWN;
- displayState (LED_id, STATE_UNKNOWN);
- }
- }
- if (current_state != last_known_state) {
- debugLog("Query " + API_id + ": new value " + (String)current_state);
- last_known_state = current_state;
- }
- http.end();
- return httpCode;
- }
- int toggleAndSubmitState(String API_id, byte LED_id, byte &last_known_state) {
- displayState (LED_id, STATE_PENDING);
- HTTPClient http;
- String httpPOSTURL = API_SET_STATE;
- String httpPOSTdata = "{\"entity_id\":\"" + API_id + "\"}";
- byte requested_state;
- if (last_known_state == STATE_UP) {
- requested_state = STATE_OFF;
- httpPOSTURL += API_id.substring(0,API_id.indexOf(".")) + "/turn_off";
- } else {
- requested_state = STATE_UP;
- httpPOSTURL += API_id.substring(0,API_id.indexOf(".")) + "/turn_on";
- }
- prepareHTTPRequest(http, httpPOSTURL);
- int httpCode = http.POST(httpPOSTdata);
- debugLog("POST " + httpPOSTURL + ": HTTP " + (String)httpCode);
- if (httpCode != 200 && httpCode != 201) {
- debugLog("Payload was " + httpPOSTdata);
- last_known_state = STATE_UNKNOWN;
- displayState (LED_id, STATE_UNKNOWN);
- } else {
- debugLog("Requested state becomes new state " + (String)requested_state);
- last_known_state = requested_state;
- displayState (LED_id, requested_state);
- }
- http.end();
- return httpCode;
- }
- void Ender3ToggleState() {
- displayState (ENDER3_LED, STATE_PENDING);
- switch (Ender3_last_known_state) {
- // If current state is off, then turn on
- case STATE_OFF:
- toggleAndSubmitState (ENDER3_API_POWER, ENDER3_LED, Ender3_last_known_state);
- break;
- // If current state is on, then checking printing state
- case STATE_ON:
- HTTPClient http;
- prepareHTTPRequest(http, API_GET_STATE + ENDER3_API_PRINTING);
- int httpCode = http.GET();
- if (httpCode != 200) {
- debugLog("Query " + ENDER3_API_PRINTING + ": HTTP " + (String)httpCode);
- Ender3_last_known_state = STATE_UNKNOWN;
- displayState (ENDER3_LED, STATE_UNKNOWN);
- } else {
- String payload = http.getString();
- debugLog3(payload);
- String value = simpleJSONExtract(payload, "state");
- debugLog2(value);
- byte current_state;
- if (value == "on") {
- debugLog("Ender 3 is printing, denied changing power to OFF");
- Ender3_last_known_state = STATE_UNKNOWN;
- displayState (ENDER3_LED, STATE_UNKNOWN);
- } else if (value == "off") {
- debugLog("Ender 3 is NOT printing, granted changing power to OFF");
- toggleAndSubmitState (ENDER3_API_POWER, ENDER3_LED, Ender3_last_known_state);
- } else {
- current_state = STATE_UNKNOWN;
- displayState (ENDER3_LED, STATE_UNKNOWN);
- }
- }
- http.end();
- break;
- }
- }
- String simplyFetchTheValue(String URL, String entity) {
- HTTPClient http;
- prepareHTTPRequest(http, URL);
- int httpCode = http.GET();
- String fetched_value;
- if (httpCode == 200) {
- fetched_value = simpleJSONExtract(http.getString(), entity);
- }
- http.end();
- return fetched_value;
- }
- void Ender3FullUpdate() {
- HTTPClient http;
- prepareHTTPRequest(http, API_GET_STATE + ENDER3_API_POWER);
- int httpCode = http.GET();
- byte current_state;
- if (httpCode != 200) {
- debugLog("Query " + ENDER3_API_POWER + ": HTTP " + (String)httpCode);
- current_state = STATE_UNKNOWN;
- displayState (ENDER3_LED, STATE_UNKNOWN);
- } else {
- String payload = http.getString();
- debugLog3(payload);
- String value = simpleJSONExtract(payload, "state");
- debugLog2(value);
- if (value == "on") {
- current_state = STATE_UP;
- } else if (value == "off") {
- current_state = STATE_DOWN;
- Ender3_was_printing = false;
- displayState (ENDER3_LED, current_state);
- } else {
- current_state = STATE_UNKNOWN;
- }
- }
- http.end();
- if (current_state != Ender3_last_known_state) {
- debugLog("Query " + ENDER3_API_POWER + ": new value " + (String)current_state);
- Ender3_last_known_state = current_state;
- }
- if (Ender3_last_known_state == STATE_ON) {
- String currently_printing = simplyFetchTheValue (API_GET_STATE + ENDER3_API_PRINTING, "state");
- if (currently_printing == "on") {
- Ender3_was_printing = true;
- displayState (ENDER3_LED, STATE_PRINTING);
- } else {
- displayState (ENDER3_LED, STATE_UP);
- }
- if (currently_printing == "off" && Ender3_was_printing) {
- float bed_temp = simplyFetchTheValue (API_GET_STATE + ENDER3_API_CURRENT_BED_TEMP, "state").toFloat();
- debugLog ("Bed temperature: " + (String)bed_temp);
- if (bed_temp == 0) {
- displayState (ENDER3_LED, STATE_HOT);
- return;
- }
- if (bed_temp > ENDER3_COOL_BED) {
- displayState (ENDER3_LED, STATE_HOT);
- return;
- }
- float extruder_temp = simplyFetchTheValue (API_GET_STATE + ENDER3_API_CURRENT_E0_TEMP, "state").toFloat();
- debugLog ("Extruder temperature: " + (String)extruder_temp);
- if (extruder_temp == 0) {
- displayState (ENDER3_LED, STATE_HOT);
- return;
- }
- if (extruder_temp > ENDER3_COOL_EXTRUDER) {
- displayState (ENDER3_LED, STATE_HOT);
- return;
- }
- displayState (ENDER3_LED, STATE_COOL);
- }
- }
- }
- /* ---- WS2812B ---- */
- void applyColorToAllLEDs (int red, int green, int blue) {
- for (int i=0; i<LED_COUNT; i++) {
- led_strip.setPixelColor (i, red, green, blue);
- }
- led_strip.show();
- }
- void applyColorToOneLED (int led, int red, int green, int blue) {
- led_strip.setPixelColor (led, red, green, blue);
- led_strip.show();
- }
- void offAllLEDs () {
- for (int i=0; i<12; i++) {
- led_strip.setPixelColor (i, 0,0,0);
- }
- led_strip.show();
- }
- void showPhase1() {
- applyColorToAllLEDs(0,0,0);
- applyColorToOneLED(LED_PHASE1, MAX_COLOR, MAX_COLOR, MAX_COLOR);
- }
- void showPhase2() {
- showPhase1();
- applyColorToOneLED(LED_PHASE2, MAX_COLOR, MAX_COLOR, MAX_COLOR);
- }
- void showPhase3() {
- showPhase2();
- applyColorToOneLED(LED_PHASE3, MAX_COLOR, MAX_COLOR, MAX_COLOR);
- }
- void showPhase4() {
- showPhase3();
- applyColorToOneLED(LED_PHASE4, MAX_COLOR, MAX_COLOR, MAX_COLOR);
- }
- void testAllLEDs() {
- // Cycle through the colors to validate the LEDs
- Serial.println ("All red");
- applyColorToAllLEDs (255, 0, 0); delay (1000);
- Serial.println ("All green");
- applyColorToAllLEDs ( 0, 255, 0); delay (1000);
- Serial.println ("All blue");
- applyColorToAllLEDs ( 0, 0, 255); delay (1000);
- Serial.println ("All off");
- applyColorToAllLEDs ( 0, 0, 0); delay (1000);
- }
- void displayState(byte LED_id, byte state) {
- switch (state) {
- case STATE_HOT:
- applyColorToOneLED (LED_id, HOT_R, HOT_G, HOT_B);
- break;
- // case STATE_DOWN:
- case STATE_OFF:
- applyColorToOneLED (LED_id, DOWN_R, DOWN_G, DOWN_B);
- break;
- case STATE_ON:
- // case STATE_UP:
- // case STATE_COOL:
- applyColorToOneLED (LED_id, UP_R, UP_G, UP_B);
- break;
- case STATE_PENDING:
- applyColorToOneLED (LED_id, PENDING_R, PENDING_G, PENDING_B);
- break;
- case STATE_UNKNOWN:
- applyColorToOneLED (LED_id, UNKNOWN_R, UNKNOWN_G, UNKNOWN_B);
- break;
- case STATE_PRINTING:
- applyColorToOneLED (LED_id, PRINTING_R, PRINTING_G, PRINTING_B);
- break;
- }
- }
- /* ---- Buttons ---- */
- void readButtons() {
- pinMode(MATRIX_COMMON_PIN, OUTPUT);
- bool button_read = false;
- buttons_read_last = millis();
- byte Ender3_button_read = 0;
- byte screens_button_read = 0;
- byte soldering_iron_button_read = 0;
- byte PC_button_read = 0;
- for (int i=0; i<5; i++) {
- /* ---- Ender 3 ---- */
- pinMode(ENDER3_BUTTON_PIN, INPUT_PULLUP);
- Ender3_button_read += digitalRead(ENDER3_BUTTON_PIN);
- pinMode(ENDER3_BUTTON_PIN, INPUT);
- /* ---- Screens ---- */
- pinMode(SCREENS_BUTTON_PIN, INPUT_PULLUP);
- screens_button_read += digitalRead(SCREENS_BUTTON_PIN);
- pinMode(SCREENS_BUTTON_PIN, INPUT);
- /* ---- Soldering iron ---- */
- pinMode(SOLDERING_IRON_BUTTON_PIN, INPUT_PULLUP);
- soldering_iron_button_read += digitalRead(SOLDERING_IRON_BUTTON_PIN);
- pinMode(SOLDERING_IRON_BUTTON_PIN, INPUT);
- /* ---- PC ---- */
- pinMode(PC_BUTTON_PIN, INPUT_PULLUP);
- PC_button_read += digitalRead(PC_BUTTON_PIN);
- pinMode(PC_BUTTON_PIN, INPUT);
- delay (1);
- }
- if (Ender3_button_read == 0) {
- if (!Ender3_button_last_known_state) {
- Ender3_button_last_known_state = true;
- Ender3_requested_change = true;
- }
- } else {
- Ender3_button_last_known_state = false;
- }
- if (screens_button_read == 0) {
- if (!screens_button_last_known_state) {
- screens_button_last_known_state = true;
- screens_requested_change = true;
- }
- } else {
- screens_button_last_known_state = false;
- }
- if (soldering_iron_button_read == 0) {
- if (!soldering_iron_button_last_known_state) {
- soldering_iron_button_last_known_state = true;
- soldering_iron_requested_change = true;
- }
- } else {
- soldering_iron_button_last_known_state = false;
- }
- if (PC_button_read == 0) {
- if (!PC_button_last_known_state) {
- PC_button_last_known_state = true;
- PC_requested_change = true;
- }
- } else {
- PC_button_last_known_state = false;
- }
- pinMode(MATRIX_COMMON_PIN, INPUT_PULLUP);
- }
- /* ---- Setup and Loop ---- */
- void setup() {
- Serial.begin(115200);
- delay(10);
- led_strip.begin();
- randomSeed (analogRead (0));
- pinMode(MATRIX_COMMON_PIN, INPUT_PULLUP);
- pinMode(ENDER3_BUTTON_PIN, INPUT);
- pinMode(SCREENS_BUTTON_PIN, INPUT);
- pinMode(SOLDERING_IRON_BUTTON_PIN, INPUT);
- pinMode(PC_BUTTON_PIN, INPUT);
- testAllLEDs();
- showPhase1(); delay(2000);
- connectWiFi();
- showPhase2(); delay(2000);
- while (WiFi.status() == WL_CONNECTED && API_never_been_up) {
- checkAPI();
- delay(COMPONENTS_INTERVAL);
- }
- delay(2000);
- }
- void loop() {
- // When is it
- uptime = millis();
- // Read button changes
- if (uptime - buttons_read_last > BUTTONS_READ_INTERVAL) {
- readButtons();
- }
- // Apply requested changes
- if (Ender3_requested_change) {
- Ender3ToggleState();
- Ender3_requested_change = false;
- }
- if (screens_requested_change) {
- toggleAndSubmitState(SCREENS_API, SCREENS_LED, screens_last_known_state);
- screens_requested_change = false;
- }
- if (soldering_iron_requested_change) {
- toggleAndSubmitState(SOLDERING_IRON_API, SOLDERING_IRON_LED, soldering_iron_last_known_state);
- soldering_iron_requested_change = false;
- }
- if (PC_requested_change) {
- toggleAndSubmitState(PC_API, PC_LED, PC_last_known_state);
- PC_requested_change = false;
- }
- // Read states from HomeAssistant
- if (uptime - API_last_hello > API_INTERVAL) {
- if (WiFi.status() == WL_CONNECTED) {
- queryAndDisplayState (SCREENS_API, SCREENS_LED, screens_last_known_state);
- queryAndDisplayState (SOLDERING_IRON_API, SOLDERING_IRON_LED, soldering_iron_last_known_state);
- queryAndDisplayState (PC_API, PC_LED, PC_last_known_state);
- Ender3FullUpdate();
- Ender3_requested_change = false;
- screens_requested_change = false;
- soldering_iron_requested_change = false;
- PC_requested_change = false;
- API_last_hello = millis();
- delay(COMPONENTS_INTERVAL);
- } else {
- checkWiFi();
- }
- }
- }
- void debugLog(String string) {
- if (DEBUG_LEVEL >= 1)
- Serial.println(string);
- }
- void debugLog2(String string) {
- if (DEBUG_LEVEL >= 2)
- Serial.println(string);
- }
- void debugLog3(String string) {
- if (DEBUG_LEVEL >= 3)
- Serial.println(string);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement