mirror of
https://github.com/esphome/esphome.git
synced 2026-05-27 11:56:11 +08:00
[ir_rf_proxy] New component (#12985)
Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
@@ -255,6 +255,7 @@ esphome/components/inkplate/* @jesserockz @JosipKuci
|
|||||||
esphome/components/integration/* @OttoWinter
|
esphome/components/integration/* @OttoWinter
|
||||||
esphome/components/internal_temperature/* @Mat931
|
esphome/components/internal_temperature/* @Mat931
|
||||||
esphome/components/interval/* @esphome/core
|
esphome/components/interval/* @esphome/core
|
||||||
|
esphome/components/ir_rf_proxy/* @kbx81
|
||||||
esphome/components/jsn_sr04t/* @Mafus1
|
esphome/components/jsn_sr04t/* @Mafus1
|
||||||
esphome/components/json/* @esphome/core
|
esphome/components/json/* @esphome/core
|
||||||
esphome/components/kamstrup_kmp/* @cfeenstra1024
|
esphome/components/kamstrup_kmp/* @cfeenstra1024
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
"""IR/RF Proxy component - provides remote_base backend for infrared platform."""
|
||||||
|
|
||||||
|
import esphome.codegen as cg
|
||||||
|
|
||||||
|
CODEOWNERS = ["@kbx81"]
|
||||||
|
|
||||||
|
# Namespace and constants exported for infrared.py platform
|
||||||
|
ir_rf_proxy_ns = cg.esphome_ns.namespace("ir_rf_proxy")
|
||||||
|
|
||||||
|
CONF_REMOTE_RECEIVER_ID = "remote_receiver_id"
|
||||||
|
CONF_REMOTE_TRANSMITTER_ID = "remote_transmitter_id"
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
"""Infrared platform implementation using remote_base (remote_transmitter/receiver)."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import infrared, remote_receiver, remote_transmitter
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_FREQUENCY
|
||||||
|
import esphome.final_validate as fv
|
||||||
|
|
||||||
|
from . import CONF_REMOTE_RECEIVER_ID, CONF_REMOTE_TRANSMITTER_ID, ir_rf_proxy_ns
|
||||||
|
|
||||||
|
CODEOWNERS = ["@kbx81"]
|
||||||
|
DEPENDENCIES = ["infrared"]
|
||||||
|
|
||||||
|
IrRfProxy = ir_rf_proxy_ns.class_("IrRfProxy", infrared.Infrared)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
infrared.infrared_schema(IrRfProxy).extend(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_FREQUENCY, default=0): cv.frequency,
|
||||||
|
cv.Optional(CONF_REMOTE_RECEIVER_ID): cv.use_id(
|
||||||
|
remote_receiver.RemoteReceiverComponent
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_REMOTE_TRANSMITTER_ID): cv.use_id(
|
||||||
|
remote_transmitter.RemoteTransmitterComponent
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.has_exactly_one_key(CONF_REMOTE_RECEIVER_ID, CONF_REMOTE_TRANSMITTER_ID),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _final_validate(config: dict[str, Any]) -> None:
|
||||||
|
"""Validate that transmitters have a proper carrier duty cycle."""
|
||||||
|
# Only validate if this is an infrared (not RF) configuration with a transmitter
|
||||||
|
if config.get(CONF_FREQUENCY, 0) != 0 or CONF_REMOTE_TRANSMITTER_ID not in config:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the transmitter configuration
|
||||||
|
transmitter_id = config[CONF_REMOTE_TRANSMITTER_ID]
|
||||||
|
full_config = fv.full_config.get()
|
||||||
|
transmitter_path = full_config.get_path_for_id(transmitter_id)[:-1]
|
||||||
|
transmitter_config = full_config.get_config_for_path(transmitter_path)
|
||||||
|
|
||||||
|
# Check if carrier_duty_percent set to 0 or 100
|
||||||
|
# Note: remote_transmitter schema requires this field and validates 1-100%,
|
||||||
|
# but we double-check here for infrared to provide a helpful error message
|
||||||
|
duty_percent = transmitter_config.get(CONF_CARRIER_DUTY_PERCENT)
|
||||||
|
if duty_percent in {0, 100}:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"Transmitter '{transmitter_id}' must have '{CONF_CARRIER_DUTY_PERCENT}' configured with "
|
||||||
|
"an intermediate value (typically 30-50%) for infrared transmission. If this is an RF "
|
||||||
|
f"transmitter, configure this infrared with a '{CONF_FREQUENCY}' value greater than 0"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
FINAL_VALIDATE_SCHEMA = _final_validate
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config: dict[str, Any]) -> None:
|
||||||
|
"""Code generation for remote_base infrared platform."""
|
||||||
|
# Create and register the infrared entity
|
||||||
|
var = await infrared.new_infrared(config)
|
||||||
|
|
||||||
|
# Set frequency / 1000; zero indicates infrared hardware
|
||||||
|
cg.add(var.set_frequency(config[CONF_FREQUENCY] / 1000))
|
||||||
|
|
||||||
|
# Link transmitter if specified
|
||||||
|
if CONF_REMOTE_TRANSMITTER_ID in config:
|
||||||
|
transmitter = await cg.get_variable(config[CONF_REMOTE_TRANSMITTER_ID])
|
||||||
|
cg.add(var.set_transmitter(transmitter))
|
||||||
|
|
||||||
|
# Link receiver if specified
|
||||||
|
if CONF_REMOTE_RECEIVER_ID in config:
|
||||||
|
receiver = await cg.get_variable(config[CONF_REMOTE_RECEIVER_ID])
|
||||||
|
cg.add(var.set_receiver(receiver))
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#include "ir_rf_proxy.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome::ir_rf_proxy {
|
||||||
|
|
||||||
|
static const char *const TAG = "ir_rf_proxy";
|
||||||
|
|
||||||
|
void IrRfProxy::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG,
|
||||||
|
"IR/RF Proxy '%s'\n"
|
||||||
|
" Supports Transmitter: %s\n"
|
||||||
|
" Supports Receiver: %s",
|
||||||
|
this->get_name().c_str(), YESNO(this->traits_.get_supports_transmitter()),
|
||||||
|
YESNO(this->traits_.get_supports_receiver()));
|
||||||
|
|
||||||
|
if (this->is_rf()) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Hardware Type: RF (%.3f MHz)", this->frequency_khz_ / 1e3f);
|
||||||
|
} else {
|
||||||
|
ESP_LOGCONFIG(TAG, " Hardware Type: Infrared");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace esphome::ir_rf_proxy
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// WARNING: This component is EXPERIMENTAL. The API may change at any time
|
||||||
|
// without following the normal breaking changes policy. Use at your own risk.
|
||||||
|
// Once the API is considered stable, this warning will be removed.
|
||||||
|
|
||||||
|
#include "esphome/components/infrared/infrared.h"
|
||||||
|
#include "esphome/components/remote_transmitter/remote_transmitter.h"
|
||||||
|
#include "esphome/components/remote_receiver/remote_receiver.h"
|
||||||
|
|
||||||
|
namespace esphome::ir_rf_proxy {
|
||||||
|
|
||||||
|
/// IrRfProxy - Infrared platform implementation using remote_transmitter/receiver as backend
|
||||||
|
class IrRfProxy : public infrared::Infrared {
|
||||||
|
public:
|
||||||
|
IrRfProxy() = default;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
/// Set RF frequency in kHz (0 = infrared, non-zero = RF)
|
||||||
|
void set_frequency(uint32_t frequency_khz) { this->frequency_khz_ = frequency_khz; }
|
||||||
|
/// Get RF frequency in kHz
|
||||||
|
uint32_t get_frequency() const { return this->frequency_khz_; }
|
||||||
|
/// Check if this is RF mode (non-zero frequency)
|
||||||
|
bool is_rf() const { return this->frequency_khz_ > 0; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// RF frequency in kHz (Hz / 1000); 0 = infrared, non-zero = RF
|
||||||
|
uint32_t frequency_khz_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace esphome::ir_rf_proxy
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
wifi:
|
||||||
|
ssid: MySSID
|
||||||
|
password: password1
|
||||||
|
|
||||||
|
api:
|
||||||
|
|
||||||
|
remote_transmitter:
|
||||||
|
id: ir_transmitter
|
||||||
|
pin: ${tx_pin}
|
||||||
|
carrier_duty_percent: 50%
|
||||||
|
|
||||||
|
remote_receiver:
|
||||||
|
id: ir_receiver
|
||||||
|
pin: ${rx_pin}
|
||||||
|
|
||||||
|
# Test various hardware types with transmitter/receiver using infrared platform
|
||||||
|
infrared:
|
||||||
|
# Infrared transmitter
|
||||||
|
- platform: ir_rf_proxy
|
||||||
|
id: ir_tx
|
||||||
|
name: "IR Transmitter"
|
||||||
|
remote_transmitter_id: ir_transmitter
|
||||||
|
|
||||||
|
# Infrared receiver
|
||||||
|
- platform: ir_rf_proxy
|
||||||
|
id: ir_rx
|
||||||
|
name: "IR Receiver"
|
||||||
|
remote_receiver_id: ir_receiver
|
||||||
|
|
||||||
|
# RF 433MHz transmitter
|
||||||
|
- platform: ir_rf_proxy
|
||||||
|
id: rf_433_tx
|
||||||
|
name: "RF 433 Transmitter"
|
||||||
|
frequency: 433 MHz
|
||||||
|
remote_transmitter_id: ir_transmitter
|
||||||
|
|
||||||
|
# RF 900MHz receiver
|
||||||
|
- platform: ir_rf_proxy
|
||||||
|
id: rf_900_rx
|
||||||
|
name: "RF 900 Receiver"
|
||||||
|
frequency: 900 MHz
|
||||||
|
remote_receiver_id: ir_receiver
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
substitutions:
|
||||||
|
tx_pin: GPIO4
|
||||||
|
rx_pin: GPIO5
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
substitutions:
|
||||||
|
tx_pin: GPIO4
|
||||||
|
rx_pin: GPIO5
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
substitutions:
|
||||||
|
tx_pin: GPIO4
|
||||||
|
rx_pin: GPIO5
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
wifi:
|
||||||
|
ssid: MySSID
|
||||||
|
password: password1
|
||||||
|
|
||||||
|
api:
|
||||||
|
|
||||||
|
remote_transmitter:
|
||||||
|
id: ir_transmitter
|
||||||
|
pin: ${tx_pin}
|
||||||
|
carrier_duty_percent: 50%
|
||||||
|
|
||||||
|
remote_receiver:
|
||||||
|
id: ir_receiver
|
||||||
|
pin: ${rx_pin}
|
||||||
|
|
||||||
|
# Test various hardware types with transmitter/receiver using infrared platform
|
||||||
|
infrared:
|
||||||
|
# Infrared transmitter
|
||||||
|
- platform: ir_rf_proxy
|
||||||
|
id: ir_tx
|
||||||
|
name: "IR Transmitter"
|
||||||
|
remote_transmitter_id: ir_transmitter
|
||||||
|
|
||||||
|
# Infrared receiver
|
||||||
|
- platform: ir_rf_proxy
|
||||||
|
id: ir_rx
|
||||||
|
name: "IR Receiver"
|
||||||
|
remote_receiver_id: ir_receiver
|
||||||
|
|
||||||
|
# RF 433MHz transmitter
|
||||||
|
- platform: ir_rf_proxy
|
||||||
|
id: rf_433_tx
|
||||||
|
name: "RF 433 Transmitter"
|
||||||
|
frequency: 433 MHz
|
||||||
|
remote_transmitter_id: ir_transmitter
|
||||||
|
|
||||||
|
# RF 900MHz receiver
|
||||||
|
- platform: ir_rf_proxy
|
||||||
|
id: rf_900_rx
|
||||||
|
name: "RF 900 Receiver"
|
||||||
|
frequency: 900 MHz
|
||||||
|
remote_receiver_id: ir_receiver
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
substitutions:
|
||||||
|
tx_pin: GPIO4
|
||||||
|
rx_pin: GPIO5
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
substitutions:
|
||||||
|
tx_pin: GPIO4
|
||||||
|
rx_pin: GPIO5
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
substitutions:
|
||||||
|
tx_pin: GPIO4
|
||||||
|
rx_pin: GPIO5
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
Reference in New Issue
Block a user