mirror of
https://github.com/esphome/esphome.git
synced 2024-11-26 17:05:21 +01:00
commit
59e6e798dd
8 changed files with 41 additions and 5 deletions
|
@ -11,6 +11,7 @@ from esphome.const import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from .. import (
|
from .. import (
|
||||||
|
MODBUS_WRITE_REGISTER_TYPE,
|
||||||
add_modbus_base_properties,
|
add_modbus_base_properties,
|
||||||
modbus_controller_ns,
|
modbus_controller_ns,
|
||||||
modbus_calc_properties,
|
modbus_calc_properties,
|
||||||
|
@ -24,6 +25,7 @@ from ..const import (
|
||||||
CONF_CUSTOM_COMMAND,
|
CONF_CUSTOM_COMMAND,
|
||||||
CONF_FORCE_NEW_RANGE,
|
CONF_FORCE_NEW_RANGE,
|
||||||
CONF_MODBUS_CONTROLLER_ID,
|
CONF_MODBUS_CONTROLLER_ID,
|
||||||
|
CONF_REGISTER_TYPE,
|
||||||
CONF_SKIP_UPDATES,
|
CONF_SKIP_UPDATES,
|
||||||
CONF_USE_WRITE_MULTIPLE,
|
CONF_USE_WRITE_MULTIPLE,
|
||||||
CONF_VALUE_TYPE,
|
CONF_VALUE_TYPE,
|
||||||
|
@ -61,6 +63,9 @@ CONFIG_SCHEMA = cv.All(
|
||||||
number.NUMBER_SCHEMA.extend(ModbusItemBaseSchema).extend(
|
number.NUMBER_SCHEMA.extend(ModbusItemBaseSchema).extend(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(ModbusNumber),
|
cv.GenerateID(): cv.declare_id(ModbusNumber),
|
||||||
|
cv.Optional(CONF_REGISTER_TYPE, default="holding"): cv.enum(
|
||||||
|
MODBUS_WRITE_REGISTER_TYPE
|
||||||
|
),
|
||||||
cv.Optional(CONF_VALUE_TYPE, default="U_WORD"): cv.enum(SENSOR_VALUE_TYPE),
|
cv.Optional(CONF_VALUE_TYPE, default="U_WORD"): cv.enum(SENSOR_VALUE_TYPE),
|
||||||
cv.Optional(CONF_WRITE_LAMBDA): cv.returning_lambda,
|
cv.Optional(CONF_WRITE_LAMBDA): cv.returning_lambda,
|
||||||
# 24 bits are the maximum value for fp32 before precison is lost
|
# 24 bits are the maximum value for fp32 before precison is lost
|
||||||
|
@ -81,6 +86,7 @@ async def to_code(config):
|
||||||
byte_offset, reg_count = modbus_calc_properties(config)
|
byte_offset, reg_count = modbus_calc_properties(config)
|
||||||
var = cg.new_Pvariable(
|
var = cg.new_Pvariable(
|
||||||
config[CONF_ID],
|
config[CONF_ID],
|
||||||
|
config[CONF_REGISTER_TYPE],
|
||||||
config[CONF_ADDRESS],
|
config[CONF_ADDRESS],
|
||||||
byte_offset,
|
byte_offset,
|
||||||
config[CONF_BITMASK],
|
config[CONF_BITMASK],
|
||||||
|
|
|
@ -11,9 +11,9 @@ using value_to_data_t = std::function<float>(float);
|
||||||
|
|
||||||
class ModbusNumber : public number::Number, public Component, public SensorItem {
|
class ModbusNumber : public number::Number, public Component, public SensorItem {
|
||||||
public:
|
public:
|
||||||
ModbusNumber(uint16_t start_address, uint8_t offset, uint32_t bitmask, SensorValueType value_type, int register_count,
|
ModbusNumber(ModbusRegisterType register_type, uint16_t start_address, uint8_t offset, uint32_t bitmask,
|
||||||
uint8_t skip_updates, bool force_new_range) {
|
SensorValueType value_type, int register_count, uint8_t skip_updates, bool force_new_range) {
|
||||||
this->register_type = ModbusRegisterType::HOLDING;
|
this->register_type = register_type;
|
||||||
this->start_address = start_address;
|
this->start_address = start_address;
|
||||||
this->offset = offset;
|
this->offset = offset;
|
||||||
this->bitmask = bitmask;
|
this->bitmask = bitmask;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import select
|
from esphome.components import select
|
||||||
from esphome.const import CONF_ADDRESS, CONF_ID, CONF_LAMBDA
|
from esphome.const import CONF_ADDRESS, CONF_ID, CONF_LAMBDA, CONF_OPTIMISTIC
|
||||||
from esphome.jsonschema import jschema_composite
|
from esphome.jsonschema import jschema_composite
|
||||||
|
|
||||||
from .. import (
|
from .. import (
|
||||||
|
@ -79,6 +79,7 @@ CONFIG_SCHEMA = cv.All(
|
||||||
cv.Optional(CONF_FORCE_NEW_RANGE, default=False): cv.boolean,
|
cv.Optional(CONF_FORCE_NEW_RANGE, default=False): cv.boolean,
|
||||||
cv.Required(CONF_OPTIONSMAP): ensure_option_map(),
|
cv.Required(CONF_OPTIONSMAP): ensure_option_map(),
|
||||||
cv.Optional(CONF_USE_WRITE_MULTIPLE, default=False): cv.boolean,
|
cv.Optional(CONF_USE_WRITE_MULTIPLE, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||||
cv.Optional(CONF_LAMBDA): cv.returning_lambda,
|
cv.Optional(CONF_LAMBDA): cv.returning_lambda,
|
||||||
cv.Optional(CONF_WRITE_LAMBDA): cv.returning_lambda,
|
cv.Optional(CONF_WRITE_LAMBDA): cv.returning_lambda,
|
||||||
},
|
},
|
||||||
|
@ -112,6 +113,7 @@ async def to_code(config):
|
||||||
cg.add(parent.add_sensor_item(var))
|
cg.add(parent.add_sensor_item(var))
|
||||||
cg.add(var.set_parent(parent))
|
cg.add(var.set_parent(parent))
|
||||||
cg.add(var.set_use_write_mutiple(config[CONF_USE_WRITE_MULTIPLE]))
|
cg.add(var.set_use_write_mutiple(config[CONF_USE_WRITE_MULTIPLE]))
|
||||||
|
cg.add(var.set_optimistic(config[CONF_OPTIMISTIC]))
|
||||||
|
|
||||||
if CONF_LAMBDA in config:
|
if CONF_LAMBDA in config:
|
||||||
template_ = await cg.process_lambda(
|
template_ = await cg.process_lambda(
|
||||||
|
|
|
@ -80,6 +80,9 @@ void ModbusSelect::control(const std::string &value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_->queue_command(write_cmd);
|
parent_->queue_command(write_cmd);
|
||||||
|
|
||||||
|
if (this->optimistic_)
|
||||||
|
this->publish_state(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace modbus_controller
|
} // namespace modbus_controller
|
||||||
|
|
|
@ -32,6 +32,7 @@ class ModbusSelect : public Component, public select::Select, public SensorItem
|
||||||
|
|
||||||
void set_parent(ModbusController *const parent) { this->parent_ = parent; }
|
void set_parent(ModbusController *const parent) { this->parent_ = parent; }
|
||||||
void set_use_write_mutiple(bool use_write_multiple) { this->use_write_multiple_ = use_write_multiple; }
|
void set_use_write_mutiple(bool use_write_multiple) { this->use_write_multiple_ = use_write_multiple; }
|
||||||
|
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||||
void set_template(transform_func_t &&f) { this->transform_func_ = f; }
|
void set_template(transform_func_t &&f) { this->transform_func_ = f; }
|
||||||
void set_write_template(write_transform_func_t &&f) { this->write_transform_func_ = f; }
|
void set_write_template(write_transform_func_t &&f) { this->write_transform_func_ = f; }
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ class ModbusSelect : public Component, public select::Select, public SensorItem
|
||||||
std::vector<int64_t> mapping_;
|
std::vector<int64_t> mapping_;
|
||||||
ModbusController *parent_;
|
ModbusController *parent_;
|
||||||
bool use_write_multiple_{false};
|
bool use_write_multiple_{false};
|
||||||
|
bool optimistic_{false};
|
||||||
optional<transform_func_t> transform_func_;
|
optional<transform_func_t> transform_func_;
|
||||||
optional<write_transform_func_t> write_transform_func_;
|
optional<write_transform_func_t> write_transform_func_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
__version__ = "2022.3.0b1"
|
__version__ = "2022.3.0b2"
|
||||||
|
|
||||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,25 @@ std::string format_hex_pretty(const uint8_t *data, size_t length) {
|
||||||
}
|
}
|
||||||
std::string format_hex_pretty(const std::vector<uint8_t> &data) { return format_hex_pretty(data.data(), data.size()); }
|
std::string format_hex_pretty(const std::vector<uint8_t> &data) { return format_hex_pretty(data.data(), data.size()); }
|
||||||
|
|
||||||
|
std::string format_hex_pretty(const uint16_t *data, size_t length) {
|
||||||
|
if (length == 0)
|
||||||
|
return "";
|
||||||
|
std::string ret;
|
||||||
|
ret.resize(5 * length - 1);
|
||||||
|
for (size_t i = 0; i < length; i++) {
|
||||||
|
ret[5 * i] = format_hex_pretty_char((data[i] & 0xF000) >> 12);
|
||||||
|
ret[5 * i + 1] = format_hex_pretty_char((data[i] & 0x0F00) >> 8);
|
||||||
|
ret[5 * i + 2] = format_hex_pretty_char((data[i] & 0x00F0) >> 4);
|
||||||
|
ret[5 * i + 3] = format_hex_pretty_char(data[i] & 0x000F);
|
||||||
|
if (i != length - 1)
|
||||||
|
ret[5 * i + 2] = '.';
|
||||||
|
}
|
||||||
|
if (length > 4)
|
||||||
|
return ret + " (" + to_string(length) + ")";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
std::string format_hex_pretty(const std::vector<uint16_t> &data) { return format_hex_pretty(data.data(), data.size()); }
|
||||||
|
|
||||||
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off) {
|
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off) {
|
||||||
if (on == nullptr && strcasecmp(str, "on") == 0)
|
if (on == nullptr && strcasecmp(str, "on") == 0)
|
||||||
return PARSE_ON;
|
return PARSE_ON;
|
||||||
|
|
|
@ -386,8 +386,12 @@ template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> std::stri
|
||||||
|
|
||||||
/// Format the byte array \p data of length \p len in pretty-printed, human-readable hex.
|
/// Format the byte array \p data of length \p len in pretty-printed, human-readable hex.
|
||||||
std::string format_hex_pretty(const uint8_t *data, size_t length);
|
std::string format_hex_pretty(const uint8_t *data, size_t length);
|
||||||
|
/// Format the word array \p data of length \p len in pretty-printed, human-readable hex.
|
||||||
|
std::string format_hex_pretty(const uint16_t *data, size_t length);
|
||||||
/// Format the vector \p data in pretty-printed, human-readable hex.
|
/// Format the vector \p data in pretty-printed, human-readable hex.
|
||||||
std::string format_hex_pretty(const std::vector<uint8_t> &data);
|
std::string format_hex_pretty(const std::vector<uint8_t> &data);
|
||||||
|
/// Format the vector \p data in pretty-printed, human-readable hex.
|
||||||
|
std::string format_hex_pretty(const std::vector<uint16_t> &data);
|
||||||
/// Format an unsigned integer in pretty-printed, human-readable hex, starting with the most significant byte.
|
/// Format an unsigned integer in pretty-printed, human-readable hex, starting with the most significant byte.
|
||||||
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> std::string format_hex_pretty(T val) {
|
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> std::string format_hex_pretty(T val) {
|
||||||
val = convert_big_endian(val);
|
val = convert_big_endian(val);
|
||||||
|
|
Loading…
Reference in a new issue