ESPHome  2024.4.0
modbus_select.cpp
Go to the documentation of this file.
1 #include "modbus_select.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace modbus_controller {
6 
7 static const char *const TAG = "modbus_controller.select";
8 
9 void ModbusSelect::dump_config() { LOG_SELECT(TAG, "Modbus Controller Select", this); }
10 
11 void ModbusSelect::parse_and_publish(const std::vector<uint8_t> &data) {
12  int64_t value = payload_to_number(data, this->sensor_value_type, this->offset, this->bitmask);
13 
14  ESP_LOGD(TAG, "New select value %lld from payload", value);
15 
16  optional<std::string> new_state;
17 
18  if (this->transform_func_.has_value()) {
19  auto val = (*this->transform_func_)(this, value, data);
20  if (val.has_value()) {
21  new_state = *val;
22  ESP_LOGV(TAG, "lambda returned option %s", new_state->c_str());
23  }
24  }
25 
26  if (!new_state.has_value()) {
27  auto map_it = std::find(this->mapping_.cbegin(), this->mapping_.cend(), value);
28 
29  if (map_it != this->mapping_.cend()) {
30  size_t idx = std::distance(this->mapping_.cbegin(), map_it);
31  new_state = this->traits.get_options()[idx];
32  ESP_LOGV(TAG, "Found option %s for value %lld", new_state->c_str(), value);
33  } else {
34  ESP_LOGE(TAG, "No option found for mapping %lld", value);
35  }
36  }
37 
38  if (new_state.has_value()) {
39  this->publish_state(new_state.value());
40  }
41 }
42 
43 void ModbusSelect::control(const std::string &value) {
44  auto options = this->traits.get_options();
45  auto opt_it = std::find(options.cbegin(), options.cend(), value);
46  size_t idx = std::distance(options.cbegin(), opt_it);
47  optional<int64_t> mapval = this->mapping_[idx];
48  ESP_LOGD(TAG, "Found value %lld for option '%s'", *mapval, value.c_str());
49 
50  std::vector<uint16_t> data;
51 
52  if (this->write_transform_func_.has_value()) {
53  auto val = (*this->write_transform_func_)(this, value, *mapval, data);
54  if (val.has_value()) {
55  mapval = *val;
56  ESP_LOGV(TAG, "write_lambda returned mapping value %lld", *mapval);
57  } else {
58  ESP_LOGD(TAG, "Communication handled by write_lambda - exiting control");
59  return;
60  }
61  }
62 
63  if (data.empty()) {
64  number_to_payload(data, *mapval, this->sensor_value_type);
65  } else {
66  ESP_LOGV(TAG, "Using payload from write lambda");
67  }
68 
69  if (data.empty()) {
70  ESP_LOGW(TAG, "No payload was created for updating select");
71  return;
72  }
73 
74  const uint16_t write_address = this->start_address + this->offset / 2;
75  ModbusCommandItem write_cmd;
76  if ((this->register_count == 1) && (!this->use_write_multiple_)) {
77  write_cmd = ModbusCommandItem::create_write_single_command(parent_, write_address, data[0]);
78  } else {
79  write_cmd = ModbusCommandItem::create_write_multiple_command(parent_, write_address, this->register_count, data);
80  }
81 
82  parent_->queue_command(write_cmd);
83 
84  if (this->optimistic_)
85  this->publish_state(value);
86 }
87 
88 } // namespace modbus_controller
89 } // namespace esphome
value_type const & value() const
Definition: optional.h:89
void queue_command(const ModbusCommandItem &command)
queues a modbus command in the send queue
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...
optional< transform_func_t > transform_func_
Definition: modbus_select.h:49
SelectTraits traits
Definition: select.h:34
mopeka_std_values val[4]
bool has_value() const
Definition: optional.h:87
void number_to_payload(std::vector< uint16_t > &data, int64_t value, SensorValueType value_type)
Convert float value to vector<uint16_t> suitable for sending.
std::vector< std::string > get_options() const
void control(const std::string &value) override
optional< write_transform_func_t > write_transform_func_
Definition: modbus_select.h:50
uint8_t options
int64_t payload_to_number(const std::vector< uint8_t > &data, SensorValueType sensor_value_type, uint8_t offset, uint32_t bitmask)
Convert vector<uint8_t> response payload to number.
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 parse_and_publish(const std::vector< uint8_t > &data) override
void publish_state(const std::string &state)
Definition: select.cpp:9
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7