Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 56 additions & 20 deletions rdtech-controller-c3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,32 +110,68 @@ modbus_controller:
setup_priority: -10
update_interval: 5s

# Persisted timestamp of the last RTC sync to the PSU. Stored in flash so
# we don't burn 6 Modbus writes on every reconnect.
globals:
- id: last_psu_time_sync
type: time_t
restore_value: yes
initial_value: '0'

time:
# Get the time from HA, so we can use it for uptime
# Get the time from HA, so we can use it for uptime and (rate-limited)
# mirror it to the PSU's RTC.
- platform: homeassistant
id: time_homeassistant
timezone: "${time_timezone}"
on_time_sync:
- logger.log: Time has been set and is valid!
- logger.log: "HA time sync received"
- component.update: sensor_uptime_timestamp
- number.set:
id: date_year
value: !lambda return id(time_homeassistant).now().year;
- number.set:
id: date_month
value: !lambda return id(time_homeassistant).now().month;
- number.set:
id: date_day
value: !lambda return id(time_homeassistant).now().day_of_month;
- number.set:
id: date_hour
value: !lambda return id(time_homeassistant).now().hour;
- number.set:
id: date_minute
value: !lambda return id(time_homeassistant).now().minute;
- number.set:
id: date_second
value: !lambda return id(time_homeassistant).now().second;
# Sync the PSU clock at most once per 24h, and only write the date/time
# registers that actually differ. Avoids the original behaviour of
# firing six Modbus writes on every HA reconnect, which contended with
# sensor polling and wore the PSU's flash.
- if:
condition:
lambda: |-
const time_t now_ts = id(time_homeassistant).utcnow().timestamp;
if (now_ts - id(last_psu_time_sync) < 86400) return false;
// Skip if the date_* numbers haven't been polled yet. This
// can happen when on_time_sync arrives before the first
// Modbus cycle completes; comparing against NaN would force
// a write and then mark last_psu_time_sync, suppressing real
// drift checks for 24h. The next on_time_sync (15 min later
// by default) will retry with fresh values.
if (std::isnan(id(date_year).state)) return false;
auto now = id(time_homeassistant).now();
const float psu_secs = id(date_hour).state * 3600.0f
+ id(date_minute).state * 60.0f
+ id(date_second).state;
const float ha_secs = now.hour * 3600.0f
+ now.minute * 60.0f
+ now.second;
return id(date_year).state != now.year
|| id(date_month).state != now.month
|| id(date_day).state != now.day_of_month
|| std::abs(psu_secs - ha_secs) > 30.0f;
then:
- lambda: |-
auto now = id(time_homeassistant).now();
auto write_if_diff = [](esphome::number::Number *n, float v) {
if (n->state != v) {
auto call = n->make_call();
call.set_value(v);
call.perform();
}
};
write_if_diff(id(date_year), now.year);
write_if_diff(id(date_month), now.month);
write_if_diff(id(date_day), now.day_of_month);
write_if_diff(id(date_hour), now.hour);
write_if_diff(id(date_minute), now.minute);
write_if_diff(id(date_second), now.second);
id(last_psu_time_sync) = id(time_homeassistant).utcnow().timestamp;
ESP_LOGI("rdtech", "PSU clock synced from HA (delta-only)");

sensor:
- platform: modbus_controller
Expand Down
76 changes: 56 additions & 20 deletions rdtech-controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,32 +108,68 @@ modbus_controller:
setup_priority: -10
update_interval: 5s

# Persisted timestamp of the last RTC sync to the PSU. Stored in flash so
# we don't burn 6 Modbus writes on every reconnect.
globals:
- id: last_psu_time_sync
type: time_t
restore_value: yes
initial_value: '0'

time:
# Get the time from HA, so we can use it for uptime
# Get the time from HA, so we can use it for uptime and (rate-limited)
# mirror it to the PSU's RTC.
- platform: homeassistant
id: time_homeassistant
timezone: "${time_timezone}"
on_time_sync:
- logger.log: Time has been set and is valid!
- logger.log: "HA time sync received"
- component.update: sensor_uptime_timestamp
- number.set:
id: date_year
value: !lambda return id(time_homeassistant).now().year;
- number.set:
id: date_month
value: !lambda return id(time_homeassistant).now().month;
- number.set:
id: date_day
value: !lambda return id(time_homeassistant).now().day_of_month;
- number.set:
id: date_hour
value: !lambda return id(time_homeassistant).now().hour;
- number.set:
id: date_minute
value: !lambda return id(time_homeassistant).now().minute;
- number.set:
id: date_second
value: !lambda return id(time_homeassistant).now().second;
# Sync the PSU clock at most once per 24h, and only write the date/time
# registers that actually differ. Avoids the original behaviour of
# firing six Modbus writes on every HA reconnect, which contended with
# sensor polling and wore the PSU's flash.
- if:
condition:
lambda: |-
const time_t now_ts = id(time_homeassistant).utcnow().timestamp;
if (now_ts - id(last_psu_time_sync) < 86400) return false;
// Skip if the date_* numbers haven't been polled yet. This
// can happen when on_time_sync arrives before the first
// Modbus cycle completes; comparing against NaN would force
// a write and then mark last_psu_time_sync, suppressing real
// drift checks for 24h. The next on_time_sync (15 min later
// by default) will retry with fresh values.
if (std::isnan(id(date_year).state)) return false;
auto now = id(time_homeassistant).now();
const float psu_secs = id(date_hour).state * 3600.0f
+ id(date_minute).state * 60.0f
+ id(date_second).state;
const float ha_secs = now.hour * 3600.0f
+ now.minute * 60.0f
+ now.second;
return id(date_year).state != now.year
|| id(date_month).state != now.month
|| id(date_day).state != now.day_of_month
|| std::abs(psu_secs - ha_secs) > 30.0f;
then:
- lambda: |-
auto now = id(time_homeassistant).now();
auto write_if_diff = [](esphome::number::Number *n, float v) {
if (n->state != v) {
auto call = n->make_call();
call.set_value(v);
call.perform();
}
};
write_if_diff(id(date_year), now.year);
write_if_diff(id(date_month), now.month);
write_if_diff(id(date_day), now.day_of_month);
write_if_diff(id(date_hour), now.hour);
write_if_diff(id(date_minute), now.minute);
write_if_diff(id(date_second), now.second);
id(last_psu_time_sync) = id(time_homeassistant).utcnow().timestamp;
ESP_LOGI("rdtech", "PSU clock synced from HA (delta-only)");

sensor:
- platform: modbus_controller
Expand Down