ESPHome 2026.5.0
Loading...
Searching...
No Matches
modbus_output.cpp
Go to the documentation of this file.
1#include "modbus_output.h"
3#include "esphome/core/log.h"
4
6
7static const char *const TAG = "modbus_controller.output";
8
9// Maximum bytes to log in verbose hex output
10static constexpr size_t MODBUS_OUTPUT_MAX_LOG_BYTES = 64;
11
16 std::vector<uint16_t> data;
17 auto original_value = value;
18 // Is there are lambda configured?
19 if (this->write_transform_func_.has_value()) {
20 // data is passed by reference
21 // the lambda can fill the empty vector directly
22 // in that case the return value is ignored
23 auto val = (*this->write_transform_func_)(this, value, data);
24 if (val.has_value()) {
25 ESP_LOGV(TAG, "Value overwritten by lambda");
26 value = val.value();
27 } else {
28 ESP_LOGV(TAG, "Communication handled by lambda - exiting control");
29 return;
30 }
31 } else {
32 value = this->multiply_by_ * value;
33 }
34 // lambda didn't set payload
35 if (data.empty()) {
37 }
38
39 ESP_LOGD(TAG, "Updating register: start address=0x%X register count=%d new value=%.02f (val=%.02f)",
40 this->start_address, this->register_count, value, original_value);
41
42 // Create and send the write command
43 ModbusCommandItem write_cmd;
44 if (this->register_count == 1 && !this->use_write_multiple_) {
45 write_cmd =
47 } else {
49 this->register_count, data);
50 }
51 this->parent_->queue_command(write_cmd);
52}
53
55 ESP_LOGCONFIG(TAG, "Modbus Float Output:");
56 LOG_FLOAT_OUTPUT(this);
57 ESP_LOGCONFIG(TAG,
58 " Device start address: 0x%X\n"
59 " Register count: %d\n"
60 " Value type: %d",
61 this->start_address, this->register_count, static_cast<int>(this->sensor_value_type));
62}
63
64// ModbusBinaryOutput
66 // This will be called every time the user requests a state change.
68 std::vector<uint8_t> data;
69
70 // Is there are lambda configured?
71 if (this->write_transform_func_.has_value()) {
72 // data is passed by reference
73 // the lambda can fill the empty vector directly
74 // in that case the return value is ignored
75 auto val = (*this->write_transform_func_)(this, state, data);
76 if (val.has_value()) {
77 ESP_LOGV(TAG, "Value overwritten by lambda");
78 state = val.value();
79 } else {
80 ESP_LOGV(TAG, "Communication handled by lambda - exiting control");
81 return;
82 }
83 }
84 if (!data.empty()) {
85#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
86 char hex_buf[format_hex_pretty_size(MODBUS_OUTPUT_MAX_LOG_BYTES)];
87#endif
88 ESP_LOGV(TAG, "Modbus binary output write raw: %s",
89 format_hex_pretty_to(hex_buf, sizeof(hex_buf), data.data(), data.size()));
91 this->parent_, data,
92 [this, cmd](ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data) {
93 this->parent_->on_write_register_response(cmd.register_type, this->start_address, data);
94 });
95 } else {
96 ESP_LOGV(TAG, "Write new state: value is %s, type is %d address = %X, offset = %x", ONOFF(state),
97 (int) this->register_type, this->start_address, this->offset);
98
99 // offset for coil and discrete inputs is the coil/register number not bytes
100 if (this->use_write_multiple_) {
101 std::vector<bool> states{state};
103 } else {
105 }
106 }
107 this->parent_->queue_command(cmd);
108}
109
111 ESP_LOGCONFIG(TAG, "Modbus Binary Output:");
112 LOG_BINARY_OUTPUT(this);
113 ESP_LOGCONFIG(TAG,
114 " Device start address: 0x%X\n"
115 " Register count: %d\n"
116 " Value type: %d",
117 this->start_address, this->register_count, static_cast<int>(this->sensor_value_type));
118}
119
120} // namespace esphome::modbus_controller
optional< write_transform_func_t > write_transform_func_
static ModbusCommandItem create_custom_command(ModbusController *modbusdevice, const std::vector< uint8_t > &values, std::function< void(ModbusRegisterType register_type, uint16_t start_address, const std::vector< uint8_t > &data)> &&handler=nullptr)
Create custom modbus command.
static ModbusCommandItem create_write_multiple_coils(ModbusController *modbusdevice, uint16_t start_address, const std::vector< bool > &values)
Create modbus write multiple registers command Function 15 (0Fhex) Write Multiple Coils.
static ModbusCommandItem create_write_single_coil(ModbusController *modbusdevice, uint16_t address, bool value)
Create modbus write single registers command Function 05 (05hex) Write Single Coil.
static ModbusCommandItem create_write_single_command(ModbusController *modbusdevice, uint16_t start_address, uint16_t value)
Create modbus write multiple registers command Function 16 (10hex) Write Multiple Registers.
static ModbusCommandItem create_write_multiple_command(ModbusController *modbusdevice, uint16_t start_address, uint16_t register_count, const std::vector< uint16_t > &values)
Create modbus read command Function code 02-04.
void on_write_register_response(ModbusRegisterType register_type, uint16_t start_address, const std::vector< uint8_t > &data)
default delegate called by process_modbus_data when a response for a write response has retrieved fro...
void queue_command(const ModbusCommandItem &command)
queues a modbus command in the send queue
void write_state(float value) override
Write a value to the device.
optional< write_transform_func_t > write_transform_func_
bool state
Definition fan.h:2
mopeka_std_values val[3]
std::vector< uint16_t > float_to_payload(float value, SensorValueType value_type)
const std::vector< uint8_t > & data
char * format_hex_pretty_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length, char separator)
Format byte array as uppercase hex to buffer (base implementation).
Definition helpers.cpp:341
constexpr size_t format_hex_pretty_size(size_t byte_count)
Calculate buffer size needed for format_hex_pretty_to with separator: "XX:XX:...:XX\0".
Definition helpers.h:1386