mirror of https://github.com/esphome/esphome.git
Merge fa412c0827
into c7c0d97a5e
This commit is contained in:
commit
a7a15a7219
|
@ -421,6 +421,7 @@ esphome/components/wk2204_spi/* @DrCoolZic
|
|||
esphome/components/wk2212_i2c/* @DrCoolZic
|
||||
esphome/components/wk2212_spi/* @DrCoolZic
|
||||
esphome/components/wl_134/* @hobbypunk90
|
||||
esphome/components/ws18x0_uart/* @Swamp-Ig
|
||||
esphome/components/x9c/* @EtienneMD
|
||||
esphome/components/xgzp68xx/* @gcormier
|
||||
esphome/components/xiaomi_hhccjcy10/* @fariouche
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.components import uart
|
||||
from esphome.const import CONF_ID, CONF_ON_TAG, CONF_TRIGGER_ID
|
||||
|
||||
CODEOWNERS = ["@Swamp-Ig"]
|
||||
DEPENDENCIES = ["uart"]
|
||||
AUTO_LOAD = ["binary_sensor"]
|
||||
MULTI_CONF = True
|
||||
|
||||
ws18x0_uart_ns = cg.esphome_ns.namespace("ws18x0_uart")
|
||||
WS18x0UARTComponent = ws18x0_uart_ns.class_(
|
||||
"WS18x0UARTComponent", cg.Component, uart.UARTDevice
|
||||
)
|
||||
WS18x0UARTTrigger = ws18x0_uart_ns.class_(
|
||||
"WS18x0UARTTrigger", automation.Trigger.template(cg.uint32)
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(WS18x0UARTComponent),
|
||||
cv.Optional(CONF_ON_TAG): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(WS18x0UARTTrigger),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
for conf in config.get(CONF_ON_TAG, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
|
||||
cg.add(var.register_trigger(trigger))
|
||||
await automation.build_automation(trigger, [(cg.uint32, "x")], conf)
|
|
@ -0,0 +1,27 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor, ws18x0_uart
|
||||
from esphome.const import CONF_UID
|
||||
from . import ws18x0_uart_ns
|
||||
|
||||
DEPENDENCIES = ["ws18x0_uart"]
|
||||
|
||||
CONF_WS18x0_UART_ID = "ws18x0_uart_id"
|
||||
WS18x0UARTBinarySensor = ws18x0_uart_ns.class_(
|
||||
"WS18x0UARTBinarySensor", binary_sensor.BinarySensor
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(WS18x0UARTBinarySensor).extend(
|
||||
{
|
||||
cv.GenerateID(CONF_WS18x0_UART_ID): cv.use_id(ws18x0_uart.WS18x0UARTComponent),
|
||||
cv.Required(CONF_UID): cv.uint32_t,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await binary_sensor.new_binary_sensor(config)
|
||||
|
||||
hub = await cg.get_variable(config[CONF_WS18x0_UART_ID])
|
||||
cg.add(hub.register_card(var))
|
||||
cg.add(var.set_id(config[CONF_UID]))
|
|
@ -0,0 +1,100 @@
|
|||
#include "ws18x0_uart.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace ws18x0_uart {
|
||||
|
||||
static const char *const TAG = "ws18x0_uart";
|
||||
|
||||
static const uint8_t WS18X0_UART_START_BYTE = 0x02;
|
||||
static const uint8_t WS18X0_UART_END_BYTE = 0x03;
|
||||
|
||||
static const int8_t WS18X0_UART_STATE_WAITING_FOR_START = -1;
|
||||
static const int8_t WS18X0_UART_STATE_WAITING_FOR_LENGTH = -2;
|
||||
static const int8_t WS18X0_UART_STATE_WAITING_FOR_CHECKSUM = 2;
|
||||
static const int8_t WS18X0_UART_STATE_WAITING_FOR_END = 1;
|
||||
|
||||
void ws18x0_uart::WS18x0UARTComponent::loop() {
|
||||
while (this->available() > 0) {
|
||||
uint8_t data;
|
||||
if (!this->read_byte(&data)) {
|
||||
ESP_LOGW(TAG, "Reading data from WS18x0UART failed!");
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this->read_state_) {
|
||||
case WS18X0_UART_STATE_WAITING_FOR_START:
|
||||
if (data == WS18X0_UART_START_BYTE) {
|
||||
this->read_state_ = WS18X0_UART_STATE_WAITING_FOR_LENGTH;
|
||||
} else {
|
||||
// Not start byte, probably not synced up correctly, skip forward.
|
||||
}
|
||||
break;
|
||||
case WS18X0_UART_STATE_WAITING_FOR_LENGTH:
|
||||
if (data >= 9 && data <= 10) {
|
||||
this->raw_ = data;
|
||||
this->read_state_ = data - 2;
|
||||
} else {
|
||||
// Invalid length. Warn and resync
|
||||
ESP_LOGW(TAG, "Reading data from WS18x0UART failed with length out of expected range: %d", data);
|
||||
this->read_state_ = WS18X0_UART_STATE_WAITING_FOR_START;
|
||||
this->status_set_warning();
|
||||
}
|
||||
break;
|
||||
case WS18X0_UART_STATE_WAITING_FOR_CHECKSUM: {
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
checksum ^= (this->raw_ >> i * 8) & 0xFF;
|
||||
|
||||
if (checksum == data) {
|
||||
this->read_state_ = WS18X0_UART_STATE_WAITING_FOR_END;
|
||||
} else {
|
||||
// Invalid checksum. Warn and resync
|
||||
ESP_LOGW(TAG,
|
||||
"Reading data from WS18x0UART failed with invalid checksum read 0x%2X != calculated 0x%2X from raw "
|
||||
"data: 0x%llX",
|
||||
data, checksum, this->raw_);
|
||||
this->read_state_ = WS18X0_UART_STATE_WAITING_FOR_START;
|
||||
this->status_set_warning();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WS18X0_UART_STATE_WAITING_FOR_END:
|
||||
if (data != WS18X0_UART_END_BYTE) {
|
||||
// Invalid end byte. Warn and resync
|
||||
ESP_LOGW(TAG, "Reading data from WS18x0UART failed with invalid end byte: 0x%2X", data);
|
||||
this->read_state_ = WS18X0_UART_STATE_WAITING_FOR_START;
|
||||
this->status_set_warning();
|
||||
} else {
|
||||
// Valid data
|
||||
this->status_clear_warning();
|
||||
bool report = this->raw_ != this->last_raw_;
|
||||
uint32_t result = (uint32_t) this->raw_;
|
||||
|
||||
for (auto *card : this->cards_) {
|
||||
if (card->process(result)) {
|
||||
report = false;
|
||||
}
|
||||
}
|
||||
for (auto *trig : this->triggers_)
|
||||
trig->process(result);
|
||||
|
||||
if (report) {
|
||||
ESP_LOGD(TAG, "Found new tag with ID %" PRIu32, result);
|
||||
}
|
||||
this->last_raw_ = this->raw_;
|
||||
this->read_state_ = WS18X0_UART_STATE_WAITING_FOR_START;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Read next byte
|
||||
this->raw_ = this->raw_ << 8 | data;
|
||||
this->read_state_--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ws18x0_uart
|
||||
} // namespace esphome
|
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace ws18x0_uart {
|
||||
|
||||
class WS18x0UARTBinarySensor;
|
||||
class WS18x0UARTTrigger;
|
||||
|
||||
class WS18x0UARTComponent : public Component, public uart::UARTDevice {
|
||||
public:
|
||||
void loop() override;
|
||||
|
||||
void register_card(WS18x0UARTBinarySensor *obj) { this->cards_.push_back(obj); }
|
||||
void register_trigger(WS18x0UARTTrigger *trig) { this->triggers_.push_back(trig); }
|
||||
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
|
||||
uint32_t id() { return (uint32_t) raw_; }
|
||||
uint64_t raw() { return raw_; }
|
||||
|
||||
protected:
|
||||
int8_t read_state_{-1};
|
||||
uint64_t raw_{0};
|
||||
uint64_t last_raw_{0};
|
||||
std::vector<WS18x0UARTBinarySensor *> cards_;
|
||||
std::vector<WS18x0UARTTrigger *> triggers_;
|
||||
};
|
||||
|
||||
class WS18x0UARTBinarySensor : public binary_sensor::BinarySensorInitiallyOff {
|
||||
public:
|
||||
void set_id(uint32_t id) { id_ = id; }
|
||||
|
||||
bool process(uint32_t id) {
|
||||
if (this->id_ == id) {
|
||||
this->publish_state(true);
|
||||
yield();
|
||||
this->publish_state(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t id_;
|
||||
};
|
||||
|
||||
class WS18x0UARTTrigger : public Trigger<uint32_t> {
|
||||
public:
|
||||
void process(uint32_t uid) { this->trigger(uid); }
|
||||
};
|
||||
|
||||
} // namespace ws18x0_uart
|
||||
} // namespace esphome
|
Loading…
Reference in New Issue