No clue where to begin with MQTT

Hi, I am fairly new to HA and brand new to MQTT and I have absolutely no clue where to begin. I build a 4-digit 7-segment LED clock and am currently using simple arduino code to run it. I do have another code I would prefer to use, that would allow me to integrate the clock into HA, but I have never used MQTT before and don’t have a clue how to begin building YAML to add the clock.

Does anyone have any suggestions? I have been looking at everything on YouTube, but the videos are either too basic (setting up Mosquitto, which I have already done) or way too complex.

Thank you in advance!!

What micro controller are you using? If it is a esp, rpipico, beken* or realtek* I highly suggest giving esphome are try :point_down:

Thank’s to the native api you don’t even need mqtt and get some advantages on top :page_with_curl:

Advantages over MQTT

The ESPHome native API has many advantages over using MQTT for communication with Home Automation software (currently only Home Assistant). But MQTT is a great protocol and will never be removed. Features of native API (vs. MQTT):

  • Much more efficient: ESPHome encodes all messages in a highly optimized format with protocol buffers - for example binary sensor state messages are about 1/10 of the size.
  • One-click configuration: ESPHome just needs one click to set up in Home Assistant - no more messing around with retained MQTT discovery messages and alike.
  • One less single point of failure: In the ESPHome native API each ESP is its own server. With MQTT, when the broker shuts off nothing can communicate anymore.
  • Stability: Since ESPHome has far more control over the protocol than with MQTT, it’s really easy for us to roll out stability improvements.
  • Low Latency: The native API is optimized for very low latency, usually this is only a couple of milliseconds and far less than can be noticed by the eye.

*currently only available in the dev branch - next week in stable :rocket:

@orange-assistant - I am using an ESP32 microcontroller (M5. I will definitely look into ESPHome.

Since I already have my LED string light clock built, I don’t know how I would begin to program that in ESPHome. Do you have any suggestions to get me started?

Thanks so much for the help!

-David

As others have suggested, do you need MQTT?

Start with showing your ESP32 code.

@stevemann - I was only using MQTT because that is what the code I had received for this clock uses. It seems that ESPHome is easier to learn…if that’s the case, I would not mind using ESPHome instead.

The Arduino clock code is very long - do you want me to post it all here?

Thanks!!

We can’t help you if we can’t see what you have done. A schematic, not a pretty picture, would also most useful.

Actually a proper schematic would be more informative than the code.

I will put the code below - I don’t have a schematic, but my main goal is to have a clock that I can control lights on/off, color, time zone, time sync, etc via HA. Secondary functionality I would like to add is timer. I don’t really care about temp, but if possible, I would eventually add that as well. Switching functions would also be taken care of in HA. Being able to control either function or clock color effects from the button on the microcontroller would also be helpful. The biggest issue I see is the order of the LEDs - this build had the data start at the bottom of the last digit and work it’s way forward. This code is set up to properly operate the LEDs based on the order of the LEDs. Hope this helps. Thank you very much for your help!!

/*
   LED NeoPixel Digital Clock
 

   26;   = NeoPixel Data Pin
   37;   = Push Button (Built-in)

   ESP32 Library             https://github.com/espressif/arduino-esp32
   FastLED Library           https://github.com/FastLED/FastLED
   ElegantOTA Library        https://github.com/ayushsharma82/ElegantOTA
   Time Library              https://github.com/PaulStoffregen/Time
   M5 Stack M5Stick C Plus   https://github.com/m5stack/M5StickC-Plus
*/

//##########################   Library/Variables   ###################################//

/***************************   Device Config ************************************/
const char* appVersion     =  "v39";
//const char* locationName   =  "Kitchen";
const char* locationName   =  "Pool";
const byte  screenRotation =  3;  // Pool = 1 / Kitchen = 3


/***************************   WiFi  ********************************************/
#include <WiFi.h>
const char* ssid     = "#########";     // SSID of Wifi
const char* password = "########";  // Wifi Password


/***************************   OTA   ********************************************/
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
AsyncWebServer server(80);


/***************************   HTTP Client  *************************************/
#include <HTTPClient.h>
#include <ArduinoJson.h>
String serverName = "https://worldtimeapi.org/api/timezone/America/Los_Angeles";  // Auto Adjust for Time Changes (SET CORRECT ONE FOR YOU http://worldtimeapi.org/)
byte hourNow = 0;
byte hourPrevious = 0;


/***************************   FastLED   ****************************************/
#include <FastLED.h>
#define DATA_PIN       26            // The Neopixel data pin
#define NUM_LEDS       86           // Number of Neopixel LED's connected
#define LED_TYPE       WS2812B       // Type of LED Chip
#define COLOR_ORDER    GRB           // Order of colors for LED Chip
#define BRIGHTNESS         255       // Max Brightness
#define FRAMES_PER_SECOND  120       // Used with FastLED.delay(1000/FRAMES_PER_SECOND);
CRGB leds[NUM_LEDS];

//  Red (0..) "HUE_RED", Orange (32..) "HUE_ORANGE", Yellow (64..) "HUE_YELLOW", Green (96..) "HUE_GREEN"
//  Aqua (128..) "HUE_AQUA", Blue (160..) "HUE_BLUE", Purple (192..) "HUE_PURPLE", Pink(224..) "HUE_PINK"

byte firstPixelHue = 0;                       // Rainbow starting color
byte brightnessLED = 128;                     // Adjustable by button
byte clockColor = 0;                          // Color for colorWipe & singleColor
const byte colorChangeAmount = 50;            // Jump between colors on colorWipe
byte colorWipePixel = 0;                      // Location of changing pixel color
byte colorWipeColor = 0 + colorChangeAmount;  // 2nd color in colorWipe that replaces 1st color
byte prevWipeColor = 0;                       // 1st color in colorWipe
// Variables for colors
int RedLED = 0;
int GreenLED = 180;
int BlueLED = 60;
byte Red_LED = 0;
byte Green_LED = 180;
byte Blue_LED = 60;


/***************************   Time  ********************************************/
#include <TimeLib.h>
#include <WiFiUdp.h>
static const char ntpServerName[] = "us.pool.ntp.org";
int timeZone = -7;                          // -8 = Pacific Standard Time (USA)  or  -7 = Pacific Daylight Time (USA)
WiFiUDP Udp;                                // UDP instance
unsigned const int localPort = 8888;        // local port to listen for UDP packets
time_t prevDisplay = 0;                     // when the digital clock was displayed
const int NTP_PACKET_SIZE = 48;             // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE];         // buffer to hold incoming & outgoing packets


/***************************   Button  ******************************************/
#define button 37
#define modeMax 19
#define modeMin 0
byte buttonPushCounter = 0;                 // counter for the number of button presses
unsigned long buttonTimer = 0;              // used to capture millis for button timer
const int longPressTime = 500;              // time to hold button for secondary action
boolean buttonActive = false;               // used for short or long press logic
boolean longPressActive = false;            // used for short or long press logic


/***************************   Variables  ***************************************/
const bool digit[15][21] =  {
  /*    1        2        3        4        5        6        7      */
  {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 0
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 1
  {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1}, // 2
  {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, // 3
  {1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 4
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0}, // 5
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 6
  {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 7
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 8
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, // 9
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 10 = Blank
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, // 11 = F
  {1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1}, // 12 = H
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 13 = upper circle
  {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 14 = lower circle
};

bool pixelNumber[130];    // Used to capture each number and correctly align with pixel numbers

byte digitOne =  0;       // Variable to designate which number to show
byte digitTwo =  0;       // Variable to designate which number to show
byte digitThree =  0;     // Variable to designate which number to show
byte digitFour =  0;      // Variable to designate which number to show


unsigned long currentMillis = 0;   // Used throughout loop as current millis
byte currentSecond = 0;            // Used throughout loop as current second
byte currentMinute = 0;            // Used throughout loop as current minute


/***************************   EEPROM  ******************************************/
#include <EEPROM.h>
int addr = 0;           // address "0" is used for switch state; address "1" is used for brightness setting
// address "2" is for timezone offset


/***************************   M5Stick-C  ***************************************/
#include <M5StickCPlus.h>



//##########################   Setup  ############################################//
void setup() {
  Serial.begin(115200);


/***************************   M5Stick-C  ***************************************/
  M5.begin();
  M5.Lcd.setRotation(screenRotation);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.setTextSize(2);
  //M5.Lcd.setTextWrap(false,false); //Doesn't Work
  M5.Lcd.setCursor(5, 6);
  M5.Lcd.printf("DEVICE STARTING UP      ");


  /***************************   EEPROM  ******************************************/
  EEPROM.begin(16);                       // Number of bytes allocated for EEPROM
  buttonPushCounter = EEPROM.read(addr);  // Sets switch state to previous state before restart
  addr++;                                 // Changes from 0 to 1
  brightnessLED = EEPROM.read(addr);      // Sets brightness to previous state before restart
  addr++;                                 // Changes from 1 to 2
  byte timeZoneByte = EEPROM.read(addr);  // Read timezone setting from before restart
  timeZone = timeZoneByte - 12;           // Adjust to actual value because byte is only positive
  updateColorLED();

  /***************************   Button  ******************************************/
  pinMode(button, INPUT);                 // Push button to control mode and brightness

  /***************************   FastLED   ****************************************/
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);   // tell FastLED about the LED strip configuration
  FastLED.setBrightness(BRIGHTNESS);                                  // Set master brightness control (max = 255)
  //for (byte i = 0; i < 130; i++) {                                    // For each pixel in strip...
  //  leds[i].setHSV(i+2, 255, 180);
  //}
  //FastLED.show();

  /***************************   WiFi  ********************************************/
    WiFi.setAutoReconnect (true);           // WiFi setting for auto reconnect (true = active)
  WiFi.mode(WIFI_STA);                    // Set WiFi to starting mode
  WiFi.begin(ssid, password);             // Initialize WiFi connection
  while (WiFi.status() != WL_CONNECTED) { // While not connected, wait
    delay(500);
  }
  M5.Lcd.setCursor(5, 6);
  M5.Lcd.printf("CONNECTED TO WIFI       ");
delay(500);

  /***************************   OTA   ********************************************/
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(200, "text/plain", "HI! This is the LED Clock.\n\n+++ Add /update to IP address to load the update webpage. +++");
  });
  AsyncElegantOTA.begin(&server);    // Start ElegantOTA
  server.begin();
  Serial.println("HTTP server started");

  /***************************   Time  ********************************************/
  Udp.begin(localPort);
  setSyncProvider(getNtpTime);
  setSyncInterval(60 * 15 * 1);     // seconds * minutes * hours

  timezoneManager();                // Call timezone update only once on boot
  M5.Lcd.setCursor(5, 6);
  M5.Lcd.printf("%s Clock Running", locationName);
 
}    // end of setup()

//##########################   Loop   ############################################//

void loop() {
  currentSecond = second();
  currentMinute = minute();
  currentMillis = millis();
  buttonControl();
  
  /***************************   Clock Mode  **************************************/
  switch (buttonPushCounter) {
    case 0:
      runClock();
      singleColor(50);
      break;
    case 1:
      runClock();
      rainbow(10);
      break;
    case 2:
      runClock();
      colorWipe(25);
      break;
    case 3:
      runClock();
      twoColor(25, 128, 160);
      break;
    case 4:
      runClock();
      solidColor(25, 0, 255); // Red
      break;
    case 5:
      runClock();
      solidColor(25, 16, 255); // Red-Orange
      break;
    case 6:
      runClock();
      solidColor(25, 32, 255); // Orange
      break;
    case 7:
      runClock();
      solidColor(25, 48, 255); // Orange-Yellow
      break;
    case 8:
      runClock();
      solidColor(25, 64, 255); // Yellow
      break;
    case 9:
      runClock();
      solidColor(25, 80, 255); // Yellow-Green
      break;
    case 10:
      runClock();
      solidColor(25, 96, 255); // Green
      break;
    case 11:
      runClock();
      solidColor(25, 112, 255); // Green-Aqua
      break;
    case 12:
      runClock();
      solidColor(25, 128, 255); // Aqua
      break;
    case 13:
      runClock();
      solidColor(25, 144, 255); // Aqua-Blue
      break;
    case 14:
      runClock();
      solidColor(25, 160, 255); // Blue
      break;
    case 15:
      runClock();
      solidColor(25, 176, 255); // Blue-Purple
      break;
    case 16:
      runClock();
      solidColor(25, 192, 255); // Purple
      break;
    case 17:
      runClock();
      solidColor(25, 208, 255); // Purple-Pink
      break;
    case 18:
      runClock();
      solidColor(25, 224, 255); // Pink
      break;
    case 19:
      runClock();
      solidColor(25, 0, 0); // White
      break;
  }
}    // end of loop()


//##########################   Functions   #########################################//

/***************************   Button  ******************************************/
void buttonControl() {
  if (digitalRead(button) == LOW) {
    if (buttonActive == false) {
      buttonActive = true;
      buttonTimer = millis();
    }
    if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {
      longPressActive = true;
      brightnessLED = brightnessLED - 32;                   // Brightness wraps around at 255
      addr = 1;                                             // Brightness address
      Serial.print("LED Brightness: ");
      Serial.println(brightnessLED);
      EEPROM.write(addr, brightnessLED);
      EEPROM.commit();
      updateColorLED();
    }
  } else {
    if (buttonActive == true) {
      if (longPressActive == true) {
        longPressActive = false;
      } else {
        buttonPushCounter++;
        if (buttonPushCounter > modeMax) buttonPushCounter = modeMin;   // Match number to the number of cases
        addr = 0;                                           // Button address
        Serial.print("Clock Mode: ");
        Serial.println(buttonPushCounter);
        EEPROM.write(addr, buttonPushCounter);
        EEPROM.commit();
        updateColorLED();
      }
      buttonActive = false;
    }
  }
}


/***************************   Clock  ********************************************/
void runClock() {
  if (timeStatus() != timeNotSet) {
    if (now() != prevDisplay) {                     //update the display only if time has changed
      prevDisplay = now();
      clockDigits();
      prepDigits();
    }
  }
}

void clockDigits() {

  digitOne = minute() % 10;
  digitTwo = (minute() - digitOne) / 10;
  digitThree = hourFormat12() % 10;
  digitFour = (hourFormat12() - digitThree) / 10;
  if (digitFour == 0) {
    digitFour = 10;       // 10 is blank
  }

  pixelNumber[42] = 1;
  pixelNumber[43] = 1;


  byte digitFourPrint = digitFour;
  if (digitFour == 10) digitFourPrint = 0;
  M5.Lcd.setCursor(10, 30);
  M5.Lcd.printf("Time: %i%i:%i%i   ",
                digitFourPrint, digitThree, digitTwo, digitOne);

}


/***************************   Digits  ********************************************/
void prepDigits() {
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i] = digit[digitOne][i];
  }
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i + 21] = digit[digitTwo][i];
  }
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i + 44] = digit[digitThree][i];
  }
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i + 65] = digit[digitFour][i];
  }
  
}


/***************************   FastLED   ****************************************/
// Input is a delay time (in milliseconds) between pixels.

void colorWipe(int wait) {                          // Fill strip pixels one after another with a color. Strip is NOT cleared first;
  for (byte i = 0; i < 130; i++) {                  //For each pixel in strip...
    if (i > colorWipePixel) {
      clockColor = prevWipeColor;
    } else {
      clockColor = colorWipeColor;
    }
    leds[i].setHSV(clockColor, 255, (brightnessLED * pixelNumber[i]));
  }
  FastLED.show();                                   //Update strip to match
  colorWipePixel++;
  if (colorWipePixel > 130) {
    colorWipePixel = 0;
    colorWipeColor = colorWipeColor + colorChangeAmount;
    prevWipeColor = prevWipeColor + colorChangeAmount;
  }
  delay(wait);
}

void rainbow(int wait) {                            // Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
  for (byte i = 0; i < 130; i++) {                  // For each pixel in strip...
    int pixelHue = firstPixelHue + (i * 2);
    leds[i].setHSV(pixelHue, 255, (brightnessLED * pixelNumber[i]));
  }
  FastLED.show();                                   // Update strip with new contents
  delay(wait);
  firstPixelHue = firstPixelHue + 1;
  if (firstPixelHue >= 255) firstPixelHue = 0;
}

void singleColor(int wait) {                        // Entire clock fades the colors of the rainbow.
  for (byte i = 0; i < 130; i++) {                  // For each pixel in strip...
    leds[i].setHSV(clockColor, 255, (brightnessLED * pixelNumber[i]));
  }
  FastLED.show();

  clockColor = clockColor + 1;
  if (clockColor >= 255) clockColor = 0;
  delay(wait);
}

void solidColor(int wait, byte solidColor, byte solidSaturation) {                         // Entire clock stays one color.
  for (byte i = 0; i < 130; i++) {                  // For each pixel in strip...
    leds[i].setHSV(solidColor, solidSaturation, (brightnessLED * pixelNumber[i]));
  }
  FastLED.show();
  delay(wait);
}

void updateColorLED() {
  if (buttonPushCounter == 4) {
    FastLED.setBrightness(brightnessLED);
  } else {
    FastLED.setBrightness(BRIGHTNESS);
  }
  float brightnessRGB = brightnessLED;
  brightnessRGB = brightnessRGB / (RedLED + GreenLED + BlueLED);
  Red_LED = (RedLED * brightnessRGB);
  Green_LED = (GreenLED * brightnessRGB);
  Blue_LED = (BlueLED * brightnessRGB);
}

void twoColor(int wait, byte colorOne, byte colorTwo) {
  if (digitOne % 2) {
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i].setHSV(colorOne, 255, (brightnessLED * pixelNumber[i]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 21].setHSV(colorTwo, 255, (brightnessLED * pixelNumber[i + 21]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 44].setHSV(colorOne, 255, (brightnessLED * pixelNumber[i + 44]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 65].setHSV(colorTwo, 255, (brightnessLED * pixelNumber[i + 65]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 88].setHSV(colorOne, 255, (brightnessLED * pixelNumber[i + 88]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 109].setHSV(colorTwo, 255, (brightnessLED * pixelNumber[i + 109]));
    }

  } else {
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i].setHSV(colorTwo, 255, (brightnessLED * pixelNumber[i]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 21].setHSV(colorOne, 255, (brightnessLED * pixelNumber[i + 21]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 44].setHSV(colorTwo, 255, (brightnessLED * pixelNumber[i + 44]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 65].setHSV(colorOne, 255, (brightnessLED * pixelNumber[i + 65]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 88].setHSV(colorTwo, 255, (brightnessLED * pixelNumber[i + 88]));
    }
    for (byte i = 0; i < 21; i++) {                  // For each pixel in strip...
      leds[i + 109].setHSV(colorOne, 255, (brightnessLED * pixelNumber[i + 109]));
    }
  }

  leds[42].setHSV(0, 0, brightnessLED);
  leds[43].setHSV(0, 0, brightnessLED);
  leds[86].setHSV(0, 0, brightnessLED);
  leds[87].setHSV(0, 0, brightnessLED);

  FastLED.show();
  delay(wait);
}


/***************************   WiFi  ********************************************/
bool wifiConnection() {
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.disconnect();
    delay(100);
    Serial.println("Wifi Reconnecting");
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    delay(200);
    if (WiFi.status() == WL_CONNECTED) {
      return 1;
    } else {
      return 0;
    }
  } else {
    return 1;
  }
}


/***************************   NTP  *********************************************/
time_t getNtpTime() {
  if (wifiConnection()) {
    IPAddress ntpServerIP;                          // NTP server's ip address
    while (Udp.parsePacket() > 0) yield();          // discard any previously received packets
    WiFi.hostByName(ntpServerName, ntpServerIP);    // get a random server from the pool
    sendNTPpacket(ntpServerIP);
    uint32_t beginWait = millis();
    while (millis() - beginWait < 1500) {
      yield();
      int size = Udp.parsePacket();
      if (size >= NTP_PACKET_SIZE) {
        Udp.read(packetBuffer, NTP_PACKET_SIZE);    // read packet into the buffer
        unsigned long secsSince1900;                // convert four bytes starting at location 40 to a long integer
        secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
        secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
        secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
        secsSince1900 |= (unsigned long)packetBuffer[43];
        return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
      }
    }
  }
  return 0;                                        // return 0 if unable to get the time
}

void sendNTPpacket(IPAddress &address)             // send an NTP request to the time server at the given address
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE);        // Set all bytes in the buffer to 0
  packetBuffer[0] = 0b11100011;                    // LI, Version, Mode
  packetBuffer[1] = 0;                             // Stratum, or type of clock
  packetBuffer[2] = 6;                             // Polling Interval
  packetBuffer[3] = 0xEC;                          // Peer Clock Precision
  packetBuffer[12] = 49;                           // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;                           // All NTP fields have been given values, now
  Udp.beginPacket(address, 123);                   // NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
  Serial.println("Time Updated");
}


/***************************  HTTP GET TIMEZONE  ********************************/
void timezoneManager() {
  if (wifiConnection()) {
    bool timezoneBool = httpGetPayload();
    byte timeZoneByte = 0;

    if (timezoneBool == false) {
      timeZone = -8;                    // -8 = Pacific Standard Time (USA)
      timeZoneByte = timeZone + 12;
      EEPROM.write(2, timeZoneByte);
      EEPROM.commit();
      Serial.println("Timezone Updated to -8 Pacific Standard Time (USA)");
    
    } else if (timezoneBool == true) {
      timeZone = -7;                    // -7 = Pacific Daylight Time (USA)
      timeZoneByte = timeZone + 12;
      EEPROM.write(2, timeZoneByte);
      EEPROM.commit();
      Serial.println("Timezone Updated to -7 = Pacific Daylight Time (USA)");     
    }    
  } else {
      byte timeZoneByte = EEPROM.read(3);  // Read timezone setting from before restart
      timeZone = timeZoneByte - 12;   
  }
}

bool httpGetPayload() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;

    // Send request
    http.useHTTP10(true);
    http.begin(serverName.c_str());
    int httpResponseCode = http.GET();

    StaticJsonDocument<256> doc;
    deserializeJson(doc, http.getStream());

    /*    DeserializationError error = deserializeJson(doc, http.getStream());

        if (error) {
          Serial.print(F("deserializeJson() failed: "));
          Serial.println(error.f_str());
          return;
        }
    */
    //const char* abbreviation = doc["abbreviation"]; // "PDT"
    //const char* client_ip = doc["client_ip"]; // "24.11.53.227"
    //const char* datetime = doc["datetime"]; // "2021-07-20T20:22:57.419423-06:00"
    //int day_of_week = doc["day_of_week"]; // 2
    //int day_of_year = doc["day_of_year"]; // 201
    bool dst = doc["dst"]; // true
    //const char* dst_from = doc["dst_from"]; // "2021-03-14T09:00:00+00:00"
    //int dst_offset = doc["dst_offset"]; // 3600
    //const char* dst_until = doc["dst_until"]; // "2021-11-07T08:00:00+00:00"
    //int raw_offset = doc["raw_offset"]; // -25200
    //const char* timezone = doc["timezone"]; // "America/Denver"
    //long unixtime = doc["unixtime"]; // 1626834177
    //const char* utc_datetime = doc["utc_datetime"]; // "2021-07-21T02:22:57.419423+00:00"
    //const char* utc_offset = doc["utc_offset"]; // "-06:00"
    //int week_number = doc["week_number"]; // 29

    // Disconnect
    http.end();

    return dst;
  }
}

What is the hardware?

The controller is an M5StickC PLUS (ESP32-PICO-D4) and the LEDs are WS2812B strings.

I assume the LEDs are in some sort of matrix?

If so you can probably use this. Addressable Light — ESPHome

Once that is set up you can write to it like a display. That is, print the current time, or any string.

No, it isn’t a matrix. Below is a pic of the direction of the data and the final with LEDs on:

Still doable although not quite as easy. You can do partitioning of the lights with Light Partition — ESPHome

This 7-segment display has a short code for a clock :point_down:

Guess you can adapt that to work with your segments based on light partitions linked by @nickrout

If you are new to ESPHome, don’t dive into the deep end from the start. Your project is entirely doable in ESPHome, and as you see there are more than one way to accomplish it.

Get an ESP device (I like the Wemos D1 Mini for projects like this). Use a proto board and a few components (LEDs and buttons) to experiment with ESPHome.

Nick, thanks for the link. I was not aware of this platform.

I found a project I am going to use to learn from - it uses a 7-segment LED clock - I will probably just have to figure out the data order for the LEDs:

(the code is in the summary)

The project uses an ESP-01…can I use an ESP-12e instead? I believe I can since they are both ESP8266, but the 12e would give me a USB port and 5v in (would rather that then having to use a programmer and a buck converter).

Thanks!
-David

Should be no problem as long as the esp has enough GPIOs exposed.

The 12e is a module made by Expressif that has in its core an ESP8266 chip. You will find the 12e module on many ESP-8266 developer boards like the NodeMCU and Wemos D1 Mini, and embedded in hundreds of WiFi products. The ESP-01 is basically an ESP8266 chip with four GPIO pins exposed. I have several projects around my home that use the ESP-01.

My go-to board is the Wemos D1 Mini. It has the power supply and UART built-in so it’s easy to use and flash. The NodeMCU is also a good option and has more GPIO pins exposed.

Some ESP32 boards expose even more GPIO pins. The ESP chips are 3.3V devices, so don’t ever put 5V on a GPIO pin.

Thank you! I ordered the D1 mini - should be here today.

I understand about the 3.3v, but the VIN can take 5v, correct?

Thanks again!!

While this is true - a ESP82xx based NodeMCU still does not have more usable GPIOs compared to a esp82xx based D1 Mini. The extra pins like SDD1, SDD2, … are already in use and connected internally to the flash chip. :point_down:

Most of them (if it’s not for some tiny line) do indeed - and the ESP32 SoC themselves have already many more usable GPIOs compared to the ESP82xx :raised_hands: