Thx for your reply!
That would be a good alternative if there is no solution in ESPHome to capture and store the time stamp the button was pressed (which I prefer as I would like to use a kind a like setup for my garage doors, first trying to find the bell working as it has less impact than my garage doors which currently work on tasmota/MQTT)
While what you want to do is doable. There’s another option:
In Lovelace I have some motion sensor configured this way.
entities:
- entity: binary_sensor.movimiento_galeria
secondary_info: last-changed
So it renders when was the last time a movement was triggered.
1 hour ago, 5 minutes ago, etc.
and if you click on the entity you will see a chart when this happened and also the timestamps in the logbook.
Now if you really want the string with the formatted string, that is doable, you need the time:
component, look at the strftime
you need to combine that with a lambda call on your text sensor to id(text_sensor).publish_state(strftime(...))
.
I really can’t figure out why you need to store this in esphome, but maybe I am just missing the point.
Sometimes I think people expect to put too much into an esphome device. While some automation on the esp device is understandable (such as the automation suggested in the docs of a button and a switch on the same esp https://esphome.io/guides/automations.html)[1], I prefer home assistant to be doing most of the controlling, and to hold the state information. One of the reasons for HA is to have everything centralised.
[1] At heart this is no more than what a smart plug has - a switch and a button.
Bit late, but just implemented this myself:
on_press:
then:
- text_sensor.template.publish:
id: last_bell_press
state: !lambda |-
char str[17];
time_t currTime = id(homeassistant_time).now().time;
strftime(str, sizeof(str), "%Y-%m-%d %H:%M", localtime(&currTime));
return { str };
Also requires:
time:
- platform: homeassistant
id: homeassistant_time
(The reason I’ve added this rather than doing it in home assistant is that I’ve had a few instances of missed notifications, so I wanted a backup mechanism to check the last time the doorbell was pressed.)
HTH,
James
Thanks James!
Will they it out over the weekend
Hey James
I just came across your solution and wanted to implement it. Unfortunately this way seems to be deprecated now. May I ask you whether you still have a working solution for this?
My relay is only on for 0.5s and won’t update its status in HA.
Thank you in advance!
I’m still using the same method described above. It’s working very well.
Which aspect has been deprecated?
James
Thanks for your fast answer - really appreciate it.
Here’s what I got as log output:
src/main.cpp: In lambda function:
src/main.cpp:226:40: warning: 'esphome::time::ESPTime::<anonymous union>::time' is deprecated: .time is deprecated, use .timestamp instead [-Wdeprecated-declarations]
time_t currTime = ha_time->now().time;
^
In file included from src/esphome/components/homeassistant/time/homeassistant_time.h:4:0,
from src/esphome.h:14,
from src/main.cpp:3:
src/esphome/components/time/real_time_clock.h:35:73: note: declared here
ESPDEPRECATED(".time is deprecated, use .timestamp instead") time_t time;
^
src/main.cpp:226:40: warning: 'esphome::time::ESPTime::<anonymous union>::time' is deprecated: .time is deprecated, use .timestamp instead [-Wdeprecated-declarations]
time_t currTime = ha_time->now().time;
^
In file included from src/esphome/components/homeassistant/time/homeassistant_time.h:4:0,
from src/esphome.h:14,
from src/main.cpp:3:
src/esphome/components/time/real_time_clock.h:35:73: note: declared here
ESPDEPRECATED(".time is deprecated, use .timestamp instead") time_t time;
^
src/main.cpp:226:40: warning: 'esphome::time::ESPTime::<anonymous union>::time' is deprecated: .time is deprecated, use .timestamp instead [-Wdeprecated-declarations]
time_t currTime = ha_time->now().time;
^
In file included from src/esphome/components/homeassistant/time/homeassistant_time.h:4:0,
from src/esphome.h:14,
from src/main.cpp:3:
src/esphome/components/time/real_time_clock.h:35:73: note: declared here
ESPDEPRECATED(".time is deprecated, use .timestamp instead") time_t time;
Yesterday when I tried this, I assumed it was an error and went back to my old yaml - but now I realize it’s only a warning & the sensor basically works perfectly fine
I tried a few things to get rid of the warning and here’s my solution if you’re interested:
time_t currTime = id(homeassistant_time).now().time;
to:
time_t currTime = id(homeassistant_time).now().timestamp;
I had a similar use case, so if someone stumbles across this old thread, this might be useful. When the goal is to publish a datetime to Home Assistant, the approach is a lot easier.
ESPHome sensor configuration:
time:
- platform: homeassistant
id: homeassistant_time
sensor:
- platform: template
name: "Display Last Update"
device_class: timestamp
id: display_last_update
Next you can write the current timestamp to the “Last Update” sensor inside the lambda of your choosing:
id(display_last_update).publish_state(id(homeassistant_time).now().timestamp);
The fact that we told Home Assistant that device_class
is “timestamp” is all that is needed to generate a pretty localized timestamp from it:
You can just use the sensor.template.publish
action instead of having the whole thing be a lambda:
- sensor.template.publish:
id: display_last_update
state: !lambda 'return id(homeassistant_time).now().timestamp;'
That’s certainly another option but it depends on your use case. In my scenario I do not need an action but a lambda one-liner. So something to consider. Just want to make this clear for others playing along at home.
Got it, I wasn’t clear on what you were replying to and now realize I mostly just repeated the earlier thing.
A question for anyone involved here: when I use a Template Sensor (or Template Text Sensor, etc.), esphome feels the need to report its state every minute. You can modify the interval though, so I made mine every 12 hours, but ideally it’d never do it except when the state changes (when we call sensor.template.publish
) since MQTT retain is on anyway. Is there a way to disable this regular updating?
Thanks for this, just what I needed, any Idea how I can show just the updated elapsed time on my display?
Hey, I am not super sure what you mean. The timestamp on the right is the actual time when “Last Fed” happened. The “9 minutes ago” is when the Home Assistant entity was last updated. Those are not necessarily the same and you would miss the point of this entity if you went with the latter.
In lovelace, just define a simple card like this:
Sorry, I was referring to a display attached to the Esp32 running Esphome, I get the time by using a template sensor extracting just the time (date not required), but I wanted to be able to show the elapsed time (9 minutes ago ) on the Esphome display.
Ah! What comes to mind:
- Store the last update timestamp in a variable
- Calculate the difference between timestamp and
now()
in seconds - Present
int(seconds/60) + " minutes ago"
More or less Does that make sense?
Sure, but I’m a real noob at templates.
you can set the update interval to never:
sensor:
- platform: template
name: My Sensor
id: my_sensor
update_interval: never
One thing to keep in mind is that upon startup, the value will be nan
until a publish command is received by that sensor. To address that, you can put a publish command in the on_boot
section of esphome:
esphome:
name: $devicename
comment: ${device_description}
on_boot:
priority: 250.0 # 250=after sensors are set up; when wifi is initializing
then:
- lambda: id(my_sensor).publish_state('42.0');
Similar request, I have a reed switch on a door, I would like to know, in and via esphome, when it last changed. I can see it in HA via “last updated” but due to wifi issues it keeps resetting, so merged all of the above together and came up with:
binary_sensor:
- platform: gpio
pin:
number: 23
mode: INPUT_PULLUP
name: ${friendly_name} Door
id: ${device_name}_door_sensor
device_class: door
on_state:
- component.update: systime
- lambda:
if (id(${device_name}_door_sensor).state) {
id(door_last_update).publish_state("Opened - " + id(systime).state);
} else {
id(door_last_update).publish_state("Closed - " + id(systime).state);
}
text_sensor:
- platform: template
id: systime
internal: true
disabled_by_default: true
update_interval: never
lambda: |-
char str[25];
time_t currTime = id(my_time).now().timestamp;
strftime(str, sizeof(str), "%d/%m/%Y %H:%M", gmtime(&currTime));
return (std::string) str;
- platform: template
update_interval: never
name: ${friendly_name} Door Last Changed
id: door_last_update
time:
- platform: sntp
id: my_time
Thank you very much, Mike!