Skip to content

Commit

Permalink
feat: support door sensor and awareness sensor
Browse files Browse the repository at this point in the history
  • Loading branch information
rxwen committed Mar 20, 2021
1 parent 4399acf commit 4318bfc
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 6 deletions.
23 changes: 19 additions & 4 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,14 @@
from .cover import (
TerncyCurtain,
)
from .binary_sensor import (
TerncyDoorSensor,
TerncyMotionSensor,
)

PLATFORM_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)

PLATFORMS = ["light", "cover", "switch"]
PLATFORMS = ["light", "cover", "switch", "binary_sensor"]

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -125,9 +129,8 @@ def terncy_event_handler(tern, ev):
platform = None
for plat in async_get_platforms(hass, DOMAIN):
if plat.config_entry.unique_id == tern.dev_id:
if plat.domain == "light":
platform = plat
break
platform = plat
break
if platform is None:
return
for ent in ents:
Expand Down Expand Up @@ -200,6 +203,10 @@ async def update_or_create_entity(dev, tern):
features = SUPPORT_TERNCY_ON_OFF
elif profile == PROFILE_CURTAIN:
features = SUPPORT_TERNCY_ON_OFF
elif profile == PROFILE_DOOR_SENSOR:
features = SUPPORT_TERNCY_ON_OFF
elif profile == PROFILE_PIR:
features = SUPPORT_TERNCY_ON_OFF
else:
_LOGGER.info("unsupported profile %d", profile)
return []
Expand All @@ -216,6 +223,10 @@ async def update_or_create_entity(dev, tern):
device = TerncySmartPlug(tern, devid, name, model, version, features)
elif profile == PROFILE_CURTAIN:
device = TerncyCurtain(tern, devid, name, model, version, features)
elif profile == PROFILE_DOOR_SENSOR:
device = TerncyDoorSensor(tern, devid, name, model, version, features)
elif profile == PROFILE_PIR:
device = TerncyMotionSensor(tern, devid, name, model, version, features)
else:
device = TerncyLight(tern, devid, name, model, version, features)
device.update_state(svc["attributes"])
Expand All @@ -229,6 +240,10 @@ async def update_or_create_entity(dev, tern):
await platform.async_add_entities([device])
elif profile == PROFILE_CURTAIN and platform.domain == "cover":
await platform.async_add_entities([device])
elif profile == PROFILE_DOOR_SENSOR and platform.domain == "binary_sensor":
await platform.async_add_entities([device])
elif profile == PROFILE_PIR and platform.domain == "binary_sensor":
await platform.async_add_entities([device])
elif isLight and platform.domain == "light":
await platform.async_add_entities([device])
tern.hass_platform_data.parsed_devices[devid] = device
Expand Down
187 changes: 187 additions & 0 deletions binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
"""Curtain platform support for Terncy."""
import logging

from homeassistant.components.binary_sensor import (
DEVICE_CLASS_MOISTURE,
DEVICE_CLASS_MOTION,
DEVICE_CLASS_SAFETY,
DEVICE_CLASS_OPENING,
DEVICE_CLASSES,
BinarySensorEntity,
)

from .const import DOMAIN, TERNCY_MANU_NAME

_LOGGER = logging.getLogger(__name__)


async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Old way of setting up Terncy curtain.
Can only be called when a user accidentally mentions Terncy platform in their
config. But even in that case it would have been ignored.
"""
_LOGGER.info(" terncy curtain async_setup_platform")


def get_attr_value(attrs, key):
"""Read attr value from terncy attributes."""
for att in attrs:
if "attr" in att and att["attr"] == key:
return att["value"]
return None


async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the Terncy curtain from a config entry."""
_LOGGER.info("setup terncy curtain platform")


class TerncyDoorSensor(BinarySensorEntity):
"""Representation of a Terncy curtain."""

def __init__(self, api, devid, name, model, version, features):
"""Initialize the curtain."""
self._device_id = devid
self.hub_id = api.dev_id
self._name = name
self.model = model
self.version = version
self.api = api
self.is_available = False
self._features = features
self._on = 0

def update_state(self, attrs):
"""Updateterncy state."""
_LOGGER.info("update state event to %s", attrs)
on = get_attr_value(attrs, "contact")
if on is not None:
self._on = on

@property
def unique_id(self):
"""Return terncy unique id."""
return self._device_id

@property
def device_id(self):
"""Return terncy device id."""
return self._device_id

@property
def name(self):
"""Return terncy device name."""
return self._name

@property
def is_on(self):
"""Return if terncy device is on."""
return self._on == 1

@property
def available(self):
"""Return if terncy device is available."""
return self.is_available

@property
def device_class(self):
"""Return if terncy device is available."""
return DEVICE_CLASS_OPENING

@property
def supported_features(self):
"""Return the terncy device feature."""
return 0

@property
def device_info(self):
"""Return the terncy device info."""
return {
"identifiers": {(DOMAIN, self.device_id)},
"name": self.name,
"manufacturer": TERNCY_MANU_NAME,
"model": self.model,
"sw_version": self.version,
"via_device": (DOMAIN, self.hub_id),
}

@property
def device_state_attributes(self):
"""Get terncy curtain states."""
return {}


class TerncyMotionSensor(BinarySensorEntity):
"""Representation of a Terncy curtain."""

def __init__(self, api, devid, name, model, version, features):
"""Initialize the curtain."""
self._device_id = devid
self.hub_id = api.dev_id
self._name = name
self.model = model
self.version = version
self.api = api
self.is_available = False
self._features = features
self._on = 0

def update_state(self, attrs):
"""Updateterncy state."""
_LOGGER.info("update state event to %s", attrs)
on = get_attr_value(attrs, "motion")
if on is not None:
self._on = on

@property
def unique_id(self):
"""Return terncy unique id."""
return self._device_id

@property
def device_id(self):
"""Return terncy device id."""
return self._device_id

@property
def name(self):
"""Return terncy device name."""
return self._name

@property
def is_on(self):
"""Return if terncy device is on."""
return self._on == 1

@property
def available(self):
"""Return if terncy device is available."""
return self.is_available

@property
def device_class(self):
"""Return if terncy device is available."""
return DEVICE_CLASS_MOTION

@property
def supported_features(self):
"""Return the terncy device feature."""
return 0

@property
def device_info(self):
"""Return the terncy device info."""
return {
"identifiers": {(DOMAIN, self.device_id)},
"name": self.name,
"manufacturer": TERNCY_MANU_NAME,
"model": self.model,
"sw_version": self.version,
"via_device": (DOMAIN, self.hub_id),
}

@property
def device_state_attributes(self):
"""Get terncy curtain states."""
return {}
5 changes: 3 additions & 2 deletions cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,9 @@ async def async_open_cover(self, **kwargs):

async def async_set_cover_position(self, **kwargs):
"""Turn on terncy curtain."""
_LOGGER.info("close cover %s", kwargs)
await self.api.set_attribute(self._device_id, "curtainPercent", 100, 0)
_LOGGER.info("set cover position %s", kwargs)
percent = kwargs[ATTR_POSITION]
await self.api.set_attribute(self._device_id, "curtainPercent", percent, 0)
self.async_write_ha_state()

@property
Expand Down

0 comments on commit 4318bfc

Please sign in to comment.