Time to C++ invalid conversion from 'uint8_t'

Hi,

I am working on a project where I want to use several inputs from Home Assistant using ESPHome and custom C++ code via an external file. The project is a wordclock, which I now have working on via Arduino, but it’s rather static. All code runs on the Arduino, and I am trying to change this to an ESP32 with connection to ESPHome/HA.

So far I have been able to add several components (2 input numbers, and 1 boolean), but I am really struggling getting anything time-related to pass to the code.

The YAML file contains the following:

esphome:
  name: wordclock
  platform: ESP32
  board: esp32doit-devkit-v1
  includes:
    - wordclock/wordclock.h
  libraries:
    - Wire
    - SPI
    - adafruit/Adafruit BusIO @ ^1.14.1
    - adafruit/Adafruit GFX Library @ ^1.11.3
    - adafruit/Adafruit NeoPixel @ ^1.10.6
    - adafruit/Adafruit NeoMatrix @ ^1.3.0
    
    

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "code..."

ota:
  password: "password..."

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Wordclock Fallback Hotspot"
    password: "h6NtbR90xUJ2"

captive_portal:

time:
  - platform: homeassistant
    id: blink_time

number:
  - platform: template
    name: "Frequency"
    id: blink_frequency
    optimistic: true
    min_value: 1
    max_value: 100
    step: 1
    restore_value: true
    
  - platform: template
    name: "Brightness"
    id: blink_brightness
    optimistic: true
    min_value: 1
    max_value: 255
    step: 1
    restore_value: true

switch:
  - platform: template
    name: "Enable"
    id: blink_enable
    optimistic: true
    restore_state: true

custom_component:
- lambda: |-
    auto myComponent = new AdvancedBlinkComponent(id(blink_enable), id(blink_frequency), id(blink_brightness), id(blink_time).now().hour);
    return {myComponent};

my wordclock/wordclock.h file contains this:

#include "esphome.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

#define LED_PIN 2
#define PIN     15
#define NUMPIXELS 16 // Popular NeoPixel ring size
#define MATRIXWIDTH 16 // Popular NeoPixel ring size
#define MATRIXHEIGHT 16 // Popular NeoPixel ring size

//Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(MATRIXWIDTH, MATRIXHEIGHT, PIN,
                          NEO_MATRIX_BOTTOM  + NEO_MATRIX_RIGHT +
                          NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
                          NEO_GRB            + NEO_KHZ800);


class AdvancedBlinkComponent : public Component
{
public:
  unsigned long last_led_change;
  bool enable = false;
  float frequency = 1;
  float brightness = 0;
  int hour = 0;

  AdvancedBlinkComponent( esphome::template_::TemplateSwitch *&_enable, 
                          esphome::template_::TemplateNumber *&_frequency, 
                          esphome::template_::TemplateNumber *&_brightness, 
                          esphome::template_::TemplateNumber *&_timetest)
  {
    _enable->add_on_state_callback([this](bool newState)
                                   { enable = newState; });
    _frequency->add_on_state_callback([this](float newFrequency)
                                      { frequency = newFrequency; });
    _brightness->add_on_state_callback([this](float newBrightness)
                                      { brightness = newBrightness; });
    _timetest->add_on_state_callback([this](int newHour)
                                      { hour = newHour; });
  }

  void setup() override
  {
    pinMode(LED_PIN, OUTPUT);
    last_led_change = millis();
    matrix.begin(); // INITIALIZE NeoMatrix object (REQUIRED)
    matrix.setBrightness(40);
    matrix.fillScreen(0);
    matrix.show();
    
    
  }

  void loop() override
  {
    if (enable == false)
    {
      matrix.fillScreen(0);
      matrix.show();
      return;
    }

    unsigned long now = millis();

    if (last_led_change + 1000 / frequency  < now)
    {
      digitalWrite(LED_PIN, !digitalRead(LED_PIN));
      last_led_change = now;
        
        
        
      // NEOMATRIX  
      matrix.setBrightness(brightness);
      matrix.fillScreen(0);
      matrix.drawPixel(0, 0, matrix.Color(0, 0, 255));
      if (digitalRead(LED_PIN) == 1) {
        matrix.setTextColor(matrix.Color(255, 0, 0));
        matrix.setCursor(2, 0);
        matrix.print(F("12"));
      }
      else {
        matrix.setTextColor(matrix.Color(0, 128, 128));
        matrix.setCursor(2, 9);
        matrix.print(F("48"));
      }
      matrix.show();
      
    }
    
  }
};

While trying to compile the code I get the following error:

error: invalid conversion from 'uint8_t {aka unsigned char}' to 'esphome::template_::TemplateNumber*' [-fpermissive]

I believe the issues lies within the wordclock.h code, but I am not sure. I have tried to use several different ways of passing the ‘hour’ value of the homeassistant_time, but I keep getting errors like this.
The fact that the 3 other values pass fine (enable, frequency, brightness) but the hour-value doesn’t, makes my head spin.

ps. I am not a c++ developer, but have so far been able to get the wordclock working via the Arduino IDE. So I have a feeling that this issue is specific to the ESPHome part of things?

In the end I use multiple parts of the time-logic, so I am not sure if it would make sense to pass the year, month, day, hour and minute separately, or to pass the timestamp and then do the split logic in my wordclock.h file. Either way, I guess if I get at least one of them working, then that example would make me able to add the rest too.

You don’t say where is the error, but the message tells you are trying to push an integer (uint8_t/char) to a pointer (esphome::template_::TemplateNumber*).

It can be on purpose (in which case you’d want to cast), but it’s unlikely…

I have 4 values to pass in this code:

custom_component:
- lambda: |-
    auto myComponent = new AdvancedBlinkComponent(id(blink_enable), id(blink_frequency), id(blink_brightness), id(blink_time).now().hour);
    return {myComponent};

and they are picked up via

AdvancedBlinkComponent( esphome::template_::TemplateSwitch *&_enable, 
                          esphome::template_::TemplateNumber *&_frequency, 
                          esphome::template_::TemplateNumber *&_brightness, 
                          esphome::template_::TemplateNumber *&_timetest)
  {
    _enable->add_on_state_callback([this](bool newState)
                                   { enable = newState; });
    _frequency->add_on_state_callback([this](float newFrequency)
                                      { frequency = newFrequency; });
    _brightness->add_on_state_callback([this](float newBrightness)
                                      { brightness = newBrightness; });
    _timetest->add_on_state_callback([this](int newHour)
                                      { hour = newHour; });
  }

These 3 work:

  • id(blink_enable) of type boolean
  • id(blink_frequency) of type float
  • id(blink_brightness) of type float

The one that does not work is:

  • id(blink_time).now().hour

As per documentation of the ESPHome Time component the .hour should give an integer between 0-23
As per the error I think it actually is an integer, but then goes wrong by picking it up in my wordclock.h code.

I am not sure if this pointer (esphome::template_::TemplateNumber) is correct, but it does work for the others. I have also tried several other things like

esphome::number::Number
esphome::time::ESPTime

But these also are incorrect.

I guess I am not understanding the workings of these pointers. I have tried to search Google many times, but can’t get an example of a time-component (timestamp, hour, minute) that works in this setup.

Hope you can point me in the right direction.

I’m not that familiar with ESPHome, and I know nothing of blink. But I can help you out a little in your misunderstandings about the parameters.

id(…) is never a boolean or float, but an object. In these cases template switches and sensors. So what you state above is technically not correct. You’d normally get the actual value from the blink.enable object using id(blink.enable).state and that is a boolean. But if you pass that to the constructor, the constructor is not able to change it. That is why it uses pointers to objects it can change. The ones you mention here are the right type of objects.

id(blink_time) may or may not be the object you need, but once you do id(blink_time).now().hour you no longer have a pointer to an object, but something from inside the object. In this case an 8 bit int or character. What you need to pass is a template sensor for a number, that the callback functions can put values in. So also something in the form id(…) and nothing after that.

1 Like

Thanks. That does make a lot of sense now. And while it did not directly lead to the solution, it definitely pushed me in the right direction.
I’ve solved it in a different way:
To my ESP32 a DS3231 RTC is connected. I wanted to get the time-value from HA, and then update the RTC via the “Arduino” code. I am now using the DS1307 option in the ESPhome to set the time to the DS3231 and with the arduino code I can then read the time from the RTC when required.

time:
  - platform: ds1307
    update_interval: never
  - platform: homeassistant
    on_time_sync:
      then:
        ds1307.write_time:

The rest is done in the Arduino code. When the RTC has lost the time (empty battery for example), then when booting it will receive the time within seconds. I am still thinking of adding a daily trigger to update the time, but for now I do not see that being necessary.

1 Like