ESPHome 2026.1.5
Loading...
Searching...
No Matches
modbus_number.cpp
Go to the documentation of this file.
1#include <vector>
2#include "modbus_number.h"
4#include "esphome/core/log.h"
5
6namespace esphome {
7namespace modbus_controller {
8
9static const char *const TAG = "modbus.number";
10
11// Maximum uint16_t registers to log in verbose hex output
12static constexpr size_t MODBUS_NUMBER_MAX_LOG_REGISTERS = 32;
13
14void ModbusNumber::parse_and_publish(const std::vector<uint8_t> &data) {
15 float result = payload_to_float(data, *this) / this->multiply_by_;
16
17 // Is there a lambda registered
18 // call it with the pre converted value and the raw data array
19 if (this->transform_func_.has_value()) {
20 // the lambda can parse the response itself
21 auto val = (*this->transform_func_)(this, result, data);
22 if (val.has_value()) {
23 ESP_LOGV(TAG, "Value overwritten by lambda");
24 result = val.value();
25 }
26 }
27 ESP_LOGD(TAG, "Number new state : %.02f", result);
28 // this->sensor_->raw_state = result;
29 this->publish_state(result);
30}
31
32void ModbusNumber::control(float value) {
33 ModbusCommandItem write_cmd;
34 std::vector<uint16_t> data;
35 float write_value = value;
36 // Is there are lambda configured?
37 if (this->write_transform_func_.has_value()) {
38 // data is passed by reference
39 // the lambda can fill the empty vector directly
40 // in that case the return value is ignored
41 auto val = (*this->write_transform_func_)(this, value, data);
42 if (val.has_value()) {
43 ESP_LOGV(TAG, "Value overwritten by lambda");
44 write_value = val.value();
45 } else {
46 ESP_LOGV(TAG, "Communication handled by lambda - exiting control");
47 return;
48 }
49 } else {
50 write_value = this->multiply_by_ * write_value;
51 }
52
53 if (!data.empty()) {
54#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
55 char hex_buf[format_hex_pretty_uint16_size(MODBUS_NUMBER_MAX_LOG_REGISTERS)];
56#endif
57 ESP_LOGV(TAG, "Modbus Number write raw: %s",
58 format_hex_pretty_to(hex_buf, sizeof(hex_buf), data.data(), data.size()));
60 this->parent_, data,
61 [this, write_cmd](ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data) {
62 this->parent_->on_write_register_response(write_cmd.register_type, this->start_address, data);
63 });
64 } else {
65 data = float_to_payload(write_value, this->sensor_value_type);
66
67 ESP_LOGD(TAG,
68 "Updating register: connected Sensor=%s start address=0x%X register count=%d new value=%.02f (val=%.02f)",
69 this->get_name().c_str(), this->start_address, this->register_count, value, write_value);
70
71 // Create and send the write command
72 if (this->register_count == 1 && !this->use_write_multiple_) {
73 // since offset is in bytes and a register is 16 bits we get the start by adding offset/2
75 data[0]);
76 } else {
78 this->parent_, this->start_address + this->offset / 2, this->register_count, data);
79 }
80 // publish new value
81 write_cmd.on_data_func = [this, write_cmd, value](ModbusRegisterType register_type, uint16_t start_address,
82 const std::vector<uint8_t> &data) {
83 // gets called when the write command is ack'd from the device
85 this->publish_state(value);
86 };
87 }
88 this->parent_->queue_command(write_cmd);
89 this->publish_state(value);
90}
91void ModbusNumber::dump_config() { LOG_NUMBER(TAG, "Modbus Number", this); }
92
93} // namespace modbus_controller
94} // namespace esphome
const StringRef & get_name() const
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_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.
std::function< void(ModbusRegisterType register_type, uint16_t start_address, const std::vector< uint8_t > &data)> on_data_func
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
optional< write_transform_func_t > write_transform_func_
optional< transform_func_t > transform_func_
void parse_and_publish(const std::vector< uint8_t > &data) override
void publish_state(float state)
Definition number.cpp:31
bool has_value() const
Definition optional.h:92
mopeka_std_values val[4]
float payload_to_float(const std::vector< uint8_t > &data, const SensorItem &item)
Convert vector<uint8_t> response payload to float.
std::vector< uint16_t > float_to_payload(float value, SensorValueType value_type)
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
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:334
constexpr size_t format_hex_pretty_uint16_size(size_t count)
Calculate buffer size needed for format_hex_pretty_to with uint16_t data: "XXXX:XXXX:....
Definition helpers.h:865