import asyncio
import logging
from caspia.meadow import errors
from caspia.toolbox.subclasses import all_subclasses
logger = logging.getLogger(__name__)
[docs]class Link:
meadow_service_type = None
def __init__(self, bridge, md_service):
self.loop = bridge.loop
self.bridge = bridge
self._md_service = md_service
self.sublinks = []
self._create_link()
def _fill_accessory_info(self, accessory):
accessory.info.set(name=self._md_service.name, manufacturer='Caspiatech')
def _create_link(self):
asyncio.ensure_future(self._setup(), loop=self.loop)
logger.debug('Created new link for %s service', self._md_service)
async def _setup(self):
for sublink in self.sublinks:
await sublink.setup()
def _update_scheduled(self):
asyncio.ensure_future(self.update(), loop=self.loop)
[docs] async def update(self):
try:
await self._reload_state()
logger.debug('State of %s reloaded', self)
except errors.NotReadyError as err:
logger.debug('Could not update state: %s, scheduling new update in 5s', err)
self.loop.call_later(5.0, self._update_scheduled)
async def _reload_state(self):
for sublink in self.sublinks:
await sublink.reload()
@property
def dependant_services(self):
return {self._md_service}
[docs] @staticmethod
def all():
return all_subclasses(Link)
def __str__(self):
return '<Link with service {}>'.format(self._md_service)
[docs]class CharacteristicLink:
def __init__(self, meadow, hap, default=None):
self.meadow: 'caspia.meadow.services.Characteristic' = meadow
self.hap: 'hap.Characteristic' = hap
if default is not None:
self.hap.value = default
[docs] async def setup(self):
self.hap.handle_write(self.on_hap_update)
self.meadow.subscribe(self.on_meadow_update)
[docs] async def reload(self):
await self.meadow.enable_notifications()
meadow_value = await self.meadow.read(timeout=5.0)
self.hap.value = self.map_meadow_to_hap(meadow_value)
[docs] def map_meadow_to_hap(self, value, **kwargs):
return value
[docs] def map_hap_to_meadow(self, value, **kwargs):
return value
[docs] async def on_meadow_update(self, value, **kwargs):
hap_value = self.map_meadow_to_hap(value, **kwargs)
self.hap.value = hap_value
[docs] async def on_hap_update(self, value, **kwargs):
meadow_value = self.map_hap_to_meadow(value, **kwargs)
await self.meadow.write(meadow_value, timeout=5.0)
self.hap.value = value
[docs]class BooleanLink(CharacteristicLink):
[docs] def map_meadow_to_hap(self, value, **kwargs):
return bool(value)
[docs] def map_hap_to_meadow(self, value, **kwargs):
return bool(value)
[docs]class FloatLink(CharacteristicLink):
[docs] def map_meadow_to_hap(self, value, **kwargs):
return float(value)
[docs] def map_hap_to_meadow(self, value, **kwargs):
return float(value)
[docs]class PercentageIntLink(CharacteristicLink):
[docs] def map_meadow_to_hap(self, value, **kwargs):
return 0 if value is None else int(value * 100)
[docs] def map_hap_to_meadow(self, value, **kwargs):
return 0.0 if value is None else float(value / 100)
[docs]class PercentageFloatLink(CharacteristicLink):
[docs] def map_meadow_to_hap(self, value, **kwargs):
return 0.0 if value is None else float(int(value * 100))
[docs] def map_hap_to_meadow(self, value, **kwargs):
return 0.0 if value is None else float(value / 100)