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

Fronius (solar energy and inverter) component #22316

Merged
merged 53 commits into from Jun 29, 2019
Merged
Changes from 46 commits
Commits
Show all changes
53 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
3fed21a
Merge branch 'dev' of https://github.com/home-assistant/home-assistan…
nielstron Mar 4, 2019
eb1960b
Update fronius requirement
nielstron Mar 21, 2019
e198da5
Various small fixes
nielstron Mar 21, 2019
15317c7
Small fixes
nielstron Mar 21, 2019
7ef0933
Formatting
nielstron Mar 21, 2019
0ca9e83
Merge branch 'dev' of https://github.com/home-assistant/home-assistan…
nielstron Mar 23, 2019
2ab0ffc
Add fronius to coverage
nielstron Mar 23, 2019
9b012f0
New structure and formatting
nielstron Mar 23, 2019
53f7e4c
Merge remote-tracking branch 'ha/dev' into pyfronius
nielstron Apr 23, 2019
231a44b
Add manifest.json
nielstron Apr 23, 2019
be17a8a
Fix data loading
nielstron Apr 23, 2019
e9c87b4
Make pylint happy
nielstron Apr 23, 2019
a7cd590
Fix issues
nielstron Apr 23, 2019
8e0e14f
Fix parse_attributes
nielstron Apr 23, 2019
e041e52
Fix docstring and platform schema
nielstron Apr 23, 2019
a5fe401
Make use of default HA-Const config values
nielstron Apr 23, 2019
52a7a48
Change configuration setup, introducing list of monitored conditions
nielstron Apr 24, 2019
ed66f06
Change the structure slightly, allowing for a list of sensors
nielstron Apr 24, 2019
17fefe7
Remove periods from logging
nielstron Apr 24, 2019
1ad6610
Formatting
nielstron Apr 24, 2019
8fe9955
Change name generation, use variable instead of string
nielstron Apr 24, 2019
f5eecab
small fixes
nielstron Apr 24, 2019
d6ccca4
Update sensor.py
balloob Jun 18, 2019
ec6b1cf
Incorporate correction proposals
nielstron Jun 23, 2019
eecde9d
Merge remote-tracking branch 'ha/dev' into pyfronius
nielstron Jun 23, 2019
a941c3d
Setting default device inside validation
nielstron Jun 23, 2019
a54e77a
Merge branch 'pyfronius' of https://github.com/nielstron/home-assista…
nielstron Jun 23, 2019
ec5cbb2
Move import on top and small format
nielstron Jun 23, 2019
798efdc
Formatting fix
nielstron Jun 27, 2019
40e2c43
Rename validation method to _device_id_validator
nielstron Jun 27, 2019
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -203,6 +203,7 @@ omit =
homeassistant/components/fritzbox_callmonitor/sensor.py
homeassistant/components/fritzbox_netmonitor/sensor.py
homeassistant/components/fritzdect/switch.py
homeassistant/components/fronius/sensor.py
homeassistant/components/frontier_silicon/media_player.py
homeassistant/components/futurenow/light.py
homeassistant/components/garadget/cover.py
@@ -78,6 +78,7 @@ homeassistant/components/flock/* @fabaff
homeassistant/components/flunearyou/* @bachya
homeassistant/components/foursquare/* @robbiet480
homeassistant/components/freebox/* @snoof85
homeassistant/components/fronius/* @nielstron
homeassistant/components/frontend/* @home-assistant/core
homeassistant/components/gearbest/* @HerrHofrat
homeassistant/components/gitter/* @fabaff
@@ -0,0 +1 @@
"""The Fronius component."""
@@ -0,0 +1,8 @@
{
"domain": "fronius",
"name": "Fronius",
"documentation": "https://www.home-assistant.io/components/fronius",
"requirements": ["pyfronius==0.4.6"],
"dependencies": [],
"codeowners": ["@nielstron"]
}
@@ -0,0 +1,184 @@
"""Support for Fronius devices."""
import logging
import voluptuous as vol

from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (CONF_RESOURCE, CONF_SENSOR_TYPE, CONF_DEVICE,
CONF_MONITORED_CONDITIONS)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity

_LOGGER = logging.getLogger(__name__)

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 = 0

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_RESOURCE):
cv.url,
vol.Required(CONF_MONITORED_CONDITIONS):
vol.All(
cv.ensure_list,
[{
vol.Required(CONF_SENSOR_TYPE): vol.In(SENSOR_TYPES),
vol.Optional(CONF_SCOPE, default=DEFAULT_SCOPE):
vol.In(SCOPE_TYPES),
vol.Optional(CONF_DEVICE, default=DEFAULT_DEVICE):
vol.All(vol.Coerce(int), vol.Range(min=0))
}]
)
})


async def async_setup_platform(hass,
config,
async_add_devices,
This conversation was marked as resolved by nielstron

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Jun 19, 2019

Member

Rename async_add_devices to async_add_entities.

This comment has been minimized.

Copy link
@nielstron

nielstron Jun 23, 2019

Author Contributor

Done

discovery_info=None):
"""Set up of Fronius platform."""
from pyfronius import Fronius
This conversation was marked as resolved by nielstron

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Jun 19, 2019

Member

This can be moved to the top of the module.


session = async_get_clientsession(hass)
fronius = Fronius(session, config[CONF_RESOURCE])

sensors = []
for condition in config[CONF_MONITORED_CONDITIONS]:

device = condition.get(CONF_DEVICE)
This conversation was marked as resolved by nielstron

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Jun 19, 2019

Member

Use dict[key] for required config keys and keys with default config schema values.

if device == 0:
if condition[CONF_SENSOR_TYPE] == TYPE_INVERTER:
device = 1
This conversation was marked as resolved by nielstron

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Jun 19, 2019

Member

All config modifications should be made in the config schema. Please make a custom validator that checks the condition and makes this modification before returning the config part.

Here's an example of a custom validator that modifies the config:

def _state_validator(config):
"""Validate the state."""
config = copy.deepcopy(config)
for state in SUPPORTED_PRETRIGGER_STATES:
if CONF_DELAY_TIME not in config[state]:
config[state][CONF_DELAY_TIME] = config[CONF_DELAY_TIME]
if CONF_TRIGGER_TIME not in config[state]:
config[state][CONF_TRIGGER_TIME] = config[CONF_TRIGGER_TIME]
for state in SUPPORTED_PENDING_STATES:
if CONF_PENDING_TIME not in config[state]:
config[state][CONF_PENDING_TIME] = config[CONF_PENDING_TIME]
return config

This comment has been minimized.

Copy link
@nielstron

nielstron Jun 23, 2019

Author Contributor

I hope the way I implemented it now is the way you intended. It was tested to work locally at least.

name = "Fronius {} {} {}".format(
condition[CONF_SENSOR_TYPE].replace('_', ' ').capitalize(),
device,
config[CONF_RESOURCE],
)
sensor_type = condition[CONF_SENSOR_TYPE]
scope = condition[CONF_SCOPE]
if sensor_type == TYPE_INVERTER:
if scope == SCOPE_SYSTEM:
sensor_cls = FroniusInverterSystem
else:
sensor_cls = FroniusInverterDevice
elif sensor_type == TYPE_METER:
if scope == SCOPE_SYSTEM:
sensor_cls = FroniusMeterSystem
else:
sensor_cls = FroniusMeterDevice
elif sensor_type == TYPE_POWER_FLOW:
sensor_cls = FroniusPowerFlow
else:
sensor_cls = FroniusStorage

sensors.append(sensor_cls(fronius, name, device))

async_add_devices(sensors, True)


class FroniusSensor(Entity):
"""The Fronius sensor implementation."""

def __init__(self, data, name, device):
"""Initialize the sensor."""
self.data = data
self._name = name
self._device = device
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):
This conversation was marked as resolved by nielstron

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Jun 19, 2019

Member

Rename this to device_state_attributes.

"""Return the state attributes."""
return self._attributes

async def async_update(self):
"""Retrieve and update latest state."""
values = {}
try:
values = await self._update()
except ConnectionError:
_LOGGER.error("Failed to update: connection error")
except ValueError:
_LOGGER.error("Failed to update: invalid response returned")

if values:
self._state = values['status']['Code']
attributes = {}
for key in values:
if 'value' in values[key]:
attributes[key] = values[key].get('value', 0)
self._attributes = attributes

def _update(self):
This conversation was marked as resolved by nielstron

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Jun 19, 2019

Member

Make this a coroutine since that's what it should be when overwritten.

"""Return values of interest."""
pass


class FroniusInverterSystem(FroniusSensor):
"""Sensor for the fronius inverter with system scope."""

async def _update(self):
"""Get the values for the current state."""
return await self.data.current_system_inverter_data()


class FroniusInverterDevice(FroniusSensor):
"""Sensor for the fronius inverter with device scope."""

async def _update(self):
"""Get the values for the current state."""
return await self.data.current_inverter_data(self._device)


class FroniusStorage(FroniusSensor):
"""Sensor for the fronius battery storage."""

async def _update(self):
"""Get the values for the current state."""
return await self.data.current_storage_data(self._device)


class FroniusMeterSystem(FroniusSensor):
"""Sensor for the fronius meter with system scope."""

async def _update(self):
"""Get the values for the current state."""
return await self.data.current_system_meter_data()


class FroniusMeterDevice(FroniusSensor):
"""Sensor for the fronius meter with device scope."""

async def _update(self):
"""Get the values for the current state."""
return await self.data.current_meter_data(self._device)


class FroniusPowerFlow(FroniusSensor):
"""Sensor for the fronius power flow."""

async def _update(self):
"""Get the values for the current state."""
return await self.data.current_power_flow()
@@ -1062,6 +1062,9 @@ pyfnip==0.2
# homeassistant.components.fritzbox
pyfritzhome==0.4.0

# homeassistant.components.fronius
pyfronius==0.4.6

# homeassistant.components.ifttt
pyfttt==0.3

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