mirror of
https://github.com/esphome/esphome.git
synced 2026-10-10 05:23:07 +00:00
[remote_base] Add Onkyo RI Wired Serial Support (#18595)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
co-authored by
Claude Opus 5.5
J. Nick Koston
J. Nick Koston
parent
9d02ab3734
commit
8084916e30
@@ -1019,6 +1019,43 @@ async def nec_action(var, config, args):
|
||||
cg.add(var.set_command_repeats(template_))
|
||||
|
||||
|
||||
# Onkyo RI
|
||||
OnkyoRIData, OnkyoRIBinarySensor, OnkyoRITrigger, OnkyoRIAction, OnkyoRIDumper = (
|
||||
declare_protocol("OnkyoRI")
|
||||
)
|
||||
ONKYORI_SCHEMA = cv.Schema({cv.Required(CONF_DATA): cv.hex_int_range(0, 0xFFF)})
|
||||
|
||||
|
||||
@register_binary_sensor("onkyori", OnkyoRIBinarySensor, ONKYORI_SCHEMA)
|
||||
def onkyori_binary_sensor(var: MockObj, config: ConfigType) -> None:
|
||||
cg.add(
|
||||
var.set_data(
|
||||
cg.StructInitializer(
|
||||
OnkyoRIData,
|
||||
("data", config[CONF_DATA]),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@register_trigger("onkyori", OnkyoRITrigger, OnkyoRIData)
|
||||
def onkyori_trigger(var: MockObj, config: ConfigType) -> None:
|
||||
"""The trigger takes no options beyond the automation."""
|
||||
|
||||
|
||||
@register_dumper("onkyori", OnkyoRIDumper)
|
||||
def onkyori_dumper(var: MockObj, config: ConfigType) -> None:
|
||||
"""The dumper takes no options."""
|
||||
|
||||
|
||||
@register_action("onkyori", OnkyoRIAction, ONKYORI_SCHEMA)
|
||||
async def onkyori_action(
|
||||
var: MockObj, config: ConfigType, args: TemplateArgsType
|
||||
) -> None:
|
||||
template_ = await cg.templatable(config[CONF_DATA], args, cg.uint16)
|
||||
cg.add(var.set_data(template_))
|
||||
|
||||
|
||||
# Pioneer
|
||||
(
|
||||
PioneerData,
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "onkyori_protocol.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::remote_base {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "remote.onkyori");
|
||||
|
||||
static constexpr uint8_t NBITS = 12;
|
||||
static constexpr uint16_t MAX_DATA = (1U << NBITS) - 1;
|
||||
static constexpr uint32_t HEADER_HIGH_US = 3000;
|
||||
static constexpr uint32_t HEADER_LOW_US = 1000;
|
||||
static constexpr uint32_t BIT_HIGH_US = 1000;
|
||||
static constexpr uint32_t BIT_ONE_LOW_US = 2000;
|
||||
static constexpr uint32_t BIT_ZERO_LOW_US = 1000;
|
||||
static constexpr uint32_t TRAILER_HIGH_US = 1000;
|
||||
|
||||
void OnkyoRIProtocol::encode(RemoteTransmitData *dst, const OnkyoRIData &data) {
|
||||
if (data.data > MAX_DATA) {
|
||||
ESP_LOGE(TAG, "Data 0x%04X does not fit in a 12-bit RI frame, not sending", data.data);
|
||||
return;
|
||||
}
|
||||
|
||||
// RI is a baseband signal on a wire, so it has no carrier to modulate.
|
||||
dst->set_carrier_frequency(0);
|
||||
dst->reserve(2 + NBITS * 2u + 1);
|
||||
|
||||
dst->item(HEADER_HIGH_US, HEADER_LOW_US);
|
||||
|
||||
for (uint32_t mask = 1UL << (NBITS - 1); mask != 0; mask >>= 1) {
|
||||
dst->item(BIT_HIGH_US, (data.data & mask) != 0 ? BIT_ONE_LOW_US : BIT_ZERO_LOW_US);
|
||||
}
|
||||
|
||||
dst->mark(TRAILER_HIGH_US);
|
||||
}
|
||||
|
||||
optional<OnkyoRIData> OnkyoRIProtocol::decode(RemoteReceiveData src) {
|
||||
OnkyoRIData out{.data = 0};
|
||||
|
||||
if (!src.expect_item(HEADER_HIGH_US, HEADER_LOW_US))
|
||||
return {};
|
||||
|
||||
for (uint8_t i = 0; i < NBITS; i++) {
|
||||
out.data <<= 1;
|
||||
if (src.expect_item(BIT_HIGH_US, BIT_ONE_LOW_US)) {
|
||||
out.data |= 1;
|
||||
} else if (!src.expect_item(BIT_HIGH_US, BIT_ZERO_LOW_US)) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (!src.expect_mark(TRAILER_HIGH_US))
|
||||
return {};
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void OnkyoRIProtocol::dump(const OnkyoRIData &data) { ESP_LOGI(TAG, "Received OnkyoRI: data=0x%03X", data.data); }
|
||||
|
||||
} // namespace esphome::remote_base
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "remote_base.h"
|
||||
|
||||
namespace esphome::remote_base {
|
||||
|
||||
struct OnkyoRIData {
|
||||
uint16_t data;
|
||||
|
||||
bool operator==(const OnkyoRIData &rhs) const { return data == rhs.data; }
|
||||
};
|
||||
|
||||
class OnkyoRIProtocol : public RemoteProtocol<OnkyoRIData> {
|
||||
public:
|
||||
void encode(RemoteTransmitData *dst, const OnkyoRIData &data);
|
||||
optional<OnkyoRIData> decode(RemoteReceiveData src);
|
||||
void dump(const OnkyoRIData &data);
|
||||
};
|
||||
|
||||
DECLARE_REMOTE_PROTOCOL(OnkyoRI)
|
||||
|
||||
template<typename... Ts> class OnkyoRIAction : public RemoteTransmitterActionBase<Ts...> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(uint16_t, data)
|
||||
|
||||
void encode(RemoteTransmitData *dst, Ts... x) override {
|
||||
OnkyoRIData data{};
|
||||
data.data = this->data_.value(x...);
|
||||
OnkyoRIProtocol().encode(dst, data);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace esphome::remote_base
|
||||
@@ -103,6 +103,11 @@ on_nexa:
|
||||
- logger.log:
|
||||
format: "on_nexa: %lu %u %u %u %u"
|
||||
args: ["long(x.device)", "x.group", "x.state", "x.channel", "x.level"]
|
||||
on_onkyori:
|
||||
then:
|
||||
- logger.log:
|
||||
format: "on_onkyori: 0x%03X"
|
||||
args: ["x.data"]
|
||||
on_panasonic:
|
||||
then:
|
||||
- logger.log:
|
||||
|
||||
@@ -252,6 +252,16 @@ button:
|
||||
channel: 1
|
||||
button: 1
|
||||
check: 1
|
||||
- platform: template
|
||||
name: OnkyoRI
|
||||
on_press:
|
||||
remote_transmitter.transmit_onkyori:
|
||||
data: 0xD9
|
||||
- platform: template
|
||||
name: OnkyoRI 12-bit
|
||||
on_press:
|
||||
remote_transmitter.transmit_onkyori:
|
||||
data: 0x170
|
||||
- platform: template
|
||||
name: Toto
|
||||
on_press:
|
||||
|
||||
Reference in New Issue
Block a user