Last Updated or created 2024-02-22
UPDATE: AccessPoint on Arduino implemented with captive portal for Wifi Configuration
Got my Waveshare Epaper Cloud running on ESPHome
This is a Epaper display with a 2000mAh Lipo and a passive buzzer.
Running parts of my Smoker monitor.
Below a little movie clip with RTTTL sound notification.
(Send from Home Assistant)
B.t.w. RTTTL are those ringtones we used to have. (Ring Tone Text Transfer Language)
Sending from HA
Parts of the ESPHOME Yaml
NOTE: For the time, you need the time integration to get hours:minutes as a sensor!
esphome: name: epaperesp32 esp32: board: esp32dev framework: type: arduino # Enable logging logger: # Enable Home Assistant API api: services: - service: play_rtttl variables: song_str: string then: - rtttl.play: rtttl: !lambda 'return song_str;' output: - platform: ledc pin: GPIO22 id: rtttl_out rtttl: output: rtttl_out on_finished_playback: - logger.log: 'Song ended!' ota: password: "xxxxxxxxxxxxxxxxxxxxxxxxxxx" wifi: ssid: !secret wifi_ssid password: !secret wifi_password # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Epaperesp32 Fallback Hotspot" password: "xxxxxxxxxxxxxxxxx" captive_portal: font: - file: 'fonts/tahoma.ttf' id: font1 size: 16 - file: 'fonts/tahoma.ttf' id: font2 size: 32 sensor: - platform: adc pin: GPIO36 name: "epaperesp32 Battery voltage" id: battery_voltage icon: mdi:battery device_class: voltage attenuation: auto filters: - multiply: 3 update_interval: 60s text_sensor: - platform: homeassistant entity_id: sensor.bbqenv name: "mystate" id: mystate internal: true - platform: homeassistant entity_id: sensor.bbqcore name: "mystate1" id: mystate1 internal: true - platform: homeassistant entity_id: sensor.time name: "mytime" id: mytime internal: true spi: clk_pin: GPIO13 mosi_pin: GPIO14 binary_sensor: - platform: gpio pin: number: GPIO12 inverted: true mode: input: true pullup: true name: "epaperesp32 button" filters: - delayed_on: 50ms on_press: - logger.log: "Button pressed" display: - platform: waveshare_epaper cs_pin: GPIO15 dc_pin: GPIO27 busy_pin: GPIO25 reset_pin: GPIO26 model: 2.13in-ttgo rotation: 270 full_update_every: 12 update_interval: 10s lambda: |- it.print(0, 0, id(font2), "BBQ Meter V3"); it.printf( 35, 32, id(font2), "%s", id(mystate).state.c_str()); it.printf( 155, 32, id(font2), "%s", id(mystate1).state.c_str());
MQTT Notifier over Internet
This is part of a test where my friends and me can have notifications LEDs over the internet.
Using certificate parts from:
Controlling the led will be done using Mattermost webhooks, or slashcommand with custom scripting.
(Mattermost is my own hosted chat server)
I flashed a Wemos with below code:
(Rotary/display/button part removed.)
#include <ESP8266WiFi.h> #include <WiFiClientSecure.h> #include <time.h> #include <PubSubClient.h> #include <Adafruit_NeoPixel.h> #define encoderCLK 5 //D1 #define encoderDT 4 //D2 #define rgbled D4 //D4 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, rgbled, NEO_RGB + NEO_KHZ400); int servoAngle = 0; int crntCLK; int prvsCLK; String myString; char ang[50]; #ifndef SECRET const char ssid[] = "MYSSID"; const char pass[] = "MYPASS"; #define HOSTNAME "henrimqtt" const char MQTT_HOST[] = "www.henriaanstoot.nl"; const int MQTT_PORT = 9883; const char MQTT_USER[] = "xxxxxx"; // leave blank if no credentials used const char MQTT_PASS[] = "xxxxxx"; // leave blank if no credentials used const char MQTT_SUB_TOPIC[] = "notification/" HOSTNAME "/in"; const char MQTT_PUB_TOPIC[] = "notification/" HOSTNAME "/out"; const char MQTT_PUB_TOPIC_angle[] = "notification/" HOSTNAME "/send"; #ifdef CHECK_CA_ROOT static const char digicert[] PROGMEM = R"EOF( -----BEGIN CERTIFICATE----- MIIFtTCCA52gAwIBAgIUXEEQRLHhYox8a95YiAYX/wQ/XeMwDQYJKoZIhvcNAQEN //--------------- SNIP SNIP ... generated cert here vht8GyCCgCH55Syvy9ls6gCyLjTT2rtllw== -----END CERTIFICATE----- )EOF"; #endif #ifdef CHECK_PUB_KEY // Extracted by: openssl x509 -pubkey -noout -in ca.crt static const char pubkey[] PROGMEM = R"KEY( -----BEGIN PUBLIC KEY----- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxx -----END PUBLIC KEY----- )KEY"; #endif #ifdef CHECK_FINGERPRINT // Extracted by: openssl x509 -fingerprint -in ca.crt static const char fp[] PROGMEM = "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD"; #endif #endif ////////////////////////////////////////////////////// #if (defined(CHECK_PUB_KEY) and defined(CHECK_CA_ROOT)) or (defined(CHECK_PUB_KEY) and defined(CHECK_FINGERPRINT)) or (defined(CHECK_FINGERPRINT) and defined(CHECK_CA_ROOT)) or (defined(CHECK_PUB_KEY) and defined(CHECK_CA_ROOT) and defined(CHECK_FINGERPRINT)) #error "cant have both CHECK_CA_ROOT and CHECK_PUB_KEY enabled" #endif BearSSL::WiFiClientSecure net; PubSubClient client(net); time_t now; unsigned long lastMillis = 0; void mqtt_connect() { while (!client.connected()) { Serial.print("Time: "); Serial.print(ctime(&now)); Serial.print("MQTT connecting ... "); if (client.connect(HOSTNAME, MQTT_USER, MQTT_PASS)) { Serial.println("connected."); client.subscribe(MQTT_SUB_TOPIC); } else { Serial.print("failed, status code ="); Serial.print(client.state()); Serial.println(". Try again in 5 seconds."); /* Wait 5 seconds before retrying */ delay(5000); } } } void receivedCallback(char* topic, byte* payload, unsigned int length) { // pixels.clear(); // Set all pixel colors to 'off' Serial.print("Received ["); Serial.print(topic); Serial.print("]: "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } if (!strncmp((char *)payload, "0", length)) { pixels.setPixelColor(0, pixels.Color(0, 0, 0)); pixels.show(); // Send the updated pixel colors to the hardware. } if (!strncmp((char *)payload, "1", length)) { pixels.setPixelColor(0, pixels.Color(150, 0, 0)); pixels.show(); // Send the updated pixel colors to the hardware. } if (!strncmp((char *)payload, "2", length)) { pixels.setPixelColor(0, pixels.Color(0, 0, 150)); pixels.show(); // Send the updated pixel colors to the hardware. } if (!strncmp((char *)payload, "3", length)) { pixels.setPixelColor(0, pixels.Color(0, 150, 0)); pixels.show(); // Send the updated pixel colors to the hardware. } } void setup() { pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) pinMode (encoderCLK,INPUT_PULLUP); pinMode (encoderDT,INPUT_PULLUP); prvsCLK = digitalRead(encoderCLK); Serial.begin(115200); Serial.println(); Serial.println(); Serial.print("Attempting to connect to SSID: "); Serial.print(ssid); WiFi.hostname(HOSTNAME); WiFi.mode(WIFI_STA); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(1000); } Serial.println("connected!"); Serial.print("Setting time using SNTP"); configTime(1 * 3600, 0, "pool.ntp.org", "time.nist.gov"); now = time(nullptr); while (now < 1510592825) { delay(500); Serial.print("."); now = time(nullptr); } Serial.println("done!"); struct tm timeinfo; gmtime_r(&now, &timeinfo); Serial.print("Current time: "); Serial.print(asctime(&timeinfo)); #ifdef CHECK_CA_ROOT BearSSL::X509List cert(digicert); net.setTrustAnchors(&cert); #endif #ifdef CHECK_PUB_KEY BearSSL::PublicKey key(pubkey); net.setKnownKey(&key); #endif #ifdef CHECK_FINGERPRINT net.setFingerprint(fp); #endif #if (!defined(CHECK_PUB_KEY) and !defined(CHECK_CA_ROOT) and !defined(CHECK_FINGERPRINT)) net.setInsecure(); #endif client.setServer(MQTT_HOST, MQTT_PORT); client.setCallback(receivedCallback); mqtt_connect(); pixels.setPixelColor(0, pixels.Color(0, 0, 0)); pixels.show(); // Send the updated pixel colors to the hardware. } void loop() { crntCLK = digitalRead(encoderCLK); if (crntCLK != prvsCLK){ // If the encoderDT state is different than the encoderCLK state then the rotary encoder is rotating counterclockwise if (digitalRead(encoderDT) != crntCLK) { servoAngle ++; } else { servoAngle --; } Serial.println(servoAngle); String myString = String(servoAngle); myString.toCharArray(ang, myString.length() + 1); client.publish(MQTT_PUB_TOPIC_angle, ang, false); } prvsCLK = crntCLK; now = time(nullptr); if (WiFi.status() != WL_CONNECTED) { Serial.print("Checking wifi"); while (WiFi.waitForConnectResult() != WL_CONNECTED) { WiFi.begin(ssid, pass); Serial.print("."); delay(10); } Serial.println("connected"); } else { if (!client.connected()) { mqtt_connect(); } else { client.loop(); } } if (millis() - lastMillis > 5000) { lastMillis = millis(); client.publish(MQTT_PUB_TOPIC, ctime(&now), false); } }