ESPHome 2026.5.0b1
Loading...
Searching...
No Matches
modbus_server.h
Go to the documentation of this file.
1#pragma once
2
4
8
9#include <utility>
10#include <vector>
11
12namespace esphome::modbus_server {
13
15
17 bool enabled{false};
18 uint16_t register_last_address{0xFFFF};
19 uint16_t register_value{0};
20};
21
23 using ReadLambda = std::function<int64_t()>;
24 using WriteLambda = std::function<bool(int64_t value)>;
25
26 public:
28 this->address = address;
29 this->value_type = value_type;
30 this->register_count = register_count;
31 }
32
33 template<typename T> void set_read_lambda(const std::function<T(uint16_t address)> &&user_read_lambda) {
34 this->read_lambda = [this, user_read_lambda]() -> int64_t {
35 T user_value = user_read_lambda(this->address);
36 if constexpr (std::is_same_v<T, float>) {
37 return bit_cast<uint32_t>(user_value);
38 } else {
39 return static_cast<int64_t>(user_value);
40 }
41 };
42 }
43
44 template<typename T>
45 void set_write_lambda(const std::function<bool(uint16_t address, const T v)> &&user_write_lambda) {
46 this->write_lambda = [this, user_write_lambda](int64_t number) {
47 if constexpr (std::is_same_v<T, float>) {
48 float float_value = bit_cast<float>(static_cast<uint32_t>(number));
49 return user_write_lambda(this->address, float_value);
50 }
51 return user_write_lambda(this->address, static_cast<T>(number));
52 };
53 }
54
55 // Formats a raw value into a string representation based on the value type for debugging
56 std::string format_value(int64_t value) const {
57 // max 44: float with %.1f can be up to 42 chars (3.4e38 → 39 integer digits + sign + decimal + 1 digit)
58 // plus null terminator = 43, rounded to 44 for 4-byte alignment
59 char buf[44];
60 switch (this->value_type) {
66 buf_append_printf(buf, sizeof(buf), 0, "%" PRIu64, static_cast<uint64_t>(value));
67 return buf;
73 buf_append_printf(buf, sizeof(buf), 0, "%" PRId64, value);
74 return buf;
77 buf_append_printf(buf, sizeof(buf), 0, "%.1f", bit_cast<float>(static_cast<uint32_t>(value)));
78 return buf;
79 default:
80 buf_append_printf(buf, sizeof(buf), 0, "%" PRId64, value);
81 return buf;
82 }
83 }
84
85 uint16_t address{0};
87 uint8_t register_count{0};
88 ReadLambda read_lambda;
89 WriteLambda write_lambda;
90};
91
93 public:
94 void dump_config() override;
95
97 void on_modbus_data(const std::vector<uint8_t> &data) override{};
99 void add_server_register(ServerRegister *server_register) { server_registers_.push_back(server_register); }
101 void on_modbus_read_registers(uint8_t function_code, uint16_t start_address, uint16_t number_of_registers) final;
103 void on_modbus_write_registers(uint8_t function_code, const std::vector<uint8_t> &data) final;
105 void set_server_courtesy_response(const ServerCourtesyResponse &server_courtesy_response) {
106 this->server_courtesy_response_ = server_courtesy_response;
107 }
110
111 protected:
113 std::vector<ServerRegister *> server_registers_{};
116 .enabled = false, .register_last_address = 0xFFFF, .register_value = 0};
117};
118
119} // namespace esphome::modbus_server
void on_modbus_read_registers(uint8_t function_code, uint16_t start_address, uint16_t number_of_registers) final
called when a modbus request (function code 0x03 or 0x04) was parsed without errors
void on_modbus_write_registers(uint8_t function_code, const std::vector< uint8_t > &data) final
called when a modbus request (function code 0x06 or 0x10) was parsed without errors
void set_server_courtesy_response(const ServerCourtesyResponse &server_courtesy_response)
Called by esphome generated code to set the server courtesy response object.
ServerCourtesyResponse get_server_courtesy_response() const
Get the server courtesy response object.
std::vector< ServerRegister * > server_registers_
Collection of all server registers for this component.
void add_server_register(ServerRegister *server_register)
Registers a server register with the controller. Called by esphomes code generator.
void on_modbus_data(const std::vector< uint8_t > &data) override
Not used for ModbusServer.
ServerCourtesyResponse server_courtesy_response_
Server courtesy response.
void set_write_lambda(const std::function< bool(uint16_t address, const T v)> &&user_write_lambda)
std::string format_value(int64_t value) const
void set_read_lambda(const std::function< T(uint16_t address)> &&user_read_lambda)
ServerRegister(uint16_t address, SensorValueType value_type, uint8_t register_count)
To bit_cast(const From &src)
Convert data between types, without aliasing issues or undefined behaviour.
Definition helpers.h:84
static void uint32_t