Skip to content

Commit

Permalink
cleanup and optimizations
Browse files Browse the repository at this point in the history
also added binary sensors for heaters and sensors for IntelliChem
  • Loading branch information
jlvaillant committed Dec 31, 2020
1 parent c48b302 commit 778a50c
Show file tree
Hide file tree
Showing 11 changed files with 839 additions and 278 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.pyc
.DS_Store
*.code-workspace
.vscode
120 changes: 86 additions & 34 deletions custom_components/intellicenter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,41 @@
from homeassistant.helpers.typing import ConfigType

from .const import DOMAIN
from .pyintellicenter import ConnectionHandler, ModelController, PoolModel, PoolObject
from .pyintellicenter import (
ACT_ATTR,
BODY_ATTR,
BODY_TYPE,
CHEM_TYPE,
CIRCGRP_TYPE,
CIRCUIT_ATTR,
CIRCUIT_TYPE,
FEATR_ATTR,
GPM_ATTR,
HEATER_ATTR,
HEATER_TYPE,
HTMODE_ATTR,
LISTORD_ATTR,
LOTMP_ATTR,
LSTTMP_ATTR,
MODE_ATTR,
PUMP_TYPE,
PWR_ATTR,
RPM_ATTR,
SCHED_TYPE,
SENSE_TYPE,
SNAME_ATTR,
SOURCE_ATTR,
STATUS_ATTR,
SUBTYP_ATTR,
SYSTEM_TYPE,
USE_ATTR,
VACFLO_ATTR,
VOL_ATTR,
ConnectionHandler,
ModelController,
PoolModel,
PoolObject,
)

_LOGGER = logging.getLogger(__name__)

Expand All @@ -35,6 +69,8 @@
WATER_HEATER_DOMAIN,
]

# -------------------------------------------------------------------------------------


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Pentair IntelliCenter Integration."""
Expand All @@ -44,28 +80,24 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up IntelliCenter integration from a config entry."""

# we don't need some of the system objects
def ignoreFunc(object):
"""Return False for the objects we want to ignore."""

return (
object.objtype
in [
"PANEL",
"MODULE",
"PERMIT",
"SYSTIM",
]
or object.subtype in ["LEGACY"]
)

attributes_map = {
"BODY": {"SNAME", "HEATER", "HTMODE", "LOTMP", "LSTTMP", "STATUS"},
"CIRCUIT": {"SNAME", "STATUS", "USE", "SUBTYPE", "FEATR"},
"CIRCGRP": {"CIRCUIT"},
"HEATER": {"SNAME", "BODY"},
"PUMP": {"SNAME", "STATUS", "PWR", "RPM", "GPM"},
"SENSE": {"SNAME", "SOURCE"},
BODY_TYPE: {
SNAME_ATTR,
HEATER_ATTR,
HTMODE_ATTR,
LOTMP_ATTR,
LSTTMP_ATTR,
STATUS_ATTR,
VOL_ATTR,
},
CIRCUIT_TYPE: {SNAME_ATTR, STATUS_ATTR, USE_ATTR, SUBTYP_ATTR, FEATR_ATTR},
CIRCGRP_TYPE: {CIRCUIT_ATTR},
CHEM_TYPE: {},
HEATER_TYPE: {SNAME_ATTR, BODY_ATTR, LISTORD_ATTR},
PUMP_TYPE: {SNAME_ATTR, STATUS_ATTR, PWR_ATTR, RPM_ATTR, GPM_ATTR},
SENSE_TYPE: {SNAME_ATTR, SOURCE_ATTR},
SCHED_TYPE: {SNAME_ATTR, ACT_ATTR, VACFLO_ATTR},
SYSTEM_TYPE: {MODE_ATTR, VACFLO_ATTR},
}
model = PoolModel(attributes_map)

Expand Down Expand Up @@ -167,6 +199,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True


# -------------------------------------------------------------------------------------


class PoolEntity(Entity):
"""Representation of an Pool entity linked to an pool object."""

Expand All @@ -175,17 +210,20 @@ def __init__(
entry: ConfigEntry,
controller: ModelController,
poolObject: PoolObject,
attribute_key="STATUS",
name_suffix="",
attribute_key=STATUS_ATTR,
name=None,
enabled_by_default=True,
extraStateAttributes=set(),
):
"""Initialize a Pool entity."""
self._entry_id = entry.entry_id
self._controller = controller
self._poolObject = poolObject
self._available = True
self._extraStateAttributes = []
self._name_suffix = name_suffix
self._extraStateAttributes = extraStateAttributes
self._name = name
self._attribute_key = attribute_key
self._enabled_by_default = enabled_by_default

_LOGGER.debug(f"mapping {poolObject}")

Expand All @@ -209,6 +247,11 @@ async def async_will_remove_from_hass(self) -> None:
"""Entity is removed from Home Assistant."""
_LOGGER.debug(f"removing entity: {self.unique_id}")

@property
def entity_registry_enabled_default(self):
"""Return True if the entity is enabled by default."""
return self._enabled_by_default

@property
def available(self):
"""Return True is the entity is available."""
Expand All @@ -217,16 +260,21 @@ def available(self):
@property
def name(self):
"""Return the name of the entity."""
name = self._poolObject.sname
if self._name_suffix:
name += " " + self._name_suffix
return name

if self._name is None:
# default is to return the name of the underlying pool object
return self._poolObject.sname
elif self._name.startswith("+"):
# name is a suffix
return self._poolObject.sname + self._name[1:]
else:
return self._name

@property
def unique_id(self):
"""Return a unique ID."""
my_id = self._entry_id + self._poolObject.objnam
if self._attribute_key != "STATUS":
if self._attribute_key != STATUS_ATTR:
my_id += self._attribute_key
return my_id

Expand Down Expand Up @@ -279,14 +327,18 @@ def requestChanges(self, changes: dict) -> None:
self._poolObject.objnam, changes, waitForResponse=False
)

def isUpdated(self, updates: Dict[str, Dict[str, str]]) -> bool:
"""Return true if the entity is updated by the updates from Intellicenter."""

return self._attribute_key in updates.get(self._poolObject.objnam, {})

@callback
def _update_callback(self, updates: Dict[str, Dict[str, str]]):
"""Update the entity if its underlying pool object has changed."""

if self._attribute_key in updates.get(self._poolObject.objnam, {}):
if self.isUpdated(updates):
self._available = True
my_updates = updates.get(self._poolObject.objnam)
_LOGGER.debug(f"updating {self} from {my_updates}")
_LOGGER.debug(f"updating {self} from {updates}")
self.async_write_ha_state()

@callback
Expand Down
92 changes: 87 additions & 5 deletions custom_components/intellicenter/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
"""Pentair Intellicenter binary sensors."""

import logging
from typing import Dict

from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.typing import HomeAssistantType

from custom_components.intellicenter.pyintellicenter.attributes import (
BODY_ATTR,
CIRCUIT_TYPE,
HEATER_TYPE,
)
from custom_components.intellicenter.water_heater import HEATER_ATTR, HTMODE_ATTR

from . import PoolEntity
from .const import DOMAIN
from .pyintellicenter import ModelController, PoolObject
from .pyintellicenter import STATUS_ATTR, ModelController, PoolObject

_LOGGER = logging.getLogger(__name__)

Expand All @@ -24,17 +32,91 @@ async def async_setup_entry(

object: PoolObject
for object in controller.model.objectList:
if (
object.objtype == "CIRCUIT" and object.subtype == "FRZ"
) or object.objtype == "PUMP":
if object.objtype == CIRCUIT_TYPE and object.subtype == "FRZ":
sensors.append(PoolBinarySensor(entry, controller, object))
elif object.objtype == HEATER_TYPE:
sensors.append(
HeaterBinarySensor(
entry,
controller,
object,
)
)
elif object.objtype == "SCHED":
sensors.append(
PoolBinarySensor(
entry,
controller,
object,
attribute_key="ACT",
name="+ (schedule)",
enabled_by_default=False,
extraStateAttributes={"VACFLO"},
)
)
elif object.objtype == "PUMP":
sensors.append(PoolBinarySensor(entry, controller, object, valueForON="10"))
async_add_entities(sensors)


# -------------------------------------------------------------------------------------


class PoolBinarySensor(PoolEntity, BinarySensorEntity):
"""Representation of a Pentair Binary Sensor."""

def __init__(
self,
entry: ConfigEntry,
controller: ModelController,
poolObject: PoolObject,
valueForON="ON",
**kwargs,
):
"""Initialize."""
super().__init__(entry, controller, poolObject, **kwargs)
self._valueForON = valueForON

@property
def is_on(self):
"""Return true if sensor is on."""
return self._poolObject.status == self._poolObject.onStatus
return self._poolObject[self._attribute_key] == self._valueForON


# -------------------------------------------------------------------------------------


class HeaterBinarySensor(PoolEntity, BinarySensorEntity):
"""Representation of a Heater binary sensor."""

def __init__(
self,
entry: ConfigEntry,
controller: ModelController,
poolObject: PoolObject,
**kwargs,
):
"""Initialize."""
super().__init__(entry, controller, poolObject, **kwargs)
self._bodies = set(poolObject[BODY_ATTR].split(" "))

@property
def is_on(self) -> bool:
"""Return true if sensor is on."""
for bodyObjnam in self._bodies:
body = self._controller.model[bodyObjnam]
if (
body[STATUS_ATTR] == "ON"
and body[HEATER_ATTR] == self._poolObject.objnam
and body[HTMODE_ATTR] != "0"
):
return True
return False

def isUpdated(self, updates: Dict[str, Dict[str, str]]) -> bool:
"""Return true if the entity is updated by the updates from Intellicenter."""

for objnam in self._bodies & updates.keys():
if {STATUS_ATTR, HEATER_ATTR, HTMODE_ATTR} & updates[objnam].keys():
return True
return False
Loading

0 comments on commit 778a50c

Please sign in to comment.