Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
0608afd
Initial diff for sensor against ##33691
May 28, 2020
0afaa46
Additional device->entity renaming
May 28, 2020
393d7aa
Improve code
May 28, 2020
3c5dd8c
Remove redundant heating state
May 28, 2020
1c2e9c7
Remove patch as PR is merged
May 28, 2020
b0cd8be
Remove Class-able defs - improve detection
May 28, 2020
d1eda7b
Apply patch, improve class, add new class
May 28, 2020
e324f61
Make sensor use new class
May 28, 2020
bb0aa73
Fixes from additional review on parent
May 29, 2020
0fe9c2a
Update homeassistant/components/plugwise/__init__.py
CoMPaTech May 30, 2020
b189a53
Update homeassistant/components/plugwise/__init__.py
CoMPaTech May 30, 2020
8c33e8a
Update homeassistant/components/plugwise/__init__.py
CoMPaTech May 30, 2020
3e22c19
Update homeassistant/components/plugwise/__init__.py
CoMPaTech May 30, 2020
d72afd0
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
9a90b75
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
de0abf0
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
98a2ced
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
4d30d75
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
088611b
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
f626761
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
971e4b0
Added consts
May 30, 2020
0f76337
Replace other consts as well
May 30, 2020
4a4080f
Replace one more set of const
May 30, 2020
377062d
Fix initial processing as discussed
May 30, 2020
57529ec
Improve consts move Sensor childclass
May 30, 2020
f9c6cfa
Remove introduced dev_classes
May 30, 2020
4158c94
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
3ff9821
Update homeassistant/components/plugwise/sensor.py
CoMPaTech May 30, 2020
ded76ae
Add consts for typemapping as suggested
May 30, 2020
e5c6570
Excluded from coverage
May 30, 2020
55f5872
Add @bouwew rework on separate auxiliary class
May 30, 2020
5de9ab9
Improve entity naming in code and fix device/entity names
May 31, 2020
3ec7c9d
Suggested logging change
May 31, 2020
5d457f0
Remove logging, add callback
May 31, 2020
2545da0
Removing icons for known device classes, effectively just drop icons
May 31, 2020
f7dc2eb
Move unique_id and collateral - cleanup unuseds
May 31, 2020
c1f9018
Further cleaning
Jun 1, 2020
64e5e89
Revert sensoric icons for non-device class (i.e. auxiliary)
Jun 1, 2020
76d9d9c
Rogue illegal device class (well spotted @bouwew)
Jun 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ omit =
homeassistant/components/plex/sensor.py
homeassistant/components/plugwise/__init__.py
homeassistant/components/plugwise/climate.py
homeassistant/components/plugwise/sensor.py
homeassistant/components/plum_lightpad/*
homeassistant/components/pocketcasts/sensor.py
homeassistant/components/point/*
Expand Down
57 changes: 50 additions & 7 deletions homeassistant/components/plugwise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import asyncio
from datetime import timedelta
import logging
from typing import Dict

from Plugwise_Smile.Smile import Smile
import async_timeout
import voluptuous as vol

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
Expand All @@ -22,7 +23,8 @@

_LOGGER = logging.getLogger(__name__)

ALL_PLATFORMS = ["climate"]
SENSOR_PLATFORMS = ["sensor"]
ALL_PLATFORMS = ["climate", "sensor"]


async def async_setup(hass: HomeAssistant, config: dict):
Expand Down Expand Up @@ -100,7 +102,13 @@ async def async_update_data():
sw_version=api.smile_version[0],
)

for component in ALL_PLATFORMS:
platforms = ALL_PLATFORMS

single_master_thermostat = api.single_master_thermostat()
if single_master_thermostat is None:
platforms = SENSOR_PLATFORMS

for component in platforms:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)
Expand All @@ -127,11 +135,17 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
class SmileGateway(Entity):
"""Represent Smile Gateway."""

def __init__(self, api, coordinator):
"""Initialise the sensor."""
def __init__(self, api, coordinator, name, dev_id):
"""Initialise the gateway."""
self._api = api
self._coordinator = coordinator
self._name = name
self._dev_id = dev_id

self._unique_id = None
self._model = None

self._entity_name = self._name

@property
def unique_id(self):
Expand All @@ -148,11 +162,40 @@ def available(self):
"""Return True if entity is available."""
return self._coordinator.last_update_success

@property
def name(self):
"""Return the name of the entity, if any."""
if not self._name:
return None
return self._name

@property
def device_info(self) -> Dict[str, any]:
"""Return the device information."""

device_information = {
"identifiers": {(DOMAIN, self._dev_id)},
"name": self._entity_name,
"manufacturer": "Plugwise",
}

if self._model is not None:
device_information["model"] = self._model.replace("_", " ").title()

if self._dev_id != self._api.gateway_id:
device_information["via_device"] = (DOMAIN, self._api.gateway_id)

return device_information

async def async_added_to_hass(self):
"""Subscribe to updates."""
self.async_on_remove(self._coordinator.async_add_listener(self._process_data))
self._async_process_data()
self.async_on_remove(
self._coordinator.async_add_listener(self._async_process_data)
)

def _process_data(self):
@callback
def _async_process_data(self):
"""Interpret and process API data."""
raise NotImplementedError

Expand Down
86 changes: 24 additions & 62 deletions homeassistant/components/plugwise/climate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Plugwise Climate component for Home Assistant."""

import logging
from typing import Dict

from Plugwise_Smile.Smile import Smile

Expand All @@ -17,16 +16,10 @@
SUPPORT_TARGET_TEMPERATURE,
)
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
from homeassistant.core import callback

from . import SmileGateway
from .const import (
DEFAULT_MAX_TEMP,
DEFAULT_MIN_TEMP,
DOMAIN,
SCHEDULE_OFF,
SCHEDULE_ON,
THERMOSTAT_ICON,
)
from .const import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP, DOMAIN, SCHEDULE_OFF, SCHEDULE_ON

HVAC_MODES_HEAT_ONLY = [HVAC_MODE_HEAT, HVAC_MODE_AUTO]
HVAC_MODES_HEAT_COOL = [HVAC_MODE_HEAT_COOL, HVAC_MODE_AUTO]
Expand All @@ -47,20 +40,20 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
"zone_thermostat",
"thermostatic_radiator_valve",
]
all_entities = api.get_all_devices()
all_devices = api.get_all_devices()

for dev_id, device in all_entities.items():
for dev_id, device_properties in all_devices.items():

if device["class"] not in thermostat_classes:
if device_properties["class"] not in thermostat_classes:
continue

thermostat = PwThermostat(
api,
coordinator,
device["name"],
device_properties["name"],
dev_id,
device["location"],
device["class"],
device_properties["location"],
device_properties["class"],
DEFAULT_MIN_TEMP,
DEFAULT_MAX_TEMP,
)
Expand All @@ -77,11 +70,9 @@ def __init__(
self, api, coordinator, name, dev_id, loc_id, model, min_temp, max_temp
):
"""Set up the Plugwise API."""
super().__init__(api, coordinator)
super().__init__(api, coordinator, name, dev_id)

self._api = api
self._name = name
self._dev_id = dev_id
self._loc_id = loc_id
self._model = model
self._min_temp = min_temp
Expand All @@ -92,9 +83,9 @@ def __init__(
self._preset_mode = None
self._presets = None
self._presets_list = None
self._boiler_state = None
self._heating_state = None
self._cooling_state = None
self._compressor_state = None
self._dhw_state = None
self._hvac_mode = None
self._schema_names = None
Expand All @@ -111,43 +102,16 @@ def __init__(
def hvac_action(self):
"""Return the current action."""
if self._single_thermostat:
if self._heating_state or self._boiler_state:
if self._heating_state:
return CURRENT_HVAC_HEAT
if self._cooling_state:
return CURRENT_HVAC_COOL
return CURRENT_HVAC_IDLE
if self._heating_state is not None or self._boiler_state is not None:
if self._heating_state is not None:
if self._setpoint > self._temperature:
return CURRENT_HVAC_HEAT
return CURRENT_HVAC_IDLE

@property
def name(self):
"""Return the name of the thermostat, if any."""
return self._name

@property
def device_info(self) -> Dict[str, any]:
"""Return the device information."""

device_information = {
"identifiers": {(DOMAIN, self._dev_id)},
"name": self._name,
"manufacturer": "Plugwise",
"model": self._model.replace("_", " ").title(),
}

if self._dev_id != self._api.gateway_id:
device_information["via_device"] = (DOMAIN, self._api.gateway_id)
del device_information["via_device"]

return device_information

@property
def icon(self):
"""Return the icon to use in the frontend."""
return THERMOSTAT_ICON

@property
def supported_features(self):
"""Return the list of supported features."""
Expand All @@ -172,8 +136,8 @@ def preset_modes(self):
@property
def hvac_modes(self):
"""Return the available hvac modes list."""
if self._heating_state is not None or self._boiler_state is not None:
if self._cooling_state is not None:
if self._heating_state is not None:
if self._compressor_state is not None:
return HVAC_MODES_HEAT_COOL
return HVAC_MODES_HEAT_ONLY

Expand Down Expand Up @@ -258,7 +222,8 @@ async def async_set_preset_mode(self, preset_mode):
except Smile.PlugwiseError:
_LOGGER.error("Error while communicating to device")

def _process_data(self):
@callback
def _async_process_data(self):
"""Update the data for this climate device."""
climate_data = self._api.get_device_data(self._dev_id)
heater_central_data = self._api.get_device_data(self._api.heater_id)
Expand Down Expand Up @@ -286,21 +251,18 @@ def _process_data(self):
if "active_preset" in climate_data:
self._preset_mode = climate_data["active_preset"]

if "boiler_state" in heater_central_data:
if heater_central_data["boiler_state"] is not None:
self._boiler_state = heater_central_data["boiler_state"]
if "heating_state" in heater_central_data:
if heater_central_data["heating_state"] is not None:
self._heating_state = heater_central_data["heating_state"]
if "cooling_state" in heater_central_data:
if heater_central_data["cooling_state"] is not None:
self._cooling_state = heater_central_data["cooling_state"]
if heater_central_data.get("heating_state") is not None:
self._heating_state = heater_central_data["heating_state"]
if heater_central_data.get("cooling_state") is not None:
self._cooling_state = heater_central_data["cooling_state"]
if heater_central_data.get("compressor_state") is not None:
self._compressor_state = heater_central_data["compressor_state"]

if self._schema_status:
self._hvac_mode = HVAC_MODE_AUTO
elif self._heating_state is not None or self._boiler_state is not None:
elif self._heating_state is not None:
self._hvac_mode = HVAC_MODE_HEAT
if self._cooling_state is not None:
if self._compressor_state is not None:
self._hvac_mode = HVAC_MODE_HEAT_COOL

self.async_write_ha_state()
2 changes: 1 addition & 1 deletion homeassistant/components/plugwise/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def async_step_user(self, user_input=None):
"""Handle the initial step."""
errors = {}
api = None

if user_input is not None:

try:
Expand Down
21 changes: 9 additions & 12 deletions homeassistant/components/plugwise/const.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""Constant for Plugwise component."""
DOMAIN = "plugwise"

# Sensor mapping
SENSOR_MAP_MODEL = 0
SENSOR_MAP_UOM = 1
SENSOR_MAP_DEVICE_CLASS = 2

# Default directives
DEFAULT_NAME = "Smile"
DEFAULT_USERNAME = "smile"
Expand All @@ -10,8 +15,6 @@
DEFAULT_MAX_TEMP = 30
DEFAULT_SCAN_INTERVAL = {"thermostat": 60, "power": 10}

DEVICE_CLASS_GAS = "gas"

# Configuration directives
CONF_MIN_TEMP = "min_temp"
CONF_MAX_TEMP = "max_temp"
Expand All @@ -22,21 +25,15 @@
CONF_GAS = "gas"

ATTR_ILLUMINANCE = "illuminance"
UNIT_LUMEN = "lm"

CURRENT_HVAC_DHW = "hot_water"

DEVICE_STATE = "device_state"

SCHEDULE_ON = "true"
SCHEDULE_OFF = "false"

# Icons
SWITCH_ICON = "mdi:electric-switch"
THERMOSTAT_ICON = "mdi:thermometer"
WATER_ICON = "mdi:water-pump"
FLAME_ICON = "mdi:fire"
COOL_ICON = "mdi:snowflake"
FLAME_ICON = "mdi:fire"
IDLE_ICON = "mdi:circle-off-outline"
GAS_ICON = "mdi:fire"
POWER_ICON = "mdi:flash"
POWER_FAILURE_ICON = "mdi:flash-off"
SWELL_SAG_ICON = "mdi:pulse"
VALVE_ICON = "mdi:valve"
1 change: 0 additions & 1 deletion homeassistant/components/plugwise/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"name": "Plugwise",
"documentation": "https://www.home-assistant.io/integrations/plugwise",
"requirements": ["Plugwise_Smile==0.2.10"],
"dependencies": [],
"codeowners": ["@CoMPaTech", "@bouwew"],
"config_flow": true
}
Loading