After my last topic I integrated my heat pump in HA via an ESP32 board. This works great but I would like to be able to select the heating/cooling mode. A text_sensor is already available to read the current setting:
text_sensor:
# System heating mode
- platform: modbus_controller
modbus_controller_id: mitsubishi
id: mitsubishi_heating_mode
name: "System heating mode"
icon: mdi:radiator
address: 0x1C ## FC3: 28
register_type: holding
bitmask: 0
raw_encode: HEXBYTES
lambda: |-
uint16_t value = modbus_controller::word_from_hex_str(x, 0);
ESP_LOGD("main", "Value for heating mode %d", value);
switch (value) {
case 0: return std::string("Heating room temperature");
case 1: return std::string("Heating flow temperature");
case 2: return std::string("Heating curve");
case 3: return std::string("Cooling room temperature");
case 4: return std::string("Cooling flow temperature");
case 5: return std::string("Heating startup procedure");
default: return std::string("Unknown");
}
return x;
I have examined the docs and I think this should best be accomplished by a modbus controller select item. Unfortunately didn’t write the code I already have, and I can only follow partly what is happening in the lambda’s.
But what should I put in the lambda and write_lambda? Unfortunately I don’t see a lot of examples on the internet, especially for the ESPhome modbus controller select option. If I take a lambda structure as for other registers I only get errors. Example of a working number:
number:
## Set tank temperature
- platform: modbus_controller
modbus_controller_id: mitsubishi
id: mitsubishi_wp_set_tank_temperature
name: "Set target tank temperature"
icon: mdi:water-thermometer-outline
address: 0x1F ## FC3: 31
unit_of_measurement: "°C"
register_type: holding
value_type: U_WORD
mode: box
step: 0.5
entity_category: config
min_value: 30
max_value: 59
lambda: "return x / 100; "
write_lambda: |-
uint16_t newtemp = x*100;
ESP_LOGI("main", "Set tank temperature %d", newtemp);
// Create a modbus command item with the flow temperature as the payload
esphome::modbus_controller::ModbusCommandItem set_payload_command = esphome::modbus_controller::ModbusCommandItem::create_write_single_command(mitsubishi, 0x1E, newtemp);
// Submit the command to the send queue
mitsubishi->queue_command(set_payload_command);
return {};
And if I look in the documentation the structure of the lambda’s should be different but I can figure out how. Does anyone know?
Yes. This sort of thing has been puzzling me too. Been trying to extract UART and Modbus data without success.
What are these types of lambda expressions called in C++, so I can do some research into them? Stuff like the double colon and “pushback” for example.
In the lambda is classic C code, and the lambda in this case includes a ‘switch’ statement (sometimes called a ‘case’ statement).
It returns to the surrounding component, e.g. the text_sensor, a pointer to a string which the component will then display as its current state. The string in question is chosen by the value tested-for by the switch statement’s ‘case’ selectors.
Alternatively, you can use the ‘optionsmap’ to achieve a similar result. They’re both doing the same thing: handing the component a string, based on the value of the device the component (here, a text_sensor) is working with (i.e. the modbus_controller).
I helped another user a few weeks ago with this same issue. Perhaps this is where you got some of the code you’re using.
Could you please give all code below Select, because I’m trying to understand how to use modbus select in my case, because I have modes for different thermo pump model. I was using switches instead, but I would like to use select function. Thank you in advance
this solution worked flawlessly! Just add this to an existing config (you still need a fully configured text_sensor for the same “address” for it to work). Name/id doesn’t matter (e.g. it should not be the same as for text_sensor for reference) - I believe it just takes “address” and matches with that