ESPHome  2022.9.1
modbus_number.cpp
Go to the documentation of this file.
1 #include <vector>
2 #include "modbus_number.h"
3 #include "esphome/core/log.h"
4 
5 namespace esphome {
6 namespace modbus_controller {
7 
8 static const char *const TAG = "modbus.number";
9 
10 void ModbusNumber::parse_and_publish(const std::vector<uint8_t> &data) {
11  float result = payload_to_float(data, *this) / multiply_by_;
12 
13  // Is there a lambda registered
14  // call it with the pre converted value and the raw data array
15  if (this->transform_func_.has_value()) {
16  // the lambda can parse the response itself
17  auto val = (*this->transform_func_)(this, result, data);
18  if (val.has_value()) {
19  ESP_LOGV(TAG, "Value overwritten by lambda");
20  result = val.value();
21  }
22  }
23  ESP_LOGD(TAG, "Number new state : %.02f", result);
24  // this->sensor_->raw_state = result;
25  this->publish_state(result);
26 }
27 
28 void ModbusNumber::control(float value) {
29  ModbusCommandItem write_cmd;
30  std::vector<uint16_t> data;
31  float write_value = value;
32  // Is there are lambda configured?
33  if (this->write_transform_func_.has_value()) {
34  // data is passed by reference
35  // the lambda can fill the empty vector directly
36  // in that case the return value is ignored
37  auto val = (*this->write_transform_func_)(this, value, data);
38  if (val.has_value()) {
39  ESP_LOGV(TAG, "Value overwritten by lambda");
40  write_value = val.value();
41  } else {
42  ESP_LOGV(TAG, "Communication handled by lambda - exiting control");
43  return;
44  }
45  } else {
46  write_value = multiply_by_ * write_value;
47  }
48 
49  if (!data.empty()) {
50  ESP_LOGV(TAG, "Modbus Number write raw: %s", format_hex_pretty(data).c_str());
52  this->parent_, data,
53  [this, write_cmd](ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data) {
54  this->parent_->on_write_register_response(write_cmd.register_type, this->start_address, data);
55  });
56  } else {
57  data = float_to_payload(write_value, this->sensor_value_type);
58 
59  ESP_LOGD(TAG,
60  "Updating register: connected Sensor=%s start address=0x%X register count=%d new value=%.02f (val=%.02f)",
61  this->get_name().c_str(), this->start_address, this->register_count, value, write_value);
62 
63  // Create and send the write command
64  if (this->register_count == 1 && !this->use_write_multiple_) {
65  // since offset is in bytes and a register is 16 bits we get the start by adding offset/2
66  write_cmd =
68  } else {
70  this->register_count, data);
71  }
72  // publish new value
73  write_cmd.on_data_func = [this, write_cmd, value](ModbusRegisterType register_type, uint16_t start_address,
74  const std::vector<uint8_t> &data) {
75  // gets called when the write command is ack'd from the device
76  parent_->on_write_register_response(write_cmd.register_type, start_address, data);
77  this->publish_state(value);
78  };
79  }
80  parent_->queue_command(write_cmd);
81  this->publish_state(value);
82 }
83 void ModbusNumber::dump_config() { LOG_NUMBER(TAG, "Modbus Number", this); }
84 
85 } // namespace modbus_controller
86 } // 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:214
optional< write_transform_func_t > write_transform_func_
Definition: modbus_number.h:41
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...
void publish_state(float state)
Definition: number.cpp:9
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...
const std::string & get_name() const
Definition: entity_base.cpp:11
bool has_value() const
Definition: optional.h:87
float payload_to_float(const std::vector< uint8_t > &data, const SensorItem &item)
Convert vector<uint8_t> response payload to float.
void parse_and_publish(const std::vector< uint8_t > &data) override
std::function< void(ModbusRegisterType register_type, uint16_t start_address, const std::vector< uint8_t > &data)> on_data_func
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.
optional< transform_func_t > transform_func_
Definition: modbus_number.h:40
Definition: a4988.cpp:4
uint32_t val
Definition: datatypes.h:85
void control(float value) override
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.