Change TCP component to use Jinja2 instead of regex

This commit is contained in:
Flyte 2016-02-17 18:12:36 +00:00
parent cf93644d54
commit 348b7abe7d
3 changed files with 26 additions and 18 deletions

View File

@ -19,7 +19,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
""" Create the BinarySensor. """ """ Create the BinarySensor. """
if not BinarySensor.validate_config(config): if not BinarySensor.validate_config(config):
return False return False
add_entities((BinarySensor(config),)) add_entities((BinarySensor(hass, config),))
class BinarySensor(Sensor, BinarySensorDevice): class BinarySensor(Sensor, BinarySensorDevice):

View File

@ -5,14 +5,16 @@ Provides a sensor which gets its values from a TCP socket.
""" """
import logging import logging
import socket import socket
import re
from select import select from select import select
from homeassistant.const import CONF_NAME, CONF_HOST from homeassistant.const import CONF_NAME, CONF_HOST
from homeassistant.util import template
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.components.tcp import ( from homeassistant.components.tcp import (
DOMAIN, CONF_PORT, CONF_TIMEOUT, CONF_PAYLOAD, CONF_UNIT, CONF_VALUE_REGEX, DOMAIN, CONF_PORT, CONF_TIMEOUT, CONF_PAYLOAD, CONF_UNIT, CONF_VALUE_REGEX,
CONF_VALUE_ON, CONF_BUFFER_SIZE, DEFAULT_TIMEOUT, DEFAULT_BUFFER_SIZE CONF_VALUE_TEMPLATE, CONF_VALUE_ON, CONF_BUFFER_SIZE, DEFAULT_TIMEOUT,
DEFAULT_BUFFER_SIZE
) )
@ -25,15 +27,16 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
""" Create the Sensor. """ """ Create the Sensor. """
if not Sensor.validate_config(config): if not Sensor.validate_config(config):
return False return False
add_entities((Sensor(config),)) add_entities((Sensor(hass, config),))
class Sensor(Entity): class Sensor(Entity):
""" Sensor Entity which gets its value from a TCP socket. """ """ Sensor Entity which gets its value from a TCP socket. """
required = tuple() required = tuple()
def __init__(self, config): def __init__(self, hass, config):
""" Set all the config values if they exist and get initial state. """ """ Set all the config values if they exist and get initial state. """
self._hass = hass
self._config = { self._config = {
CONF_NAME: config.get(CONF_NAME), CONF_NAME: config.get(CONF_NAME),
CONF_HOST: config[CONF_HOST], CONF_HOST: config[CONF_HOST],
@ -42,6 +45,7 @@ class Sensor(Entity):
CONF_PAYLOAD: config[CONF_PAYLOAD], CONF_PAYLOAD: config[CONF_PAYLOAD],
CONF_UNIT: config.get(CONF_UNIT), CONF_UNIT: config.get(CONF_UNIT),
CONF_VALUE_REGEX: config.get(CONF_VALUE_REGEX), CONF_VALUE_REGEX: config.get(CONF_VALUE_REGEX),
CONF_VALUE_TEMPLATE: config.get(CONF_VALUE_TEMPLATE),
CONF_VALUE_ON: config.get(CONF_VALUE_ON), CONF_VALUE_ON: config.get(CONF_VALUE_ON),
CONF_BUFFER_SIZE: config.get( CONF_BUFFER_SIZE: config.get(
CONF_BUFFER_SIZE, DEFAULT_BUFFER_SIZE), CONF_BUFFER_SIZE, DEFAULT_BUFFER_SIZE),
@ -78,6 +82,7 @@ class Sensor(Entity):
def update(self): def update(self):
""" Get the latest value for this sensor. """ """ Get the latest value for this sensor. """
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try: try:
sock.connect((self._config[CONF_HOST], self._config[CONF_PORT])) sock.connect((self._config[CONF_HOST], self._config[CONF_PORT]))
except socket.error as err: except socket.error as err:
@ -85,6 +90,7 @@ class Sensor(Entity):
"Unable to connect to %s on port %s: %s", "Unable to connect to %s on port %s: %s",
self._config[CONF_HOST], self._config[CONF_PORT], err) self._config[CONF_HOST], self._config[CONF_PORT], err)
return return
try: try:
sock.send(self._config[CONF_PAYLOAD].encode()) sock.send(self._config[CONF_PAYLOAD].encode())
except socket.error as err: except socket.error as err:
@ -93,6 +99,7 @@ class Sensor(Entity):
self._config[CONF_PAYLOAD], self._config[CONF_HOST], self._config[CONF_PAYLOAD], self._config[CONF_HOST],
self._config[CONF_PORT], err) self._config[CONF_PORT], err)
return return
readable, _, _ = select([sock], [], [], self._config[CONF_TIMEOUT]) readable, _, _ = select([sock], [], [], self._config[CONF_TIMEOUT])
if not readable: if not readable:
_LOGGER.warning( _LOGGER.warning(
@ -101,20 +108,20 @@ class Sensor(Entity):
self._config[CONF_TIMEOUT], self._config[CONF_PAYLOAD], self._config[CONF_TIMEOUT], self._config[CONF_PAYLOAD],
self._config[CONF_HOST], self._config[CONF_PORT]) self._config[CONF_HOST], self._config[CONF_PORT])
return return
value = sock.recv(self._config[CONF_BUFFER_SIZE]).decode() value = sock.recv(self._config[CONF_BUFFER_SIZE]).decode()
if self._config[CONF_VALUE_REGEX] is not None:
match = re.match(self._config[CONF_VALUE_REGEX], value) if self._config[CONF_VALUE_TEMPLATE] is not None:
if match is None:
_LOGGER.warning(
"Unable to match value using value_regex of %r: %r",
self._config[CONF_VALUE_REGEX], value)
return
try: try:
self._state = match.groups()[0] self._state = template.render(
except IndexError: self._hass,
_LOGGER.error( self._config[CONF_VALUE_TEMPLATE],
"You must include a capture group in the regex for %r: %r", value=value)
self.name, self._config[CONF_VALUE_REGEX])
return return
return except TemplateError as err:
_LOGGER.error(
"Unable to render template of %r with value: %r",
self._config[CONF_VALUE_TEMPLATE], value)
return
self._state = value self._state = value

View File

@ -10,6 +10,7 @@ CONF_TIMEOUT = "timeout"
CONF_PAYLOAD = "payload" CONF_PAYLOAD = "payload"
CONF_UNIT = "unit" CONF_UNIT = "unit"
CONF_VALUE_REGEX = "value_regex" CONF_VALUE_REGEX = "value_regex"
CONF_VALUE_TEMPLATE = "value_template"
CONF_VALUE_ON = "value_on" CONF_VALUE_ON = "value_on"
CONF_BUFFER_SIZE = "buffer_size" CONF_BUFFER_SIZE = "buffer_size"