esphome/esphomeyaml/components/remote_transmitter.py
Otto Winter 17ec2bb905
Update
2018-11-19 22:12:24 +01:00

121 lines
5.0 KiB
Python

import voluptuous as vol
from esphomeyaml import pins
from esphomeyaml.components.remote_receiver import RemoteControlComponentBase, remote_ns
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ADDRESS, CONF_CARRIER_DUTY_PERCENT, CONF_CHANNEL, CONF_CODE, \
CONF_DEVICE, CONF_FAMILY, CONF_GROUP, CONF_ID, CONF_INVERTED, CONF_ONE, CONF_PIN, \
CONF_PROTOCOL, CONF_PULSE_LENGTH, CONF_STATE, CONF_SYNC, CONF_ZERO
from esphomeyaml.core import HexInt
from esphomeyaml.cpp_generator import Pvariable, add
from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, Component
RemoteTransmitterComponent = remote_ns.class_('RemoteTransmitterComponent',
RemoteControlComponentBase, Component)
RCSwitchProtocol = remote_ns.class_('RCSwitchProtocol')
rc_switch_protocols = remote_ns.rc_switch_protocols
def validate_rc_switch_code(value):
if not isinstance(value, (str, unicode)):
raise vol.Invalid("All RCSwitch codes must be in quotes ('')")
for c in value:
if c not in ('0', '1'):
raise vol.Invalid(u"Invalid RCSwitch code character '{}'. Only '0' and '1' are allowed"
u"".format(c))
if len(value) > 32:
raise vol.Invalid("Maximum length for RCSwitch codes is 32, code '{}' has length {}"
"".format(value, len(value)))
if not value:
raise vol.Invalid("RCSwitch code must not be empty")
return value
RC_SWITCH_TIMING_SCHEMA = vol.All([cv.uint8_t], vol.Length(min=2, max=2))
RC_SWITCH_PROTOCOL_SCHEMA = vol.Any(
vol.All(vol.Coerce(int), vol.Range(min=1, max=7)),
vol.Schema({
vol.Required(CONF_PULSE_LENGTH): cv.uint32_t,
vol.Optional(CONF_SYNC, default=[1, 31]): RC_SWITCH_TIMING_SCHEMA,
vol.Optional(CONF_ZERO, default=[1, 3]): RC_SWITCH_TIMING_SCHEMA,
vol.Optional(CONF_ONE, default=[3, 1]): RC_SWITCH_TIMING_SCHEMA,
vol.Optional(CONF_INVERTED, default=False): cv.boolean,
})
)
RC_SWITCH_RAW_SCHEMA = vol.Schema({
vol.Required(CONF_CODE): validate_rc_switch_code,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
RC_SWITCH_TYPE_A_SCHEMA = vol.Schema({
vol.Required(CONF_GROUP): vol.All(validate_rc_switch_code, vol.Length(min=5, max=5)),
vol.Required(CONF_DEVICE): vol.All(validate_rc_switch_code, vol.Length(min=5, max=5)),
vol.Required(CONF_STATE): cv.boolean,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
RC_SWITCH_TYPE_B_SCHEMA = vol.Schema({
vol.Required(CONF_ADDRESS): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
vol.Required(CONF_CHANNEL): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
vol.Required(CONF_STATE): cv.boolean,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
RC_SWITCH_TYPE_C_SCHEMA = vol.Schema({
vol.Required(CONF_FAMILY): vol.All(
cv.string, vol.Lower,
cv.one_of('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p')),
vol.Required(CONF_GROUP): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
vol.Required(CONF_DEVICE): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
vol.Required(CONF_STATE): cv.boolean,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
RC_SWITCH_TYPE_D_SCHEMA = vol.Schema({
vol.Required(CONF_GROUP): vol.All(cv.string, vol.Lower, cv.one_of('a', 'b', 'c', 'd')),
vol.Required(CONF_DEVICE): vol.All(cv.uint8_t, vol.Range(min=1, max=3)),
vol.Required(CONF_STATE): cv.boolean,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
cv.GenerateID(): cv.declare_variable_id(RemoteTransmitterComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(cv.percentage_int,
vol.Range(min=1, max=100)),
}).extend(cv.COMPONENT_SCHEMA.schema)])
def build_rc_switch_protocol(config):
if isinstance(config, int):
return rc_switch_protocols[config]
pl = config[CONF_PULSE_LENGTH]
return RCSwitchProtocol(config[CONF_SYNC][0] * pl, config[CONF_SYNC][1] * pl,
config[CONF_ZERO][0] * pl, config[CONF_ZERO][1] * pl,
config[CONF_ONE][0] * pl, config[CONF_ONE][1] * pl,
config[CONF_INVERTED])
def binary_code(value):
code = 0
for val in value:
code <<= 1
code |= val == '1'
return HexInt(code)
def to_code(config):
for conf in config:
for pin in gpio_output_pin_expression(conf[CONF_PIN]):
yield
rhs = App.make_remote_transmitter_component(pin)
transmitter = Pvariable(conf[CONF_ID], rhs)
if CONF_CARRIER_DUTY_PERCENT in conf:
add(transmitter.set_carrier_duty_percent(conf[CONF_CARRIER_DUTY_PERCENT]))
setup_component(transmitter, conf)
BUILD_FLAGS = '-DUSE_REMOTE_TRANSMITTER'