Skip to content

Commit

Permalink
[BREAKING] Reworked base Things (#117)
Browse files Browse the repository at this point in the history
This is a squashed commit. More details on GitHub
  • Loading branch information
s-kostyuk committed May 20, 2018
1 parent c19b4f5 commit 9d9ac1b
Show file tree
Hide file tree
Showing 35 changed files with 1,335 additions and 186 deletions.
557 changes: 557 additions & 0 deletions docs/source/developer/generic_thing_types.rst

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Platform itself is hosted on GitHub: https://github.com/s-kostyuk/adpl/

developer/capabilities
developer/capability_list
developer/generic_thing_types
developer/dev_overview
developer/base_components
developer/dev_integrations
Expand Down
80 changes: 0 additions & 80 deletions dpl/integrations/abs_switch.py

This file was deleted.

50 changes: 50 additions & 0 deletions dpl/integrations/base_things/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
This package contains definitions of base (abstract) implementations of Things,
recommended to be used by developers of integrations
"""


from .abs_value_sensor import AbsValueSensor
from .abs_binary_sensor import AbsBinarySensor
from .abs_button import AbsButton
from .abs_switch import AbsSwitch
from .abs_contact_sensor import AbsContactSensor
from .abs_temp_sensor import AbsTemperatureSensor

from .abs_actuator import (
AbsActuator, UnsupportedCommandError, UnacceptableCommandArgumentsError
)
from .abs_on_off import AbsOnOff
from .abs_open_closed import AbsOpenClosed
from .abs_togglable_actuator import AbsTogglableActuator
from .abs_lock import AbsLock
from .abs_door_actuator import AbsDoorActuator
from .abs_shades import AbsShades
from .abs_light import AbsLight
from .abs_dimmable_light import AbsDimmableLight
from .abs_ct_light import AbsColorTemperatureLight
from .abs_color_light import AbsColorLight
from .abs_power_switch import AbsPowerSwitch
from .abs_valve import AbsValve
from .abs_fan import AbsFan
from .abs_vs_fan import AbsVariableSpeedFan
from .abs_player import AbsPlayer
from .abs_pausable_player import AbsPausablePlayer
from .abs_track_player import AbsTrackPlayer
from .abs_speaker import AbsSpeaker
from .abs_speaker_system import AbsSpeakerSystem


__all__ = (
'AbsValueSensor', 'AbsBinarySensor', 'AbsButton', 'AbsSwitch',
'AbsContactSensor', 'AbsTemperatureSensor',

'UnsupportedCommandError', 'UnacceptableCommandArgumentsError',
'AbsActuator', 'AbsOnOff', 'AbsOpenClosed', 'AbsTogglableActuator',

'AbsLock', 'AbsDoorActuator', 'AbsShades', 'AbsLight',
'AbsDimmableLight', 'AbsColorTemperatureLight', 'AbsColorLight',
'AbsPowerSwitch', 'AbsValve', 'AbsFan', 'AbsVariableSpeedFan',
'AbsPlayer', 'AbsPausablePlayer', 'AbsTrackPlayer',
'AbsSpeaker', 'AbsSpeakerSystem'
)
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,24 @@
UnsupportedCommandError,
UnacceptableCommandArgumentsError
)
from dpl.things.capabilities import IsActive
from dpl.things.thing import Thing, TDomainId, Connection
from dpl.things.commands_filler_meta import CommandsFiller


class AbsActuator(Thing, Actuator, HasState, IsActive):
class AbsActuator(
Thing, Actuator, HasState, metaclass=CommandsFiller
):
"""
Actuator is an abstraction of devices that can 'act', perform some commands
and change their states after that.
Every actuator implementation must guarantee that:
- it can be in one of two states: 'activated' or 'deactivated';
- 'activation' is a switching of a device to some specific active state
(like 'on' for LightBulb, 'opened' for Door and 'capturing' for Camera
and 'playing' for Player);
- 'deactivation' is a switching of a device to some specific non-active
state (like 'off' for LightBulb, 'closed' for Door and 'idle' for Camera
and 'stopped'/'paused' for Player);
- it can be toggled between those to states;
- it provides a list of available commands;
- each available command can be executed;
- if command can't be executed for any reason, corresponding method raises
an exception (FIXME: CC9: or returns an error code???)
AbsActuator is a base implementation of Actuator interface. Such actuators
always have a set of available commands and usually have some state
associated with them.
It's expected that all derivative classes will just implement methods and
properties that are specific for concrete Thing type while the base
implementation or properties and commands will be left unchanged. But it's
not obligatorily if the derivative class will manage all the functionality
by itself (i.e. will notify all the subscribers on changes, implement all
declared properties and methods and so on).
"""
def __init__(
self, domain_id: TDomainId,
Expand Down Expand Up @@ -78,12 +73,17 @@ def _state(self, new_value: 'AbsActuator.States') -> None:
@property
def commands(self) -> Iterable[str]:
"""
Returns a list of available commands. Must be overridden in derivative
classes.
Returns a list of available commands.
By default the list of available commands is fetched from the
_all_commands private property, filled by a metaclass. So, by default,
all commands declared in inherited Capabilities will be listed.
Derivative classes are allowed to override this method.
:return: a tuple of command names (strings)
"""
return 'activate', 'deactivate', 'toggle'
return self._all_commands

# FIXME: CC9: or return an error code???
def execute(self, command: str, args: Mapping = EMPTY_MAPPING) -> None:
Expand Down Expand Up @@ -113,30 +113,3 @@ def execute(self, command: str, args: Mapping = EMPTY_MAPPING) -> None:
return command_method(**args)
except TypeError as e:
raise UnacceptableCommandArgumentsError() from e

def activate(self) -> None:
"""
Switches the Thing to one of the 'active' states
:return: None
"""
raise NotImplementedError()

def deactivate(self) -> None:
"""
Switches the Thing to one of the 'inactive' states
:return: None
"""
raise NotImplementedError()

def toggle(self) -> None:
"""
Switches an object from the current state to the opposite one
:return: None
"""
if self.is_active:
return self.deactivate()
else:
return self.activate()
30 changes: 30 additions & 0 deletions dpl/integrations/base_things/abs_binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Include standard modules
# Include 3rd-party modules
# Include DPL modules
from dpl.things.capabilities import IsActive
from .abs_value_sensor import AbsValueSensor


class AbsBinarySensor(AbsValueSensor[bool], IsActive):
"""
The most primitive (but not necessary the base) type of Sensors in the
system. Can have only one of two integer values: 1 and 0. Where 1 is
mapped to the "active" state and 0 is mapped to "not active".
Usually is inherited by more specific implementations of a Binary Sensor,
including buttons, leakage sensors, reed switches (detects an opening
of a door or window), motion sensors and so on.
"""
_type = "binary_sensor"

@property
def is_active(self) -> bool:
"""
Returns if this object is currently in one of the
'active' states (like 'on' for lighting, 'open'
for a door and 'playing' for player)
:return: True if the measured value for the sensor is not zero
(i.e. is 1) or is True
"""
return bool(self.value)
17 changes: 17 additions & 0 deletions dpl/integrations/base_things/abs_button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Include standard modules
# Include 3rd-party modules
# Include DPL modules
from .abs_binary_sensor import AbsBinarySensor


class AbsButton(AbsBinarySensor):
"""
An abstraction of all the Buttons connected to the system.
Its value is set to 1 while the button is pressed and sets to 0 just after
the button was released. There is no long press detection, double press
detection and so on. Just "pressed" (1) and released (0).
All the other functionality is the same as in Binary Sensor.
"""
_type = "button"
27 changes: 27 additions & 0 deletions dpl/integrations/base_things/abs_color_light.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Include standard modules
# Include 3rd-party modules
# Include DPL modules
from dpl.things.capabilities import HasColorHSB
from .abs_ct_light import AbsColorTemperatureLight


class AbsColorLight(AbsColorTemperatureLight, HasColorHSB):
"""
AbsColorTemperatureLight is an abstraction of all lighting devices with
controllable color temperature
"""
_type = "color_light"

def set_color(self, hue: float, saturation: float) -> None:
"""
Sets the new value of color for this Thing using HSB format.
The brightness is expected to be left unchanged
:param hue: a new value for color hue to be set;
floating point values from 0.0 including
to 360.0 not including
:param saturation: a new value for color saturation to be set;
floating point values from 0.0 to 100.0 including
:return: None
"""
raise NotImplementedError()
28 changes: 28 additions & 0 deletions dpl/integrations/base_things/abs_contact_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Include standard modules
# Include 3rd-party modules
# Include DPL modules
from dpl.things.capabilities import HasState, OpenClosed
from .abs_switch import AbsSwitch


class AbsContactSensor(AbsSwitch, OpenClosed, HasState):
"""
The special subtype of a Switch. Adds a new field to the list: a
"has_state" field which can take either "opened" or "closed" value,
where "opened" is equal to 1 and "closed" is equal to 0.
"""
_type = "contact_sensor"

@property
def state(self) -> OpenClosed.States:
"""
Return a current state of the Thing
:return: an instance of self.State
"""
if self.value is None:
return self.States.unknown
elif self.value:
return self.States.opened
else:
return self.States.closed
22 changes: 22 additions & 0 deletions dpl/integrations/base_things/abs_ct_light.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Include standard modules
# Include 3rd-party modules
# Include DPL modules
from dpl.things.capabilities import HasColorTemperature
from .abs_dimmable_light import AbsDimmableLight


class AbsColorTemperatureLight(AbsDimmableLight, HasColorTemperature):
"""
AbsColorTemperatureLight is an abstraction of all lighting devices with
controllable color temperature
"""
_type = "ct_light"

def set_color_temp(self, color_temp: int) -> None:
"""
Sets the new value of color temperature for this Thing
:param color_temp: a new value to be set; integers from 1000 to 100000
:return: None
"""
raise NotImplementedError()
22 changes: 22 additions & 0 deletions dpl/integrations/base_things/abs_dimmable_light.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Include standard modules
# Include 3rd-party modules
# Include DPL modules
from dpl.things.capabilities import HasBrightness
from .abs_light import AbsLight


class AbsDimmableLight(AbsLight, HasBrightness):
"""
AbsOnOff is an abstraction of all dimmable lighting devices, i.e. for all
lighting devices which can change their brightness.
"""
_type = "dimmable_light"

def set_brightness(self, brightness: float) -> None:
"""
Sets the new value of brightness for this Thing
:param brightness: a new value to be set; floats from 0.0 to 100.0
:return: None
"""
raise NotImplementedError()

0 comments on commit 9d9ac1b

Please sign in to comment.