1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-13 00:32:20 +01:00

Add support for acting as Modbus server (#4874)

Co-authored-by: Jeroen van Oort <jeroen.vanoort@webparking.nl>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
Jeroen van Oort
2024-05-22 06:17:32 +02:00
committed by GitHub
parent 76abf2200c
commit 1ca7c2d7dd
7 changed files with 203 additions and 21 deletions

View File

@@ -23,6 +23,8 @@ CODEOWNERS = ["@martgras"]
AUTO_LOAD = ["modbus"]
CONF_READ_LAMBDA = "read_lambda"
CONF_SERVER_REGISTERS = "server_registers"
MULTI_CONF = True
modbus_controller_ns = cg.esphome_ns.namespace("modbus_controller")
@@ -31,6 +33,7 @@ ModbusController = modbus_controller_ns.class_(
)
SensorItem = modbus_controller_ns.struct("SensorItem")
ServerRegister = modbus_controller_ns.struct("ServerRegister")
ModbusFunctionCode_ns = modbus_controller_ns.namespace("ModbusFunctionCode")
ModbusFunctionCode = ModbusFunctionCode_ns.enum("ModbusFunctionCode")
@@ -94,10 +97,18 @@ TYPE_REGISTER_MAP = {
"FP32_R": 2,
}
MULTI_CONF = True
_LOGGER = logging.getLogger(__name__)
ModbusServerRegisterSchema = cv.Schema(
{
cv.GenerateID(): cv.declare_id(ServerRegister),
cv.Required(CONF_ADDRESS): cv.positive_int,
cv.Optional(CONF_VALUE_TYPE, default="U_WORD"): cv.enum(SENSOR_VALUE_TYPE),
cv.Required(CONF_READ_LAMBDA): cv.returning_lambda,
}
)
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
@@ -106,6 +117,9 @@ CONFIG_SCHEMA = cv.All(
CONF_COMMAND_THROTTLE, default="0ms"
): cv.positive_time_period_milliseconds,
cv.Optional(CONF_OFFLINE_SKIP_UPDATES, default=0): cv.positive_int,
cv.Optional(
CONF_SERVER_REGISTERS,
): cv.ensure_list(ModbusServerRegisterSchema),
}
)
.extend(cv.polling_component_schema("60s"))
@@ -154,6 +168,17 @@ def validate_modbus_register(config):
return config
def _final_validate(config):
if CONF_SERVER_REGISTERS in config:
return modbus.final_validate_modbus_device("modbus_controller", role="server")(
config
)
return config
FINAL_VALIDATE_SCHEMA = _final_validate
def modbus_calc_properties(config):
byte_offset = 0
reg_count = 0
@@ -183,7 +208,7 @@ def modbus_calc_properties(config):
async def add_modbus_base_properties(
var, config, sensor_type, lamdba_param_type=cg.float_, lamdba_return_type=float
var, config, sensor_type, lambda_param_type=cg.float_, lambda_return_type=float
):
if CONF_CUSTOM_COMMAND in config:
cg.add(var.set_custom_data(config[CONF_CUSTOM_COMMAND]))
@@ -196,13 +221,13 @@ async def add_modbus_base_properties(
config[CONF_LAMBDA],
[
(sensor_type.operator("ptr"), "item"),
(lamdba_param_type, "x"),
(lambda_param_type, "x"),
(
cg.std_vector.template(cg.uint8).operator("const").operator("ref"),
"data",
),
],
return_type=cg.optional.template(lamdba_return_type),
return_type=cg.optional.template(lambda_return_type),
)
cg.add(var.set_template(template_))
@@ -211,6 +236,23 @@ async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE]))
cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES]))
if CONF_SERVER_REGISTERS in config:
for server_register in config[CONF_SERVER_REGISTERS]:
cg.add(
var.add_server_register(
cg.new_Pvariable(
server_register[CONF_ID],
server_register[CONF_ADDRESS],
server_register[CONF_VALUE_TYPE],
TYPE_REGISTER_MAP[server_register[CONF_VALUE_TYPE]],
await cg.process_lambda(
server_register[CONF_READ_LAMBDA],
[],
return_type=cg.float_,
),
)
)
)
await register_modbus_device(var, config)