ESPHome  2024.4.0
modbus_output.cpp
Go to the documentation of this file.
1 #include "modbus_output.h"
2 #include "esphome/core/helpers.h"
3 #include "esphome/core/log.h"
4 
5 namespace esphome {
6 namespace modbus_controller {
7 
8 static const char *const TAG = "modbus_controller.output";
9 
13 void ModbusFloatOutput::write_state(float value) {
14  std::vector<uint16_t> data;
15  auto original_value = value;
16  // Is there are lambda configured?
17  if (this->write_transform_func_.has_value()) {
18  // data is passed by reference
19  // the lambda can fill the empty vector directly
20  // in that case the return value is ignored
21  auto val = (*this->write_transform_func_)(this, value, data);
22  if (val.has_value()) {
23  ESP_LOGV(TAG, "Value overwritten by lambda");
24  value = val.value();
25  } else {
26  ESP_LOGV(TAG, "Communication handled by lambda - exiting control");
27  return;
28  }
29  } else {
30  value = multiply_by_ * value;
31  }
32  // lambda didn't set payload
33  if (data.empty()) {
34  data = float_to_payload(value, this->sensor_value_type);
35  }
36 
37  ESP_LOGD(TAG, "Updating register: start address=0x%X register count=%d new value=%.02f (val=%.02f)",
38  this->start_address, this->register_count, value, original_value);
39 
40  // Create and send the write command
41  ModbusCommandItem write_cmd;
42  if (this->register_count == 1 && !this->use_write_multiple_) {
44  } else {
46  this->register_count, data);
47  }
48  parent_->queue_command(write_cmd);
49 }
50 
52  ESP_LOGCONFIG(TAG, "Modbus Float Output:");
53  LOG_FLOAT_OUTPUT(this);
54  ESP_LOGCONFIG(TAG, " Device start address: 0x%X", this->start_address);
55  ESP_LOGCONFIG(TAG, " Register count: %d", this->register_count);
56  ESP_LOGCONFIG(TAG, " Value type: %d", static_cast<int>(this->sensor_value_type));
57 }
58 
59 // ModbusBinaryOutput
61  // This will be called every time the user requests a state change.
63  std::vector<uint8_t> data;
64 
65  // Is there are lambda configured?
66  if (this->write_transform_func_.has_value()) {
67  // data is passed by reference
68  // the lambda can fill the empty vector directly
69  // in that case the return value is ignored
70  auto val = (*this->write_transform_func_)(this, state, data);
71  if (val.has_value()) {
72  ESP_LOGV(TAG, "Value overwritten by lambda");
73  state = val.value();
74  } else {
75  ESP_LOGV(TAG, "Communication handled by lambda - exiting control");
76  return;
77  }
78  }
79  if (!data.empty()) {
80  ESP_LOGV(TAG, "Modbus binary output write raw: %s", format_hex_pretty(data).c_str());
82  this->parent_, data,
83  [this, cmd](ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data) {
84  this->parent_->on_write_register_response(cmd.register_type, this->start_address, data);
85  });
86  } else {
87  ESP_LOGV(TAG, "Write new state: value is %s, type is %d address = %X, offset = %x", ONOFF(state),
88  (int) this->register_type, this->start_address, this->offset);
89 
90  // offset for coil and discrete inputs is the coil/register number not bytes
91  if (this->use_write_multiple_) {
92  std::vector<bool> states{state};
94  } else {
96  }
97  }
98  this->parent_->queue_command(cmd);
99 }
100 
102  ESP_LOGCONFIG(TAG, "Modbus Binary Output:");
103  LOG_BINARY_OUTPUT(this);
104  ESP_LOGCONFIG(TAG, " Device start address: 0x%X", this->start_address);
105  ESP_LOGCONFIG(TAG, " Register count: %d", this->register_count);
106  ESP_LOGCONFIG(TAG, " Value type: %d", static_cast<int>(this->sensor_value_type));
107 }
108 
109 } // namespace modbus_controller
110 } // namespace esphome
void queue_command(const ModbusCommandItem &command)
queues a modbus command in the send queue
std::string format_hex_pretty(const uint8_t *data, size_t length)
Format the byte array data of length len in pretty-printed, human-readable hex.
Definition: helpers.cpp:361
std::vector< uint16_t > float_to_payload(float value, SensorValueType value_type)
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...
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...
mopeka_std_values val[4]
bool has_value() const
Definition: optional.h:87
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.
void write_state(float value) override
Write a value to the device.
optional< write_transform_func_t > write_transform_func_
Definition: modbus_output.h:38
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_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.
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
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.
stm32_cmd_t * cmd
Definition: stm32flash.h:96
bool state
Definition: fan.h:34