|
| 1 | +from yarl import URL |
| 2 | + |
| 3 | +from dingz import make_call |
| 4 | +from dingz.constants import DIMMER |
| 5 | +from dingz.registry import BaseRegistry, organize_by_absolute_index |
| 6 | + |
| 7 | + |
| 8 | +class Dimmer(object): |
| 9 | + def __init__(self, absolute_index, dingz): |
| 10 | + self.dingz = dingz |
| 11 | + self.absolute_index = absolute_index |
| 12 | + self.on = None |
| 13 | + self.brightness_pct = None |
| 14 | + self.enabled = None |
| 15 | + self.dimmable = None |
| 16 | + self.output = None |
| 17 | + self.name = None |
| 18 | + self.seen_state = False |
| 19 | + |
| 20 | + async def toggle(self, brightness_pct=100): |
| 21 | + """ |
| 22 | + Toggle light (based on internal state). |
| 23 | + :param brightness_pct: brightness in percent, or None |
| 24 | + :return: |
| 25 | + """ |
| 26 | + action = "off" if self.on else "on" |
| 27 | + await self.operate_light(action, brightness_pct) |
| 28 | + |
| 29 | + async def turn_on(self, brightness_pct=100): |
| 30 | + """ Turn light on. |
| 31 | + :param brightness_pct: brightness in percent, or None. |
| 32 | + """ |
| 33 | + await self.operate_light("on", brightness_pct) |
| 34 | + |
| 35 | + async def turn_off(self): |
| 36 | + """ Rurn light off.""" |
| 37 | + await self.operate_light("off") |
| 38 | + |
| 39 | + VALID_OPERATIONS = ('on', 'off') |
| 40 | + |
| 41 | + async def operate_light(self, action, brightness_pct=None): |
| 42 | + """ |
| 43 | + Operate the light (turn it on or off). |
| 44 | + :param action: 'on' or 'off' |
| 45 | + :param brightness_pct: brightness in percent or None if not defined |
| 46 | + :return: |
| 47 | + """ |
| 48 | + if action not in Dimmer.VALID_OPERATIONS: |
| 49 | + raise ValueError("invalid action %s, expected one of %s" % |
| 50 | + (repr(action), repr(Dimmer.VALID_OPERATIONS))) |
| 51 | + |
| 52 | + if brightness_pct is not None and (brightness_pct > 100 or brightness_pct < 0): |
| 53 | + raise ValueError("invalid brightness_pct %s, expected value between 0 and 100" % |
| 54 | + (repr(brightness_pct))) |
| 55 | + |
| 56 | + url = URL(self.dingz.uri).join(URL("%s/%s/%s" % (DIMMER, self.index_relative, action))) |
| 57 | + params = {} |
| 58 | + if brightness_pct is not None: |
| 59 | + params["value"] = str(brightness_pct) |
| 60 | + |
| 61 | + await make_call(self.dingz, uri=url, method="POST", parameters=params) |
| 62 | + self.on = action |
| 63 | + if brightness_pct is not None: |
| 64 | + self.brightness_pct = brightness_pct |
| 65 | + |
| 66 | + def _consume_state(self, state_details): |
| 67 | + """ |
| 68 | + Example for state_details: |
| 69 | + { |
| 70 | + "on": true, "output": 100, "ramp": 0, "readonly": false, |
| 71 | + "index": { "relative": 0, "absolute": 2 } |
| 72 | + } |
| 73 | + :param state_details: |
| 74 | + :return: |
| 75 | + """ |
| 76 | + assert self.absolute_index == state_details['index']['absolute'] |
| 77 | + self.seen_state = True |
| 78 | + self.index_relative = state_details['index']['relative'] |
| 79 | + self.on = state_details['on'] |
| 80 | + self.brightness_pct = state_details['output'] |
| 81 | + |
| 82 | + def _consume_config(self, config): |
| 83 | + # "output": "halogen", "name": "Dimmable 3", "feedback": null, "feedback_intensity": 10 |
| 84 | + self.output = config['output'] |
| 85 | + self.enabled = config['output'] != 'not_connected' |
| 86 | + self.dimmable = config['output'] != 'non_dimmable' |
| 87 | + self.name = config['name'] |
| 88 | + |
| 89 | + |
| 90 | +class DimmerRegistry(BaseRegistry[Dimmer]): |
| 91 | + def __init__(self, dingz): |
| 92 | + super().__init__(factory=lambda absolute_index: Dimmer(absolute_index, dingz)) |
| 93 | + |
| 94 | + def _consume_config(self, dimmer_configs): |
| 95 | + for absolute_index, dimmer_config in enumerate(dimmer_configs): |
| 96 | + dimmer = self._get_or_create(absolute_index) |
| 97 | + dimmer._consume_config(dimmer_config) |
| 98 | + |
| 99 | + def _consume_dimmer_state(self, dimmer_states): |
| 100 | + for absolute_index, dimmer_state in organize_by_absolute_index(dimmer_states): |
| 101 | + dimmer = self._get_or_create(absolute_index) |
| 102 | + dimmer._consume_state(dimmer_state) |
0 commit comments