mirror of
https://github.com/esphome/esphome.git
synced 2024-12-25 15:04:54 +01:00
Add Dooya protocol to remote_base (#6488)
This commit is contained in:
parent
3adfed3675
commit
522b43bb41
5 changed files with 227 additions and 2 deletions
|
@ -33,6 +33,9 @@ from esphome.const import (
|
|||
CONF_WAND_ID,
|
||||
CONF_LEVEL,
|
||||
CONF_DELTA,
|
||||
CONF_ID,
|
||||
CONF_BUTTON,
|
||||
CONF_CHECK,
|
||||
)
|
||||
from esphome.core import coroutine
|
||||
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
||||
|
@ -512,6 +515,57 @@ async def dish_action(var, config, args):
|
|||
cg.add(var.set_command(template_))
|
||||
|
||||
|
||||
# Dooya
|
||||
DooyaData, DooyaBinarySensor, DooyaTrigger, DooyaAction, DooyaDumper = declare_protocol(
|
||||
"Dooya"
|
||||
)
|
||||
DOOYA_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.hex_int_range(0, 16777215),
|
||||
cv.Required(CONF_CHANNEL): cv.hex_int_range(0, 255),
|
||||
cv.Required(CONF_BUTTON): cv.hex_int_range(0, 15),
|
||||
cv.Required(CONF_CHECK): cv.hex_int_range(0, 15),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@register_binary_sensor("dooya", DooyaBinarySensor, DOOYA_SCHEMA)
|
||||
def dooya_binary_sensor(var, config):
|
||||
cg.add(
|
||||
var.set_data(
|
||||
cg.StructInitializer(
|
||||
DooyaData,
|
||||
("id", config[CONF_ID]),
|
||||
("channel", config[CONF_CHANNEL]),
|
||||
("button", config[CONF_BUTTON]),
|
||||
("check", config[CONF_CHECK]),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@register_trigger("dooya", DooyaTrigger, DooyaData)
|
||||
def dooya_trigger(var, config):
|
||||
pass
|
||||
|
||||
|
||||
@register_dumper("dooya", DooyaDumper)
|
||||
def dooya_dumper(var, config):
|
||||
pass
|
||||
|
||||
|
||||
@register_action("dooya", DooyaAction, DOOYA_SCHEMA)
|
||||
async def dooya_action(var, config, args):
|
||||
template_ = await cg.templatable(config[CONF_ID], args, cg.uint32)
|
||||
cg.add(var.set_id(template_))
|
||||
template_ = await cg.templatable(config[CONF_CHANNEL], args, cg.uint8)
|
||||
cg.add(var.set_channel(template_))
|
||||
template_ = await cg.templatable(config[CONF_BUTTON], args, cg.uint8)
|
||||
cg.add(var.set_button(template_))
|
||||
template_ = await cg.templatable(config[CONF_CHECK], args, cg.uint8)
|
||||
cg.add(var.set_check(template_))
|
||||
|
||||
|
||||
# JVC
|
||||
JVCData, JVCBinarySensor, JVCTrigger, JVCAction, JVCDumper = declare_protocol("JVC")
|
||||
JVC_SCHEMA = cv.Schema({cv.Required(CONF_DATA): cv.hex_uint32_t})
|
||||
|
|
120
esphome/components/remote_base/dooya_protocol.cpp
Normal file
120
esphome/components/remote_base/dooya_protocol.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
#include "dooya_protocol.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace remote_base {
|
||||
|
||||
static const char *const TAG = "remote.dooya";
|
||||
|
||||
static const uint32_t HEADER_HIGH_US = 5000;
|
||||
static const uint32_t HEADER_LOW_US = 1500;
|
||||
static const uint32_t BIT_ZERO_HIGH_US = 750;
|
||||
static const uint32_t BIT_ZERO_LOW_US = 350;
|
||||
static const uint32_t BIT_ONE_HIGH_US = 350;
|
||||
static const uint32_t BIT_ONE_LOW_US = 750;
|
||||
|
||||
void DooyaProtocol::encode(RemoteTransmitData *dst, const DooyaData &data) {
|
||||
dst->set_carrier_frequency(0);
|
||||
dst->reserve(2 + 40 * 2u);
|
||||
|
||||
dst->item(HEADER_HIGH_US, HEADER_LOW_US);
|
||||
|
||||
for (uint32_t mask = 1UL << (23); mask != 0; mask >>= 1) {
|
||||
if (data.id & mask) {
|
||||
dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US);
|
||||
} else {
|
||||
dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t mask = 1UL << (7); mask != 0; mask >>= 1) {
|
||||
if (data.channel & mask) {
|
||||
dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US);
|
||||
} else {
|
||||
dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t mask = 1UL << (3); mask != 0; mask >>= 1) {
|
||||
if (data.button & mask) {
|
||||
dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US);
|
||||
} else {
|
||||
dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t mask = 1UL << (3); mask != 0; mask >>= 1) {
|
||||
if (data.check & mask) {
|
||||
dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US);
|
||||
} else {
|
||||
dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US);
|
||||
}
|
||||
}
|
||||
}
|
||||
optional<DooyaData> DooyaProtocol::decode(RemoteReceiveData src) {
|
||||
DooyaData out{
|
||||
.id = 0,
|
||||
.channel = 0,
|
||||
.button = 0,
|
||||
.check = 0,
|
||||
};
|
||||
if (!src.expect_item(HEADER_HIGH_US, HEADER_LOW_US))
|
||||
return {};
|
||||
|
||||
for (uint8_t i = 0; i < 24; i++) {
|
||||
if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) {
|
||||
out.id = (out.id << 1) | 1;
|
||||
} else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) {
|
||||
out.id = (out.id << 1) | 0;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) {
|
||||
out.channel = (out.channel << 1) | 1;
|
||||
} else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) {
|
||||
out.channel = (out.channel << 1) | 0;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) {
|
||||
out.button = (out.button << 1) | 1;
|
||||
} else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) {
|
||||
out.button = (out.button << 1) | 0;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) {
|
||||
out.check = (out.check << 1) | 1;
|
||||
} else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) {
|
||||
out.check = (out.check << 1) | 0;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
// Last bit is not received properly but can be decoded
|
||||
if (src.expect_mark(BIT_ONE_HIGH_US)) {
|
||||
out.check = (out.check << 1) | 1;
|
||||
} else if (src.expect_mark(BIT_ZERO_HIGH_US)) {
|
||||
out.check = (out.check << 1) | 0;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
void DooyaProtocol::dump(const DooyaData &data) {
|
||||
ESP_LOGI(TAG, "Received Dooya: id=0x%08" PRIX32 ", channel=%d, button=%d, check=%d", data.id, data.channel,
|
||||
data.button, data.check);
|
||||
}
|
||||
|
||||
} // namespace remote_base
|
||||
} // namespace esphome
|
49
esphome/components/remote_base/dooya_protocol.h
Normal file
49
esphome/components/remote_base/dooya_protocol.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "remote_base.h"
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace remote_base {
|
||||
|
||||
struct DooyaData {
|
||||
uint32_t id;
|
||||
uint8_t channel;
|
||||
uint8_t button;
|
||||
uint8_t check;
|
||||
|
||||
bool operator==(const DooyaData &rhs) const {
|
||||
return id == rhs.id && channel == rhs.channel && button == rhs.button && check == rhs.check;
|
||||
}
|
||||
};
|
||||
|
||||
class DooyaProtocol : public RemoteProtocol<DooyaData> {
|
||||
public:
|
||||
void encode(RemoteTransmitData *dst, const DooyaData &data) override;
|
||||
optional<DooyaData> decode(RemoteReceiveData src) override;
|
||||
void dump(const DooyaData &data) override;
|
||||
};
|
||||
|
||||
DECLARE_REMOTE_PROTOCOL(Dooya)
|
||||
|
||||
template<typename... Ts> class DooyaAction : public RemoteTransmitterActionBase<Ts...> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(uint32_t, id)
|
||||
TEMPLATABLE_VALUE(uint8_t, channel)
|
||||
TEMPLATABLE_VALUE(uint8_t, button)
|
||||
TEMPLATABLE_VALUE(uint8_t, check)
|
||||
|
||||
void encode(RemoteTransmitData *dst, Ts... x) override {
|
||||
DooyaData data{};
|
||||
data.id = this->id_.value(x...);
|
||||
data.channel = this->channel_.value(x...);
|
||||
data.button = this->button_.value(x...);
|
||||
data.check = this->check_.value(x...);
|
||||
DooyaProtocol().encode(dst, data);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace remote_base
|
||||
} // namespace esphome
|
|
@ -8,6 +8,7 @@ from esphome.const import (
|
|||
DEVICE_CLASS_LIGHT,
|
||||
DEVICE_CLASS_MOTION,
|
||||
CONF_ID,
|
||||
CONF_BUTTON,
|
||||
)
|
||||
from esphome.core import TimePeriod
|
||||
|
||||
|
@ -15,8 +16,6 @@ from . import XiaomiRTCGQ02LM
|
|||
|
||||
DEPENDENCIES = ["xiaomi_rtcgq02lm"]
|
||||
|
||||
CONF_BUTTON = "button"
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
|
|
|
@ -96,6 +96,7 @@ CONF_BUFFER_SIZE = "buffer_size"
|
|||
CONF_BUILD_PATH = "build_path"
|
||||
CONF_BUS_VOLTAGE = "bus_voltage"
|
||||
CONF_BUSY_PIN = "busy_pin"
|
||||
CONF_BUTTON = "button"
|
||||
CONF_BYTES = "bytes"
|
||||
CONF_CALCULATED_LUX = "calculated_lux"
|
||||
CONF_CALIBRATE_LINEAR = "calibrate_linear"
|
||||
|
@ -110,6 +111,7 @@ CONF_CHANGE_MODE_EVERY = "change_mode_every"
|
|||
CONF_CHANNEL = "channel"
|
||||
CONF_CHANNELS = "channels"
|
||||
CONF_CHARACTERISTIC_UUID = "characteristic_uuid"
|
||||
CONF_CHECK = "check"
|
||||
CONF_CHIPSET = "chipset"
|
||||
CONF_CLEAR_IMPEDANCE = "clear_impedance"
|
||||
CONF_CLIENT_CERTIFICATE = "client_certificate"
|
||||
|
@ -220,6 +222,7 @@ CONF_DNS_ADDRESS = "dns_address"
|
|||
CONF_DNS1 = "dns1"
|
||||
CONF_DNS2 = "dns2"
|
||||
CONF_DOMAIN = "domain"
|
||||
CONF_DOOYA = "dooya"
|
||||
CONF_DRY_ACTION = "dry_action"
|
||||
CONF_DRY_MODE = "dry_mode"
|
||||
CONF_DUMMY_RECEIVER = "dummy_receiver"
|
||||
|
|
Loading…
Reference in a new issue