mirror of
https://github.com/esphome/esphome.git
synced 2025-04-16 07:40:29 +01:00
Initialize Dallas PIO component to manage 1-wire Dallas addressable switches as DS2413, DS2406, DS2408
This commit is contained in:
parent
df26ace0f1
commit
efcefe6627
8
esphome/components/dallas_pio/__init__.py
Normal file
8
esphome/components/dallas_pio/__init__.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from .dallas_pio import CONFIG_SCHEMA, DallasPio, to_code
|
||||||
|
|
||||||
|
CODEOWNERS = ["@tdy91"]
|
||||||
|
|
||||||
|
DEPENDENCIES = ["one_wire", "binary_sensor", "switch"]
|
||||||
|
AUTO_LOAD = ["binary_sensor", "switch"]
|
||||||
|
|
||||||
|
__all__ = ["CONFIG_SCHEMA", "DallasPio", "to_code"]
|
84
esphome/components/dallas_pio/binary_sensor.cpp
Normal file
84
esphome/components/dallas_pio/binary_sensor.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "binary_sensor.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace dallas_pio {
|
||||||
|
|
||||||
|
void DallasPioBinarySensor::setup() {
|
||||||
|
if (this->dallas_pio_ == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "DallasPioBinarySensor setup failed - DallasPio not set for this binary sensor.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "DallasPioBinarySensor setup - DallasPio set for this binary sensor.");
|
||||||
|
|
||||||
|
this->address_ = this->dallas_pio_->get_address();
|
||||||
|
this->reference_ = this->dallas_pio_->get_reference();
|
||||||
|
this->family_code_ = this->dallas_pio_->get_family_code();
|
||||||
|
// this->bus_ = this->dallas_pio_->get_bus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DallasPioBinarySensor::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Dallas PIO Binary Sensor:");
|
||||||
|
ESP_LOGCONFIG(TAG, " dallas_pio_id: %s", this->dallas_pio_->get_id().c_str());
|
||||||
|
|
||||||
|
if (this->reference_ == "DS2408") {
|
||||||
|
ESP_LOGCONFIG(TAG, " pin: P%c", '0' - 1 + this->pin_); // P0, P1, ...
|
||||||
|
} else {
|
||||||
|
ESP_LOGCONFIG(TAG, " pin: PIO%c", 'A' - 1 + this->pin_); // PIOA, PIOB, ...
|
||||||
|
}
|
||||||
|
ESP_LOGCONFIG(TAG, " pin inverted: %s", this->pin_inverted_ ? "true" : "false");
|
||||||
|
/*
|
||||||
|
if (this->address_ == 0) {
|
||||||
|
ESP_LOGCONFIG(TAG, " address: invalid (null)");
|
||||||
|
} else {
|
||||||
|
ESP_LOGCONFIG(TAG, " address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
|
||||||
|
(uint8_t) (this->address_ >> 56),
|
||||||
|
(uint8_t) (this->address_ >> 48),
|
||||||
|
(uint8_t) (this->address_ >> 40),
|
||||||
|
(uint8_t) (this->address_ >> 32),
|
||||||
|
(uint8_t) (this->address_ >> 24),
|
||||||
|
(uint8_t) (this->address_ >> 16),
|
||||||
|
(uint8_t) (this->address_ >> 8),
|
||||||
|
(uint8_t) (this->address_));
|
||||||
|
ESP_LOGCONFIG(TAG, " Family code: 0x%02X", this->family_code_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Reference: %s", this->reference_.c_str());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
ESP_LOGCONFIG(TAG, " Name: %s", this->EntityBase::name_.c_str());
|
||||||
|
|
||||||
|
// this->component_->log_one_wire_device();
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DallasPioBinarySensor::update() {
|
||||||
|
// Ref Analog Devices DS2413.pdf p6 of 19
|
||||||
|
// | b7 b6 b5 b4 | b3 | b2 | b1 | b0 |
|
||||||
|
// | Complement of b3 to b0 | PIOB Output | PIOB Pin | PIOA Output | PIOA Pin |
|
||||||
|
// | | Latch State | State | Latch State | State |
|
||||||
|
// ESP_LOGCONFIG(TAG, "Dallas PIO Binary Sensor Update !");
|
||||||
|
uint8_t state = 0;
|
||||||
|
if (this->dallas_pio_->check_address() == 0) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->status_clear_warning();
|
||||||
|
|
||||||
|
if (this->reference_ == "DS2413") {
|
||||||
|
if (!this->dallas_pio_->read_state(state, this->pin_)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (this->reference_ == "DS2406") {
|
||||||
|
// Action pour DS2406
|
||||||
|
} else if (this->reference_ == "DS2408") {
|
||||||
|
// Action pour DS2408
|
||||||
|
} else {
|
||||||
|
// Action par défaut
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->pin_inverted_) {
|
||||||
|
state = !state;
|
||||||
|
}
|
||||||
|
this->publish_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dallas_pio
|
||||||
|
} // namespace esphome
|
42
esphome/components/dallas_pio/binary_sensor.h
Normal file
42
esphome/components/dallas_pio/binary_sensor.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
|
#include "dallas_pio_constants.h"
|
||||||
|
#include "dallas_pio.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace dallas_pio {
|
||||||
|
|
||||||
|
class DallasPioBinarySensor : public PollingComponent, public binary_sensor::BinarySensor {
|
||||||
|
public:
|
||||||
|
DallasPioBinarySensor() : dallas_pio_(nullptr), pio_pin_(0) {}
|
||||||
|
DallasPioBinarySensor(DallasPio *dallas_pio, uint8_t pio_pin) : dallas_pio_(dallas_pio), pio_pin_(pio_pin) {}
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
void update() override;
|
||||||
|
using EntityBase::set_name;
|
||||||
|
void set_dallas_pio(DallasPio *dallas_pio) { this->dallas_pio_ = dallas_pio; }
|
||||||
|
void set_address(uint64_t address) { this->address_ = address; }
|
||||||
|
void set_pin(uint8_t pin) { this->pin_ = pin; }
|
||||||
|
void set_pin_inverted(bool pin_inverted) { this->pin_inverted_ = pin_inverted; }
|
||||||
|
void set_pin_mode(bool input, bool output) {
|
||||||
|
this->is_input_ = input;
|
||||||
|
this->is_output_ = output;
|
||||||
|
}
|
||||||
|
// void set_inverted(bool inverted) { this->inverted_ = inverted; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DallasPio *dallas_pio_;
|
||||||
|
uint8_t pio_pin_;
|
||||||
|
std::string reference_;
|
||||||
|
uint8_t family_code_;
|
||||||
|
uint64_t address_;
|
||||||
|
uint8_t pin_;
|
||||||
|
bool pin_inverted_;
|
||||||
|
bool is_input_;
|
||||||
|
bool is_output_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dallas_pio
|
||||||
|
} // namespace esphome
|
68
esphome/components/dallas_pio/binary_sensor.py
Normal file
68
esphome/components/dallas_pio/binary_sensor.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import binary_sensor
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.const import CONF_INVERTED, CONF_MODE, CONF_PIN
|
||||||
|
|
||||||
|
DEPENDENCIES = ["binary_sensor", "dallas_pio"]
|
||||||
|
AUTO_LOAD = ["binary_sensor"]
|
||||||
|
|
||||||
|
dallas_pio_ns = cg.esphome_ns.namespace("dallas_pio")
|
||||||
|
DallasPioBinarySensor = dallas_pio_ns.class_(
|
||||||
|
"DallasPioBinarySensor",
|
||||||
|
cg.PollingComponent,
|
||||||
|
binary_sensor.BinarySensor,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_mode(value):
|
||||||
|
if value.get("input", False) is not True:
|
||||||
|
raise cv.Invalid(
|
||||||
|
"The 'input' field must always be 'true' for Dallas PIO binary sensors."
|
||||||
|
)
|
||||||
|
if value.get("output", False) is True:
|
||||||
|
raise cv.Invalid("The 'output' field must be 'false' if 'input' is 'true'.")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
CUSTOM_PIN_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required("number"): cv.one_of("PIOA", "PIOB", upper=True),
|
||||||
|
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_MODE, default={"input": True}): validate_mode,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
binary_sensor.binary_sensor_schema(
|
||||||
|
DallasPioBinarySensor,
|
||||||
|
)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_PIN): CUSTOM_PIN_SCHEMA,
|
||||||
|
cv.Required("dallas_pio_id"): cv.use_id(dallas_pio_ns.class_("DallasPio")),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("1s"))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = await binary_sensor.new_binary_sensor(config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
dallas_pio_ref = await cg.get_variable(config["dallas_pio_id"])
|
||||||
|
cg.add(var.set_dallas_pio(dallas_pio_ref))
|
||||||
|
|
||||||
|
# Extract pin configuration
|
||||||
|
pin_config = config[CONF_PIN]
|
||||||
|
pin_number = pin_config["number"] # "PIOA" or "PIOB"
|
||||||
|
pin_inverted = pin_config[CONF_INVERTED]
|
||||||
|
pin_mode = pin_config[CONF_MODE]
|
||||||
|
# C++ configuration association
|
||||||
|
if pin_number == "PIOA":
|
||||||
|
cg.add(var.set_pin(0x01)) # PIOA assiociated to 0x01
|
||||||
|
elif pin_number == "PIOB":
|
||||||
|
cg.add(var.set_pin(0x02)) # PIOB assiociated to 0x02
|
||||||
|
cg.add(var.set_pin_inverted(pin_inverted))
|
||||||
|
cg.add(var.set_pin_mode(pin_mode.get("input", True), pin_mode.get("output", False)))
|
||||||
|
# cg.add(var.set_inverted(inverted))
|
406
esphome/components/dallas_pio/dallas_pio.cpp
Normal file
406
esphome/components/dallas_pio/dallas_pio.cpp
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
#include "dallas_pio.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace dallas_pio {
|
||||||
|
|
||||||
|
DallasPio::DallasPio()
|
||||||
|
: id_(""),
|
||||||
|
one_wire_id_(),
|
||||||
|
name_(""),
|
||||||
|
reference_(""),
|
||||||
|
address_(0),
|
||||||
|
reference_from_address_(""),
|
||||||
|
family_code_(0),
|
||||||
|
is_setup_done_(false) {}
|
||||||
|
|
||||||
|
void DallasPio::set_id(const std::string &id) { this->id_ = id; }
|
||||||
|
|
||||||
|
void DallasPio::set_name(const std::string &name) { this->name_ = name; }
|
||||||
|
|
||||||
|
void DallasPio::set_address(uint64_t address) {
|
||||||
|
this->address_ = address;
|
||||||
|
OneWireDevice::set_address(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DallasPio::set_reference(const std::string &reference) { this->reference_ = reference; }
|
||||||
|
|
||||||
|
void DallasPio::set_crc_enabled(bool enabled) { this->crc_enabled_ = enabled; }
|
||||||
|
|
||||||
|
void DallasPio::set_one_wire_id(const std::string &one_wire_id) { this->one_wire_id_ = one_wire_id; }
|
||||||
|
|
||||||
|
bool DallasPio::check_address() { return this->check_address_(); }
|
||||||
|
|
||||||
|
void DallasPio::setup() {
|
||||||
|
if (this->is_setup_done_)
|
||||||
|
return;
|
||||||
|
// ESP_LOGD("dallas_pio", "Setting up DallasPio: %s", this->name_.c_str());
|
||||||
|
this->initialize_reference_();
|
||||||
|
this->is_setup_done_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DallasPio::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Dallas PIO :");
|
||||||
|
ESP_LOGCONFIG(TAG, " Id: %s", this->id_.c_str());
|
||||||
|
ESP_LOGCONFIG(TAG, " Reference: %s", this->reference_.c_str());
|
||||||
|
if (this->address_ == 0) {
|
||||||
|
ESP_LOGCONFIG(TAG, " address: invalid (null)");
|
||||||
|
} else {
|
||||||
|
ESP_LOGCONFIG(TAG, " address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", (uint8_t) (this->address_ >> 56),
|
||||||
|
(uint8_t) (this->address_ >> 48), (uint8_t) (this->address_ >> 40), (uint8_t) (this->address_ >> 32),
|
||||||
|
(uint8_t) (this->address_ >> 24), (uint8_t) (this->address_ >> 16), (uint8_t) (this->address_ >> 8),
|
||||||
|
(uint8_t) (this->address_));
|
||||||
|
ESP_LOGCONFIG(TAG, " Family code: 0x%02X", this->family_code_);
|
||||||
|
if (reference_ != reference_from_address_) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Reference from family code: %s", this->reference_from_address_.c_str());
|
||||||
|
ESP_LOGW(TAG, " WARNING: reference from family code does not match reference !!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_LOGCONFIG(TAG, " Name: %s", this->name_.c_str());
|
||||||
|
if (this->one_wire_id_.has_value()) {
|
||||||
|
ESP_LOGCONFIG(TAG, " OneWire ID: %s", this->one_wire_id_->c_str());
|
||||||
|
} else {
|
||||||
|
ESP_LOGCONFIG(TAG, " OneWire ID: not defined");
|
||||||
|
}
|
||||||
|
LOG_ONE_WIRE_DEVICE(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DallasPio::read_state(uint8_t &state, uint8_t pin) {
|
||||||
|
this->pin_ = pin;
|
||||||
|
if (this->reference_ == "DS2413") {
|
||||||
|
// ESP_LOGD(TAG, "DallasPio read_state %u pin %u", state, this->pin_);
|
||||||
|
return this->ds2413_get_state_(state);
|
||||||
|
} else if (this->reference_ == "DS2406") {
|
||||||
|
return this->ds2406_get_state_(state, this->crc_enabled_);
|
||||||
|
} else if (this->reference_ == "DS2408") {
|
||||||
|
// Action pour DS2408
|
||||||
|
} else {
|
||||||
|
// Action par défaut
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DallasPio::write_state(bool state, uint8_t pin, bool pin_inverted) {
|
||||||
|
this->pin_ = pin;
|
||||||
|
this->pin_inverted_ = pin_inverted;
|
||||||
|
// ESP_LOGW(TAG, "DallasPio write_state %u pin %u pin_ %u", state, pin, this->pin_);
|
||||||
|
if (this->reference_ == "DS2413") {
|
||||||
|
this->ds2413_write_state_(state);
|
||||||
|
} else if (this->reference_ == "DS2406") {
|
||||||
|
this->ds2406_write_state_(state, this->crc_enabled_);
|
||||||
|
} else if (this->reference_ == "DS2408") {
|
||||||
|
// Action for DS2408
|
||||||
|
} else {
|
||||||
|
// Default action
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************/
|
||||||
|
/* DS2413 */
|
||||||
|
/************/
|
||||||
|
|
||||||
|
bool DallasPio::ds2413_get_state_(uint8_t &state) {
|
||||||
|
// Ref DS2413.pdf p6 of 9
|
||||||
|
// | b7 b6 b5 b4 | b3 | b2 | b1 | b0 |
|
||||||
|
// | Complement of b3 to b0 | PIOB Output | PIOB Pin | PIOA Output | PIOA Pin |
|
||||||
|
// | | Latch State | State | Latch State | State |
|
||||||
|
// ESP_LOGCONFIG(TAG, "Dallas PIO Binary Sensor Update !");
|
||||||
|
uint8_t results;
|
||||||
|
bool ok = false;
|
||||||
|
// Initialize One-Wire bus for this device
|
||||||
|
if (!this->check_address_()) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this->bus_->reset()) {
|
||||||
|
ESP_LOGW(TAG, "Failed to reset One-Wire bus.");
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InterruptLock lock;
|
||||||
|
this->send_command_(DALLAS_COMMAND_PIO_ACCESS_READ);
|
||||||
|
results = this->bus_->read8();
|
||||||
|
}
|
||||||
|
ok = (~results & 0x0F) == (results >> 4);
|
||||||
|
// ESP_LOGD(TAG, "results1=%02x", results);
|
||||||
|
results &= 0x0F;
|
||||||
|
// ESP_LOGD(TAG, "results2=%02x", results);
|
||||||
|
if (!this->bus_->reset()) {
|
||||||
|
ESP_LOGW(TAG, "Failed to reset One-Wire bus.");
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (this->pin_) {
|
||||||
|
case 0x01: // PIOA
|
||||||
|
state = (results & 0x01);
|
||||||
|
break;
|
||||||
|
case 0x02: // PIOB
|
||||||
|
state = ((results >> 2) & 0x01);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // ds2413_get_state_
|
||||||
|
|
||||||
|
void DallasPio::ds2413_write_state_(bool state) {
|
||||||
|
// Ref Analog Devices DS2413.pdf p8 of 19
|
||||||
|
// | b7 b6 b5 b4 b3 b2 | b1 | b0 |
|
||||||
|
// | x x x x x x | PIOB | PIOA |
|
||||||
|
uint8_t ack = 0;
|
||||||
|
// Initialize One-Wire bus for this device
|
||||||
|
if (!this->check_address_()) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this->bus_->reset()) {
|
||||||
|
ESP_LOGW(TAG, "Failed to reset One-Wire bus.");
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((this->pin_ >= 1) && (this->pin_ <= 2)) {
|
||||||
|
uint8_t mask = 1 << (this->pin_ - 1);
|
||||||
|
// If state different than this->pin_inverted_
|
||||||
|
if (state ^ this->pin_inverted_) {
|
||||||
|
this->PioOutputRegister_ &= ~mask; // set bit bx to 0
|
||||||
|
} else {
|
||||||
|
this->PioOutputRegister_ |= mask; // set bx to 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InterruptLock lock;
|
||||||
|
this->send_command_(DALLAS_COMMAND_PIO_ACCESS_WRITE);
|
||||||
|
this->bus_->write8(this->PioOutputRegister_); // Send data
|
||||||
|
this->bus_->write8(~this->PioOutputRegister_); // Invert data and resend
|
||||||
|
ack = this->bus_->read8(); // 0xAA=success, 0xFF=failure
|
||||||
|
}
|
||||||
|
if (ack == DALLAS_COMMAND_PIO_ACK_SUCCESS) {
|
||||||
|
this->bus_->read8(); // Read the PIOA PIOB status byte
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this->bus_->reset()) { // reset to end command
|
||||||
|
ESP_LOGW(TAG, "Failed to reset One-Wire bus.");
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} // ds2413_write_state
|
||||||
|
|
||||||
|
/************/
|
||||||
|
/* DS2406 */
|
||||||
|
/************/
|
||||||
|
|
||||||
|
bool DallasPio::ds2406_get_state_(uint8_t &state, bool use_crc = false) {
|
||||||
|
// Ref Dallas Semiconductor MAXIM DS2406.pdf
|
||||||
|
// Dallas Semiconductor Application Note 27 app27.pdf
|
||||||
|
// CHANNEL CONTROL BYTE 1
|
||||||
|
// b7 b6 b5 b4 b3 b2 b1 b0
|
||||||
|
// ALR IM TOG IC CHS1 CHS0 CRC1 CRC0
|
||||||
|
// ALR=0 & IM=1, TOG=0 & IC=0 : do not change activity latch, read all bits from the selected channel & async mode
|
||||||
|
// CHANNEL CONTROL BYTE 2
|
||||||
|
// reserved for future development, must always be 0xFF
|
||||||
|
// CHANNEL INFO BYTE
|
||||||
|
// b7 b6 b5 b4 b3 b2 b1 b0
|
||||||
|
// Supply Number of PIOB PIOA PIOB PIOA PIOB PIOA
|
||||||
|
// Indication Channels Activity Activity Sensed Sensed Channel Channel
|
||||||
|
// 0 = no 0 = channel Latch Latch Level Level Flip-Flop Q Flip-Flop Q
|
||||||
|
// supply A only
|
||||||
|
// Please note :
|
||||||
|
// CRC1 CRC0
|
||||||
|
// 0 0 : CRC mode 0 = CRC disabled (no CRC at all)
|
||||||
|
// 0 1 : CRC mode 1 = CRC after every byte
|
||||||
|
|
||||||
|
uint8_t channel_control_byte_1;
|
||||||
|
uint8_t channel_control_byte_2 = 0xFF;
|
||||||
|
uint8_t channel_info_byte;
|
||||||
|
uint8_t received_crc = 0;
|
||||||
|
const char *strPIO = nullptr;
|
||||||
|
// Initialize One-Wire bus for this device
|
||||||
|
if (!this->check_address_()) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this->bus_->reset()) {
|
||||||
|
ESP_LOGW(TAG, "Failed to reset One-Wire bus.");
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (this->pin_) {
|
||||||
|
case 0x01: // PIOA
|
||||||
|
channel_control_byte_1 = use_crc ? 0b10000101 : 0b10000100; // ALR=1, CHS0=1, CRC mode 1 or mode 0
|
||||||
|
break;
|
||||||
|
case 0x02: // PIOB
|
||||||
|
channel_control_byte_1 = use_crc ? 0b10001001 : 0b10001000; // ALR=1, CHS1=1, CRC mode 1 or mode 0
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InterruptLock lock;
|
||||||
|
this->send_command_(DALLAS_COMMAND_PIO_ACCESS_READ);
|
||||||
|
// write CHANNEL CONTROL BYTE 1
|
||||||
|
this->bus_->write8(channel_control_byte_1);
|
||||||
|
// write CHANNEL CONTROL BYTE 2
|
||||||
|
this->bus_->write8(channel_control_byte_2);
|
||||||
|
// read CHANNEL INFO BYTE
|
||||||
|
channel_info_byte = this->bus_->read8();
|
||||||
|
if (use_crc) {
|
||||||
|
received_crc = this->bus_->read8();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (use_crc) {
|
||||||
|
ESP_LOGD(TAG, "CRC for Channel Info Byte: 0x%04X", use_crc);
|
||||||
|
if (!this->ds2406_verify_crc_(channel_control_byte_1, channel_control_byte_2, channel_info_byte, use_crc)) {
|
||||||
|
ESP_LOGW(TAG, "CRC verification failed!");
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->bus_->reset()) {
|
||||||
|
ESP_LOGW(TAG, "Failed to reset One-Wire bus.");
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// read CHANNEL INFO BYTE
|
||||||
|
bool pio_flipflop;
|
||||||
|
bool pio_sensed_level;
|
||||||
|
bool pio_activity_latch;
|
||||||
|
const bool has_channel_b = channel_info_byte & 0x40;
|
||||||
|
const bool has_supply = channel_info_byte & 0x80;
|
||||||
|
switch (this->pin_) {
|
||||||
|
case 0x01: // PIOA
|
||||||
|
pio_flipflop = channel_info_byte & 0x01;
|
||||||
|
pio_sensed_level = channel_info_byte & 0x04;
|
||||||
|
pio_activity_latch = channel_info_byte & 0x10;
|
||||||
|
strPIO = "PIOA";
|
||||||
|
break;
|
||||||
|
case 0x02: // PIOB
|
||||||
|
pio_flipflop = channel_info_byte & 0x02;
|
||||||
|
pio_sensed_level = channel_info_byte & 0x08;
|
||||||
|
pio_activity_latch = channel_info_byte & 0x20;
|
||||||
|
strPIO = "PIOB";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGW(TAG, "DallasPio DS2406 pin %u does not exist !", this->pin_);
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pio_flipflop == 0) {
|
||||||
|
ESP_LOGW(TAG, "DallasPio DS2406 PIO flipflop must be 1 to read %s", strPIO);
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
state = pio_sensed_level;
|
||||||
|
return true;
|
||||||
|
} // ds2406_get_state_
|
||||||
|
|
||||||
|
void DallasPio::ds2406_write_state_(bool state, bool use_crc = false) {
|
||||||
|
// Ref Dallas Semiconductor MAXIM DS2406.pdf
|
||||||
|
// Dallas Semiconductor Application Note 27 app27.pdf
|
||||||
|
// CHANNEL CONTROL BYTE 1
|
||||||
|
// b7 b6 b5 b4 b3 b2 b1 b0
|
||||||
|
// ALR IM TOG IC CHS1 CHS0 CRC1 CRC0
|
||||||
|
// ALR=0 & IM=0, TOG=0 & IC=0 : do not change activity latch, write all bits to the selected channel & async mode
|
||||||
|
// CHS1=01 CHS0=1 : PIOA, CHS1=1 CHS0=0 : PIOB
|
||||||
|
// CHANNEL CONTROL BYTE 2
|
||||||
|
// reserved for future development, must always be 0xFF
|
||||||
|
// CHANNEL INFO BYTE
|
||||||
|
// b7 b6 b5 b4 b3 b2 b1 b0
|
||||||
|
// Supply Number of PIOB PIOA PIOB PIOA PIOB PIOA
|
||||||
|
// Indication Channels Activity Activity Sensed Sensed Channel Channel
|
||||||
|
// 0 = no 0 = channel Latch Latch Level Level Flip-Flop Q Flip-Flop Q
|
||||||
|
// supply A only
|
||||||
|
// Initialize One-Wire bus for this device
|
||||||
|
if (!this->check_address_()) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this->bus_->reset()) {
|
||||||
|
ESP_LOGW(TAG, "Failed to reset One-Wire bus.");
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ALR=0,IM=0,TOG=0,IC=0, PIOA:CHS1=0,CHS0=1, PIOB:CHS1=1,CHS0=0, CRC1=0, CRC0=0
|
||||||
|
uint8_t channel_control_byte_1;
|
||||||
|
switch (this->pin_) {
|
||||||
|
case 0x01: // PIOA
|
||||||
|
channel_control_byte_1 = use_crc ? 0b00000101 : 0b00000100;
|
||||||
|
break;
|
||||||
|
case 0x02: // PIOB
|
||||||
|
channel_control_byte_1 = use_crc ? 0b00001001 : 0b00001000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uint8_t channel_control_byte_2 = 0xFF;
|
||||||
|
uint8_t channel_info_byte;
|
||||||
|
{
|
||||||
|
InterruptLock lock;
|
||||||
|
this->send_command_(DALLAS_COMMAND_PIO_ACCESS_READ);
|
||||||
|
// write CHANNEL CONTROL BYTE 1
|
||||||
|
this->bus_->write8(channel_control_byte_1);
|
||||||
|
// write CHANNEL CONTROL BYTE 2
|
||||||
|
this->bus_->write8(channel_control_byte_2);
|
||||||
|
channel_info_byte = this->bus_->read8();
|
||||||
|
this->bus_->write8(state ? 0xFF : 0x00);
|
||||||
|
}
|
||||||
|
if (!this->bus_->reset()) {
|
||||||
|
ESP_LOGW(TAG, "Failed to reset One-Wire bus.");
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} // ds2406_write_state
|
||||||
|
|
||||||
|
bool DallasPio::ds2406_verify_crc_(uint8_t control1, uint8_t control2, uint8_t info, uint16_t received_crc) {
|
||||||
|
uint16_t computed_crc = 0;
|
||||||
|
this->crc_reset_();
|
||||||
|
this->crc_shift_byte_(DALLAS_COMMAND_PIO_ACCESS_READ);
|
||||||
|
this->crc_shift_byte_(control1);
|
||||||
|
this->crc_shift_byte_(control2);
|
||||||
|
this->crc_shift_byte_(info);
|
||||||
|
computed_crc = this->crc_read_();
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Computed CRC: 0x%04X", computed_crc);
|
||||||
|
return computed_crc == received_crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************/
|
||||||
|
/* DS2408 */
|
||||||
|
/************/
|
||||||
|
|
||||||
|
bool DallasPio::ds2408_get_state_(uint8_t &state, bool use_crc = false) {
|
||||||
|
ESP_LOGW(TAG, "DallasPio DS2408 : ds2408_get_state_ to be implemented");
|
||||||
|
this->status_set_warning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DallasPio::ds2408_write_state_(bool state, bool use_crc = false) {
|
||||||
|
ESP_LOGW(TAG, "DallasPio DS2408 : ds2408_write_state_ to be implemented");
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DallasPio::crc_reset_() { this->crc_ = 0x0000; }
|
||||||
|
|
||||||
|
void DallasPio::crc_shift_byte_(uint8_t byte) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
bool mix = (this->crc_ ^ byte) & 0x01;
|
||||||
|
this->crc_ >>= 1;
|
||||||
|
if (mix)
|
||||||
|
this->crc_ ^= 0xA001;
|
||||||
|
byte >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t DallasPio::crc_read_() const { return this->crc_; }
|
||||||
|
|
||||||
|
} // namespace dallas_pio
|
||||||
|
} // namespace esphome
|
96
esphome/components/dallas_pio/dallas_pio.h
Normal file
96
esphome/components/dallas_pio/dallas_pio.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/one_wire/one_wire.h"
|
||||||
|
#include "dallas_pio_constants.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace dallas_pio {
|
||||||
|
|
||||||
|
class DallasPio : public Component, public one_wire::OneWireDevice {
|
||||||
|
public:
|
||||||
|
DallasPio();
|
||||||
|
std::string id_;
|
||||||
|
optional<std::string> one_wire_id_;
|
||||||
|
|
||||||
|
void set_id(const std::string &id);
|
||||||
|
void set_name(const std::string &name);
|
||||||
|
void set_address(uint64_t address);
|
||||||
|
void set_reference(const std::string &reference);
|
||||||
|
void set_crc_enabled(bool enabled);
|
||||||
|
void set_one_wire_id(const std::string &one_wire_id);
|
||||||
|
bool check_address();
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
void initialize_reference_() {
|
||||||
|
this->family_code_ = static_cast<uint8_t>(this->address_ & 0xFF);
|
||||||
|
switch (this->family_code_) {
|
||||||
|
case DALLAS_MODEL_DS2413:
|
||||||
|
this->reference_from_address_ = "DS2413";
|
||||||
|
break;
|
||||||
|
case DALLAS_MODEL_DS2406:
|
||||||
|
this->reference_from_address_ = "DS2406";
|
||||||
|
break;
|
||||||
|
case DALLAS_MODEL_DS2408:
|
||||||
|
this->reference_from_address_ = "DS2408";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this->reference_from_address_ = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (this->reference_ == "") {
|
||||||
|
if (this->reference_from_address_ == "Unknown") {
|
||||||
|
this->reference_ = "DS2413";
|
||||||
|
} else {
|
||||||
|
this->reference_ = this->reference_from_address_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->reference_ == "DS2413") {
|
||||||
|
PioOutputRegister_ = 0xFF;
|
||||||
|
} else if (this->reference_ == "DS2406") {
|
||||||
|
// Action pour DS2406
|
||||||
|
} else if (this->reference_ == "DS2408") {
|
||||||
|
// Action pour DS2408
|
||||||
|
} else {
|
||||||
|
// Action par défaut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_state(uint8_t &state, uint8_t pin);
|
||||||
|
bool write_state(bool state, uint8_t pin, bool pin_inverted);
|
||||||
|
|
||||||
|
const std::string &get_name() const { return this->name_; }
|
||||||
|
const std::string &get_id() const { return this->id_; }
|
||||||
|
uint64_t get_address() const { return this->address_; }
|
||||||
|
const std::string &get_reference() const { return this->reference_; }
|
||||||
|
uint8_t get_family_code() const { return this->family_code_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string name_;
|
||||||
|
std::string reference_;
|
||||||
|
uint64_t address_;
|
||||||
|
std::string reference_from_address_;
|
||||||
|
uint8_t family_code_;
|
||||||
|
bool is_setup_done_ = false;
|
||||||
|
bool ds2413_get_state_(uint8_t &state);
|
||||||
|
void ds2413_write_state_(bool state);
|
||||||
|
bool ds2406_get_state_(uint8_t &state, bool use_crc);
|
||||||
|
void ds2406_write_state_(bool state, bool use_crc);
|
||||||
|
bool ds2408_get_state_(uint8_t &state, bool use_crc);
|
||||||
|
void ds2408_write_state_(bool state, bool use_crc);
|
||||||
|
uint16_t crc_;
|
||||||
|
bool crc_enabled_ = false;
|
||||||
|
bool ds2406_verify_crc_(uint8_t control1, uint8_t control2, uint8_t info, uint16_t received_crc);
|
||||||
|
void crc_reset_();
|
||||||
|
void crc_shift_byte_(uint8_t byte);
|
||||||
|
uint16_t crc_read_() const;
|
||||||
|
// uint8_t calculate_crc_(std::initializer_list<uint8_t> data);
|
||||||
|
uint8_t pin_;
|
||||||
|
bool pin_inverted_;
|
||||||
|
uint8_t PioOutputRegister_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dallas_pio
|
||||||
|
} // namespace esphome
|
62
esphome/components/dallas_pio/dallas_pio.py
Normal file
62
esphome/components/dallas_pio/dallas_pio.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import one_wire
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.const import CONF_ADDRESS, CONF_ID, CONF_NAME
|
||||||
|
|
||||||
|
dallas_pio_ns = cg.esphome_ns.namespace("dallas_pio")
|
||||||
|
DallasPio = dallas_pio_ns.class_(
|
||||||
|
"DallasPio",
|
||||||
|
cg.Component,
|
||||||
|
one_wire.OneWireDevice,
|
||||||
|
)
|
||||||
|
|
||||||
|
CONF_REFERENCE = "reference"
|
||||||
|
CONF_CRC = "crc"
|
||||||
|
|
||||||
|
|
||||||
|
def validate_crc_option(config_list):
|
||||||
|
for conf in config_list:
|
||||||
|
reference = conf.get("reference", "").upper()
|
||||||
|
if not reference: # Si 'reference' n'est pas défini, on passe
|
||||||
|
continue
|
||||||
|
if reference == "DS2406" and "crc" not in conf:
|
||||||
|
raise cv.Invalid("Option 'crc' is required when 'reference' is DS2406.")
|
||||||
|
if reference != "DS2406" and "crc" in conf:
|
||||||
|
raise cv.Invalid("Option 'crc' is not supported for this reference.")
|
||||||
|
return config_list
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
cv.ensure_list(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(DallasPio),
|
||||||
|
cv.Optional(CONF_NAME): cv.string_strict,
|
||||||
|
cv.Required(CONF_ADDRESS): cv.hex_uint64_t,
|
||||||
|
cv.Optional(CONF_REFERENCE, default=""): cv.one_of(
|
||||||
|
"", "DS2413", "DS2406", "DS2408", upper=True
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CRC, default=False): cv.boolean,
|
||||||
|
}
|
||||||
|
).extend(one_wire.one_wire_device_schema())
|
||||||
|
),
|
||||||
|
validate_crc_option,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
for conf in config:
|
||||||
|
var = cg.new_Pvariable(conf[CONF_ID])
|
||||||
|
if CONF_NAME in conf:
|
||||||
|
cg.add(var.set_name(conf[CONF_NAME]))
|
||||||
|
cg.add(var.set_address(conf[CONF_ADDRESS]))
|
||||||
|
if CONF_REFERENCE in conf:
|
||||||
|
cg.add(var.set_reference(conf[CONF_REFERENCE]))
|
||||||
|
if CONF_CRC in conf and conf[CONF_REFERENCE] == "DS2406":
|
||||||
|
cg.add(var.set_crc_enabled(conf[CONF_CRC]))
|
||||||
|
if CONF_ID in conf:
|
||||||
|
cg.add(var.set_id(conf[CONF_ID].id))
|
||||||
|
if "one_wire_id" in conf:
|
||||||
|
cg.add(var.set_one_wire_id(conf["one_wire_id"].id))
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await one_wire.register_one_wire_device(var, conf)
|
17
esphome/components/dallas_pio/dallas_pio_constants.h
Normal file
17
esphome/components/dallas_pio/dallas_pio_constants.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace dallas_pio {
|
||||||
|
|
||||||
|
static const char *const TAG = "dallas_pio";
|
||||||
|
|
||||||
|
static const uint8_t DALLAS_MODEL_DS2413 = 0xBA;
|
||||||
|
static const uint8_t DALLAS_MODEL_DS2406 = 0x12;
|
||||||
|
static const uint8_t DALLAS_MODEL_DS2408 = 0x29;
|
||||||
|
static const uint8_t DALLAS_COMMAND_PIO_ACCESS_READ = 0xF5;
|
||||||
|
static const uint8_t DALLAS_COMMAND_PIO_ACCESS_WRITE = 0x5A;
|
||||||
|
static const uint8_t DALLAS_COMMAND_PIO_ACK_SUCCESS = 0xAA;
|
||||||
|
static const uint8_t DALLAS_COMMAND_PIO_ACK_ERROR = 0xFF;
|
||||||
|
|
||||||
|
} // namespace dallas_pio
|
||||||
|
} // namespace esphome
|
81
esphome/components/dallas_pio/switch.cpp
Normal file
81
esphome/components/dallas_pio/switch.cpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include "switch.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace dallas_pio {
|
||||||
|
|
||||||
|
void DallasPioSwitch::setup() {
|
||||||
|
if (this->dallas_pio_ == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "DallasPioSwitch setup failed - DallasPio not set for this switch.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "DallasPioSwitch setup - DallasPio set for this switch.");
|
||||||
|
|
||||||
|
this->address_ = this->dallas_pio_->get_address();
|
||||||
|
this->reference_ = this->dallas_pio_->get_reference();
|
||||||
|
this->family_code_ = this->dallas_pio_->get_family_code();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DallasPioSwitch::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Dallas PIO Switch:");
|
||||||
|
ESP_LOGCONFIG(TAG, " dallas_pio_id: %s", this->dallas_pio_->get_id().c_str());
|
||||||
|
if (this->reference_ == "DS2408") {
|
||||||
|
ESP_LOGCONFIG(TAG, " pin: P%c", '0' - 1 + this->pin_); // P0, P1, ...
|
||||||
|
} else {
|
||||||
|
ESP_LOGCONFIG(TAG, " pin: PIO%c", 'A' - 1 + this->pin_); // PIOA, PIOB, ...
|
||||||
|
}
|
||||||
|
ESP_LOGCONFIG(TAG, " pin inverted: %s", this->pin_inverted_ ? "true" : "false");
|
||||||
|
ESP_LOGCONFIG(TAG, " inverted: %s", this->inverted_ ? "true" : "false");
|
||||||
|
/*
|
||||||
|
if (this->address_ == 0) {
|
||||||
|
ESP_LOGCONFIG(TAG, " address: invalid (null)");
|
||||||
|
} else {
|
||||||
|
ESP_LOGCONFIG(TAG, " address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
|
||||||
|
(uint8_t) (this->address_ >> 56),
|
||||||
|
(uint8_t) (this->address_ >> 48),
|
||||||
|
(uint8_t) (this->address_ >> 40),
|
||||||
|
(uint8_t) (this->address_ >> 32),
|
||||||
|
(uint8_t) (this->address_ >> 24),
|
||||||
|
(uint8_t) (this->address_ >> 16),
|
||||||
|
(uint8_t) (this->address_ >> 8),
|
||||||
|
(uint8_t) (this->address_));
|
||||||
|
ESP_LOGCONFIG(TAG, " Family code: 0x%02X", this->family_code_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Reference: %s", this->reference_.c_str());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
ESP_LOGCONFIG(TAG, " Name: %s", this->EntityBase::name_.c_str());
|
||||||
|
|
||||||
|
// this->component_->log_one_wire_device();
|
||||||
|
// LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DallasPioSwitch::loop() {}
|
||||||
|
|
||||||
|
void DallasPioSwitch::write_state(bool state) {
|
||||||
|
ESP_LOGD(TAG, "DallasPioSwitch write_state %u", state);
|
||||||
|
|
||||||
|
if (this->inverted_) {
|
||||||
|
state = !state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->dallas_pio_->check_address() == 0) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->status_clear_warning();
|
||||||
|
|
||||||
|
if (this->reference_ == "DS2413") {
|
||||||
|
if (!this->dallas_pio_->write_state(state, this->pin_, this->pin_inverted_)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (this->reference_ == "DS2406") {
|
||||||
|
// Action pour DS2406
|
||||||
|
} else if (this->reference_ == "DS2408") {
|
||||||
|
// Action pour DS2408
|
||||||
|
} else {
|
||||||
|
// Action par défaut
|
||||||
|
}
|
||||||
|
this->publish_state(state); // Set state in ESPHome
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dallas_pio
|
||||||
|
} // namespace esphome
|
45
esphome/components/dallas_pio/switch.h
Normal file
45
esphome/components/dallas_pio/switch.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/switch/switch.h"
|
||||||
|
#include "dallas_pio_constants.h"
|
||||||
|
#include "dallas_pio.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace dallas_pio {
|
||||||
|
|
||||||
|
class DallasPioSwitch : public Component, public switch_::Switch {
|
||||||
|
public:
|
||||||
|
DallasPioSwitch() : dallas_pio_(nullptr), pio_pin_(0) {}
|
||||||
|
DallasPioSwitch(DallasPio *dallas_pio, uint8_t pio_pin) : dallas_pio_(dallas_pio), pio_pin_(pio_pin) {}
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
void loop() override;
|
||||||
|
void write_state(bool state) override;
|
||||||
|
|
||||||
|
using EntityBase::set_name;
|
||||||
|
void set_dallas_pio(DallasPio *dallas_pio) { this->dallas_pio_ = dallas_pio; }
|
||||||
|
void set_address(uint64_t address) { this->address_ = address; }
|
||||||
|
void set_pin(uint8_t pin) { this->pin_ = pin; }
|
||||||
|
void set_pin_inverted(bool pin_inverted) { this->pin_inverted_ = pin_inverted; }
|
||||||
|
void set_pin_mode(bool input, bool output) {
|
||||||
|
this->is_input_ = input;
|
||||||
|
this->is_output_ = output;
|
||||||
|
}
|
||||||
|
void set_inverted(bool inverted) { this->inverted_ = inverted; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DallasPio *dallas_pio_;
|
||||||
|
uint8_t pio_pin_;
|
||||||
|
std::string reference_;
|
||||||
|
uint8_t family_code_;
|
||||||
|
uint64_t address_;
|
||||||
|
uint8_t pin_;
|
||||||
|
bool pin_inverted_;
|
||||||
|
bool inverted_;
|
||||||
|
bool is_input_;
|
||||||
|
bool is_output_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dallas_pio
|
||||||
|
} // namespace esphome
|
68
esphome/components/dallas_pio/switch.py
Normal file
68
esphome/components/dallas_pio/switch.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import switch
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.const import CONF_INVERTED, CONF_MODE, CONF_PIN
|
||||||
|
|
||||||
|
DEPENDENCIES = ["switch", "dallas_pio"]
|
||||||
|
AUTO_LOAD = ["switch"]
|
||||||
|
|
||||||
|
dallas_pio_ns = cg.esphome_ns.namespace("dallas_pio")
|
||||||
|
DallasPioSwitch = dallas_pio_ns.class_(
|
||||||
|
"DallasPioSwitch",
|
||||||
|
cg.Component,
|
||||||
|
switch.Switch,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_mode(value):
|
||||||
|
if value.get("output", False) is not True:
|
||||||
|
raise cv.Invalid(
|
||||||
|
"The 'output' field must always be 'true' for Dallas PIO switches."
|
||||||
|
)
|
||||||
|
if value.get("input", False) is True:
|
||||||
|
raise cv.Invalid("The 'input' field must be 'false' if 'output' is 'true'.")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
CUSTOM_PIN_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required("number"): cv.one_of("PIOA", "PIOB", upper=True),
|
||||||
|
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_MODE, default={"output": True}): validate_mode,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = switch.switch_schema(
|
||||||
|
DallasPioSwitch,
|
||||||
|
).extend(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_PIN): CUSTOM_PIN_SCHEMA,
|
||||||
|
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||||
|
cv.Required("dallas_pio_id"): cv.use_id(dallas_pio_ns.class_("DallasPio")),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = await switch.new_switch(config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
dallas_pio_ref = await cg.get_variable(config["dallas_pio_id"])
|
||||||
|
cg.add(var.set_dallas_pio(dallas_pio_ref))
|
||||||
|
# cg.add(dallas_pio_ref.setup())
|
||||||
|
# cg.add(var.set_address(dallas_pio_ref.get_address()))
|
||||||
|
|
||||||
|
# Extract pin configuration
|
||||||
|
pin_config = config[CONF_PIN]
|
||||||
|
pin_number = pin_config["number"] # "PIOA" or "PIOB"
|
||||||
|
pin_inverted = pin_config[CONF_INVERTED]
|
||||||
|
pin_mode = pin_config[CONF_MODE]
|
||||||
|
# C++ configuration association
|
||||||
|
if pin_number == "PIOA":
|
||||||
|
cg.add(var.set_pin(0x01)) # PIOA assiociated to 0x01
|
||||||
|
elif pin_number == "PIOB":
|
||||||
|
cg.add(var.set_pin(0x02)) # PIOB assiociated to 0x02
|
||||||
|
cg.add(var.set_pin_inverted(pin_inverted))
|
||||||
|
cg.add(var.set_pin_mode(pin_mode.get("input", False), pin_mode.get("output", True)))
|
||||||
|
if CONF_INVERTED in config:
|
||||||
|
cg.add(var.set_inverted(config[CONF_INVERTED]))
|
Loading…
x
Reference in New Issue
Block a user