[modbus_controller] Add on_command_sent trigger (#7078)

Co-authored-by: Leo Schelvis <leo.schelvis@gmail.com>
This commit is contained in:
leejoow 2024-07-22 03:33:11 +02:00 committed by GitHub
parent a464e46d4d
commit 0a7d883633
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 57 additions and 2 deletions

View file

@ -1,8 +1,16 @@
import binascii import binascii
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome import automation
from esphome.components import modbus from esphome.components import modbus
from esphome.const import CONF_ADDRESS, CONF_ID, CONF_NAME, CONF_LAMBDA, CONF_OFFSET from esphome.const import (
CONF_ADDRESS,
CONF_ID,
CONF_NAME,
CONF_LAMBDA,
CONF_OFFSET,
CONF_TRIGGER_ID,
)
from esphome.cpp_helpers import logging from esphome.cpp_helpers import logging
from .const import ( from .const import (
CONF_BITMASK, CONF_BITMASK,
@ -12,6 +20,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_ON_COMMAND_SENT,
CONF_REGISTER_COUNT, CONF_REGISTER_COUNT,
CONF_REGISTER_TYPE, CONF_REGISTER_TYPE,
CONF_RESPONSE_SIZE, CONF_RESPONSE_SIZE,
@ -97,6 +106,10 @@ TYPE_REGISTER_MAP = {
"FP32_R": 2, "FP32_R": 2,
} }
ModbusCommandSentTrigger = modbus_controller_ns.class_(
"ModbusCommandSentTrigger", automation.Trigger.template(cg.int_, cg.int_)
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ModbusServerRegisterSchema = cv.Schema( ModbusServerRegisterSchema = cv.Schema(
@ -120,13 +133,19 @@ CONFIG_SCHEMA = cv.All(
cv.Optional( cv.Optional(
CONF_SERVER_REGISTERS, CONF_SERVER_REGISTERS,
): cv.ensure_list(ModbusServerRegisterSchema), ): cv.ensure_list(ModbusServerRegisterSchema),
cv.Optional(CONF_ON_COMMAND_SENT): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
ModbusCommandSentTrigger
),
}
),
} }
) )
.extend(cv.polling_component_schema("60s")) .extend(cv.polling_component_schema("60s"))
.extend(modbus.modbus_device_schema(0x01)) .extend(modbus.modbus_device_schema(0x01))
) )
ModbusItemBaseSchema = cv.Schema( ModbusItemBaseSchema = cv.Schema(
{ {
cv.GenerateID(CONF_MODBUS_CONTROLLER_ID): cv.use_id(ModbusController), cv.GenerateID(CONF_MODBUS_CONTROLLER_ID): cv.use_id(ModbusController),
@ -254,6 +273,11 @@ async def to_code(config):
) )
) )
await register_modbus_device(var, config) await register_modbus_device(var, config)
for conf in config.get(CONF_ON_COMMAND_SENT, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(
trigger, [(int, "function_code"), (int, "address")], conf
)
async def register_modbus_device(var, config): async def register_modbus_device(var, config):

View file

@ -0,0 +1,19 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/automation.h"
#include "esphome/components/modbus_controller/modbus_controller.h"
namespace esphome {
namespace modbus_controller {
class ModbusCommandSentTrigger : public Trigger<int, int> {
public:
ModbusCommandSentTrigger(ModbusController *a_modbuscontroller) {
a_modbuscontroller->add_on_command_sent_callback(
[this](int function_code, int address) { this->trigger(function_code, address); });
}
};
} // namespace modbus_controller
} // namespace esphome

View file

@ -6,6 +6,7 @@ CONF_CUSTOM_COMMAND = "custom_command"
CONF_FORCE_NEW_RANGE = "force_new_range" CONF_FORCE_NEW_RANGE = "force_new_range"
CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id" CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id"
CONF_MODBUS_FUNCTIONCODE = "modbus_functioncode" CONF_MODBUS_FUNCTIONCODE = "modbus_functioncode"
CONF_ON_COMMAND_SENT = "on_command_sent"
CONF_RAW_ENCODE = "raw_encode" CONF_RAW_ENCODE = "raw_encode"
CONF_REGISTER_COUNT = "register_count" CONF_REGISTER_COUNT = "register_count"
CONF_REGISTER_TYPE = "register_type" CONF_REGISTER_TYPE = "register_type"

View file

@ -43,7 +43,11 @@ bool ModbusController::send_next_command_() {
ESP_LOGV(TAG, "Sending next modbus command to device %d register 0x%02X count %d", this->address_, ESP_LOGV(TAG, "Sending next modbus command to device %d register 0x%02X count %d", this->address_,
command->register_address, command->register_count); command->register_address, command->register_count);
command->send(); command->send();
this->last_command_timestamp_ = millis(); this->last_command_timestamp_ = millis();
this->command_sent_callback_.call((int) command->function_code, command->register_address);
// remove from queue if no handler is defined // remove from queue if no handler is defined
if (!command->on_data_func) { if (!command->on_data_func) {
command_queue_.pop_front(); command_queue_.pop_front();
@ -659,5 +663,9 @@ int64_t payload_to_number(const std::vector<uint8_t> &data, SensorValueType sens
return value; return value;
} }
void ModbusController::add_on_command_sent_callback(std::function<void(int, int)> &&callback) {
this->command_sent_callback_.add(std::move(callback));
}
} // namespace modbus_controller } // namespace modbus_controller
} // namespace esphome } // namespace esphome

View file

@ -456,6 +456,8 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
size_t get_command_queue_length() { return command_queue_.size(); } size_t get_command_queue_length() { return command_queue_.size(); }
/// get if the module is offline, didn't respond the last command /// get if the module is offline, didn't respond the last command
bool get_module_offline() { return module_offline_; } bool get_module_offline() { return module_offline_; }
/// Set callback for commands
void add_on_command_sent_callback(std::function<void(int, int)> &&callback);
protected: protected:
/// parse sensormap_ and create range of sequential addresses /// parse sensormap_ and create range of sequential addresses
@ -488,6 +490,7 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
bool module_offline_; bool module_offline_;
/// how many updates to skip if module is offline /// how many updates to skip if module is offline
uint16_t offline_skip_updates_; uint16_t offline_skip_updates_;
CallbackManager<void(int, int)> command_sent_callback_{};
}; };
/** Convert vector<uint8_t> response payload to float. /** Convert vector<uint8_t> response payload to float.