mirror of
https://github.com/esphome/esphome.git
synced 2025-02-07 00:11:59 +01:00
Added node discovery
This commit is contained in:
parent
f5321024f1
commit
07fb218412
@ -9,12 +9,19 @@ DEPENDENCIES = ["uart"]
|
||||
|
||||
duco_ns = cg.esphome_ns.namespace("duco")
|
||||
Duco = duco_ns.class_("Duco", cg.Component, uart.UARTDevice)
|
||||
# ModbusDevice = duco_ns.class_("ModbusDevice")
|
||||
DucoDiscovery = duco_ns.class_(
|
||||
"DucoDiscovery", cg.PollingComponent, cg.Parented.template(Duco)
|
||||
)
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_DUCO_ID = "duco_id"
|
||||
CONF_SEND_WAIT_TIME = "send_wait_time"
|
||||
|
||||
CONF_DISCOVERY = "discovery"
|
||||
|
||||
# A schema for components like sensors
|
||||
DUCO_COMPONENT_SCHEMA = cv.Schema({cv.GenerateID(CONF_DUCO_ID): cv.use_id(Duco)})
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
@ -23,15 +30,19 @@ CONFIG_SCHEMA = (
|
||||
CONF_SEND_WAIT_TIME, default="250ms"
|
||||
): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_DISABLE_CRC, default=False): cv.boolean,
|
||||
cv.Optional(CONF_DISCOVERY): cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(DucoDiscovery),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(DUCO_COMPONENT_SCHEMA),
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
)
|
||||
|
||||
# A schema for components like sensors
|
||||
DUCO_COMPONENT_SCHEMA = cv.Schema({cv.GenerateID(CONF_DUCO_ID): cv.use_id(Duco)})
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
cg.add_global(duco_ns.using)
|
||||
@ -42,3 +53,10 @@ async def to_code(config):
|
||||
|
||||
cg.add(var.set_send_wait_time(config[CONF_SEND_WAIT_TIME]))
|
||||
cg.add(var.set_disable_crc(config[CONF_DISABLE_CRC]))
|
||||
|
||||
if CONF_DISCOVERY in config:
|
||||
discovery_config = config[CONF_DISCOVERY]
|
||||
discovery_var = cg.new_Pvariable(discovery_config[CONF_ID])
|
||||
await cg.register_component(discovery_var, discovery_config)
|
||||
|
||||
cg.add(discovery_var.set_parent(var))
|
||||
|
@ -189,5 +189,73 @@ void Duco::debug_hex(std::vector<uint8_t> bytes, uint8_t separator) {
|
||||
delay(10);
|
||||
}
|
||||
|
||||
const std::string DucoDiscovery::NODE_TYPE_UCBAT = "UCBAT";
|
||||
const std::string DucoDiscovery::NODE_TYPE_UC = "UC";
|
||||
const std::string DucoDiscovery::NODE_TYPE_UCCO2 = "UCCO2";
|
||||
const std::string DucoDiscovery::NODE_TYPE_BOX = "BOX";
|
||||
const std::string DucoDiscovery::NODE_TYPE_SWITCH = "SWITCH";
|
||||
const std::string DucoDiscovery::NODE_TYPE_UNKNOWN = "UNKNOWN";
|
||||
|
||||
const std::string friendly_node_type(uint8_t type_code) {
|
||||
switch (type_code) {
|
||||
case DucoDiscovery::NODE_TYPE_CODE_UCBAT:
|
||||
return DucoDiscovery::NODE_TYPE_UCBAT;
|
||||
case DucoDiscovery::NODE_TYPE_CODE_UC:
|
||||
return DucoDiscovery::NODE_TYPE_UC;
|
||||
case DucoDiscovery::NODE_TYPE_CODE_UCCO2:
|
||||
return DucoDiscovery::NODE_TYPE_UCCO2;
|
||||
case DucoDiscovery::NODE_TYPE_CODE_BOX:
|
||||
return DucoDiscovery::NODE_TYPE_BOX;
|
||||
case DucoDiscovery::NODE_TYPE_CODE_SWITCH:
|
||||
return DucoDiscovery::NODE_TYPE_SWITCH;
|
||||
default:
|
||||
return DucoDiscovery::NODE_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void DucoDiscovery::update() {
|
||||
// display all found nodes
|
||||
for (auto &node : nodes_) {
|
||||
ESP_LOGW(TAG, "Node %d: type %d (%s)", std::get<0>(node), std::get<1>(node),
|
||||
friendly_node_type(std::get<1>(node)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void DucoDiscovery::loop() {
|
||||
if (delay_ > 0) {
|
||||
delay_--;
|
||||
return;
|
||||
}
|
||||
if (next_node_ > 0x44) {
|
||||
// discovery is finished
|
||||
return;
|
||||
}
|
||||
if (!waiting_for_response_) {
|
||||
ESP_LOGD(TAG, "Discover next node (%d = 0x%02x)", next_node_, next_node_);
|
||||
// request the next node
|
||||
std::vector<uint8_t> message = {0x01, next_node_};
|
||||
this->parent_->send(0x0c, message, this);
|
||||
|
||||
waiting_for_response_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DucoDiscovery::receive_response(std::vector<uint8_t> message) {
|
||||
if (message[1] == 0x0e) {
|
||||
ESP_LOGV(TAG, "Discovery response message: %s", format_hex_pretty(message).c_str());
|
||||
this->parent_->stop_waiting(message[2]);
|
||||
|
||||
if (message[3] != 0x00) {
|
||||
// node was found, store its information
|
||||
nodes_.push_back(std::make_tuple(next_node_, message[3]));
|
||||
}
|
||||
|
||||
next_node_++;
|
||||
waiting_for_response_ = false;
|
||||
// delay execution for 100 loops
|
||||
delay_ = 100;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace duco
|
||||
} // namespace esphome
|
||||
|
@ -53,5 +53,34 @@ class DucoDevice : public Parented<Duco> {
|
||||
virtual void receive_response(std::vector<uint8_t> message) {}
|
||||
};
|
||||
|
||||
class DucoDiscovery : public DucoDevice, public PollingComponent {
|
||||
public:
|
||||
void loop() override;
|
||||
void update() override;
|
||||
|
||||
void receive_response(std::vector<uint8_t> message) override;
|
||||
|
||||
static const std::string NODE_TYPE_UCBAT;
|
||||
static const std::string NODE_TYPE_UC;
|
||||
static const std::string NODE_TYPE_UCCO2;
|
||||
static const std::string NODE_TYPE_BOX;
|
||||
static const std::string NODE_TYPE_SWITCH;
|
||||
static const std::string NODE_TYPE_UNKNOWN;
|
||||
|
||||
static const uint8_t NODE_TYPE_CODE_UCBAT = 8;
|
||||
static const uint8_t NODE_TYPE_CODE_UC = 9;
|
||||
static const uint8_t NODE_TYPE_CODE_UCCO2 = 12;
|
||||
static const uint8_t NODE_TYPE_CODE_BOX = 17;
|
||||
static const uint8_t NODE_TYPE_CODE_SWITCH = 18;
|
||||
|
||||
protected:
|
||||
// start with a delay of 1000 loops
|
||||
uint32_t delay_{1000};
|
||||
uint8_t next_node_{0};
|
||||
bool waiting_for_response_ = false;
|
||||
|
||||
std::vector<std::tuple<uint8_t, uint8_t>> nodes_;
|
||||
};
|
||||
|
||||
} // namespace duco
|
||||
} // namespace esphome
|
||||
|
Loading…
Reference in New Issue
Block a user