diff --git a/homeassistant/actors.py b/homeassistant/actors.py index aa38c550614..74cc0fe6cb2 100644 --- a/homeassistant/actors.py +++ b/homeassistant/actors.py @@ -11,25 +11,18 @@ import os import logging from datetime import datetime, timedelta import re -import webbrowser -import dateutil.parser -from phue import Bridge import requests -from .packages import pychromecast, pykeyboard - -from . import track_state_change -from .util import sanitize_filename -from .observers import ( +import homeassistant as ha +import homeassistant.util as util +from homeassistant.observers import ( STATE_CATEGORY_SUN, SUN_STATE_BELOW_HORIZON, SUN_STATE_ABOVE_HORIZON, STATE_CATEGORY_ALL_DEVICES, DEVICE_STATE_HOME, DEVICE_STATE_NOT_HOME, - STATE_CATEGORY_NEXT_SUN_SETTING, track_time_change) + STATE_CATEGORY_NEXT_SUN_SETTING) LIGHT_TRANSITION_TIME = timedelta(minutes=15) -HUE_MAX_TRANSITION_TIME = 9000 # 900 seconds = 15 minutes - EVENT_DOWNLOAD_FILE = "download_file" EVENT_BROWSE_URL = "browse_url" EVENT_CHROMECAST_YOUTUBE_VIDEO = "chromecast.play_youtube_video" @@ -43,7 +36,9 @@ EVENT_KEYBOARD_MEDIA_PLAY_PAUSE = "keyboard.media_play_pause" def _hue_process_transition_time(transition_seconds): """ Transition time is in 1/10th seconds and cannot exceed MAX_TRANSITION_TIME. """ - return min(HUE_MAX_TRANSITION_TIME, transition_seconds * 10) + + # Max transition time for Hue is 900 seconds/15 minutes + return min(9000, transition_seconds * 10) # pylint: disable=too-few-public-methods @@ -60,18 +55,18 @@ class LightTrigger(object): # Track home coming of each seperate device for category in device_tracker.device_state_categories(): - track_state_change(eventbus, category, + ha.track_state_change(eventbus, category, DEVICE_STATE_NOT_HOME, DEVICE_STATE_HOME, self._handle_device_state_change) # Track when all devices are gone to shut down lights - track_state_change(eventbus, STATE_CATEGORY_ALL_DEVICES, + ha.track_state_change(eventbus, STATE_CATEGORY_ALL_DEVICES, DEVICE_STATE_HOME, DEVICE_STATE_NOT_HOME, self._handle_device_state_change) # Track every time sun rises so we can schedule a time-based # pre-sun set event - track_state_change(eventbus, STATE_CATEGORY_SUN, + ha.track_state_change(eventbus, STATE_CATEGORY_SUN, SUN_STATE_BELOW_HORIZON, SUN_STATE_ABOVE_HORIZON, self._handle_sun_rising) @@ -109,7 +104,7 @@ class LightTrigger(object): return lambda now: self._turn_light_on_before_sunset(light_id) for index, light_id in enumerate(self.light_control.light_ids): - track_time_change(self.eventbus, turn_on(light_id), + ha.track_time_change(self.eventbus, turn_on(light_id), point_in_time=start_point + index * LIGHT_TRANSITION_TIME) @@ -176,7 +171,7 @@ class LightTrigger(object): def _next_sun_setting(self): """ Returns the datetime object representing the next sun setting. """ - return dateutil.parser.parse( + return util.str_to_datetime( self.statemachine.get_state(STATE_CATEGORY_NEXT_SUN_SETTING).state) def _time_for_light_before_sun_set(self): @@ -193,14 +188,21 @@ class HueLightControl(object): """ Class to interface with the Hue light system. """ def __init__(self, host=None): - self.bridge = Bridge(host) + try: + import phue + except ImportError: + logging.getLogger(__name__).error(("HueLightControl:" + "Unable to init due to missing dependency phue.")) + return + + self.bridge = phue.Bridge(host) self.lights = self.bridge.get_light_objects() self.light_ids = [light.light_id for light in self.lights] def is_light_on(self, light_id=None): """ Returns if specified or all light are on. """ - if light_id is None: + if not light_id: return sum([1 for light in self.lights if light.on]) > 0 else: @@ -209,7 +211,7 @@ class HueLightControl(object): def turn_light_on(self, light_id=None, transition_seconds=None): """ Turn the specified or all lights on. """ - if light_id is None: + if not light_id: light_id = self.light_ids command = {'on': True, 'xy': [0.5119, 0.4147], 'bri':164} @@ -223,7 +225,7 @@ class HueLightControl(object): def turn_light_off(self, light_id=None, transition_seconds=None): """ Turn the specified or all lights off. """ - if light_id is None: + if not light_id: light_id = self.light_ids command = {'on': False} @@ -243,7 +245,8 @@ def setup_file_downloader(eventbus, download_path): if not os.path.isdir(download_path): logger.error( - "Download path {} does not exist. File Downloader not active.". + ("FileDownloader:" + "Download path {} does not exist. File Downloader not active."). format(download_path)) return @@ -270,7 +273,7 @@ def setup_file_downloader(eventbus, download_path): filename = "ha_download" # Remove stuff to ruin paths - filename = sanitize_filename(filename) + filename = util.sanitize_filename(filename) path, ext = os.path.splitext(os.path.join(download_path, filename)) @@ -303,11 +306,16 @@ def setup_file_downloader(eventbus, download_path): def setup_webbrowser(eventbus): """ Listen for browse_url events and open the url in the default webbrowser. """ + + import webbrowser + eventbus.listen(EVENT_BROWSE_URL, lambda event: webbrowser.open(event.data['url'])) def setup_chromecast(eventbus, host): """ Listen for chromecast events. """ + from homeassistant.packages import pychromecast + eventbus.listen("start_fireplace", lambda event: pychromecast.play_youtube_video(host, "eyU3bRy2x44")) @@ -319,6 +327,13 @@ def setup_chromecast(eventbus, host): def setup_media_buttons(eventbus): """ Listen for keyboard events. """ + try: + import pykeyboard + except ImportError: + logging.getLogger(__name__).error(("MediaButtons:" + "Unable to setup due to missing dependency PyUserInput.")) + return + keyboard = pykeyboard.PyKeyboard() keyboard.special_key_assignment() diff --git a/homeassistant/httpinterface.py b/homeassistant/httpinterface.py index 015a129017e..041154378a9 100644 --- a/homeassistant/httpinterface.py +++ b/homeassistant/httpinterface.py @@ -31,7 +31,8 @@ import logging from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from urlparse import urlparse, parse_qs -from . import EVENT_START +import homeassistant +import homeassistant.util as util SERVER_PORT = 8123 @@ -64,7 +65,7 @@ class HTTPInterface(threading.Thread): self.server.statemachine = statemachine self.server.api_password = api_password - eventbus.listen(EVENT_START, lambda event: self.start()) + eventbus.listen(homeassistant.EVENT_START, lambda event: self.start()) def run(self): """ Start the HTTP interface. """ @@ -117,7 +118,7 @@ class RequestHandler(BaseHTTPRequestHandler): write("{}{}{}". format(category, state, - last_changed.strftime("%H:%M:%S %d-%m-%Y"))) + util.datetime_to_str(last_changed))) write("") diff --git a/homeassistant/observers.py b/homeassistant/observers.py index 0d912f8a0c7..e26c60d7810 100644 --- a/homeassistant/observers.py +++ b/homeassistant/observers.py @@ -16,9 +16,9 @@ import re import json import requests -import ephem -from . import track_time_change +import homeassistant as ha +import homeassistant.util as util STATE_CATEGORY_SUN = "weather.sun" STATE_CATEGORY_NEXT_SUN_RISING = "weather.next_sun_rising" @@ -45,9 +45,16 @@ KNOWN_DEVICES_FILE = "known_devices.csv" def track_sun(eventbus, statemachine, latitude, longitude): """ Tracks the state of the sun. """ + logger = logging.getLogger(__name__) + + try: + import ephem + except ImportError: + logger.error(("TrackSun:" + "Unable to setup due to missing dependency ephem.")) + return sun = ephem.Sun() # pylint: disable=no-member - logger = logging.getLogger(__name__) def update_sun_state(now): # pylint: disable=unused-argument """ Method to update the current state of the sun and @@ -72,12 +79,12 @@ def track_sun(eventbus, statemachine, latitude, longitude): statemachine.set_state(STATE_CATEGORY_SUN, new_state) statemachine.set_state(STATE_CATEGORY_NEXT_SUN_RISING, - next_rising.isoformat()) + util.datetime_to_str(next_rising)) statemachine.set_state(STATE_CATEGORY_NEXT_SUN_SETTING, - next_setting.isoformat()) + util.datetime_to_str(next_setting)) # +10 seconds to be sure that the change has occured - track_time_change(eventbus, update_sun_state, + ha.track_time_change(eventbus, update_sun_state, point_in_time=next_change + timedelta(seconds=10)) update_sun_state(None) @@ -156,7 +163,7 @@ class DeviceTracker(object): format(KNOWN_DEVICES_FILE)) - track_time_change(eventbus, + ha.track_time_change(eventbus, lambda time: self.update_devices(device_scanner.scan_devices())) def device_state_categories(self): diff --git a/homeassistant/packages/__init__.py b/homeassistant/packages/__init__.py index 021eeacba10..1c236efa17c 100644 --- a/homeassistant/packages/__init__.py +++ b/homeassistant/packages/__init__.py @@ -7,10 +7,5 @@ PyChromecast ------------ https://github.com/balloob/pychromecast -PyKeyboard ----------- -Forked from https://github.com/SavinaRoja/PyUserInput -Patched with some code to get it working on OS X: -https://github.com/balloob/PyUserInput """ diff --git a/homeassistant/packages/pykeyboard/__init__.py b/homeassistant/packages/pykeyboard/__init__.py deleted file mode 100644 index 2de415d8a60..00000000000 --- a/homeassistant/packages/pykeyboard/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -#Copyright 2013 Paul Barton -# -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation, either version 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with this program. If not, see . - -""" -The goal of PyMouse is to have a cross-platform way to control the mouse. -PyMouse should work on Windows, Mac and any Unix that has xlib. - -PyKeyboard is a part of PyUserInput, along with PyMouse, for more information -about this project, see: -http://github.com/SavinaRoja/PyUserInput -""" - -import sys - -if sys.platform.startswith('java'): - from .java_ import PyKeyboard - -elif sys.platform == 'darwin': - from .mac import PyKeyboard, PyKeyboardEvent - -elif sys.platform == 'win32': - from .windows import PyKeyboard, PyKeyboardEvent - -else: - from .x11 import PyKeyboard, PyKeyboardEvent diff --git a/homeassistant/packages/pykeyboard/base.py b/homeassistant/packages/pykeyboard/base.py deleted file mode 100644 index 8a475efad9a..00000000000 --- a/homeassistant/packages/pykeyboard/base.py +++ /dev/null @@ -1,102 +0,0 @@ -#Copyright 2013 Paul Barton -# -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation, either version 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with this program. If not, see . - -""" -As the base file, this provides a rough operational model along with the -framework to be extended by each platform. -""" - -import time -from threading import Thread - -class PyKeyboardMeta(object): - """ - The base class for PyKeyboard. Represents basic operational model. - """ - - def press_key(self, character=''): - """Press a given character key.""" - raise NotImplementedError - - def release_key(self, character=''): - """Release a given character key.""" - raise NotImplementedError - - def tap_key(self, character='', n=1, interval=0): - """Press and release a given character key n times.""" - for i in xrange(n): - self.press_key(character) - self.release_key(character) - time.sleep(interval) - - def type_string(self, char_string, interval=0): - """A convenience method for typing longer strings of characters.""" - for i in char_string: - time.sleep(interval) - self.tap_key(i) - - def special_key_assignment(self): - """Makes special keys more accessible.""" - raise NotImplementedError - - def lookup_character_value(self, character): - """ - If necessary, lookup a valid API value for the key press from the - character. - """ - raise NotImplementedError - - def is_char_shifted(self, character): - """Returns True if the key character is uppercase or shifted.""" - if character.isupper(): - return True - if character in '<>?:"{}|~!@#$%^&*()_+': - return True - return False - -class PyKeyboardEventMeta(Thread): - """ - The base class for PyKeyboard. Represents basic operational model. - """ - def __init__(self, capture=False): - Thread.__init__(self) - self.daemon = True - self.capture = capture - self.state = True - - def run(self): - self.state = True - - def stop(self): - self.state = False - - def handler(self): - raise NotImplementedError - - def key_press(self, key): - """Subclass this method with your key press event handler.""" - pass - - def key_release(self, key): - """Subclass this method with your key release event handler.""" - pass - - def escape_code(self): - """ - Defines a means to signal a stop to listening. Subclass this with your - escape behavior. - """ - escape = None - return escape diff --git a/homeassistant/packages/pykeyboard/java_.py b/homeassistant/packages/pykeyboard/java_.py deleted file mode 100644 index be3b9576ce6..00000000000 --- a/homeassistant/packages/pykeyboard/java_.py +++ /dev/null @@ -1,14 +0,0 @@ -#Copyright 2013 Paul Barton -# -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation, either version 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with this program. If not, see . diff --git a/homeassistant/packages/pykeyboard/mac.py b/homeassistant/packages/pykeyboard/mac.py deleted file mode 100644 index 8b378657fea..00000000000 --- a/homeassistant/packages/pykeyboard/mac.py +++ /dev/null @@ -1,201 +0,0 @@ -#Copyright 2013 Paul Barton -# -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation, either version 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with this program. If not, see . - -import time -from Quartz import * -from AppKit import NSEvent -from .base import PyKeyboardMeta, PyKeyboardEventMeta - -# Taken from events.h -# /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h -character_translate_table = { - 'a': 0x00, - 's': 0x01, - 'd': 0x02, - 'f': 0x03, - 'h': 0x04, - 'g': 0x05, - 'z': 0x06, - 'x': 0x07, - 'c': 0x08, - 'v': 0x09, - 'b': 0x0b, - 'q': 0x0c, - 'w': 0x0d, - 'e': 0x0e, - 'r': 0x0f, - 'y': 0x10, - 't': 0x11, - '1': 0x12, - '2': 0x13, - '3': 0x14, - '4': 0x15, - '6': 0x16, - '5': 0x17, - '=': 0x18, - '9': 0x19, - '7': 0x1a, - '-': 0x1b, - '8': 0x1c, - '0': 0x1d, - ']': 0x1e, - 'o': 0x1f, - 'u': 0x20, - '[': 0x21, - 'i': 0x22, - 'p': 0x23, - 'l': 0x25, - 'j': 0x26, - '\'': 0x27, - 'k': 0x28, - ';': 0x29, - '\\': 0x2a, - ',': 0x2b, - '/': 0x2c, - 'n': 0x2d, - 'm': 0x2e, - '.': 0x2f, - '`': 0x32, - ' ': 0x31, - '\r': 0x24, - '\t': 0x30, - 'shift': 0x38 -} - -# Taken from ev_keymap.h -# http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-86.1/IOHIDSystem/IOKit/hidsystem/ev_keymap.h -special_key_translate_table = { - 'KEYTYPE_SOUND_UP': 0, - 'KEYTYPE_SOUND_DOWN': 1, - 'KEYTYPE_BRIGHTNESS_UP': 2, - 'KEYTYPE_BRIGHTNESS_DOWN': 3, - 'KEYTYPE_CAPS_LOCK': 4, - 'KEYTYPE_HELP': 5, - 'POWER_KEY': 6, - 'KEYTYPE_MUTE': 7, - 'UP_ARROW_KEY': 8, - 'DOWN_ARROW_KEY': 9, - 'KEYTYPE_NUM_LOCK': 10, - 'KEYTYPE_CONTRAST_UP': 11, - 'KEYTYPE_CONTRAST_DOWN': 12, - 'KEYTYPE_LAUNCH_PANEL': 13, - 'KEYTYPE_EJECT': 14, - 'KEYTYPE_VIDMIRROR': 15, - 'KEYTYPE_PLAY': 16, - 'KEYTYPE_NEXT': 17, - 'KEYTYPE_PREVIOUS': 18, - 'KEYTYPE_FAST': 19, - 'KEYTYPE_REWIND': 20, - 'KEYTYPE_ILLUMINATION_UP': 21, - 'KEYTYPE_ILLUMINATION_DOWN': 22, - 'KEYTYPE_ILLUMINATION_TOGGLE': 23 -} - -class PyKeyboard(PyKeyboardMeta): - def press_key(self, key): - if key in special_key_translate_table: - self._press_special_key(key, True) - else: - self._press_normal_key(key, True) - - def release_key(self, key): - if key in special_key_translate_table: - self._press_special_key(key, False) - else: - self._press_normal_key(key, False) - - def special_key_assignment(self): - self.volume_mute_key = 'KEYTYPE_MUTE' - self.volume_down_key = 'KEYTYPE_SOUND_DOWN' - self.volume_up_key = 'KEYTYPE_SOUND_UP' - self.media_play_pause_key = 'KEYTYPE_PLAY' - - # Doesn't work :( - # self.media_next_track_key = 'KEYTYPE_NEXT' - # self.media_prev_track_key = 'KEYTYPE_PREVIOUS' - - def _press_normal_key(self, key, down): - try: - if self.is_char_shifted(key): - key_code = character_translate_table[key.lower()] - - event = CGEventCreateKeyboardEvent(None, - character_translate_table['shift'], down) - CGEventPost(kCGHIDEventTap, event) - # Tiny sleep to let OS X catch up on us pressing shift - time.sleep(.01) - - else: - key_code = character_translate_table[key] - - - event = CGEventCreateKeyboardEvent(None, key_code, down) - CGEventPost(kCGHIDEventTap, event) - - - except KeyError: - raise RuntimeError("Key {} not implemented.".format(key)) - - def _press_special_key(self, key, down): - """ Helper method for special keys. - - Source: http://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac - """ - key_code = special_key_translate_table[key] - - ev = NSEvent.otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_( - NSSystemDefined, # type - (0,0), # location - 0xa00 if down else 0xb00, # flags - 0, # timestamp - 0, # window - 0, # ctx - 8, # subtype - (key_code << 16) | ((0xa if down else 0xb) << 8), # data1 - -1 # data2 - ) - - CGEventPost(0, ev.CGEvent()) - -class PyKeyboardEvent(PyKeyboardEventMeta): - def run(self): - tap = CGEventTapCreate( - kCGSessionEventTap, - kCGHeadInsertEventTap, - kCGEventTapOptionDefault, - CGEventMaskBit(kCGEventKeyDown) | - CGEventMaskBit(kCGEventKeyUp), - self.handler, - None) - - loopsource = CFMachPortCreateRunLoopSource(None, tap, 0) - loop = CFRunLoopGetCurrent() - CFRunLoopAddSource(loop, loopsource, kCFRunLoopDefaultMode) - CGEventTapEnable(tap, True) - - while self.state: - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 5, False) - - def handler(self, proxy, type, event, refcon): - key = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) - if type == kCGEventKeyDown: - self.key_press(key) - elif type == kCGEventKeyUp: - self.key_release(key) - - if self.capture: - CGEventSetType(event, kCGEventNull) - - return event diff --git a/homeassistant/packages/pykeyboard/mir.py b/homeassistant/packages/pykeyboard/mir.py deleted file mode 100644 index be3b9576ce6..00000000000 --- a/homeassistant/packages/pykeyboard/mir.py +++ /dev/null @@ -1,14 +0,0 @@ -#Copyright 2013 Paul Barton -# -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation, either version 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with this program. If not, see . diff --git a/homeassistant/packages/pykeyboard/wayland.py b/homeassistant/packages/pykeyboard/wayland.py deleted file mode 100644 index be3b9576ce6..00000000000 --- a/homeassistant/packages/pykeyboard/wayland.py +++ /dev/null @@ -1,14 +0,0 @@ -#Copyright 2013 Paul Barton -# -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation, either version 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with this program. If not, see . diff --git a/homeassistant/packages/pykeyboard/windows.py b/homeassistant/packages/pykeyboard/windows.py deleted file mode 100644 index fddbd8ad110..00000000000 --- a/homeassistant/packages/pykeyboard/windows.py +++ /dev/null @@ -1,318 +0,0 @@ -#Copyright 2013 Paul Barton -# -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation, either version 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with this program. If not, see . - -from ctypes import * -import win32api -from win32con import * -import pythoncom - -from .base import PyKeyboardMeta, PyKeyboardEventMeta - -import time - -class SupportError(Exception): - """For keys not supported on this system""" - def __init__(self, value): - self.value = value - - def __str__(self): - return('The {0} key is not supported in Windows'.format(self.value)) - -class PyKeyboard(PyKeyboardMeta): - """ - The PyKeyboard implementation for Windows systems. This allows one to - simulate keyboard input. - """ - def __init__(self): - PyKeyboardMeta.__init__(self) - self.special_key_assignment() - - def press_key(self, character=''): - """ - Press a given character key. - """ - try: - shifted = self.is_char_shifted(character) - except AttributeError: - win32api.keybd_event(character, 0, 0, 0) - else: - if shifted: - win32api.keybd_event(self.shift_key, 0, 0, 0) - char_vk = win32api.VkKeyScan(character) - win32api.keybd_event(char_vk, 0, 0, 0) - - def release_key(self, character=''): - """ - Release a given character key. - """ - try: - shifted = self.is_char_shifted(character) - except AttributeError: - win32api.keybd_event(character, 0, KEYEVENTF_KEYUP, 0) - else: - if shifted: - win32api.keybd_event(self.shift_key, 0, KEYEVENTF_KEYUP, 0) - char_vk = win32api.VkKeyScan(character) - win32api.keybd_event(char_vk, 0, KEYEVENTF_KEYUP, 0) - - def special_key_assignment(self): - """ - Special Key assignment for windows - """ - #As defined by Microsoft, refer to: - #http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx - self.backspace_key = VK_BACK - self.tab_key = VK_TAB - self.clear_key = VK_CLEAR - self.return_key = VK_RETURN - self.enter_key = self.return_key # Because many keyboards call it "Enter" - self.shift_key = VK_SHIFT - self.shift_l_key = VK_LSHIFT - self.shift_r_key = VK_RSHIFT - self.control_key = VK_CONTROL - self.control_l_key = VK_LCONTROL - self.control_r_key = VK_RCONTROL - #Windows uses "menu" to refer to Alt... - self.menu_key = VK_MENU - self.alt_l_key = VK_LMENU - self.alt_r_key = VK_RMENU - self.alt_key = self.alt_l_key - self.pause_key = VK_PAUSE - self.caps_lock_key = VK_CAPITAL - self.capital_key = self.caps_lock_key - self.num_lock_key = VK_NUMLOCK - self.scroll_lock_key = VK_SCROLL - #Windows Language Keys, - self.kana_key = VK_KANA - self.hangeul_key = VK_HANGEUL # old name - should be here for compatibility - self.hangul_key = VK_HANGUL - self.junjua_key = VK_JUNJA - self.final_key = VK_FINAL - self.hanja_key = VK_HANJA - self.kanji_key = VK_KANJI - self.convert_key = VK_CONVERT - self.nonconvert_key = VK_NONCONVERT - self.accept_key = VK_ACCEPT - self.modechange_key = VK_MODECHANGE - #More Keys - self.escape_key = VK_ESCAPE - self.space_key = VK_SPACE - self.prior_key = VK_PRIOR - self.next_key = VK_NEXT - self.page_up_key = self.prior_key - self.page_down_key = self.next_key - self.home_key = VK_HOME - self.up_key = VK_UP - self.down_key = VK_DOWN - self.left_key = VK_LEFT - self.right_key = VK_RIGHT - self.end_key = VK_END - self.select_key = VK_SELECT - self.print_key = VK_PRINT - self.snapshot_key = VK_SNAPSHOT - self.print_screen_key = self.snapshot_key - self.execute_key = VK_EXECUTE - self.insert_key = VK_INSERT - self.delete_key = VK_DELETE - self.help_key = VK_HELP - self.windows_l_key = VK_LWIN - self.super_l_key = self.windows_l_key - self.windows_r_key = VK_RWIN - self.super_r_key = self.windows_r_key - self.apps_key = VK_APPS - #Numpad - self.keypad_keys = {'Space': None, - 'Tab': None, - 'Enter': None, # Needs Fixing - 'F1': None, - 'F2': None, - 'F3': None, - 'F4': None, - 'Home': VK_NUMPAD7, - 'Left': VK_NUMPAD4, - 'Up': VK_NUMPAD8, - 'Right': VK_NUMPAD6, - 'Down': VK_NUMPAD2, - 'Prior': None, - 'Page_Up': VK_NUMPAD9, - 'Next': None, - 'Page_Down': VK_NUMPAD3, - 'End': VK_NUMPAD1, - 'Begin': None, - 'Insert': VK_NUMPAD0, - 'Delete': VK_DECIMAL, - 'Equal': None, # Needs Fixing - 'Multiply': VK_MULTIPLY, - 'Add': VK_ADD, - 'Separator': VK_SEPARATOR, - 'Subtract': VK_SUBTRACT, - 'Decimal': VK_DECIMAL, - 'Divide': VK_DIVIDE, - 0: VK_NUMPAD0, - 1: VK_NUMPAD1, - 2: VK_NUMPAD2, - 3: VK_NUMPAD3, - 4: VK_NUMPAD4, - 5: VK_NUMPAD5, - 6: VK_NUMPAD6, - 7: VK_NUMPAD7, - 8: VK_NUMPAD8, - 9: VK_NUMPAD9} - self.numpad_keys = self.keypad_keys - #FKeys - self.function_keys = [None, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6, - VK_F7, VK_F8, VK_F9, VK_F10, VK_F11, VK_F12, - VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18, - VK_F19, VK_F20, VK_F21, VK_F22, VK_F23, VK_F24, - None, None, None, None, None, None, None, None, - None, None, None] #Up to 36 as in x11 - #Miscellaneous - self.cancel_key = VK_CANCEL - self.break_key = self.cancel_key - self.mode_switch_key = VK_MODECHANGE - self.browser_back_key = VK_BROWSER_BACK - self.browser_forward_key = VK_BROWSER_FORWARD - self.processkey_key = VK_PROCESSKEY - self.attn_key = VK_ATTN - self.crsel_key = VK_CRSEL - self.exsel_key = VK_EXSEL - self.ereof_key = VK_EREOF - self.play_key = VK_PLAY - self.zoom_key = VK_ZOOM - self.noname_key = VK_NONAME - self.pa1_key = VK_PA1 - self.oem_clear_key = VK_OEM_CLEAR - self.volume_mute_key = VK_VOLUME_MUTE - self.volume_down_key = VK_VOLUME_DOWN - self.volume_up_key = VK_VOLUME_UP - self.media_next_track_key = VK_MEDIA_NEXT_TRACK - self.media_prev_track_key = VK_MEDIA_PREV_TRACK - self.media_play_pause_key = VK_MEDIA_PLAY_PAUSE - self.begin_key = self.home_key - #LKeys - Unsupported - self.l_keys = [None] * 11 - #RKeys - Unsupported - self.r_keys = [None] * 16 - - #Other unsupported Keys from X11 - self.linefeed_key = None - self.find_key = None - self.meta_l_key = None - self.meta_r_key = None - self.sys_req_key = None - self.hyper_l_key = None - self.hyper_r_key = None - self.undo_key = None - self.redo_key = None - self.script_switch_key = None - -class PyKeyboardEvent(PyKeyboardEventMeta): - """ - The PyKeyboardEvent implementation for Windows Systems. This allows one - to listen for keyboard input. - """ - def __init__(self): - import pyHook - - PyKeyboardEventMeta.__init__(self) - self.hm = pyHook.HookManager() - self.shift_state = 0 # 0 is off, 1 is on - self.alt_state = 0 # 0 is off, 2 is on - - def run(self): - """Begin listening for keyboard input events.""" - self.state = True - self.hm.KeyAll = self.handler - self.hm.HookKeyboard() - while self.state: - time.sleep(0.01) - pythoncom.PumpWaitingMessages() - - def stop(self): - """Stop listening for keyboard input events.""" - self.hm.UnhookKeyboard() - self.state = False - - def handler(self, reply): - """Upper level handler of keyboard events.""" - if reply.Message == pyHook.HookConstants.WM_KEYDOWN: - self._key_press(reply) - elif reply.Message == pyHook.HookConstants.WM_KEYUP: - self._key_release(reply) - elif reply.Message == pyHook.HookConstants.WM_SYSKEYDOWN: - self._key_press(reply) - elif reply.Message == pyHook.HookConstants.WM.SYSKEYUP: - self._key_release(reply) - else: - print('Keyboard event message unhandled: {0}'.format(reply.Message)) - return not self.capture - - def _key_press(self, event): - if self.escape_code(event): #Quit if this returns True - self.stop() - if event.GetKey() in ['Shift', 'Lshift', 'Rshift', 'Capital']: - self.toggle_shift_state() - if event.GetKey() in ['Menu', 'Lmenu', 'Rmenu']: - self.toggle_alt_state() - #print('Key Pressed!') - #print('GetKey: {0}'.format(event.GetKey())) # Name of the virtual keycode, str - #print('IsAlt: {0}'.format(event.IsAlt())) # Was the alt key depressed?, bool - #print('IsExtended: {0}'.format(event.IsExtended())) # Is this an extended key?, bool - #print('IsInjected: {0}'.format(event.IsInjected())) # Was this event generated programmatically?, bool - #print('IsTransition: {0}'.format(event.IsTransition())) #Is this a transition from up to down or vice versa?, bool - #print('ASCII: {0}'.format(event.Ascii)) # ASCII value, if one exists, str - #print('KeyID: {0}'.format(event.KeyID)) # Virtual key code, int - #print('ScanCode: {0}'.format(event.ScanCode)) # Scan code, int - - def _key_release(self, event): - if event.GetKey() in ['Shift', 'Lshift', 'Rshift', 'Capital']: - self.toggle_shift_state() - if event.GetKey() in ['Menu', 'Lmenu', 'Rmenu']: - self.toggle_alt_state() - self.key_release() - #print('Key Released!') - #print('GetKey: {0}'.format(event.GetKey())) # Name of the virtual keycode, str - #print('IsAlt: {0}'.format(event.IsAlt())) # Was the alt key depressed?, bool - #print('IsExtended: {0}'.format(event.IsExtended())) # Is this an extended key?, bool - #print('IsInjected: {0}'.format(event.IsInjected())) # Was this event generated programmatically?, bool - #print('IsTransition: {0}'.format(event.IsTransition())) #Is this a transition from up to down or vice versa?, bool - #print('ASCII: {0}'.format(event.Ascii)) # ASCII value, if one exists, str - #print('KeyID: {0}'.format(event.KeyID)) # Virtual key code, int - #print('ScanCode: {0}'.format(event.ScanCode)) # Scan code, int - - def escape_code(self, event): - if event.KeyID == VK_ESCAPE: - return True - return False - - def toggle_shift_state(self): - '''Does toggling for the shift state.''' - if self.shift_state == 0: - self.shift_state = 1 - elif self.shift_state == 1: - self.shift_state = 0 - else: - return False - return True - - def toggle_alt_state(self): - '''Does toggling for the alt state.''' - if self.alt_state == 0: - self.alt_state = 2 - elif self.alt_state == 2: - self.alt_state = 0 - else: - return False - return True \ No newline at end of file diff --git a/homeassistant/packages/pykeyboard/x11.py b/homeassistant/packages/pykeyboard/x11.py deleted file mode 100644 index c19149f20fb..00000000000 --- a/homeassistant/packages/pykeyboard/x11.py +++ /dev/null @@ -1,363 +0,0 @@ -#Copyright 2013 Paul Barton -# -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation, either version 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -#along with this program. If not, see . - -from Xlib.display import Display -from Xlib import X -from Xlib.ext.xtest import fake_input -from Xlib.XK import string_to_keysym, keysym_to_string -from Xlib.ext import record -from Xlib.protocol import rq - -from .base import PyKeyboardMeta, PyKeyboardEventMeta - -import time - -special_X_keysyms = { - ' ': "space", - '\t': "Tab", - '\n': "Return", # for some reason this needs to be cr, not lf - '\r': "Return", - '\e': "Escape", - '!': "exclam", - '#': "numbersign", - '%': "percent", - '$': "dollar", - '&': "ampersand", - '"': "quotedbl", - '\'': "apostrophe", - '(': "parenleft", - ')': "parenright", - '*': "asterisk", - '=': "equal", - '+': "plus", - ',': "comma", - '-': "minus", - '.': "period", - '/': "slash", - ':': "colon", - ';': "semicolon", - '<': "less", - '>': "greater", - '?': "question", - '@': "at", - '[': "bracketleft", - ']': "bracketright", - '\\': "backslash", - '^': "asciicircum", - '_': "underscore", - '`': "grave", - '{': "braceleft", - '|': "bar", - '}': "braceright", - '~': "asciitilde" - } - -class PyKeyboard(PyKeyboardMeta): - """ - The PyKeyboard implementation for X11 systems (mostly linux). This - allows one to simulate keyboard input. - """ - def __init__(self, display=None): - PyKeyboardMeta.__init__(self) - self.display = Display(display) - self.display2 = Display(display) - self.special_key_assignment() - - def press_key(self, character=''): - """ - Press a given character key. Also works with character keycodes as - integers, but not keysyms. - """ - try: # Detect uppercase or shifted character - shifted = self.is_char_shifted(character) - except AttributeError: # Handle the case of integer keycode argument - fake_input(self.display, X.KeyPress, character) - self.display.sync() - else: - if shifted: - fake_input(self.display, X.KeyPress, self.shift_key) - char_val = self.lookup_character_value(character) - fake_input(self.display, X.KeyPress, char_val) - self.display.sync() - - def release_key(self, character=''): - """ - Release a given character key. Also works with character keycodes as - integers, but not keysyms. - """ - try: # Detect uppercase or shifted character - shifted = self.is_char_shifted(character) - except AttributeError: # Handle the case of integer keycode argument - fake_input(self.display, X.KeyRelease, character) - self.display.sync() - else: - if shifted: - fake_input(self.display, X.KeyRelease, self.shift_key) - char_val = self.lookup_character_value(character) - fake_input(self.display, X.KeyRelease, char_val) - self.display.sync() - - def special_key_assignment(self): - """ - Determines the keycodes for common special keys on the keyboard. These - are integer values and can be passed to the other key methods. - Generally speaking, these are non-printable codes. - """ - #This set of keys compiled using the X11 keysymdef.h file as reference - #They comprise a relatively universal set of keys, though there may be - #exceptions which may come up for other OSes and vendors. Countless - #special cases exist which are not handled here, but may be extended. - #TTY Function Keys - self.backspace_key = self.lookup_character_value('BackSpace') - self.tab_key = self.lookup_character_value('Tab') - self.linefeed_key = self.lookup_character_value('Linefeed') - self.clear_key = self.lookup_character_value('Clear') - self.return_key = self.lookup_character_value('Return') - self.enter_key = self.return_key # Because many keyboards call it "Enter" - self.pause_key = self.lookup_character_value('Pause') - self.scroll_lock_key = self.lookup_character_value('Scroll_Lock') - self.sys_req_key = self.lookup_character_value('Sys_Req') - self.escape_key = self.lookup_character_value('Escape') - self.delete_key = self.lookup_character_value('Delete') - #Modifier Keys - self.shift_l_key = self.lookup_character_value('Shift_L') - self.shift_r_key = self.lookup_character_value('Shift_R') - self.shift_key = self.shift_l_key # Default Shift is left Shift - self.alt_l_key = self.lookup_character_value('Alt_L') - self.alt_r_key = self.lookup_character_value('Alt_R') - self.alt_key = self.alt_l_key # Default Alt is left Alt - self.control_l_key = self.lookup_character_value('Control_L') - self.control_r_key = self.lookup_character_value('Control_R') - self.control_key = self.control_l_key # Default Ctrl is left Ctrl - self.caps_lock_key = self.lookup_character_value('Caps_Lock') - self.capital_key = self.caps_lock_key # Some may know it as Capital - self.shift_lock_key = self.lookup_character_value('Shift_Lock') - self.meta_l_key = self.lookup_character_value('Meta_L') - self.meta_r_key = self.lookup_character_value('Meta_R') - self.super_l_key = self.lookup_character_value('Super_L') - self.windows_l_key = self.super_l_key # Cross-support; also it's printed there - self.super_r_key = self.lookup_character_value('Super_R') - self.windows_r_key = self.super_r_key # Cross-support; also it's printed there - self.hyper_l_key = self.lookup_character_value('Hyper_L') - self.hyper_r_key = self.lookup_character_value('Hyper_R') - #Cursor Control and Motion - self.home_key = self.lookup_character_value('Home') - self.up_key = self.lookup_character_value('Up') - self.down_key = self.lookup_character_value('Down') - self.left_key = self.lookup_character_value('Left') - self.right_key = self.lookup_character_value('Right') - self.end_key = self.lookup_character_value('End') - self.begin_key = self.lookup_character_value('Begin') - self.page_up_key = self.lookup_character_value('Page_Up') - self.page_down_key = self.lookup_character_value('Page_Down') - self.prior_key = self.lookup_character_value('Prior') - self.next_key = self.lookup_character_value('Next') - #Misc Functions - self.select_key = self.lookup_character_value('Select') - self.print_key = self.lookup_character_value('Print') - self.print_screen_key = self.print_key # Seems to be the same thing - self.snapshot_key = self.print_key # Another name for printscreen - self.execute_key = self.lookup_character_value('Execute') - self.insert_key = self.lookup_character_value('Insert') - self.undo_key = self.lookup_character_value('Undo') - self.redo_key = self.lookup_character_value('Redo') - self.menu_key = self.lookup_character_value('Menu') - self.apps_key = self.menu_key # Windows... - self.find_key = self.lookup_character_value('Find') - self.cancel_key = self.lookup_character_value('Cancel') - self.help_key = self.lookup_character_value('Help') - self.break_key = self.lookup_character_value('Break') - self.mode_switch_key = self.lookup_character_value('Mode_switch') - self.script_switch_key = self.lookup_character_value('script_switch') - self.num_lock_key = self.lookup_character_value('Num_Lock') - #Keypad Keys: Dictionary structure - keypad = ['Space', 'Tab', 'Enter', 'F1', 'F2', 'F3', 'F4', 'Home', - 'Left', 'Up', 'Right', 'Down', 'Prior', 'Page_Up', 'Next', - 'Page_Down', 'End', 'Begin', 'Insert', 'Delete', 'Equal', - 'Multiply', 'Add', 'Separator', 'Subtract', 'Decimal', - 'Divide', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - self.keypad_keys = {k: self.lookup_character_value('KP_'+str(k)) for k in keypad} - self.numpad_keys = self.keypad_keys - #Function Keys/ Auxilliary Keys - #FKeys - self.function_keys = [None] + [self.lookup_character_value('F'+str(i)) for i in xrange(1,36)] - #LKeys - self.l_keys = [None] + [self.lookup_character_value('L'+str(i)) for i in xrange(1,11)] - #RKeys - self.r_keys = [None] + [self.lookup_character_value('R'+str(i)) for i in xrange(1,16)] - - #Unsupported keys from windows - self.kana_key = None - self.hangeul_key = None # old name - should be here for compatibility - self.hangul_key = None - self.junjua_key = None - self.final_key = None - self.hanja_key = None - self.kanji_key = None - self.convert_key = None - self.nonconvert_key = None - self.accept_key = None - self.modechange_key = None - self.sleep_key = None - - def lookup_character_value(self, character): - """ - Looks up the keysym for the character then returns the keycode mapping - for that keysym. - """ - ch_keysym = string_to_keysym(character) - if ch_keysym == 0: - ch_keysym = string_to_keysym(special_X_keysyms[character]) - return self.display.keysym_to_keycode(ch_keysym) - -class PyKeyboardEvent(PyKeyboardEventMeta): - """ - The PyKeyboardEvent implementation for X11 systems (mostly linux). This - allows one to listen for keyboard input. - """ - def __init__(self, display=None): - PyKeyboardEventMeta.__init__(self) - self.display = Display(display) - self.display2 = Display(display) - self.ctx = self.display2.record_create_context( - 0, - [record.AllClients], - [{ - 'core_requests': (0, 0), - 'core_replies': (0, 0), - 'ext_requests': (0, 0, 0, 0), - 'ext_replies': (0, 0, 0, 0), - 'delivered_events': (0, 0), - 'device_events': (X.KeyPress, X.KeyRelease), - 'errors': (0, 0), - 'client_started': False, - 'client_died': False, - }]) - self.shift_state = 0 # 0 is off, 1 is on - self.alt_state = 0 # 0 is off, 2 is on - self.mod_keycodes = self.get_mod_keycodes() - - def run(self): - """Begin listening for keyboard input events.""" - self.state = True - if self.capture: - self.display2.screen().root.grab_keyboard(True, X.KeyPressMask | X.KeyReleaseMask, X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime) - - self.display2.record_enable_context(self.ctx, self.handler) - self.display2.record_free_context(self.ctx) - - def stop(self): - """Stop listening for keyboard input events.""" - self.state = False - self.display.record_disable_context(self.ctx) - self.display.ungrab_keyboard(X.CurrentTime) - self.display.flush() - self.display2.record_disable_context(self.ctx) - self.display2.ungrab_keyboard(X.CurrentTime) - self.display2.flush() - - def handler(self, reply): - """Upper level handler of keyboard events.""" - data = reply.data - while len(data): - event, data = rq.EventField(None).parse_binary_value(data, self.display.display, None, None) - if event.type == X.KeyPress: - if self.escape_code(event): # Quit if this returns True - self.stop() - else: - self._key_press(event.detail) - elif event.type == X.KeyRelease: - self._key_release(event.detail) - else: - print('WTF: {0}'.format(event.type)) - - def _key_press(self, keycode): - """A key has been pressed, do stuff.""" - #Alter modification states - if keycode in self.mod_keycodes['Shift'] or keycode in self.mod_keycodes['Lock']: - self.toggle_shift_state() - elif keycode in self.mod_keycodes['Alt']: - self.toggle_alt_state() - else: - self.key_press(keycode) - - def _key_release(self, keycode): - """A key has been released, do stuff.""" - #Alter modification states - if keycode in self.mod_keycodes['Shift']: - self.toggle_shift_state() - elif keycode in self.mod_keycodes['Alt']: - self.toggle_alt_state() - else: - self.key_release(keycode) - - def escape_code(self, event): - if event.detail == self.lookup_character_value('Escape'): - return True - return False - - def lookup_char_from_keycode(self, keycode): - keysym =self.display.keycode_to_keysym(keycode, self.shift_state + self.alt_state) - if keysym: - char = self.display.lookup_string(keysym) - return char - else: - return None - - def get_mod_keycodes(self): - """ - Detects keycodes for modifiers and parses them into a dictionary - for easy access. - """ - modifier_mapping = self.display.get_modifier_mapping() - modifier_dict = {} - nti = [('Shift', X.ShiftMapIndex), - ('Control', X.ControlMapIndex), ('Mod1', X.Mod1MapIndex), - ('Alt', X.Mod1MapIndex), ('Mod2', X.Mod2MapIndex), - ('Mod3', X.Mod3MapIndex), ('Mod4', X.Mod4MapIndex), - ('Mod5', X.Mod5MapIndex), ('Lock', X.LockMapIndex)] - for n, i in nti: - modifier_dict[n] = list(modifier_mapping[i]) - return modifier_dict - - def lookup_character_value(self, character): - """ - Looks up the keysym for the character then returns the keycode mapping - for that keysym. - """ - ch_keysym = string_to_keysym(character) - if ch_keysym == 0: - ch_keysym = string_to_keysym(special_X_keysyms[character]) - return self.display.keysym_to_keycode(ch_keysym) - - def toggle_shift_state(self): - '''Does toggling for the shift state.''' - if self.shift_state == 0: - self.shift_state = 1 - elif self.shift_state == 1: - self.shift_state = 0 - else: - return False - return True - - def toggle_alt_state(self): - '''Does toggling for the alt state.''' - if self.alt_state == 0: - self.alt_state = 2 - elif self.alt_state == 2: - self.alt_state = 0 - else: - return False - return True diff --git a/homeassistant/test.py b/homeassistant/test.py index 197c4796db8..c0a7426a8fe 100644 --- a/homeassistant/test.py +++ b/homeassistant/test.py @@ -11,13 +11,13 @@ import time import requests -from . import EventBus, StateMachine, EVENT_START -from .httpinterface import HTTPInterface, SERVER_PORT +import homeassistant as ha +import homeassistant.httpinterface as httpinterface API_PASSWORD = "test1234" -HTTP_BASE_URL = "http://127.0.0.1:{}".format(SERVER_PORT) +HTTP_BASE_URL = "http://127.0.0.1:{}".format(httpinterface.SERVER_PORT) # pylint: disable=too-many-public-methods class TestHTTPInterface(unittest.TestCase): @@ -30,11 +30,12 @@ class TestHTTPInterface(unittest.TestCase): if not TestHTTPInterface.HTTP_init: TestHTTPInterface.HTTP_init = True - HTTPInterface(self.eventbus, self.statemachine, API_PASSWORD) + httpinterface.HTTPInterface(self.eventbus, self.statemachine, + API_PASSWORD) self.statemachine.set_state("test", "INIT_STATE") - self.eventbus.fire(EVENT_START) + self.eventbus.fire(ha.EVENT_START) # Give objects time to startup time.sleep(1) @@ -42,8 +43,8 @@ class TestHTTPInterface(unittest.TestCase): @classmethod def setUpClass(cls): # pylint: disable=invalid-name """ things to be run when tests are started. """ - cls.eventbus = EventBus() - cls.statemachine = StateMachine(cls.eventbus) + cls.eventbus = ha.EventBus() + cls.statemachine = ha.StateMachine(cls.eventbus) def test_debug_interface(self): """ Test if we can login by comparing not logged in screen to diff --git a/homeassistant/util.py b/homeassistant/util.py index 7b1e7514706..ba11542b682 100644 --- a/homeassistant/util.py +++ b/homeassistant/util.py @@ -1,7 +1,18 @@ """ Helper methods for various modules. """ +from datetime import datetime import re +DATE_STR_FORMAT = "%H:%M:%S %d-%m-%Y" + def sanitize_filename(filename): """ Sanitizes a filename by removing .. / and \\. """ return re.sub(r"(~|(\.\.)|/|\+)", "", filename) + +def datetime_to_str(dattim): + """ Converts datetime to a string format. """ + return dattim.strftime(DATE_STR_FORMAT) + +def str_to_datetime(dt_str): + """ Converts a string to a datetime object. """ + return datetime.strptime(dt_str, DATE_STR_FORMAT)