Updates to canbus

This commit is contained in:
Chris Stuurman 2025-09-03 22:37:03 +02:00
parent da5effe922
commit d28a51602a
6 changed files with 856 additions and 492 deletions

View File

@ -1,29 +1,15 @@
substitutions: substitutions:
CB_CANBUS_ID1: 0x501 # heartbeat messages
CB_CANBUS_ID2: 0x502 CB_CANBUS_ID01: 0x501
CB_CANBUS_ID3: 0x503 CB_CANBUS_ID02: 0x502
CB_CANBUS_ID4: 0x504 CB_CANBUS_ID03: 0x503
CB_CANBUS_ID5: 0x505 CB_CANBUS_ID04: 0x504
CB_CANBUS_ID6: 0x506 CB_CANBUS_ID05: 0x505
CB_CANBUS_ID7: 0x507 CB_CANBUS_ID06: 0x506
CB_CANBUS_ID8: 0x508 CB_CANBUS_ID07: 0x507
CB_CANBUS_ID9: 0x509 CB_CANBUS_ID08: 0x508
CB_CANBUS_ID09: 0x509
CB_CANBUS_ID10: 0x50A CB_CANBUS_ID10: 0x50A
CB_GEYSER_ENERGISED: 0x400
CB_UTILITY_POWER_ON: 0x401
CB_GEYSER_TOP_TEMPERATURE: 0x410
CB_GEYSER_BOTTOM_TEMPERATURE: 0x411
CB_AMBIENT_TEMPERATURE: 0x412
CB_MAINS_VOLTAGE: 0x420
CB_INVERTER_OUTPUT_VOLTAGE: 0x421
CB_MAINS_CURRENT: 0x430
CB_INVERTER_OUTPUT_CURRENT: 0x431
CB_GEYSER_CURRENT: 0x432
CB_POOL_CURRENT: 0x433
CB_MAINS_POWER: 0x440
CB_INVERTER_POWER: 0x441
CB_GEYSER_POWER: 0x442
CB_POOL_POWER: 0x443
# battery messages # battery messages
CB_BATTERY_LIMITS: 0x351 CB_BATTERY_LIMITS: 0x351
@ -32,3 +18,25 @@ substitutions:
CB_BATTERY_FAULT: 0x359 CB_BATTERY_FAULT: 0x359
CB_BATTERY_REQUEST_FLAG: 0x35C CB_BATTERY_REQUEST_FLAG: 0x35C
CB_BATTERY_MANUFACTURER: 0x35E 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

View File

@ -3,6 +3,11 @@ substitutions:
HEATING_WARM: 45 HEATING_WARM: 45
HEATING_LUKE_WARM: 35 HEATING_LUKE_WARM: 35
HEATING_HOT: 70 HEATING_HOT: 70
HEATING_DAY_TYPES: 4
HEATING_DAY_BLOCKS: 6
HEATING_TEMP_SCALE: 1000.0 HEATING_TEMP_SCALE: 1000.0
HEATING_DAY_BLOCKS: 6
GEYSER_MODES: 5
GM_SUNDAY: 0
GM_WORKDAY: 1
GM_SATURDAY: 2
GM_PUBLIC_HOLIDAY: 3
GM_SCHOOL_HOLIDAY: 4

View File

@ -3,14 +3,14 @@ wifi:
networks: networks:
- ssid: !secret wifi_ssid1 - ssid: !secret wifi_ssid1
password: !secret wifi_password1 password: !secret wifi_password1
- ssid: !secret wifi_ssid2 # - ssid: !secret wifi_ssid2
password: !secret wifi_password2 # password: !secret wifi_password2
- ssid: !secret wifi_ssid3 # - ssid: !secret wifi_ssid3
password: !secret wifi_password3 # password: !secret wifi_password3
- ssid: !secret wifi_ssid4 # - ssid: !secret wifi_ssid4
password: !secret wifi_password4 # password: !secret wifi_password4
- ssid: !secret wifi_ssid5 # - ssid: !secret wifi_ssid5
password: !secret wifi_password5 # password: !secret wifi_password5
manual_ip: manual_ip:
# For faster connection startup, # For faster connection startup,
# NB! set a static IP address in main config file # NB! set a static IP address in main config file

View File

@ -31,18 +31,31 @@ globals:
type: bool type: bool
restore_value: no restore_value: no
initial_value: '0' initial_value: '0'
- id: g_geyser_top_temperature # CAN BUS
type: double - id: can_msgctr
restore_value: yes type: int
initial_value: '0' restore_value: no
- id: g_geyser_bottom_temperature - id: g_cb_cache
type: double type: solar::cbf_cache
restore_value: yes restore_value: no
initial_value: '0'
esphome: esphome:
name: "${name}" name: "${name}"
friendly_name: "${friendly_name}" friendly_name: "${friendly_name}"
includes:
- source # copies folder with files to relevant to be included in esphome compile
- <source/solar/cb_frame.h> # angle brackets ensure file is included above globals in main.cpp. Make sure to use include GUARDS in the file to prevent double inclusion
- <source/solar/cbf_store.h>
- <source/solar/cbf_pylon.h>
- <source/solar/cbf_store_pylon.h>
- <source/solar/cbf_sthome.h>
- <source/solar/cbf_store_sthome.h>
- <source/solar/cbf_cache.h>
on_boot:
- priority: 600 # This is where most sensors are set up (higher number means higher priority)
then:
- lambda: |-
id(can_msgctr) = 0;
esp32: esp32:
board: esp32-s3-devkitc-1 board: esp32-s3-devkitc-1
@ -58,7 +71,10 @@ psram:
# Enable logging # Enable logging
logger: logger:
# level: verbose level: very_verbose
initial_level: INFO
logs:
canbus: INFO
# Enable Home Assistant API # Enable Home Assistant API
api: api:
@ -127,7 +143,9 @@ font:
glyphs: [ glyphs: [
0123456789,.,°,a,n, 0123456789,.,°,a,n,
"\u0020", # space "\u0020", # space
"\u002D", # minus
"\u003A", # colon "\u003A", # colon
"\u003F", # question mark
] ]
- file: "gfonts://Roboto" - file: "gfonts://Roboto"
id: roboto_192 id: roboto_192
@ -136,7 +154,9 @@ font:
glyphs: [ glyphs: [
0123456789,.,°,a,n, 0123456789,.,°,a,n,
"\u0020", # space "\u0020", # space
"\u002D", # minus
"\u003A", # colon "\u003A", # colon
"\u003F", # question mark
] ]
- file: "gfonts://Roboto" - file: "gfonts://Roboto"
id: geyser_temperature_font2 id: geyser_temperature_font2
@ -184,13 +204,9 @@ sun:
longitude: !secret longitude longitude: !secret longitude
interval: interval:
- interval: 10s - interval: 30s
then: then:
- canbus.send: - script.execute: send_info_request
canbus_id: canbus_sthome
data: [0x48, 0x45, 0x4C, 0x4C, 0x4F]
- lambda: |-
ESP_LOGI("SND:${CB_CANBUS_ID10}", "HELLO");
spi: spi:
- id: spi_bus0 - id: spi_bus0
@ -217,111 +233,48 @@ canbus:
spi_id: spi_bus0 spi_id: spi_bus0
id: canbus_sthome id: canbus_sthome
can_id: ${CB_CANBUS_ID10} can_id: ${CB_CANBUS_ID10}
#mode: NORMAL #LISTENONLY bit_rate: 500KBPS
bit_rate: 500KBPS #20KBPS
on_frame: on_frame:
- can_id: 0 - can_id: 0
can_id_mask: 0 can_id_mask: 0
then: then:
- lambda: |- - lambda: |-
std::string b(x.begin(), x.end()); id(can_msgctr)++;
ESP_LOGI("REC: 0", "%s", &b[0] ); using namespace solar;
- can_id: ${CB_GEYSER_ENERGISED} auto time_obj = id(time_source).now();
then: if(time_obj.is_valid()) {
- lvgl.widget.update: if(can_id >= 0x350 && can_id < 0x380) {
id: ind_geyser_on auto cbitem = cbf_store_pylon(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
hidden: !lambda |- bool publish = id(g_cb_cache).additem(cbitem);
std::string on_state(x.begin(), x.end()); if(publish) {
//ESP_LOGI("REC:${CB_GEYSER_ENERGISED}", "GEYSER IS: %s", on_state.c_str()); ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
if(on_state == "ON") {
id(g_geyser_heating_on) = true;
return false; // not hidden
} }
else if(on_state == "OFF") {
id(g_geyser_heating_on) = false;
return true; // hidden
} }
//ESP_LOGW("REC:${CB_GEYSER_ENERGISED}", "Invalid ON/OFF value: %s", on_state.c_str()); else if(can_id >= 0x400 && can_id <= 0x580) {
return true; // default auto cbitem = cbf_store_sthome(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
- can_id: ${CB_UTILITY_POWER_ON} bool publish = id(g_cb_cache).additem(cbitem);
then: if(publish) {
- lvgl.widget.update: ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
id: ind_utility_on switch (can_id) {
hidden: !lambda |- case cbf_sthome::CB_CONTROLLER_STATES:
std::string on_state(x.begin(), x.end()); if(x[1] & 0x80 == 0)
ESP_LOGI("REC:${CB_UTILITY_POWER_ON}", "UTILITY IS: %s", on_state.c_str()); lv_obj_add_flag(id(ind_geyser_on), LV_OBJ_FLAG_HIDDEN);
if(on_state == "ON") { else
id(g_utility_on) = true; lv_obj_clear_flag(id(ind_geyser_on), LV_OBJ_FLAG_HIDDEN);
return false; // not 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);
break;
case cbf_sthome::CB_GEYSER_TEMPERATURES:
id(update_temperature_display).execute(x);
}
}
}
else {
ESP_LOGI("WARN", "CAN ID within unhandled range: 0x%X", can_id);
} }
else if(on_state == "OFF") {
id(g_utility_on) = false;
return true; // hidden
} }
ESP_LOGW("REC:${CB_UTILITY_POWER_ON}", "Invalid ON/OFF value: %s", on_state.c_str());
return true; // default
- can_id: ${CB_GEYSER_TOP_TEMPERATURE}
then:
- lambda: |-
id(update_temperature_display).execute(x, id(g_geyser_top_temperature), rect_gtoptemp, ind_utility_on, lbl_gtoptemp);
- can_id: ${CB_GEYSER_BOTTOM_TEMPERATURE}
then:
- lambda: |-
id(update_temperature_display).execute(x, id(g_geyser_bottom_temperature) , rect_gbottemp, ind_geyser_on, lbl_gbottemp);
# - can_id: ${CB_CANBUS_ID1}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID1}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID2}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID2}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID3}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID3}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID4}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID4}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID5}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID5}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID6}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID6}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID7}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID7}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID8}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID8}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID9}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID9}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID10}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID10}", "%s", &b[0] );
display: display:
- platform: ili9xxx - platform: ili9xxx
@ -336,7 +289,7 @@ display:
auto_clear_enabled: false auto_clear_enabled: false
update_interval: never update_interval: never
invert_colors: false invert_colors: false
show_test_card: true # show_test_card: true
transform: transform:
swap_xy: true # landscape swap_xy: true # landscape
# mirror_x: true # landscape # mirror_x: true # landscape
@ -1226,10 +1179,48 @@ sensor:
# #
script: 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 - id: update_temperature_display
parameters: parameters:
x: std::vector<uint8_t>& x: std::vector<uint8_t>&
globalvar: double& 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);
}
//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: update_temp_display
parameters:
value: double
rect: lv_obj_t* rect: lv_obj_t*
indicator: lv_obj_t* indicator: lv_obj_t*
label: lv_obj_t* label: lv_obj_t*
@ -1237,8 +1228,6 @@ script:
- lambda: |- - lambda: |-
char buffer [4]; char buffer [4];
buffer[0] = '\0'; buffer[0] = '\0';
double value = x[3] + ((double)((x[2] << 16) + (x[1] << 8) + x[0]))/16777216;
globalvar = value;
snprintf (buffer, 4, "%.0f", value); snprintf (buffer, 4, "%.0f", value);
auto bgcolor = lv_color_hex(0xFF0000); auto bgcolor = lv_color_hex(0xFF0000);
auto ind_color = lv_color_hex(0xFF0000); auto ind_color = lv_color_hex(0xFF0000);
@ -1256,6 +1245,9 @@ script:
} }
lv_obj_set_style_bg_color(rect, bgcolor, LV_PART_MAIN); lv_obj_set_style_bg_color(rect, bgcolor, LV_PART_MAIN);
lv_obj_set_style_img_recolor(indicator, ind_color, LV_PART_MAIN); lv_obj_set_style_img_recolor(indicator, ind_color, LV_PART_MAIN);
if(isnan(value))
lv_label_set_text(label, "??");
else
lv_label_set_text(label, buffer); lv_label_set_text(label, buffer);
# - id: time_update # - id: time_update

View File

@ -5,18 +5,37 @@ packages:
substitutions: substitutions:
name: sthome-ut3 name: sthome-ut3
friendly_name: "sthome-ut3" friendly_name: "sthome-ut3"
v_ON: "{ 0x4F,0x4E }"
v_OFF: "{ 0x4F, 0x46, 0x46 }"
esphome: esphome:
name: "${name}" name: "${name}"
friendly_name: "${friendly_name}" friendly_name: "${friendly_name}"
includes:
- source # copies folder with files to relevant to be included in esphome compile
- <source/solar/cb_frame.h> # angle brackets ensure file is included above globals in main.cpp. Make sure to use include GUARDS in the file to prevent double inclusion
- <source/solar/cbf_store.h>
- <source/solar/cbf_pylon.h>
- <source/solar/cbf_store_pylon.h>
- <source/solar/cbf_sthome.h>
- <source/solar/cbf_store_sthome.h>
- <source/solar/cbf_cache.h>
on_boot:
- priority: 600 # This is where most sensors are set up (higher number means higher priority)
then:
- lambda: |-
id(can_msgctr) = 0;
globals: globals:
- id: geyser_relay_status - id: geyser_relay_status
type: bool type: bool
restore_value: yes restore_value: yes
initial_value: 'false' initial_value: 'false'
# CANBUS
- id: can_msgctr
type: int
restore_value: no
- id: g_cb_cache
type: solar::cbf_cache
restore_value: no
esp32: esp32:
board: nodemcu-32s #esp32dev board: nodemcu-32s #esp32dev
@ -29,7 +48,10 @@ esp32:
# Enable logging # Enable logging
logger: logger:
level: verbose level: VERY_VERBOSE
initial_level: INFO
logs:
canbus: INFO
# Enable Home Assistant API # Enable Home Assistant API
api: api:
@ -73,60 +95,13 @@ time:
interval: interval:
- interval: 30s - interval: 30s
then: then:
- if:
condition:
lambda: 'return !isnan(id(geyser_top_temperature).raw_state);'
then:
- canbus.send:
canbus_id: canbus_sthome
can_id: ${CB_GEYSER_TOP_TEMPERATURE}
data: !lambda |-
double temp = id(geyser_top_temperature).raw_state;
int value = (int) (temp * 16777216);
std::vector<uint8_t> byte_stream(sizeof(value));
memcpy(byte_stream.data(), &value, sizeof(value));
ESP_LOGI("SND:${CB_GEYSER_TOP_TEMPERATURE}", "Geyser TOP temp: %d (%f)", value, temp);
//ESP_LOGI("SND:0x400", "Geyser TOP temp: %f, x3: %d, x2: %d, x1: %d, x0: %d, xSize: %d", temp, byte_stream[3],byte_stream[2], byte_stream[1], byte_stream[0], byte_stream.size());
return byte_stream;
- delay: 1s
- if:
condition:
lambda: 'return !isnan(id(geyser_bottom_temperature).raw_state);'
then:
- canbus.send:
canbus_id: canbus_sthome
can_id: ${CB_GEYSER_BOTTOM_TEMPERATURE}
data: !lambda |-
double temp = id(geyser_bottom_temperature).raw_state;
int value = (int) (temp * 16777216);
std::vector<uint8_t> byte_stream(sizeof(value));
memcpy(byte_stream.data(), &value, sizeof(value));
ESP_LOGI("SND:${CB_GEYSER_BOTTOM_TEMPERATURE}", "Geyser BOTTOM temp: %d (%f)", value, temp);
//ESP_LOGI("SND:0x401", "Geyser BOTTOM temp: %f", temp, byte_stream[3],byte_stream[2], byte_stream[1], byte_stream[0], byte_stream.size());
return byte_stream;
- delay: 1s
- canbus.send:
canbus_id: canbus_sthome
can_id: ${CB_GEYSER_ENERGISED}
data: !lambda |-
if (id(geyser_heating).state) {
std::vector<uint8_t> byte_stream = ${v_ON};
ESP_LOGI("SND:${CB_GEYSER_ENERGISED}", "Geyser state: %c%c", byte_stream[0], byte_stream[1]);
return byte_stream;
}
else {
std::vector<uint8_t> byte_stream = ${v_OFF};
ESP_LOGI("SND:${CB_GEYSER_ENERGISED}", "Geyser state: %c%c%c", byte_stream[0], byte_stream[1], byte_stream[2]);
return byte_stream;
}
- interval: 10s
then:
- canbus.send:
canbus_id: canbus_sthome
data: [0x48, 0x45, 0x4C, 0x4C, 0x4F]
- lambda: |- - lambda: |-
ESP_LOGI("SND:${CB_CANBUS_ID3}", "HELLO"); using namespace solar;
std::vector<uint8_t> data(cbf_sthome::heartbeat.begin(), cbf_sthome::heartbeat.end());
for (int i = 0; i < 5; i++) {
id(canbus_sthome)->send_data(cbf_sthome::CB_CANBUS_ID03, false, data);
}
ESP_LOGI("SND:${CB_CANBUS_ID03}", "%s", cbf_sthome::heartbeat.c_str());
spi: spi:
- id: spi_bus0 - id: spi_bus0
@ -142,79 +117,25 @@ canbus:
spi_id: spi_bus0 spi_id: spi_bus0
mode: NORMAL mode: NORMAL
id: canbus_sthome id: canbus_sthome
can_id: ${CB_CANBUS_ID3} can_id: ${CB_CANBUS_ID03}
bit_rate: 500KBPS #20KBPS bit_rate: 500KBPS #20KBPS
on_frame: on_frame:
# - can_id: 0
# can_id_mask: 0
# then:
# - logger.log:
# format: "ID: 0x%03X -> %s"
# args: [ id, x ]
# tag: "canbus"
- can_id: 0 - can_id: 0
can_id_mask: 0 can_id_mask: 0
then: then:
- lambda: |- - lambda: |-
std::string b(x.begin(), x.end()); id(can_msgctr)++;
ESP_LOGI("REC: 0", "%s", &b[0] ); using namespace solar;
//ESP_LOGI("canbus", "REC: ID: %d, data: %s, rtr: %s", auto time_obj = id(time_source).now();
// x.can_id, if(time_obj.is_valid()) {
// x.data.c_str(), auto cbitem = cbf_store_sthome(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
// x.remote_transmission_request ? "true" : "false"); bool publish = id(g_cb_cache).additem(cbitem);
if(publish) {
ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
}
}
# - can_id: ${CB_CANBUS_ID1}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID1}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID2}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID2}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID3}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID3}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID4}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID4}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID5}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID5}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID6}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID6}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID7}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID7}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID8}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID8}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID9}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID9}", "%s", &b[0] );
# - can_id: ${CB_CANBUS_ID10}
# then:
# - lambda: |-
# std::string b(x.begin(), x.end());
# ESP_LOGI("REC:${CB_CANBUS_ID10}", "%s", &b[0] );
# Define a PWM output on the ESP32 # Define a PWM output on the ESP32
output: output:
- platform: ledc - platform: ledc
@ -234,74 +155,61 @@ switch:
name: "${name} Restart" name: "${name} Restart"
id: "restart_switch" id: "restart_switch"
binary_sensor:
- platform: homeassistant
name: "Geyser Heating"
entity_id: binary_sensor.sthome_ut8_heating
id: geyser_heating
on_press:
then:
- canbus.send:
canbus_id: canbus_sthome
can_id: ${CB_GEYSER_ENERGISED}
data: !lambda |-
std::vector<uint8_t> byte_stream = ${v_ON};
ESP_LOGI("SND:${CB_GEYSER_ENERGISED}", "Geyser state: %c%c", byte_stream[0], byte_stream[1]);
return byte_stream;
on_release:
then:
- canbus.send:
canbus_id: canbus_sthome
can_id: ${CB_GEYSER_ENERGISED}
data: !lambda |-
std::vector<uint8_t> byte_stream = ${v_OFF};
ESP_LOGI("SND:${CB_GEYSER_ENERGISED}", "Geyser state: %c%c%c", byte_stream[0], byte_stream[1], byte_stream[2]);
return byte_stream;
sensor: #sensor:
- platform: homeassistant # - platform: homeassistant
name: "Geyser Top Temperature" # name: "Geyser Top Temperature"
entity_id: sensor.sthome_ut8_geyser_top_temperature # entity_id: sensor.sthome_ut8_geyser_top_temperature
id: geyser_top_temperature # id: geyser_top_temperature
on_raw_value: # on_raw_value:
then: # then:
- canbus.send: # - script.execute: canbus_send_temperatures
canbus_id: canbus_sthome ## - canbus.send:
can_id: ${CB_GEYSER_TOP_TEMPERATURE} ## canbus_id: canbus_sthome
data: !lambda |- ## can_id: ${CB_GEYSER_TOP_TEMPERATURE}
double temp = id(geyser_top_temperature).raw_state; ## data: !lambda |-
int value = (int) (temp * 16777216); ## double temp = id(geyser_top_temperature).raw_state;
std::vector<uint8_t> byte_stream(sizeof(value)); ## int value = (int) (temp * 16777216);
memcpy(byte_stream.data(), &value, sizeof(value)); ## std::vector<uint8_t> byte_stream(sizeof(value));
ESP_LOGI("SND:${CB_GEYSER_TOP_TEMPERATURE}", "Geyser TOP temp: %d (%f)", value, temp); ## memcpy(byte_stream.data(), &value, sizeof(value));
//ESP_LOGI("SND:0x400", "Geyser TOP temp: %f, x3: %d, x2: %d, x1: %d, x0: %d, xSize: %d", temp, byte_stream[3],byte_stream[2], byte_stream[1], byte_stream[0], byte_stream.size()); ## ESP_LOGI("SND:${CB_GEYSER_TOP_TEMPERATURE}", "Geyser TOP temp: %d (%f)", value, temp);
return byte_stream; ## //ESP_LOGI("SND:0x400", "Geyser TOP temp: %f, x3: %d, x2: %d, x1: %d, x0: %d, xSize: %d", temp, byte_stream[3],byte_stream[2], byte_stream[1], byte_stream[0], byte_stream.size());
## return byte_stream;
- platform: homeassistant #
name: "Geyser Bottom Temperature" # - platform: homeassistant
entity_id: sensor.sthome_ut8_geyser_bottom_temperature # name: "Geyser Bottom Temperature"
id: geyser_bottom_temperature # entity_id: sensor.sthome_ut8_geyser_bottom_temperature
on_raw_value: # id: geyser_bottom_temperature
then: # on_raw_value:
- canbus.send: # then:
canbus_id: canbus_sthome # - script.execute: canbus_send_temperatures
can_id: ${CB_GEYSER_BOTTOM_TEMPERATURE} ## - canbus.send:
data: !lambda |- ## canbus_id: canbus_sthome
double temp = id(geyser_bottom_temperature).raw_state; ## can_id: ${CB_GEYSER_BOTTOM_TEMPERATURE}
int value = (int) (temp * 16777216); ## data: !lambda |-
std::vector<uint8_t> byte_stream(sizeof(value)); ## double temp = id(geyser_bottom_temperature).raw_state;
memcpy(byte_stream.data(), &value, sizeof(value)); ## int value = (int) (temp * 16777216);
ESP_LOGI("SND:${CB_GEYSER_BOTTOM_TEMPERATURE}", "Geyser BOTTOM temp: %d (%f)", value, temp); ## std::vector<uint8_t> byte_stream(sizeof(value));
//ESP_LOGI("SND:0x401", "Geyser BOTTOM temp: %f", temp, byte_stream[3],byte_stream[2], byte_stream[1], byte_stream[0], byte_stream.size()); ## memcpy(byte_stream.data(), &value, sizeof(value));
return byte_stream; ## ESP_LOGI("SND:${CB_GEYSER_BOTTOM_TEMPERATURE}", "Geyser BOTTOM temp: %d (%f)", value, temp);
## //ESP_LOGI("SND:0x401", "Geyser BOTTOM temp: %f", temp, byte_stream[3],byte_stream[2], byte_stream[1], byte_stream[0], byte_stream.size());
# Report wifi signal strength every 5 min if changed ## return byte_stream;
- platform: wifi_signal #
name: WiFi Signal # - platform: homeassistant
id: wifi_sig # name: "Ambient Temperature"
update_interval: 300s # entity_id: sensor.sthome_ut8_ambient_temperature
filters: # id: ambient_temperature
- delta: 10% # on_raw_value:
# then:
# - script.execute: canbus_send_temperatures
#
# # Report wifi signal strength every 5 min if changed
# - platform: wifi_signal
# name: WiFi Signal
# id: wifi_sig
# update_interval: 300s
# filters:
# - delta: 10%
text_sensor: text_sensor:
# - platform: template # - platform: template
@ -337,3 +245,50 @@ text_sensor:
id: device_last_restart id: device_last_restart
icon: mdi:clock icon: mdi:clock
entity_category: diagnostic entity_category: diagnostic
#script:
# - id: canbus_send_data
# then:
# - script.execute: canbus_send_temperatures
# - canbus.send:
# canbus_id: canbus_sthome
# can_id: ${CB_GEYSER_ENERGISED}
# data: !lambda |-
# if (id(geyser_heating).state) {
# std::vector<uint8_t> byte_stream = ${v_ON};
# ESP_LOGI("SND:${CB_GEYSER_ENERGISED}", "Geyser state: %c%c", byte_stream[0], byte_stream[1]);
# return byte_stream;
# }
# else {
# std::vector<uint8_t> byte_stream = ${v_OFF};
# ESP_LOGI("SND:${CB_GEYSER_ENERGISED}", "Geyser state: %c%c%c", byte_stream[0], byte_stream[1], byte_stream[2]);
# return byte_stream;
# }
#
# - id: canbus_send_temperatures
# then:
# - if:
# condition:
# lambda: 'return !isnan(id(geyser_top_temperature).raw_state) || !isnan(id(geyser_bottom_temperature).raw_state) || !isnan(id(ambient_temperature).raw_state);'
# then:
# - canbus.send:
# canbus_id: canbus_sthome
# can_id: ${CB_GEYSER_TEMPERATURES}
# data: !lambda |-
# double temp_top = isnan(id(geyser_top_temperature).raw_state) ? 0 : id(geyser_top_temperature).raw_state;
# double temp_bot = isnan(id(geyser_bottom_temperature).raw_state) ? 0 : id(geyser_bottom_temperature).raw_state;
# double temp_amb = isnan(id(ambient_temperature).raw_state) ? 0 : id(ambient_temperature).raw_state;
# int temp_top_int = (int)(temp_top * 256);
# int temp_bot_int = (int)(temp_bot * 256);
# int temp_amb_int = (int)(temp_amb * 256);
# std::vector<uint8_t> byte_stream(8, 0);
# byte_stream[0] = temp_top_int % 256;
# byte_stream[1] = (temp_top_int >> 8) % 256;
# byte_stream[2] = temp_bot_int % 256;
# byte_stream[3] = (temp_bot_int >> 8) % 256;
# byte_stream[4] = temp_amb_int % 256;
# byte_stream[5] = (temp_amb_int >> 8) % 256;
# ESP_LOGI("SND:${CB_GEYSER_TEMPERATURES}", "Geyser temps: %04X %04X %04X (%f, %f, %f)", byte_stream[0] + 256 * byte_stream[1], byte_stream[2] + 256 * byte_stream[3], byte_stream[4] + 256 * byte_stream[5], temp_top, temp_bot, temp_amb);
# return byte_stream;

File diff suppressed because it is too large Load Diff