2016-08-10 02:45:40 +00:00
|
|
|
"""
|
2016-10-31 12:18:47 +00:00
|
|
|
Component to create an interface to a Pilight daemon.
|
2016-08-10 02:45:40 +00:00
|
|
|
|
2016-08-11 09:14:24 +00:00
|
|
|
For more details about this component, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/pilight/
|
2016-08-10 02:45:40 +00:00
|
|
|
"""
|
|
|
|
import logging
|
|
|
|
import socket
|
|
|
|
|
|
|
|
import voluptuous as vol
|
|
|
|
|
|
|
|
import homeassistant.helpers.config_validation as cv
|
2016-09-02 04:28:52 +00:00
|
|
|
from homeassistant.const import (
|
|
|
|
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, CONF_HOST, CONF_PORT,
|
2016-10-31 12:18:47 +00:00
|
|
|
CONF_WHITELIST, CONF_PROTOCOL)
|
2016-08-10 02:45:40 +00:00
|
|
|
|
2016-10-19 20:02:11 +00:00
|
|
|
REQUIREMENTS = ['pilight==0.1.1']
|
2016-08-10 02:45:40 +00:00
|
|
|
|
2016-09-02 04:28:52 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
2016-08-10 02:45:40 +00:00
|
|
|
|
2016-09-02 04:28:52 +00:00
|
|
|
DEFAULT_HOST = '127.0.0.1'
|
|
|
|
DEFAULT_PORT = 5000
|
|
|
|
DOMAIN = 'pilight'
|
|
|
|
|
|
|
|
EVENT = 'pilight_received'
|
2016-08-10 02:45:40 +00:00
|
|
|
|
2016-10-31 12:18:47 +00:00
|
|
|
# The Pilight code schema depends on the protocol. Thus only require to have
|
|
|
|
# the protocol information. Ensure that protocol is in a list otherwise
|
|
|
|
# segfault in pilight-daemon, https://github.com/pilight/pilight/issues/296
|
|
|
|
RF_CODE_SCHEMA = vol.Schema({
|
|
|
|
vol.Required(CONF_PROTOCOL): vol.All(cv.ensure_list, [cv.string]),
|
|
|
|
}, extra=vol.ALLOW_EXTRA)
|
|
|
|
|
2016-09-02 04:28:52 +00:00
|
|
|
SERVICE_NAME = 'send'
|
2016-08-10 02:45:40 +00:00
|
|
|
|
2016-09-02 04:28:52 +00:00
|
|
|
CONFIG_SCHEMA = vol.Schema({
|
|
|
|
DOMAIN: vol.Schema({
|
2016-10-31 12:18:47 +00:00
|
|
|
vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
|
|
|
|
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
2016-09-02 04:28:52 +00:00
|
|
|
vol.Optional(CONF_WHITELIST, default={}): {cv.string: [cv.string]}
|
|
|
|
}),
|
|
|
|
}, extra=vol.ALLOW_EXTRA)
|
2016-08-10 02:45:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
def setup(hass, config):
|
2016-10-31 12:18:47 +00:00
|
|
|
"""Setup the Pilight component."""
|
2016-08-10 02:45:40 +00:00
|
|
|
from pilight import pilight
|
|
|
|
|
2016-09-02 04:28:52 +00:00
|
|
|
host = config[DOMAIN][CONF_HOST]
|
|
|
|
port = config[DOMAIN][CONF_PORT]
|
|
|
|
|
2016-08-10 02:45:40 +00:00
|
|
|
try:
|
2016-09-02 04:28:52 +00:00
|
|
|
pilight_client = pilight.Client(host=host, port=port)
|
2016-08-10 02:45:40 +00:00
|
|
|
except (socket.error, socket.timeout) as err:
|
2016-09-02 04:28:52 +00:00
|
|
|
_LOGGER.error("Unable to connect to %s on port %s: %s",
|
|
|
|
host, port, err)
|
2016-08-10 02:45:40 +00:00
|
|
|
return False
|
|
|
|
|
|
|
|
def start_pilight_client(_):
|
2016-10-31 12:18:47 +00:00
|
|
|
"""Called once when Home Assistant starts."""
|
2016-08-10 02:45:40 +00:00
|
|
|
pilight_client.start()
|
|
|
|
|
|
|
|
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_pilight_client)
|
|
|
|
|
|
|
|
def stop_pilight_client(_):
|
2016-10-31 12:18:47 +00:00
|
|
|
"""Called once when Home Assistant stops."""
|
2016-08-10 02:45:40 +00:00
|
|
|
pilight_client.stop()
|
|
|
|
|
|
|
|
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_pilight_client)
|
|
|
|
|
|
|
|
def send_code(call):
|
|
|
|
"""Send RF code to the pilight-daemon."""
|
2016-10-31 12:18:47 +00:00
|
|
|
# Change type to dict from mappingproxy since data has to be JSON
|
|
|
|
# serializable
|
2016-09-13 01:28:11 +00:00
|
|
|
message_data = dict(call.data)
|
2016-08-10 02:45:40 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
pilight_client.send_code(message_data)
|
|
|
|
except IOError:
|
|
|
|
_LOGGER.error('Pilight send failed for %s', str(message_data))
|
|
|
|
|
2016-10-31 12:18:47 +00:00
|
|
|
hass.services.register(
|
|
|
|
DOMAIN, SERVICE_NAME, send_code, schema=RF_CODE_SCHEMA)
|
2016-08-10 02:45:40 +00:00
|
|
|
|
|
|
|
# Publish received codes on the HA event bus
|
|
|
|
# A whitelist of codes to be published in the event bus
|
2016-09-02 04:28:52 +00:00
|
|
|
whitelist = config[DOMAIN].get(CONF_WHITELIST)
|
2016-08-10 02:45:40 +00:00
|
|
|
|
|
|
|
def handle_received_code(data):
|
|
|
|
"""Called when RF codes are received."""
|
|
|
|
# Unravel dict of dicts to make event_data cut in automation rule
|
|
|
|
# possible
|
2016-10-31 12:18:47 +00:00
|
|
|
data = dict({'protocol': data['protocol'], 'uuid': data['uuid']},
|
|
|
|
**data['message'])
|
2016-08-10 02:45:40 +00:00
|
|
|
|
|
|
|
# No whitelist defined, put data on event bus
|
|
|
|
if not whitelist:
|
|
|
|
hass.bus.fire(EVENT, data)
|
|
|
|
# Check if data matches the defined whitelist
|
2016-10-19 20:02:11 +00:00
|
|
|
elif all(str(data[key]) in whitelist[key] for key in whitelist):
|
2016-08-10 02:45:40 +00:00
|
|
|
hass.bus.fire(EVENT, data)
|
|
|
|
|
|
|
|
pilight_client.set_callback(handle_received_code)
|
|
|
|
|
|
|
|
return True
|