Do you mind sharing it or the approach you’ve taken?
Thanks in advance!
Patience. I’m from Ukraine. We have power outages and missile attacks, so I can’t test the code often. I’ll definitely share when I finish.
Hi, I’d like this approach to set the clock and I’m on LVGL environment so I would put clock directly on display if needed
Waiting for your precious piece of code
substitutions:
timezone: "Europe/Kiev"
esp32:
board: esp32-s3-devkitc-1
variant: esp32s3
flash_size: 16MB
framework:
type: arduino
esphome:
name: "time"
friendly_name: "time"
platformio_options:
board_build.flash_mode: dio
on_boot:
- priority: 200
then:
- ds1307.read_time:
id: rtc_time
psram:
mode: octal
speed: 80MHz
i2c:
- id: bus_slow
sda: GPIO01
scl: GPIO02
scan: True
frequency: 100kHz
number:
- platform: template
name: "Year Select"
icon: "mdi:hours-24"
id: year_select
mode: BOX
min_value: 2025
max_value: 2040
step: 1
initial_value: 2025
unit_of_measurement: "Year"
update_interval: 0s
optimistic: true
- platform: template
name: "Month Select"
icon: "mdi:hours-24"
id: month_select
mode: BOX
min_value: 1
max_value: 12
step: 1
initial_value: 1
unit_of_measurement: "Month"
update_interval: 0s
optimistic: true
- platform: template
name: "Day Select"
icon: "mdi:hours-24"
id: day_select
mode: BOX
min_value: 1
max_value: 31
step: 1
initial_value: 1
unit_of_measurement: "Day"
update_interval: 0s
optimistic: true
- platform: template
name: "Hours Select"
icon: "mdi:hours-24"
id: hours_select
mode: BOX
min_value: 0
max_value: 23
step: 1
initial_value: 0
unit_of_measurement: "Hours"
update_interval: 0s
optimistic: true
- platform: template
name: "Minutes Select"
icon: "mdi:hours-24"
id: minutes_select
mode: BOX
min_value: 0
max_value: 59
step: 1
initial_value: 0
unit_of_measurement: "Minutes"
update_interval: 0s
optimistic: true
text_sensor:
- platform: template
name: "Current Time"
id: current_time
icon: mdi:clock-time-eight-outline
lambda: |-
auto time = id(rtc_time).now();
return time.strftime("%Y-%m-%d / %H:%M");
update_interval: 5s
button:
- platform: template
name: "Set Manual Time"
id: set_time_button
icon: mdi:clock-time-six-outline
on_press:
- script.execute: set_time
script:
- id: set_time
then:
- lambda: |-
setenv("TZ", "${timezone}", 1);
tzset();
struct tm time_info;
time_info.tm_year = id(year_select).state - 1900;
time_info.tm_mon = id(month_select).state - 1;
time_info.tm_mday = id(day_select).state;
time_info.tm_hour = id(hours_select).state;
time_info.tm_min = id(minutes_select).state;
time_info.tm_sec = 0;
time_info.tm_isdst = -1;
std::time_t t = mktime(&time_info);
struct timeval tv = {t, 0};
settimeofday(&tv, NULL);
ESP_LOGD("main", "Time set to: %s", ctime(&t));
- delay: 1s
- component.update: current_time
- ds1307.write_time:
id: rtc_time
- logger.log: Time synchronized ds1307
- delay: 1s
- ds1307.read_time:
id: rtc_time
- logger.log: Time read by ds1307
time:
- platform: homeassistant
id: ha_time
update_interval: 60s
on_time_sync:
then:
- ds1307.write_time:
id: rtc_time
- logger.log: Time synchronized ds1307
- delay: 1s
- ds1307.read_time:
id: rtc_time
- logger.log: Time read by ds1307
- platform: ds1307
id: rtc_time
timezone: "unknown"
i2c_id: bus_slow
address: 0x68
update_interval: never
if there is no connection with the home assistant, then the time can be set manually… when the connection appears, the time will be adjusted automatically
Just for my understanding do you just spoof the device in thinking it has a ds rtc attached but doesn’t and then set the time locally? My use case is devices connected via rs485 so time will be provided over serial from a master controller which has a rtc. Thanks
Of course I’m lying… there is no real time clock.They are not even present in my code. ![]()
- platform: ds1307
id: rtc_time
timezone: "unknown"
i2c_id: bus_slow
address: 0x68
update_interval: never
You are very observant.
Ok thank you, very clever solution
That’s a clever way to make sure the esp always runs on the correct time. In my case: my aquarium lights! Thank you!
It’s not that clever really… The ds1307 will drift between 2 - 10s every day so, the longer it goes without network access the greater the time drift will become. These arent really made for anything more than keeping time over a several hour internet outage or power outage beyond maybe 72 hours at least for people who need a high degree of accuracy in the timing.
You are absolutely right. I wouldn’t have even thought about such a function if… There’s a war in my country. I’m from Ukraine. There are frequent power and internet outages. I was just trying to make the time setting independent.
You can also run a local NTP server in your lan, even on an esp32 (a bit dodgy, due to wireless connectivity). The bigger question is how to get a reliable time source into this ntpd, ‘normally’ the answer would involve GPS (to resync the RTC) or reading an AM time signal transmitter (e.g. DCF77), but I assume those will be affected around you as well.
This is using the esp32 rtc not ds1370. He is just spoofing esphome codebase to believe the ds rtc is attached . But actually time is set after each power cycle manually.
My use case is a heating system where master node is generally connected to HA but has a DS3231 and distributes time via rs485 to the slaves. These are all powered off a ups. Regardless of state of HA and network the heating system will opperate. (Biomass with large thermal store)
No politics please.
I am having a similar problem. A custom PCB with an ESP32C6 on it with a DS3231M as RTC to keep the time while without power. The problem is that I have to set the time manually once when the user connects the first time via webbrowser.
time:
- platform: ds1307
id: ds1307_time
update_interval: 12h
datetime:
- platform: template
name: "Datum & Zeit überschreiben"
type: datetime
id: my_date_picker
optimistic: true
# This keeps it synced or allows logic to run when changed
on_value:
then:
- lambda: |-
struct tm t = {0};
t.tm_year = x.year - 1900;
t.tm_mon = x.month - 1;
t.tm_mday = x.day_of_month;
t.tm_hour = x.hour;
t.tm_min = x.minute;
t.tm_sec = x.second;
t.tm_isdst = -1;
time_t epoch = mktime(&t);
struct timeval tv = { .tv_sec = epoch, .tv_usec = 0 };
settimeofday(&tv, NULL);
ESP_LOGI("custom", "Internal system clock forced to UI time.");
- ds1307.write_time
This works well, a datepicker can be used in the browser to set the time.
However, it would be simpler to have only a “Sync” button in the webinterface which takes the time from the user´s browser and writes it to the internal clock and RTC.
I thought about altering the webserver-v1.min.js to achieve that, but maybe someone else has another smart idea?
Seems like a good idea. The v1 webserver is not maintained however, v2 is the default and v3 is the latest, it should target those.
I suspect something might have to be added to the time and webserver components as well as the client code to make it happen - there needs to be an action via a POST request to send the time.