"Hopefully" improved comms on sthome canbus.
This commit is contained in:
parent
d28a51602a
commit
28e1253fc0
@ -20,23 +20,6 @@ substitutions:
|
||||
CB_BATTERY_MANUFACTURER: 0x35E
|
||||
|
||||
# sthome messages
|
||||
# can also use CB_GEYSER_TEMPERATURES: !lambda "return esphome::solar::cbf_sthome::CB_GEYSER_TEMPERATURES;", but will fail is assigned to non-templateable config option in .yaml config file
|
||||
CB_GEYSER_TEMPERATURES: 0x400
|
||||
CB_GEYSER_HEATING: 0x401
|
||||
CB_GEYSER_ACTIVE_SCHEDULE: 0x402
|
||||
CB_POWER_MAINS: 0x403
|
||||
CB_POWER_INVERTER: 0x404
|
||||
CB_POWER_PLUGS: 0x405
|
||||
CB_POWER_LIGHTS: 0x406
|
||||
CB_POWER_GEYSER: 0x407
|
||||
CB_POWER_POOL: 0x408
|
||||
CB_POWER_GENERATED: 0x409
|
||||
CB_ENERGY_MAINS: 0x40A
|
||||
CB_ENERGY_GEYSER: 0x40B
|
||||
CB_ENERGY_POOL: 0x40C
|
||||
CB_ENERGY_PLUGS: 0x40D
|
||||
CB_ENERGY_LIGHTS: 0x40E
|
||||
CB_ENERGY_HOUSE: 0x40F
|
||||
CB_ENERGY_GENERATED: 0x410
|
||||
CB_ENERGY_LOSS: 0x411
|
||||
CB_CONTROLLER_STATES: 0x412
|
||||
CB_MAX_RETRANSMISSIONS: 10
|
||||
CB_RETRANSMISSION_INTERVAL: 1000ms
|
||||
|
||||
|
||||
161
sthome-ut10.yaml
161
sthome-ut10.yaml
@ -23,21 +23,13 @@ globals:
|
||||
type: char[1 + ${DD_MAX_YEARS} * 5]
|
||||
restore_value: yes
|
||||
# initial_value: "{2022\n2023\n2024\n2025\n2026}"
|
||||
- id: g_geyser_heating_on
|
||||
type: bool
|
||||
restore_value: no
|
||||
initial_value: '0'
|
||||
- id: g_utility_on
|
||||
type: bool
|
||||
restore_value: no
|
||||
initial_value: '0'
|
||||
# CAN BUS
|
||||
- id: can_msgctr
|
||||
type: int
|
||||
restore_value: no
|
||||
- id: g_cb_cache
|
||||
type: solar::cbf_cache
|
||||
restore_value: no
|
||||
restore_value: no
|
||||
|
||||
esphome:
|
||||
name: "${name}"
|
||||
@ -56,6 +48,7 @@ esphome:
|
||||
then:
|
||||
- lambda: |-
|
||||
id(can_msgctr) = 0;
|
||||
id(update_heating_display).execute(false);
|
||||
|
||||
esp32:
|
||||
board: esp32-s3-devkitc-1
|
||||
@ -101,8 +94,8 @@ time:
|
||||
- platform: homeassistant
|
||||
id: time_source
|
||||
update_interval: 360min # Change sync interval from default 5min to 6 hours
|
||||
on_time_sync:
|
||||
then:
|
||||
# on_time_sync:
|
||||
# then:
|
||||
# - if: # Publish the time the device was last restarted, but only once.
|
||||
# condition:
|
||||
# lambda: 'return id(device_last_restart).state == "";'
|
||||
@ -110,15 +103,13 @@ time:
|
||||
# - text_sensor.template.publish:
|
||||
# id: device_last_restart
|
||||
# state: !lambda 'return id(time_source).now().strftime("%a %d %b %Y - %I:%M:%S %p");'
|
||||
- script.execute: ind_heating_update
|
||||
# - script.execute: time_update
|
||||
# - script.execute: init_calendar
|
||||
|
||||
on_time:
|
||||
- minutes: '*'
|
||||
seconds: '*'
|
||||
then:
|
||||
- script.execute: ind_heating_update
|
||||
# on_time:
|
||||
# - minutes: '*'
|
||||
# seconds: '*'
|
||||
# then:
|
||||
# - script.execute: time_update
|
||||
# - lambda: |-
|
||||
# id(get_calendar_days_state).execute("T");
|
||||
@ -207,6 +198,9 @@ interval:
|
||||
- interval: 30s
|
||||
then:
|
||||
- script.execute: send_info_request
|
||||
- interval: 500ms
|
||||
then:
|
||||
- script.execute: send_quick_update_request
|
||||
|
||||
spi:
|
||||
- id: spi_bus0
|
||||
@ -247,27 +241,60 @@ canbus:
|
||||
auto cbitem = cbf_store_pylon(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
|
||||
bool publish = id(g_cb_cache).additem(cbitem);
|
||||
if(publish) {
|
||||
ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
//ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
switch (can_id) {
|
||||
case cbf_pylon::CB_BATTERY_STATE:
|
||||
{
|
||||
uint soc = static_cast<uint16_t>((x[1] << 8) + x[0]);
|
||||
uint soh = static_cast<uint16_t>((x[3] << 8) + x[2]);
|
||||
ESP_LOGI(cbitem.tag().c_str(), "SOC= %d%% SOH= %d%%", soc, soh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(can_id >= 0x400 && can_id <= 0x580) {
|
||||
auto cbitem = cbf_store_sthome(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
|
||||
bool publish = id(g_cb_cache).additem(cbitem);
|
||||
//ESP_LOGI(cbitem.tag().c_str(), "%s P[%s]", cbitem.to_string().c_str(), publish ? "Y" : "N");
|
||||
if(publish) {
|
||||
ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
//ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
switch (can_id) {
|
||||
case cbf_sthome::CB_CONTROLLER_STATES:
|
||||
if(x[1] & 0x80 == 0)
|
||||
lv_obj_add_flag(id(ind_geyser_on), LV_OBJ_FLAG_HIDDEN);
|
||||
else
|
||||
lv_obj_clear_flag(id(ind_geyser_on), LV_OBJ_FLAG_HIDDEN);
|
||||
if(x[1] & 0x10 == 0)
|
||||
lv_obj_add_flag(id(ind_utility_on), LV_OBJ_FLAG_HIDDEN);
|
||||
else
|
||||
lv_obj_clear_flag(id(ind_utility_on), LV_OBJ_FLAG_HIDDEN);
|
||||
{
|
||||
uint8_t alarms = x[0];
|
||||
uint8_t states = x[1];
|
||||
uint8_t modes = x[2];
|
||||
id(update_heating_display).execute(states & 0x80 != 0);
|
||||
//if(states & 0x40 == 0) {
|
||||
// lv_obj_add_flag(id(ind_geyser_relay_on), LV_OBJ_FLAG_HIDDEN);
|
||||
//}
|
||||
//else {
|
||||
// lv_obj_clear_flag(id(ind_geyser_relay_on), LV_OBJ_FLAG_HIDDEN);
|
||||
//}
|
||||
if(states & 0x20 == 0) {
|
||||
lv_obj_add_flag(id(ind_utility_on), LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
else {
|
||||
lv_obj_clear_flag(id(ind_utility_on), LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_TEMPERATURE_TOP:
|
||||
{
|
||||
double temperature = (x[1] == 0xFF && x[0] == 0xFF) ? std::numeric_limits<double>::quiet_NaN() : (double) static_cast<int16_t>(256 * x[1] + x[0]) / 256;
|
||||
if(!isnan(temperature)) {
|
||||
id(update_temp_display).execute(temperature, rect_gtoptemp, ind_utility_on, lbl_gtoptemp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_TEMPERATURE_BOTTOM:
|
||||
{
|
||||
double temperature = (x[1] == 0xFF && x[0] == 0xFF) ? std::numeric_limits<double>::quiet_NaN() : (double) static_cast<int16_t>(256 * x[1] + x[0]) / 256;
|
||||
if(!isnan(temperature)) {
|
||||
id(update_temp_display).execute(temperature, rect_gbottemp, ind_geyser_heating_on, lbl_gbottemp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_TEMPERATURES:
|
||||
id(update_temperature_display).execute(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -455,7 +482,7 @@ lvgl:
|
||||
scrollbar_mode: "OFF"
|
||||
widgets:
|
||||
- image:
|
||||
id: ind_geyser_on
|
||||
id: ind_geyser_heating_on
|
||||
align: CENTER #BOTTOM_RIGHT #TOP_RIGHT
|
||||
src: icon_fire
|
||||
image_recolor: RED
|
||||
@ -1179,46 +1206,38 @@ sensor:
|
||||
#
|
||||
|
||||
script:
|
||||
- id: send_info_request
|
||||
then:
|
||||
- script.execute: send_request_block
|
||||
- delay: 100ms
|
||||
- script.execute: send_request_block
|
||||
- delay: 100ms
|
||||
- script.execute: send_request_block
|
||||
- delay: 100ms
|
||||
- script.execute: send_request_block
|
||||
- delay: 100ms
|
||||
- script.execute: send_request_block
|
||||
|
||||
- id: send_request_block
|
||||
then:
|
||||
- lambda: |-
|
||||
using namespace solar;
|
||||
id(g_cb_cache).send_request(id(canbus_sthome), cbf_sthome::CB_GEYSER_TEMPERATURES);
|
||||
id(g_cb_cache).send_request(id(canbus_sthome), cbf_sthome::CB_CONTROLLER_STATES);
|
||||
|
||||
- id: update_temperature_display
|
||||
parameters:
|
||||
x: std::vector<uint8_t>&
|
||||
- id: send_quick_update_request
|
||||
then:
|
||||
- lambda: |-
|
||||
using namespace solar;
|
||||
double temp_top = (x[1] == 0xFF && x[0] == 0xFF) ? std::numeric_limits<double>::quiet_NaN() : (double) static_cast<int16_t>(256 * x[1] + x[0]) / 256;
|
||||
double temp_bot = (x[3] == 0xFF && x[2] == 0xFF) ? std::numeric_limits<double>::quiet_NaN() : (double) static_cast<int16_t>(256 * x[3] + x[2]) / 256;
|
||||
double temp_amb = (x[5] == 0xFF && x[4] == 0xFF) ? std::numeric_limits<double>::quiet_NaN() : (double) static_cast<int16_t>(256 * x[5] + x[4]) / 256;
|
||||
if(isnan(temp_top) || isnan(temp_bot)) {
|
||||
// immediately request another can frame
|
||||
id(g_cb_cache).send_request(id(canbus_sthome), cbf_sthome::CB_GEYSER_TEMPERATURES);
|
||||
for(int i = 0; i < ${CB_MAX_RETRANSMISSIONS}; i++) {
|
||||
id(send_request_block1).execute();
|
||||
}
|
||||
//ESP_LOGI("REC: ", "Geyser Temperatures: Top %.4f°C Bottom %.4f°C Ambient %.4f°C", temp_top, temp_bot, temp_amb);
|
||||
if(!isnan(temp_top))
|
||||
id(update_temp_display).execute(temp_top, rect_gtoptemp, ind_utility_on, lbl_gtoptemp);
|
||||
if(!isnan(temp_bot))
|
||||
id(update_temp_display).execute(temp_bot, rect_gbottemp, ind_geyser_on, lbl_gbottemp);
|
||||
|
||||
- id: send_info_request
|
||||
then:
|
||||
- lambda: |-
|
||||
for(int i = 0; i < ${CB_MAX_RETRANSMISSIONS}; i++) {
|
||||
id(send_request_block2).execute();
|
||||
}
|
||||
|
||||
- id: send_request_block1
|
||||
mode: queued
|
||||
then:
|
||||
- lambda: "id(g_cb_cache).send_request(id(canbus_sthome), solar::cbf_sthome::CB_CONTROLLER_STATES);"
|
||||
- delay: 20ms
|
||||
|
||||
- id: send_request_block2
|
||||
mode: queued
|
||||
then:
|
||||
- lambda: "id(g_cb_cache).send_request(id(canbus_sthome), solar::cbf_pylon::CB_BATTERY_STATE);"
|
||||
- delay: 50ms
|
||||
- lambda: "id(g_cb_cache).send_request(id(canbus_sthome), solar::cbf_sthome::CB_GEYSER_TEMPERATURE_TOP);"
|
||||
- delay: 50ms
|
||||
- lambda: "id(g_cb_cache).send_request(id(canbus_sthome), solar::cbf_sthome::CB_GEYSER_TEMPERATURE_BOTTOM);"
|
||||
- delay: 50ms
|
||||
|
||||
- id: update_temp_display
|
||||
mode: queued
|
||||
parameters:
|
||||
value: double
|
||||
rect: lv_obj_t*
|
||||
@ -1250,6 +1269,14 @@ script:
|
||||
else
|
||||
lv_label_set_text(label, buffer);
|
||||
|
||||
- id: update_heating_display
|
||||
parameters:
|
||||
heat_on: bool
|
||||
then:
|
||||
- lvgl.widget.update:
|
||||
id: ind_geyser_heating_on
|
||||
hidden: !lambda 'return !heat_on;'
|
||||
|
||||
# - id: time_update
|
||||
# then:
|
||||
# - lvgl.indicator.update:
|
||||
@ -1286,12 +1313,6 @@ script:
|
||||
# auto time_obj = id(time_source).now();
|
||||
# return time_obj.strftime("%H:%M");
|
||||
|
||||
- id: ind_heating_update
|
||||
then:
|
||||
- lvgl.widget.update:
|
||||
id: ind_geyser_on
|
||||
hidden: !lambda return !id(g_geyser_heating_on);
|
||||
|
||||
# - id: init_calendar
|
||||
# then:
|
||||
# - lambda: |-
|
||||
|
||||
359
sthome-ut8.yaml
359
sthome-ut8.yaml
@ -32,6 +32,7 @@ esphome:
|
||||
id(timer_start) = 0;
|
||||
id(can1_msgctr) = 0;
|
||||
id(can2_msgctr) = 0;
|
||||
id(g_cb_request_queue) = std::queue< std::set<uint32_t> >();
|
||||
id(time_synched) = false;
|
||||
id(init_fixed_public_holidays).execute();
|
||||
id(init_schedule).execute();
|
||||
@ -165,7 +166,11 @@ globals:
|
||||
restore_value: no
|
||||
- id: g_cb_cache # the cache is used to only accept a frame after it has been received a specified number of times within a specified period. this hopefully will iron out spurious corrupted frames
|
||||
type: solar::cbf_cache
|
||||
restore_value: no
|
||||
restore_value: no
|
||||
- id: g_cb_request_queue
|
||||
type: std::queue< std::set<uint32_t> >
|
||||
restore_value: no
|
||||
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
@ -361,111 +366,158 @@ time:
|
||||
return time_obj.strftime("%Y-%m-%d %H:%M:%S");
|
||||
|
||||
interval:
|
||||
- interval: 10s
|
||||
- interval: 100ms
|
||||
then:
|
||||
lambda: |-
|
||||
using namespace solar;
|
||||
bool success = false;
|
||||
if(!id(g_cb_request_queue).empty()) {
|
||||
auto canid_set = id(g_cb_request_queue).front();
|
||||
std::set<uint32_t> unhandled_set, failed_set;
|
||||
for(auto& can_id : canid_set) {
|
||||
switch(can_id) {
|
||||
// pylon ids
|
||||
case cbf_pylon::CB_BATTERY_LIMITS:
|
||||
id(canbus_send_battery_limits).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_STATE:
|
||||
id(canbus_send_battery_state).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_STATUS:
|
||||
id(canbus_send_battery_status).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_FAULT:
|
||||
id(canbus_send_battery_fault).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_REQUEST_FLAGS:
|
||||
id(canbus_send_battery_request_flags).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_MANUFACTURER:
|
||||
id(canbus_send_battery_manufacturer).execute();
|
||||
break;
|
||||
// sthome ids
|
||||
case cbf_sthome::CB_POWER_MAINS:
|
||||
id(canbus_send_power_mains).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_INVERTER:
|
||||
id(canbus_send_power_inverter).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_PLUGS:
|
||||
id(canbus_send_power_plugs).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_LIGHTS:
|
||||
id(canbus_send_power_lights).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_GEYSER:
|
||||
id(canbus_send_power_geyser).execute();
|
||||
break;
|
||||
//case cbf_sthome::CB_POWER_POOL:
|
||||
// id(canbus_send_power_pool).execute();
|
||||
// break;
|
||||
case cbf_sthome::CB_POWER_GENERATED:
|
||||
id(canbus_send_power_generated).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_MAINS:
|
||||
id(canbus_send_energy_mains).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_GEYSER:
|
||||
id(canbus_send_energy_geyser).execute();
|
||||
break;
|
||||
//case cbf_sthome::CB_ENERGY_POOL:
|
||||
// id(canbus_send_energy_pool).execute();
|
||||
// break;
|
||||
case cbf_sthome::CB_ENERGY_PLUGS:
|
||||
id(canbus_send_energy_plugs).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_LIGHTS:
|
||||
id(canbus_send_energy_lights).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_HOUSE:
|
||||
id(canbus_send_energy_house).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_GENERATED:
|
||||
id(canbus_send_energy_generated).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_LOSS:
|
||||
id(canbus_send_energy_loss).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_TEMPERATURE_TOP:
|
||||
id(canbus_send_temperature_top).execute(success);
|
||||
if(!success) {
|
||||
failed_set.insert(can_id);
|
||||
}
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_TEMPERATURE_BOTTOM:
|
||||
id(canbus_send_temperature_bottom).execute(success);
|
||||
if(!success) {
|
||||
failed_set.insert(can_id);
|
||||
}
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_TEMPERATURE_AMBIENT:
|
||||
id(canbus_send_temperature_ambient).execute(success);
|
||||
if(!success) {
|
||||
failed_set.insert(can_id);
|
||||
}
|
||||
break;
|
||||
case cbf_sthome::CB_CANBUS_ID08:
|
||||
id(canbus_send_heartbeat).execute();
|
||||
break;
|
||||
default:
|
||||
unhandled_set.insert(can_id);
|
||||
}
|
||||
}
|
||||
id(g_cb_request_queue).pop(); // remove from queue
|
||||
// do remaining can_ids, if any
|
||||
bool time_isvalid = id(time_source).now().is_valid();
|
||||
if(time_isvalid) {
|
||||
for(auto& can_id : unhandled_set) {
|
||||
switch(can_id) {
|
||||
case cbf_sthome::CB_CONTROLLER_STATES:
|
||||
id(canbus_send_controller_states).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_HEATING:
|
||||
id(canbus_send_geyser_heating).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_ACTIVE_SCHEDULE:
|
||||
id(canbus_send_geyser_active_schedule).execute();
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW("Unknown CAN_ID", "CAN_ID: 0x%X. Remote transmission request ignored!", can_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// re-insert unhandled can-ids to the back of the queue
|
||||
id(canbus_add_to_queue).execute(unhandled_set, 5);
|
||||
}
|
||||
id(canbus_add_to_queue).execute(failed_set, 5);
|
||||
}
|
||||
|
||||
- interval: ${CB_RETRANSMISSION_INTERVAL}
|
||||
then:
|
||||
lambda: |-
|
||||
using namespace solar;
|
||||
// we use the cache to handle recently received remote transmission requests. this allows for ironing out invalid (non-repeated) frames
|
||||
ESP_LOGI("processing RTRs ", "%d publishable request(s) in cache", std::count_if(id(g_cb_cache).cache_map.begin(), id(g_cb_cache).cache_map.end(), [](auto& it) { auto& store = it.second.get_store(); return store.rtr && store.getpublish(); }));
|
||||
// we have an outer loop to send 5 blocks of the requested frames to ensure delivery
|
||||
for(int i = 0; i < 5; i++) {
|
||||
// we have an outer loop to queue 5 blocks of the requested frames to ensure delivery
|
||||
for(int i = 0; i < ${CB_MAX_RETRANMISSIONS}; i++) {
|
||||
std::set<uint32_t> canid_set;
|
||||
for(auto& kvp : id(g_cb_cache).cache_map) {
|
||||
const auto& item = kvp.second;
|
||||
auto& store = item.get_store();
|
||||
if(store.rtr) {
|
||||
//ESP_LOGI(store.tag().c_str(), "%s", store.to_string().c_str());
|
||||
if(store.getpublish()) {
|
||||
if(i == 4) {
|
||||
ESP_LOGI(store.tag().c_str(), "%s", store.to_string().c_str()); // we display once using opportunity at end of sequence (when publish flag is reset)
|
||||
canid_set.insert(store.can_id);
|
||||
if(i == ${CB_MAX_RETRANMISSIONS} - 1) {
|
||||
ESP_LOGI(store.tag().c_str(), "%s", store.to_string().c_str()); // we display once, using opportunity at end of sequence (when publish flag is reset)
|
||||
store.setpublish(false);
|
||||
}
|
||||
switch(store.can_id) {
|
||||
case cbf_sthome::CB_CANBUS_ID08:
|
||||
ESP_LOGI("RTR", "HEARTBEAT");
|
||||
id(canbus_send_heartbeat).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_TEMPERATURES:
|
||||
id(canbus_send_temperatures).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_HEATING:
|
||||
id(canbus_send_geyser_heating).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_GEYSER_ACTIVE_SCHEDULE:
|
||||
id(canbus_send_geyser_active_schedule).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_MAINS:
|
||||
id(canbus_send_power_mains).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_INVERTER:
|
||||
id(canbus_send_power_inverter).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_PLUGS:
|
||||
id(canbus_send_power_plugs).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_LIGHTS:
|
||||
id(canbus_send_power_lights).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_POWER_GEYSER:
|
||||
id(canbus_send_power_geyser).execute();
|
||||
break;
|
||||
//case cbf_sthome::CB_POWER_POOL:
|
||||
// id(canbus_send_power_pool).execute();
|
||||
// break;
|
||||
case cbf_sthome::CB_POWER_GENERATED:
|
||||
id(canbus_send_power_generated).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_CONTROLLER_STATES:
|
||||
id(canbus_send_controller_states).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_MAINS:
|
||||
id(canbus_send_energy_mains).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_GEYSER:
|
||||
id(canbus_send_energy_geyser).execute();
|
||||
break;
|
||||
//case cbf_sthome::CB_ENERGY_POOL:
|
||||
// id(canbus_send_energy_pool).execute();
|
||||
// break;
|
||||
case cbf_sthome::CB_ENERGY_PLUGS:
|
||||
id(canbus_send_energy_plugs).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_LIGHTS:
|
||||
id(canbus_send_energy_lights).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_HOUSE:
|
||||
id(canbus_send_energy_house).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_GENERATED:
|
||||
id(canbus_send_energy_generated).execute();
|
||||
break;
|
||||
case cbf_sthome::CB_ENERGY_LOSS:
|
||||
id(canbus_send_energy_loss).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_LIMITS:
|
||||
id(canbus_send_battery_limits).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_STATE:
|
||||
id(canbus_send_battery_state).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_STATUS:
|
||||
id(canbus_send_battery_status).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_FAULT:
|
||||
id(canbus_send_battery_fault).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_REQUEST_FLAGS:
|
||||
id(canbus_send_battery_request_flags).execute();
|
||||
break;
|
||||
case cbf_pylon::CB_BATTERY_MANUFACTURER:
|
||||
id(canbus_send_battery_manufacturer).execute();
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(store.tag().c_str(), "Unhandled remote transmission request recieved!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
id(g_cb_request_queue).push(canid_set);
|
||||
}
|
||||
|
||||
canbus:
|
||||
@ -484,12 +536,24 @@ canbus:
|
||||
id(can2_msgctr)++;
|
||||
using namespace solar;
|
||||
auto time_obj = id(time_source).now();
|
||||
if(time_obj.is_valid()) {
|
||||
auto cbitem = cbf_store_sthome(id(can2_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
|
||||
bool publish = id(g_cb_cache).additem(cbitem);
|
||||
if(publish) {
|
||||
ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
if(time_obj.is_valid()) {
|
||||
if(can_id >= 0x350 && can_id < 0x380) {
|
||||
auto cbitem = cbf_store_pylon(id(can2_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
|
||||
bool publish = id(g_cb_cache).additem(cbitem);
|
||||
//if(publish) {
|
||||
// ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
//}
|
||||
}
|
||||
else if(can_id >= 0x400 && can_id <= 0x580) {
|
||||
auto cbitem = cbf_store_sthome(id(can2_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
|
||||
bool publish = id(g_cb_cache).additem(cbitem);
|
||||
//if(publish) {
|
||||
// ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
//}
|
||||
}
|
||||
else {
|
||||
ESP_LOGI("WARN", "Request within unhandled range CAN_ID: 0x%X. Request ignored!", can_id);
|
||||
}
|
||||
}
|
||||
|
||||
- platform: mcp2515
|
||||
@ -2725,31 +2789,43 @@ script:
|
||||
j++;
|
||||
}
|
||||
|
||||
- id: canbus_send_all_data
|
||||
- id: canbus_add_to_queue
|
||||
parameters:
|
||||
can_id_set: std::set<uint32_t>&
|
||||
max_requests: int
|
||||
then:
|
||||
- script.execute: canbus_send_temperatures
|
||||
- script.execute: canbus_send_power_mains
|
||||
- script.execute: canbus_send_power_inverter
|
||||
- script.execute: canbus_send_power_plugs
|
||||
- script.execute: canbus_send_power_lights
|
||||
- script.execute: canbus_send_power_geyser
|
||||
- script.execute: canbus_send_power_generated
|
||||
- script.execute: canbus_send_energy_mains
|
||||
- script.execute: canbus_send_energy_geyser
|
||||
#- script.execute: canbus_send_energy_pool
|
||||
- script.execute: canbus_send_energy_plugs
|
||||
- script.execute: canbus_send_energy_lights
|
||||
- script.execute: canbus_send_energy_house
|
||||
- script.execute: canbus_send_energy_generated
|
||||
- script.execute: canbus_send_energy_loss
|
||||
# do date/time dependent values next
|
||||
- if:
|
||||
condition:
|
||||
lambda: "return id(time_source).now().is_valid();"
|
||||
then:
|
||||
- script.execute: canbus_send_controller_states
|
||||
- script.execute: canbus_send_geyser_heating
|
||||
- script.execute: canbus_send_geyser_active_schedule
|
||||
lambda: |-
|
||||
if(!can_id_set.empty()) {
|
||||
// check how many times can_ids are queued already
|
||||
auto qcpy = id(g_cb_request_queue);
|
||||
std::map<uint32_t, int> request_counts;
|
||||
while (!qcpy.empty()) {
|
||||
auto& cid_set = qcpy.front();
|
||||
for(auto& can_id : can_id_set) {
|
||||
if(cid_set.contains(can_id)) {
|
||||
const auto& ret = request_counts.emplace(can_id, 1);
|
||||
if(!ret.second) {
|
||||
auto& kvp = *ret.first;
|
||||
kvp.second++;
|
||||
}
|
||||
}
|
||||
}
|
||||
qcpy.pop();
|
||||
}
|
||||
std::set<uint32_t> newset;
|
||||
// re-insert only those can-ids into newset that are queued less than max_requests times
|
||||
for(const auto& kvp : request_counts) {
|
||||
const auto& count = kvp.second;
|
||||
if(count <= max_requests) {
|
||||
newset.insert(kvp.first);
|
||||
}
|
||||
//else {
|
||||
// ESP_LOGI("request_counts", "CAN_ID 0x%X, COUNT: %d not inserted!", kvp.first, count);
|
||||
//}
|
||||
}
|
||||
// insert newset at the back of the queue with can_id request counts < max_requests
|
||||
id(g_cb_request_queue).push(newset);
|
||||
}
|
||||
|
||||
- id: canbus_send_heartbeat
|
||||
then:
|
||||
@ -2758,13 +2834,46 @@ script:
|
||||
std::vector<uint8_t> x(cbf_sthome::heartbeat.begin(), cbf_sthome::heartbeat.end());
|
||||
id(g_cb_cache).send_frame(id(canbus_sthome), cbf_sthome::CB_CANBUS_ID08, x);
|
||||
|
||||
- id: canbus_send_temperatures
|
||||
# this one has a success output parameter, which will determine whether the frame should be resent later
|
||||
- id: canbus_send_temperature_top
|
||||
parameters:
|
||||
success: bool&
|
||||
then:
|
||||
lambda: |-
|
||||
using namespace solar;
|
||||
if(!isnan(id(geyser_top_temperature).raw_state) || !isnan(id(geyser_bottom_temperature).raw_state) || !isnan(id(ambient_temperature).raw_state)) {
|
||||
auto x = cb_frame::get_byte_stream(id(geyser_top_temperature).raw_state, -256, id(geyser_bottom_temperature).raw_state, -256, id(ambient_temperature).raw_state, -256);
|
||||
id(g_cb_cache).send_frame(id(canbus_sthome), cbf_sthome::CB_GEYSER_TEMPERATURES, x);
|
||||
auto temperature = id(geyser_top_temperature).raw_state;
|
||||
success = !isnan(temperature);
|
||||
if(success) {
|
||||
auto x = cb_frame::get_byte_stream(temperature, -256);
|
||||
id(g_cb_cache).send_frame(id(canbus_sthome), cbf_sthome::CB_GEYSER_TEMPERATURE_TOP, x);
|
||||
}
|
||||
|
||||
# this one has a success output parameter, which will determine whether the frame should be resent later
|
||||
- id: canbus_send_temperature_bottom
|
||||
parameters:
|
||||
success: bool&
|
||||
then:
|
||||
lambda: |-
|
||||
using namespace solar;
|
||||
auto temperature = id(geyser_bottom_temperature).raw_state;
|
||||
success = !isnan(temperature);
|
||||
if(success) {
|
||||
auto x = cb_frame::get_byte_stream(temperature, -256);
|
||||
id(g_cb_cache).send_frame(id(canbus_sthome), cbf_sthome::CB_GEYSER_TEMPERATURE_BOTTOM, x);
|
||||
}
|
||||
|
||||
# this one has a success output parameter, which will determine whether the frame should be resent later
|
||||
- id: canbus_send_temperature_ambient
|
||||
parameters:
|
||||
success: bool&
|
||||
then:
|
||||
lambda: |-
|
||||
using namespace solar;
|
||||
auto temperature = id(ambient_temperature).raw_state;
|
||||
success = !isnan(temperature);
|
||||
if(success) {
|
||||
auto x = cb_frame::get_byte_stream(temperature, -256);
|
||||
id(g_cb_cache).send_frame(id(canbus_sthome), cbf_sthome::CB_GEYSER_TEMPERATURE_AMBIENT, x);
|
||||
}
|
||||
|
||||
- id: canbus_send_geyser_heating
|
||||
@ -2836,14 +2945,14 @@ script:
|
||||
then:
|
||||
lambda: |-
|
||||
using namespace solar;
|
||||
std::vector<uint8_t> byte_stream(8, 0);
|
||||
std::vector<uint8_t> byte_stream(3, 0);
|
||||
uint8_t& alarms = byte_stream[0];
|
||||
uint8_t& states = byte_stream[1];
|
||||
uint8_t& modes = byte_stream[2];
|
||||
int geysermode = 0;
|
||||
id(get_geyser_mode).execute(geysermode);
|
||||
alarms = ((id(inverter_1_battery).state) ? 0x80 : 0) | ((id(inverter_2_battery).state) ? 0x10 : 0) | ((id(inverter1_2_overload).state) ? 0x08 : 0);
|
||||
states = ((id(geyser_heating).state) ? 0x80 : 0) | ((id(mains_supply).state) ? 0x20 : 0) | ((id(battery_charging).state) ? 0x08 : 0);
|
||||
states = ((id(geyser_heating).state) ? 0x80 : 0) | ((id(geyser_relay).state) ? 0x40 : 0) | ((id(mains_supply).state) ? 0x20 : 0) | ((id(battery_charging).state) ? 0x08 : 0);
|
||||
modes = ((id(vacation_mode).state) ? 0x80 : 0) | ((geysermode << 4) & 0x70);
|
||||
id(g_cb_cache).send_frame(id(canbus_sthome), cbf_sthome::CB_CONTROLLER_STATES, byte_stream);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user