Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sensor component for Fronius inverters, storages, and smart meters #11446

Closed
wants to merge 23 commits into from
Closed
Changes from 16 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
785740e
Introduced fronius component that adds ability to track Fronius devic…
gbeine Jan 2, 2018
2c78c92
Use device parameter for fetching inverter data
gbeine Jan 3, 2018
06a3f68
Fixed handling of default scope
gbeine Jan 3, 2018
937e582
Handle exceptions from yield
gbeine Jan 4, 2018
cdc06d9
Fulfill PR requirements
gbeine Jan 4, 2018
737cc59
Fixed houndci violations
gbeine Jan 4, 2018
3b5f800
Found the last hound violation
gbeine Jan 4, 2018
6ff5c0e
Fixed docstring (https://github.com/home-assistant/home-assistant/pul…
gbeine Feb 18, 2018
bf4d4ec
Fixed import order with isort (https://github.com/home-assistant/home…
gbeine Feb 18, 2018
24d2694
CONF_DEVICE is now CONF_DEVICEID (https://github.com/home-assistant/h…
gbeine Feb 18, 2018
5683589
Added docstring to class FroniusSensor (https://github.com/home-assis…
gbeine Feb 18, 2018
70d78f7
Fixed docstring for state (https://github.com/home-assistant/home-ass…
gbeine Feb 18, 2018
07b3287
Added/fixed docstrings (https://github.com/home-assistant/home-assist…
gbeine Feb 18, 2018
b177d4b
Remove redundant log entry (https://github.com/home-assistant/home-as…
gbeine Feb 18, 2018
3caca8b
Fixed error message if sensor update fails (https://github.com/home-a…
gbeine Feb 18, 2018
d368713
Fixed error log messages (https://github.com/home-assistant/home-assi…
gbeine Feb 18, 2018
d98d944
Satisfy hound
gbeine Feb 18, 2018
b78147a
Handle exceptions explicit (https://github.com/home-assistant/home-as…
gbeine Feb 18, 2018
3fa6462
Removed unnecessary call of update (https://github.com/home-assistant…
gbeine Feb 18, 2018
6cfdbc1
The point makes the difference.
gbeine Feb 18, 2018
2d268ca
Removed unrelated requirements
gbeine Feb 18, 2018
97fdcbc
Remove config logging (https://github.com/home-assistant/home-assista…
gbeine Feb 22, 2018
b1b491f
Reorder and fix imports (https://github.com/home-assistant/home-assis…
gbeine Feb 22, 2018
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -522,6 +522,7 @@ omit =
homeassistant/components/sensor/fixer.py
homeassistant/components/sensor/fritzbox_callmonitor.py
homeassistant/components/sensor/fritzbox_netmonitor.py
homeassistant/components/sensor/fronius.py
homeassistant/components/sensor/gearbest.py
homeassistant/components/sensor/geizhals.py
homeassistant/components/sensor/gitter.py
@@ -0,0 +1,159 @@
"""
Support for Fronius devices.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/sensor.fronius/
"""
import asyncio
from concurrent.futures._base import TimeoutError

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

import this from asyncio

from datetime import timedelta
import logging

from aiohttp.client_exceptions import ServerDisconnectedError
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_HOST, CONF_SCAN_INTERVAL
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity

This comment has been minimized.

Copy link
@fabaff

fabaff Feb 2, 2018

Member

Please keep the imports ordered. Use isort if you don't want to do it manually.

from homeassistant.helpers.event import async_track_time_interval
import voluptuous as vol

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

please put 3rd party imports above home assistant imports

This comment has been minimized.

Copy link
@gbeine

gbeine Feb 19, 2018

Author

Hm... this order has been generated from isort.
Somewhere else @fabaff asked me to use isort for the imports.
What's the right way?

This comment has been minimized.

Copy link
@fabaff

fabaff Apr 28, 2018

Member

This is not sorted by isort. It would look like this

...
import logging

from aiohttp.client_exceptions import ServerDisconnectedError
import voluptuous as vol

from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_HOST, CONF_SCAN_INTERVAL
...

REQUIREMENTS = ['pyfronius==0.2']

_LOGGER = logging.getLogger(__name__)

CONF_TYPE = 'type'
CONF_DEVICEID = 'device'
CONF_SCOPE = 'scope'

TYPE_INVERTER = 'inverter'
TYPE_STORAGE = 'storage'
TYPE_METER = 'meter'
TYPE_POWER_FLOW = 'power_flow'
SCOPE_DEVICE = 'device'
SCOPE_SYSTEM = 'system'

DEFAULT_SCOPE = SCOPE_DEVICE
DEFAULT_DEVICE = None

SENSOR_TYPES = [TYPE_INVERTER, TYPE_STORAGE, TYPE_METER, TYPE_POWER_FLOW]
SCOPE_TYPES = [SCOPE_DEVICE, SCOPE_SYSTEM]

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_TYPE): vol.In(SENSOR_TYPES),
vol.Optional(CONF_SCOPE, default=DEFAULT_SCOPE):
vol.All(cv.ensure_list, [vol.In(SCOPE_TYPES)]),
vol.Optional(CONF_DEVICEID): cv.positive_int,
})


@asyncio.coroutine

This comment has been minimized.

Copy link
@houndci-bot

houndci-bot Jan 4, 2018

expected 2 blank lines, found 1

def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up of Fronius platform."""
_LOGGER.debug(config)

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

Let's remove this debug as it contains the config.

import pyfronius

session = async_get_clientsession(hass)
fronius = pyfronius.Fronius(session, config[CONF_HOST])

name = "fronius_{}_{}".format(config[CONF_TYPE], config[CONF_HOST])
if CONF_DEVICEID in config.keys():

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

No need for keys()

This comment has been minimized.

Copy link
@gbeine

gbeine Feb 19, 2018

Author

I'll try it, but AFAIR without keys() something different happened.

device = config[CONF_DEVICEID]
name = name + "_{}".format(device)
else:
device = DEFAULT_DEVICE

sensor = FroniusSensor(
fronius, name, config[CONF_TYPE], config[CONF_SCOPE], device)

async_add_devices([sensor])

@asyncio.coroutine
def async_fronius(event):
"""Update all the fronius sensors."""
try:
yield from sensor.async_update()
except:

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

Bare excepts are not allowed. Specify the exceptions that you expect.

_LOGGER.error("Update of sensor data failed.")

interval = config.get(CONF_SCAN_INTERVAL) or timedelta(seconds=10)

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

Don't do this. The Entity Platform takes care of this.

This comment has been minimized.

Copy link
@gbeine

gbeine Feb 19, 2018

Author

Ok, is this described somewhere?
How can I access the interval?

This comment has been minimized.

Copy link
@nielstron

nielstron Feb 19, 2018

Contributor

Why would you need to access the interval time? The Entity superclass already handles calling the update method on a regular basis (based on time interval).

This comment has been minimized.

Copy link
@gbeine

gbeine Feb 19, 2018

Author

How does the Entity superclass know about the interval that is configured?
Where does this magic happen?
Can I leave the configuration parameter as it is or is there a pattern that I need to follow?

This comment has been minimized.

Copy link
@balloob
async_track_time_interval(hass, async_fronius, interval)

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

Remove this, entity platform will do this if should_poll returns True.

This comment has been minimized.

Copy link
@gbeine

gbeine Feb 19, 2018

Author

I'll search for this. Did this change soon?
I've got these two lines from another sensor.



class FroniusSensor(Entity):

This comment has been minimized.

Copy link
@fabaff

fabaff Feb 2, 2018

Member

Docstring for the class is missing.

This comment has been minimized.

Copy link
@gbeine

gbeine Feb 18, 2018

Author

Hm... I've added a docstring as in other components, but this comment still persists...

"""The Fronius sensor implementation"""

def __init__(self, data, name, device_type, scope, device):
"""Initialize the sensor."""
self.data = data
self._name = name
self._type = device_type
self._device = device
self._scope = scope
self._state = None
self._attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return self._name

@property
def state(self):
"""Return the current state."""
return self._state

@property
def state_attributes(self):
"""Return the state attributes."""
return self._attributes

@asyncio.coroutine
def async_update(self):
"""Retrieve and update latest state."""
_LOGGER.debug("Update {}".format(self.name))

values = {}

try:
values = yield from self._update()
except ServerDisconnectedError:
_LOGGER.error("Sensor data cannot be updated because of connection error.")

This comment has been minimized.

Copy link
@houndci-bot

houndci-bot Feb 18, 2018

line too long (87 > 79 characters)

except TimeoutError:
_LOGGER.error("Sensor data cannot be updated because of timeout.")

_LOGGER.debug(values)

if values:
self._state = values['status']['Code']
self._attributes = self._get_attributes(values)
self.async_update_ha_state()

This comment has been minimized.

Copy link
@fabaff

fabaff Feb 2, 2018

Member

Is that really needed?

This comment has been minimized.

Copy link
@gbeine

gbeine Feb 3, 2018

Author

Which part of these lines do you mean?
All? Or just the update?

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

This is a coroutine. Just calling it like this does nothing so it can be safely removed.


@asyncio.coroutine
def _update(self):

This comment has been minimized.

Copy link
@fabaff

fabaff Feb 2, 2018

Member

Docstring is missing.

"""Get the values for the current state."""
if self._type == TYPE_INVERTER:
if self._scope == SCOPE_SYSTEM:
return self.data.current_system_inverter_data()

This comment has been minimized.

Copy link
@balloob

balloob Feb 18, 2018

Member

Is this doing I/O ?

This comment has been minimized.

Copy link
@gbeine

gbeine Feb 19, 2018

Author

This triggers an HTTP request, so it is I/O via network.

This comment has been minimized.

Copy link
@balloob

balloob Feb 22, 2018

Member

This function is a coroutine. You are not allowed to do I/O inside a coroutine.

This comment has been minimized.

Copy link
@balloob

balloob Feb 22, 2018

Member

Remove asyncio.coroutine and name your update method update instead of async_update

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Feb 26, 2018

Member

This call returns a coroutine object according to the source in pyfronius.

elif self._scope == SCOPE_DEVICE and self._device:
return self.data.current_inverter_data(self._device)
elif self._scope == SCOPE_DEVICE:
return self.data.current_inverter_data()
elif self._type == TYPE_STORAGE:
return self.data.current_storage_data()
elif self._type == TYPE_METER:
return self.data.current_meter_data()
elif self._type == TYPE_POWER_FLOW:
return self.data.current_power_flow()

def _get_attributes(self, values):

This comment has been minimized.

Copy link
@fabaff

fabaff Feb 2, 2018

Member

Docstring is missing.

"""Map the attributes and ensure proper values."""

This comment has been minimized.

Copy link
@houndci-bot

houndci-bot Feb 18, 2018

trailing whitespace

attributes = {}
for key in values:
if 'value' in values[key] and values[key]['value']:
attributes[key] = values[key]['value']
else:
attributes[key] = 0

return attributes
@@ -348,6 +348,9 @@ http://github.com/tgaugry/suds-passworddigest-py3/archive/86fc50e39b4d2b89974819
# homeassistant.components.remember_the_milk
httplib2==0.10.3

# homeassistant.components.xiaomi
https://github.com/Danielhiversen/PyXiaomiGateway/archive/aa9325fe6fdd62a8ef8c9ca1dce31d3292f484bb.zip#PyXiaomiGateway==0.2.0

# homeassistant.components.sensor.dht
# https://github.com/adafruit/Adafruit_Python_DHT/archive/da8cddf7fb629c1ef4f046ca44f42523c9cf2d11.zip#Adafruit_DHT==1.3.2

@@ -682,6 +685,9 @@ pyfido==1.0.1
# homeassistant.components.climate.flexit
pyflexit==0.3

# homeassistant.components.sensor.fronius
pyfronius==0.2

# homeassistant.components.ifttt
pyfttt==0.3

@@ -866,6 +872,9 @@ python-juicenet==0.0.5
# homeassistant.components.vacuum.xiaomi_miio
python-miio==0.3.2

# homeassistant.components.switch.xiaomi_vacuum
python-mirobo==0.1.2

# homeassistant.components.media_player.mpd
python-mpd2==0.5.5

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.