Skip to content

Commit

Permalink
Issue #93: Use THEN to execute (moved device class)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nekmo committed Oct 15, 2018
1 parent ebd5a21 commit cd189a5
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 90 deletions.
6 changes: 5 additions & 1 deletion amazon_dash/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from jsonschema import validate, ValidationError

from amazon_dash.device import Device
from then.configs.base import LoadConfig
from then.configs.components import LoadComponentConfigs
from then.configs.templates import LoadTemplates
Expand Down Expand Up @@ -236,7 +237,10 @@ def read(self):
"""
then = Then(LoadComponentConfigs(self.file, section='actions'))
self.templates = then.templates(LoadTemplates(self.file))
self.devices = LoadConfig(self.file, 'devices')
devices = LoadConfig(self.file, 'devices')
devices = {device['mac']: device for device in devices.data} if isinstance(devices.data, list) else devices
devices = {key: Device(key, value.get('name'), value.get('actions', [])) for key, value in devices.items()}
self.devices = devices
pass
# try:
# data = load(open(self.file), Loader)
Expand Down
71 changes: 71 additions & 0 deletions amazon_dash/device.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from amazon_dash.confirmations import get_confirmation
from amazon_dash.exceptions import InvalidConfig
from amazon_dash.execute import ExecuteCmd, ExecuteUrl, ExecuteHomeAssistant, ExecuteOpenHab, ExecuteIFTTT, logger

EXECUTE_CLS = {
'cmd': ExecuteCmd,
'url': ExecuteUrl,
'homeassistant': ExecuteHomeAssistant,
'openhab': ExecuteOpenHab,
'ifttt': ExecuteIFTTT,
}


class Device(object):
"""Set the execution method for the device
"""
execute_instance = None #: Execute cls instance

def __init__(self, src, name, actions, config=None):
"""
:param str src: Mac address
:param data: device data
"""
config = config or {}

if isinstance(src, Device):
src = src.src
self.src = src.lower()
self.name = name or self.src
self.actions = actions
self.config = config

def execute(self, root_allowed=False):
"""Execute this device
:param bool root_allowed: Only used for ExecuteCmd
:return: None
"""
logger.debug('%s device executed (mac %s)', self.name, self.src)
if not self.execute_instance:
msg = '%s: There is not execution method in device conf.'
logger.warning(msg, self.name)
self.send_confirmation(msg % self.name, False)
return
try:
result = self.execute_instance.execute(root_allowed)
except Exception as e:
self.send_confirmation('Error executing the device {}: {}'.format(self.name, e), False)
raise
else:
result = 'The {} device has been started and is running right now'.format(self.name) \
if result is None else result
result = result or 'The {} device has been executed successfully'.format(self.name)
self.send_confirmation(result)
return result

def send_confirmation(self, message, success=True):
"""Send success or error message to configured confirmation
:param str message: Body message to send
:param bool success: Device executed successfully to personalize message
:return: None
"""
message = message.strip()
if not self.confirmation:
return
try:
self.confirmation.send(message, success)
except Exception as e:
logger.warning('Error sending confirmation on device {}: {}'.format(self.name, e))
90 changes: 3 additions & 87 deletions amazon_dash/listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,16 @@
import threading

from amazon_dash.config import Config
from amazon_dash.confirmations import get_confirmation
from amazon_dash.exceptions import InvalidConfig, InvalidDevice
from amazon_dash.execute import logger, ExecuteCmd, ExecuteUrl, ExecuteHomeAssistant, ExecuteOpenHab, ExecuteIFTTT
from amazon_dash.device import Device
from amazon_dash.exceptions import InvalidDevice
from amazon_dash.execute import logger
from amazon_dash.scan import scan_devices

DEFAULT_DELAY = 10
"""
On seconds. By default, 10 seconds. Minimum time that must pass between pulsations of the Amazon Dash button.
"""

EXECUTE_CLS = {
'cmd': ExecuteCmd,
'url': ExecuteUrl,
'homeassistant': ExecuteHomeAssistant,
'openhab': ExecuteOpenHab,
'ifttt': ExecuteIFTTT,
}
"""
Execute classes registered.
"""
Expand All @@ -31,83 +24,6 @@
"""


class Device(object):
"""Set the execution method for the device
"""
execute_instance = None #: Execute cls instance

def __init__(self, src, data=None, config=None):
"""
:param str src: Mac address
:param data: device data
"""
data = data or {}
config = config or {}

if isinstance(src, Device):
src = src.src
self.src = src.lower()
self.data = data
execs = [cls(self.name, data) for name, cls in EXECUTE_CLS.items() if name in self.data]
if len(execs) > 1:
raise InvalidConfig(
extra_body='There can only be one method of execution on a device. The device is {}. '.format(self.name)
)
elif len(execs):
self.execute_instance = execs[0]
self.execute_instance.validate()
self.confirmation = get_confirmation(src, data, config.get('confirmations', {}))

@property
def name(self):
"""Name on self.data or mac address
:return: name
:rtype: str
"""
return self.data.get('name', self.src)

def execute(self, root_allowed=False):
"""Execute this device
:param bool root_allowed: Only used for ExecuteCmd
:return: None
"""
logger.debug('%s device executed (mac %s)', self.name, self.src)
if not self.execute_instance:
msg = '%s: There is not execution method in device conf.'
logger.warning(msg, self.name)
self.send_confirmation(msg % self.name, False)
return
try:
result = self.execute_instance.execute(root_allowed)
except Exception as e:
self.send_confirmation('Error executing the device {}: {}'.format(self.name, e), False)
raise
else:
result = 'The {} device has been started and is running right now'.format(self.name) \
if result is None else result
result = result or 'The {} device has been executed successfully'.format(self.name)
self.send_confirmation(result)
return result

def send_confirmation(self, message, success=True):
"""Send success or error message to configured confirmation
:param str message: Body message to send
:param bool success: Device executed successfully to personalize message
:return: None
"""
message = message.strip()
if not self.confirmation:
return
try:
self.confirmation.send(message, success)
except Exception as e:
logger.warning('Error sending confirmation on device {}: {}'.format(self.name, e))


class Listener(object):
"""Start listener daemon for execute on button press
"""
Expand Down
2 changes: 1 addition & 1 deletion amazon_dash/tests/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ._compat import patch

from amazon_dash.discovery import BANNED_DEVICES, pkt_text, AMAZON_DEVICES, mac_id_list, discovery_print
from amazon_dash.listener import Device
from amazon_dash.device import Device


class TestDiscovery(unittest.TestCase):
Expand Down
3 changes: 2 additions & 1 deletion amazon_dash/tests/test_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from amazon_dash.confirmations import DisabledConfirmation
from amazon_dash.execute import ExecuteCmd
from amazon_dash.exceptions import InvalidConfig, InvalidDevice
from amazon_dash.listener import Listener, Device, last_execution, logger, test_device
from amazon_dash.listener import Listener, last_execution, logger, test_device
from amazon_dash.device import Device
from amazon_dash.tests.base import ConfigFileMockBase, ExecuteMockBase

dirname = os.path.abspath(os.path.dirname(__file__))
Expand Down

0 comments on commit cd189a5

Please sign in to comment.