Update SMA sensor to pysma 0.2.2 (#17988)

This commit is contained in:
Johann Kellerman 2018-10-31 21:09:00 +02:00 committed by GitHub
parent 93706fa568
commit 7363378ac4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 65 deletions

View file

@ -12,14 +12,14 @@ import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_HOST, CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_SSL,
CONF_VERIFY_SSL, EVENT_HOMEASSISTANT_STOP)
CONF_HOST, CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_SSL, CONF_VERIFY_SSL,
EVENT_HOMEASSISTANT_STOP)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_time_interval
REQUIREMENTS = ['pysma==0.2']
REQUIREMENTS = ['pysma==0.2.2']
_LOGGER = logging.getLogger(__name__)
@ -30,35 +30,28 @@ CONF_KEY = 'key'
CONF_SENSORS = 'sensors'
CONF_UNIT = 'unit'
GROUP_INSTALLER = 'installer'
GROUP_USER = 'user'
GROUPS = [GROUP_USER, GROUP_INSTALLER]
SENSOR_OPTIONS = [
'current_consumption',
'current_power',
'total_consumption',
'total_yield',
]
GROUPS = ['user', 'installer']
def _check_sensor_schema(conf):
"""Check sensors and attributes are valid."""
import pysma
valid = list(conf[CONF_CUSTOM].keys())
valid.extend(SENSOR_OPTIONS)
for sensor, attrs in conf[CONF_SENSORS].items():
if sensor not in valid:
raise vol.Invalid("{} does not exist".format(sensor))
valid.extend([s.name for s in pysma.SENSORS])
for sname, attrs in conf[CONF_SENSORS].items():
if sname not in valid:
raise vol.Invalid("{} does not exist".format(sname))
for attr in attrs:
if attr in valid:
continue
raise vol.Invalid("{} does not exist [{}]".format(attr, sensor))
raise vol.Invalid("{} does not exist [{}]".format(attr, sname))
return conf
CUSTOM_SCHEMA = vol.Any({
vol.Required(CONF_KEY):
vol.All(cv.string, vol.Length(min=13, max=13)),
vol.All(cv.string, vol.Length(min=13, max=15)),
vol.Required(CONF_UNIT): cv.string,
vol.Optional(CONF_FACTOR, default=1): vol.Coerce(float),
})
@ -80,37 +73,26 @@ async def async_setup_platform(
"""Set up SMA WebConnect sensor."""
import pysma
# Sensor_defs from the library
sensor_defs = dict(zip(SENSOR_OPTIONS, [
(pysma.KEY_CURRENT_CONSUMPTION_W, 'W', 1),
(pysma.KEY_CURRENT_POWER_W, 'W', 1),
(pysma.KEY_TOTAL_CONSUMPTION_KWH, 'kWh', 1000),
(pysma.KEY_TOTAL_YIELD_KWH, 'kWh', 1000)]))
# Sensor_defs from the custom config
for name, prop in config[CONF_CUSTOM].items():
if name in sensor_defs:
_LOGGER.warning("Custom sensor %s replace built-in sensor", name)
sensor_defs[name] = (prop['key'], prop['unit'], prop['factor'])
n_s = pysma.Sensor(name, prop['key'], prop['unit'], prop['factor'])
pysma.add_sensor(n_s)
# Prepare all HASS sensor entities
hass_sensors = []
used_sensors = []
for name, attr in config[CONF_SENSORS].items():
hass_sensors.append(SMAsensor(name, attr, sensor_defs))
sub_sensors = [pysma.get_sensor(s) for s in attr]
hass_sensors.append(SMAsensor(pysma.get_sensor(name), sub_sensors))
used_sensors.append(name)
used_sensors.extend(attr)
# Remove sensor_defs not in use
sensor_defs = {name: val for name, val in sensor_defs.items()
if name in used_sensors}
async_add_entities(hass_sensors)
used_sensors = [pysma.get_sensor(s) for s in set(used_sensors)]
# Init the SMA interface
session = async_get_clientsession(hass, verify_ssl=config[CONF_VERIFY_SSL])
grp = {GROUP_INSTALLER: pysma.GROUP_INSTALLER,
GROUP_USER: pysma.GROUP_USER}[config[CONF_GROUP]]
grp = config[CONF_GROUP]
url = "http{}://{}".format(
"s" if config[CONF_SSL] else "", config[CONF_HOST])
@ -124,10 +106,6 @@ async def async_setup_platform(
hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, async_close_session)
# Read SMA values periodically & update sensors
names_to_query = list(sensor_defs.keys())
keys_to_query = [sensor_defs[name][0] for name in names_to_query]
backoff = 0
async def async_sma(event):
@ -137,17 +115,14 @@ async def async_setup_platform(
backoff -= 1
return
values = await sma.read(keys_to_query)
values = await sma.read(used_sensors)
if values is None:
backoff = 3
backoff = 10
return
values = [0 if val is None else val for val in values]
res = dict(zip(names_to_query, values))
res = {key: val // sensor_defs[key][2] for key, val in res.items()}
_LOGGER.debug("Update sensors %s %s %s", keys_to_query, values, res)
tasks = []
for sensor in hass_sensors:
task = sensor.async_update_values(res)
task = sensor.async_update_values()
if task:
tasks.append(task)
if tasks:
@ -160,18 +135,18 @@ async def async_setup_platform(
class SMAsensor(Entity):
"""Representation of a SMA sensor."""
def __init__(self, sensor_name, attr, sensor_defs):
def __init__(self, pysma_sensor, sub_sensors):
"""Initialize the sensor."""
self._name = sensor_name
self._key, self._unit_of_measurement, _ = sensor_defs[sensor_name]
self._state = None
self._sensor_defs = sensor_defs
self._attr = {att: "" for att in attr}
self._sensor = pysma_sensor
self._sub_sensors = sub_sensors
self._attr = {s.name: "" for s in sub_sensors}
self._state = self._sensor.value
@property
def name(self):
"""Return the name of the sensor."""
return self._name
return self._sensor.name
@property
def state(self):
@ -181,7 +156,7 @@ class SMAsensor(Entity):
@property
def unit_of_measurement(self):
"""Return the unit the value is expressed in."""
return self._unit_of_measurement
return self._sensor.unit
@property
def device_state_attributes(self):
@ -193,19 +168,18 @@ class SMAsensor(Entity):
"""SMA sensors are updated & don't poll."""
return False
def async_update_values(self, key_values):
"""Update this sensor using the data."""
def async_update_values(self):
"""Update this sensor."""
update = False
for key, val in self._attr.items():
newval = '{} {}'.format(key_values[key], self._sensor_defs[key][1])
if val != newval:
for sens in self._sub_sensors:
newval = '{} {}'.format(sens.value, sens.unit)
if self._attr[sens.name] != newval:
update = True
self._attr[key] = newval
self._attr[sens.name] = newval
new_state = key_values[self._name]
if new_state != self._state:
if self._sensor.value != self._state:
update = True
self._state = new_state
self._state = self._sensor.value
return self.async_update_ha_state() if update else None

View file

@ -1084,7 +1084,7 @@ pysesame==0.1.0
pysher==1.0.4
# homeassistant.components.sensor.sma
pysma==0.2
pysma==0.2.2
# homeassistant.components.device_tracker.snmp
# homeassistant.components.sensor.snmp