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

Add Solar-Log platform #27036

Merged
merged 31 commits into from Oct 23, 2019
Merged
Changes from 22 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
87274e8
Add Solar-Log sensor
Ernst79 Sep 28, 2019
89ad652
Codeowners update
Ernst79 Sep 28, 2019
46767e8
Update homeassistant/components/solarlog/manifest.json
Ernst79 Oct 4, 2019
f6236d5
remove sunwatcher from gen_requirements_all.py
Ernst79 Oct 5, 2019
b7d39b1
remove sunwatcher from requirements_test_all.txt
Ernst79 Oct 5, 2019
77e95e5
Remove scan_interval as configuration variable
Ernst79 Oct 5, 2019
e5ef989
Fix black format
Ernst79 Oct 5, 2019
d6be6fe
Config flow added (__init__.py)
Ernst79 Oct 17, 2019
91e8bcf
Config flow added (manifest.json)
Ernst79 Oct 17, 2019
e8a0fa3
Config flow added (const.py)
Ernst79 Oct 17, 2019
b808cac
Config flow added (config_flow.py)
Ernst79 Oct 17, 2019
52cddfa
Config flow added (strings.json)
Ernst79 Oct 17, 2019
bf813b1
Config flow added (en.json translation)
Ernst79 Oct 17, 2019
28b232e
Config flow added (sensor.py rewritten)
Ernst79 Oct 17, 2019
1d77b73
Config flow added (sensor.py)
Ernst79 Oct 17, 2019
fba45d3
Config flow added (config_flows.py)
Ernst79 Oct 17, 2019
414bbf9
resolve conflict config_flows.py
Ernst79 Oct 17, 2019
69c3c4f
Merge branch 'dev' into solarlog
balloob Oct 18, 2019
680064e
Add tests
Ernst79 Oct 18, 2019
a4f44c6
add tests
Ernst79 Oct 18, 2019
a9d597d
add tests
Ernst79 Oct 18, 2019
f122b14
Update .coverage to include all files for solarlog
Ernst79 Oct 19, 2019
1eba1e0
Fix await the unload
Ernst79 Oct 20, 2019
04afd6a
Adjust icons, add http:// to default host
Ernst79 Oct 20, 2019
bb2264c
Change icons
Ernst79 Oct 20, 2019
7a39428
Add http:// to host if not provided, fix await
Ernst79 Oct 20, 2019
ee2179c
Add http:// to host if not provided, fix await
Ernst79 Oct 20, 2019
1259ef2
Adjust tests for http:// added to host
Ernst79 Oct 20, 2019
494fb88
remove line
Ernst79 Oct 20, 2019
dff8115
Remove without http:// requirement
Ernst79 Oct 21, 2019
3f82f44
Remove without http;// requirement
Ernst79 Oct 21, 2019
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -617,6 +617,7 @@ omit =
homeassistant/components/solaredge/__init__.py
homeassistant/components/solaredge/sensor.py
homeassistant/components/solaredge_local/sensor.py
homeassistant/components/solarlog/*
homeassistant/components/solax/sensor.py
homeassistant/components/soma/cover.py
homeassistant/components/soma/__init__.py
@@ -264,6 +264,7 @@ homeassistant/components/smartthings/* @andrewsayre
homeassistant/components/smarty/* @z0mbieprocess
homeassistant/components/smtp/* @fabaff
homeassistant/components/solaredge_local/* @drobtravels @scheric
homeassistant/components/solarlog/* @Ernst79
homeassistant/components/solax/* @squishykid
homeassistant/components/soma/* @ratsept
homeassistant/components/somfy/* @tetienne
@@ -0,0 +1,21 @@
{
"config": {
"title": "Solar-Log",
"step": {
"user": {
"title": "Define your Solar-Log connection",
"data": {
"host": "The hostname or ip-address of your Solar-Log device (without http://)",
"name": "The prefix to be used for your Solar-Log sensors"
}
}
},
"error": {
"already_configured": "Device is already configured",
"cannot_connect": "Failed to connect, please verify host address"
},
"abort": {
"already_configured": "Device is already configured"
}
}
}
@@ -0,0 +1,24 @@
"""Solar-Log integration."""
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.typing import HomeAssistantType


async def async_setup(hass, config):
"""Component setup, do nothing."""
return True


async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
"""Set up a config entry for solarlog."""
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "sensor")
)
return True


async def async_unload_entry(hass, entry):
"""Unload a config entry."""
hass.async_create_task(
This conversation was marked as resolved by Ernst79

This comment has been minimized.

Copy link
@balloob

balloob Oct 19, 2019

Member

Please await the unload.

return await hass.config_entries.async_forward_entry_unload(…)

This comment has been minimized.

Copy link
@Ernst79

Ernst79 Oct 21, 2019

Author Contributor

Fixed.

hass.config_entries.async_forward_entry_unload(entry, "sensor")
)
return True
@@ -0,0 +1,85 @@
"""Config flow for solarlog integration."""
from requests.exceptions import HTTPError, Timeout
from sunwatcher.solarlog.solarlog import SolarLog
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import CONF_HOST, CONF_NAME
from homeassistant.core import HomeAssistant, callback
from homeassistant.util import slugify

from .const import DEFAULT_HOST, DEFAULT_NAME, DOMAIN


@callback
def solarlog_entries(hass: HomeAssistant):
"""Return the hosts already configured."""
return set(
entry.data[CONF_HOST] for entry in hass.config_entries.async_entries(DOMAIN)
)


class SolarLogConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for solarlog."""

VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

def __init__(self) -> None:
"""Initialize the config flow."""
self._errors = {}

def _host_in_configuration_exists(self, user_input) -> bool:
"""Return True if host exists in configuration."""
host = user_input.get(CONF_HOST, DEFAULT_HOST)
if host in solarlog_entries(self.hass):
return True
return False

async def _test_connection(self, user_input=None):
"""Check if we can connect to the Solar-Log device."""
host = user_input.get(CONF_HOST, DEFAULT_HOST)
try:
SolarLog(f"http://{host}")
This conversation was marked as resolved by Ernst79

This comment has been minimized.

Copy link
@balloob

balloob Oct 19, 2019

Member

This is doing I/O and so cannot be run inside an async function. Run it in the executor instead:

await self.hass.async_add_executor_job(SolarLog, f"http://{host}")

This comment has been minimized.

Copy link
@Ernst79

Ernst79 Oct 21, 2019

Author Contributor

Fixed

return True
except (OSError, HTTPError, Timeout):
self._errors[CONF_HOST] = "cannot_connect"
return False

async def async_step_user(self, user_input=None):
"""Step when user intializes a integration."""
self._errors = {}
if user_input is not None:
# set some defaults in case we need to return to the form
if self._host_in_configuration_exists(user_input):
self._errors[CONF_HOST] = "already_configured"
else:
if await self._test_connection(user_input):
name = slugify(user_input.get(CONF_NAME, DEFAULT_NAME))
host = user_input.get(CONF_HOST, DEFAULT_HOST)
return self.async_create_entry(title=name, data={CONF_HOST: host})
else:
user_input = {}
user_input[CONF_NAME] = DEFAULT_NAME
user_input[CONF_HOST] = DEFAULT_HOST

return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(
CONF_NAME, default=user_input.get(CONF_NAME, DEFAULT_NAME)
): str,
vol.Required(
CONF_HOST, default=user_input.get(CONF_HOST, DEFAULT_HOST)
): str,
}
),
errors=self._errors,
)

async def async_step_import(self, user_input=None):
"""Import a config entry."""
if self._host_in_configuration_exists(user_input):
return self.async_abort(reason="already_configured")
return await self.async_step_user(user_input)
@@ -0,0 +1,94 @@
"""Constants for the Solar-Log integration."""
from datetime import timedelta

from homeassistant.const import POWER_WATT, ENERGY_KILO_WATT_HOUR

DOMAIN = "solarlog"

"""Default config for solarlog."""
DEFAULT_HOST = "solar-log"
DEFAULT_NAME = "solarlog"

"""Fixed constants."""
SCAN_INTERVAL = timedelta(seconds=60)

"""Supported sensor types."""
SENSOR_TYPES = {
"time": ["TIME", "last update", None, "mdi:solar-power"],
"power_ac": ["powerAC", "power AC", POWER_WATT, "mdi:solar-power"],
"power_dc": ["powerDC", "power DC", POWER_WATT, "mdi:solar-power"],
"voltage_ac": ["voltageAC", "voltage AC", "V", "mdi:solar-power"],
"voltage_dc": ["voltageDC", "voltage DC", "V", "mdi:solar-power"],
"yield_day": ["yieldDAY", "yield day", ENERGY_KILO_WATT_HOUR, "mdi:solar-power"],
"yield_yesterday": [
"yieldYESTERDAY",
"yield yesterday",
ENERGY_KILO_WATT_HOUR,
"mdi:solar-power",
],
"yield_month": [
"yieldMONTH",
"yield month",
ENERGY_KILO_WATT_HOUR,
"mdi:solar-power",
],
"yield_year": ["yieldYEAR", "yield year", ENERGY_KILO_WATT_HOUR, "mdi:solar-power"],
"yield_total": [
"yieldTOTAL",
"yield total",
ENERGY_KILO_WATT_HOUR,
"mdi:solar-power",
],
"consumption_ac": [
"consumptionAC",
"consumption AC",
POWER_WATT,
"mdi:solar-power",
],
"consumption_day": [
"consumptionDAY",
"consumption day",
ENERGY_KILO_WATT_HOUR,
"mdi:solar-power",
],
"consumption_yesterday": [
"consumptionYESTERDAY",
"consumption yesterday",
ENERGY_KILO_WATT_HOUR,
"mdi:solar-power",
],
"consumption_month": [
"consumptionMONTH",
"consumption month",
ENERGY_KILO_WATT_HOUR,
"mdi:solar-power",
],
"consumption_year": [
"consumptionYEAR",
"consumption year",
ENERGY_KILO_WATT_HOUR,
"mdi:solar-power",
],
"consumption_total": [
"consumptionTOTAL",
"consumption total",
ENERGY_KILO_WATT_HOUR,
"mdi:solar-power",
],
"total_power": ["totalPOWER", "total power", "Wp", "mdi:solar-power"],
"alternator_loss": [
"alternatorLOSS",
"alternator loss",
POWER_WATT,
"mdi:solar-power",
],
"capacity": ["CAPACITY", "capacity", "%", "mdi:solar-power"],
"efficiency": ["EFFICIENCY", "efficiency", "% W/Wp", "mdi:solar-power"],
"power_available": [
"powerAVAILABLE",
"power available",
POWER_WATT,
"mdi:solar-power",
],
"usage": ["USAGE", "usage", None, "mdi:solar-power"],
}
@@ -0,0 +1,9 @@
{
"domain": "solarlog",
"name": "Solar-Log",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integration/solarlog",
"dependencies": [],
"codeowners": ["@Ernst79"],
"requirements": ["sunwatcher==0.2.1"]
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.