galets
(galets)
1
Suppose I want to have a switch which would be:
-
on in bit 1 on on hold register 20 and bits 1 and 229 are on on register 11 and 4 are on on register 229, and off otherwise
-
when turning it on, I want to set all the bits I mentioned previously, and no other bits (e.g.: read/set/write pattern)
-
on esphome load, I don’t want anything changed, e.g. on_turn_on/on_turn_off should not trigger without UI interaction
Here’s my initial definition, which I want to fix. During load, events trigger, which is already a no-go for me. Can someone suggest how?
- platform: modbus_controller
modbus_controller_id: modbus_conroller1
name: Smart Load 1
id: smartLoad1On
icon: mdi:ev-station
register_type: holding
address: 20
bitmask: 0x0001
on_turn_off:
then:
- switch.turn_off: smartLoad1GridAlwaysOn
on_turn_on:
then:
- switch.turn_on: smartLoad1GridAlwaysOn
- platform: modbus_controller
modbus_controller_id: modbus_conroller1
name: Smart Load 1 Grid Always On
id: smartLoad1GridAlwaysOn
internal: true
icon: mdi:ev-station
register_type: holding
address: 229
bitmask: 0x0011
In general… Is there a recommended way to just read/write registers in lambda?
Karosm
(Karosm)
2
So what the switch state would be ON/OFF in binary or hex?
One register has only 16bits…
galets
(galets)
3
My bad. Read:
on in bit 1 on on hold register 20 and bits 1 and 4 are on on register 229, and off otherwise
Karosm
(Karosm)
4
Only those bits, so all others are 0?
ON>> register 20 is 0x0001 and register 229 is 0x0009?
OFF>> all zero?
galets
(galets)
5
Here’s what I ended up doing:
define internal sensors:
number:
- platform: modbus_controller
modbus_controller_id: modbus_conroller1
id: smartLoadOnOff
internal: true
register_type: holding
address: 20
value_type: U_WORD
min_value: 0x0000
max_value: 0xFFFF
step: 1
on_value:
then:
- lambda: sync_smart_loads();
- platform: modbus_controller
modbus_controller_id: modbus_conroller1
id: smartLoadExtraSettings
internal: true
register_type: holding
address: 229
value_type: U_WORD
min_value: 0x0000
max_value: 0xFFFF
step: 1
on_value:
then:
- lambda: sync_smart_loads();
switch:
- platform: template
name: Smart Load 1
id: smartLoad1On
icon: mdi:ev-station
optimistic: True
turn_on_action:
then:
- lambda: |-
set_bits(id(smartLoadOnOff), 0x0003 << 0, 0x0001 << 0);
set_bits(id(smartLoadExtraSettings), 0x0011 << 0, 0x0011 << 0);
turn_off_action:
then:
- lambda: |-
set_bits(id(smartLoadOnOff), 0x0003 << 0, 0);
...
and code:
#pragma once
void sync_smart_loads() {
if (id(smartLoadOnOff).has_state() && id(smartLoadExtraSettings).has_state()) {
uint16_t oo = id(smartLoadOnOff).state;
uint16_t es = id(smartLoadExtraSettings).state;
ESP_LOGD("smart_loads", "smartLoadOnOff has state: 0x%04X, smartLoadExtraSettings: 0x%04X", oo, es);
id(smartLoad1On).publish_state((oo & 0x0003) == 0x0001 && (es & 0x0011) == 0x0011);
...
}
}
void set_bits(esphome::number::Number *num, uint16_t mask, uint16_t value) {
if (id(smartLoadOnOff).has_state() && id(smartLoadExtraSettings).has_state()) {
uint16_t state = num->state;
uint16_t desired = state & ~mask | value;
ESP_LOGD("smart_loads", "%s has state: 0x%04X, wanted: 0x%04X", num->get_name(), state, desired);
if (state != desired) {
ESP_LOGI("smart_loads", "Updating state of %s to: 0x%04X", num->get_name(), desired);
auto call = num->make_call();
call.set_value(desired);
call.perform();
}
}
}