From 781574d6d21e117a09309fce3f4a6a747f39c5a3 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 3 Dec 2017 17:07:54 +0000 Subject: [PATCH] Minor Bug Fix + Code Tidy-up Minor Bug Fix + Code Tidy-up --- .../Contents/Info.plist | 2 +- .../Contents/Server Plugin/discovery.py | 65 +---- .../Server Plugin/discovery_logging.py | 18 +- .../Contents/Server Plugin/hue_listener.py | 92 +++--- .../Contents/Server Plugin/menuItems.xml | 4 + .../Contents/Server Plugin/plugin.py | 268 +++++++++--------- README.md | 4 +- 7 files changed, 187 insertions(+), 266 deletions(-) diff --git a/Alexa-Hue Bridge.indigoPlugin/Contents/Info.plist b/Alexa-Hue Bridge.indigoPlugin/Contents/Info.plist index a7ac9ae..23e2136 100755 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Info.plist +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Info.plist @@ -3,7 +3,7 @@ PluginVersion - 3.0.19 + 3.0.20 ServerApiVersion 2.0 IwsApiVersion diff --git a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery.py b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery.py index 9e8bda1..4398228 100755 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery.py +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery.py @@ -68,10 +68,6 @@ def __init__(self, plugin, ahbDevId): try: self.ahbDevId = ahbDevId - # self._host = PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['host'] - # self._port = PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'] - # self.uuid = PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['uuid'] - # self._timeout = PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] PLUGIN.broadcasterLogger.debug("Broadcaster.__init__ for '{}' is running".format(PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['hubName'])) @@ -116,29 +112,6 @@ def stop(self): PLUGIN.broadcasterLogger.debug("Broadcaster thread stopped") self.interrupted = True - # @property - # def host(self): - # return self._host - - # @host.setter - # def host(self, host): - # self._host = host - - # @property - # def port(self): - # return self._port - - # @port.setter - # def port(self, port): - # self._port = port - - # @property - # def timeout(self): - # return self._timeout - - # @timeout.setter - # def timeout(self, timeout): - # self._timeout = timeout class Responder(threading.Thread): def __init__(self, plugin, ahbDevId): @@ -149,17 +122,13 @@ def __init__(self, plugin, ahbDevId): try: self.ahbDevId = ahbDevId - # self._host = PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['host'] - # self._port = PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'] - # self.uuid = PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['uuid'] - # self._timeout = PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] PLUGIN.responderLogger.debug("Responder.__init__ for '{}' is running".format(PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['hubName'])) self.interrupted = False - response_data = {"server_ip": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['host'], - "server_port": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], + response_data = {"server_ip": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['host'], + "server_port": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], "uuid": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['uuid']} self.response_packet = response_packet % response_data except StandardError, e: @@ -195,7 +164,7 @@ def run(self): return else: if M_SEARCH_REQ_MATCH in data: - PLUGIN.responderLogger.debug("Responder.run: received: %s" % str(data)) + PLUGIN.responderLogger.debug("Responder.run: received: {}".format(str(data))) self.respond(addr) except socket.error as e: # This is the exception thrown when someone else has bound to the UPNP port, so write some errors and @@ -228,30 +197,4 @@ def respond(self, addr): output_socket.sendto(self.response_packet, addr) PLUGIN.responderLogger.debug("Responder.respond: closing output_socket") output_socket.close() - PLUGIN.responderLogger.debug("Responder.respond: UDP Response sent to %s" % str(addr)) - - - # @property - # def host(self): - # return self._host - - # @host.setter - # def host(self, host): - # self._host = host - - # @property - # def port(self): - # return self._port - - # @port.setter - # def port(self, port): - # self._port = port - - # @property - # def timeout(self): - # return self._timeout - - # @timeout.setter - # def timeout(self, timeout): - # self._timeout = timeout - + PLUGIN.responderLogger.debug("Responder.respond: UDP Response sent to {}".format(str(addr))) diff --git a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery_logging.py b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery_logging.py index f3e94fd..7e8db05 100644 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery_logging.py +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery_logging.py @@ -11,6 +11,7 @@ import indigo except ImportError, e: pass + import Queue import sys import threading @@ -18,6 +19,7 @@ PLUGIN = None + class ThreadDiscoveryLogging(threading.Thread): def __init__(self, plugin): @@ -33,21 +35,21 @@ def run(self): while True: try: - discoveryId, discoveryName, discoveryList = PLUGIN.globals['queues']['discoveryLogging'].get(True, 5) + discoveryId, client_address, discoveryName, discoveryList = PLUGIN.globals['queues']['discoveryLogging'].get(True, 5) if len(discoveryList) > 0: discoveryList.sort() - PLUGIN.serverLogger.info(u"Alexa-Hue Bridge '%s' responding to Alexa discovery [request id: %s] ..." % (discoveryName, discoveryId)) + PLUGIN.serverLogger.info(u"Alexa-Hue Bridge '{}' responding to Alexa discovery from {} [request id: {}] ...".format(discoveryName, client_address, discoveryId)) deviceCount = 0 for deviceName in discoveryList: deviceCount += 1 - PLUGIN.serverLogger.info(u"+ Publishing device '%s' to Alexa" % deviceName) + PLUGIN.serverLogger.info(u"+ Publishing device '{}' to Alexa".format(deviceName)) if deviceCount == 0: deviceString = 'No device' # This probably won't occur ? elif deviceCount == 1: deviceString = 'One device' else: - deviceString = '%s devices' % str(deviceCount) - PLUGIN.serverLogger.info(u"... %s discovered by Alexa on Alexa-Hue Bridge '%s'." % (deviceString, discoveryName)) + deviceString = '{} devices'.format(str(deviceCount)) + PLUGIN.serverLogger.info(u"... {} discovered by Alexa on Alexa-Hue Bridge '{}'.".format(deviceString, discoveryName)) del PLUGIN.globals['discoveryLists'][discoveryId] @@ -57,9 +59,9 @@ def run(self): PLUGIN.serverLogger.error(u"StandardError detected in Discovery Logging") errorLines = traceback.format_exc().splitlines() for errorLine in errorLines: - PLUGIN.serverLogger.error(u"%s" % errorLine) + PLUGIN.serverLogger.error(u"{}".format(errorLine)) except StandardError, e: - PLUGIN.serverLogger.error(u"StandardError detected in Discovery Logging thread. Line '%s' has error='%s'" % (sys.exc_traceback.tb_lineno, e)) + PLUGIN.serverLogger.error(u"StandardError detected in Discovery Logging thread. Line '{}' has error='{}'".format(sys.exc_traceback.tb_lineno, e)) - PLUGIN.serverLogger.debug(u"Discovery Logging thread ended.") \ No newline at end of file + PLUGIN.serverLogger.debug(u"Discovery Logging thread ended.") diff --git a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/hue_listener.py b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/hue_listener.py index 938905f..7852283 100755 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/hue_listener.py +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/hue_listener.py @@ -87,13 +87,15 @@ def __init__(self, plugin, ahbDevId): self.ahbDevId = ahbDevId # Alexa-Hue Bridge device Id self.server = None self.stopped = False + self.retry = False + self.retryLimit = 3 + self.retryCount = 0 def run(self): PLUGIN.serverLogger.debug("Httpd.run called") - retryLimit = 3 - retryCount = 0 + self.retryCount = 0 self.stopped = False - while retryLimit: + while self.retryLimit: # This gets forced to zero (False) if retry limit hit - thereby ending thread try: PLUGIN.serverLogger.debug("Httpd.run SocketServer.ThreadingTCPServer") self.server = SocketServer.ThreadingTCPServer((PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['host'], PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port']), HttpdRequestHandler) @@ -102,52 +104,33 @@ def run(self): self.server.alexaHueBridgeId = self.ahbDevId PLUGIN.serverLogger.debug("Httpd.run calling server.serve_forever()") self.server.serve_forever() - retryLimit = 3 - if retryCount > 0: - retryCount = 0 - PLUGIN.serverLogger.info("'{}' now has access to HTTP port {} - retry succesful".format(indigo.devices[self.ahbDevId].name, PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'])) - try: - discoveryOn = indigo.devices[self.ahbDevId].onState - PLUGIN.serverLogger.debug(u'SET DEVICE DISCOVERY STATE = %s' % discoveryOn) - if discoveryOn: - indigo.devices[self.ahbDevId].updateStateOnServer("onOffState", True, uiValue="Discovery: On") - if self.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] == 0: - indigo.devices[self.ahbDevId].updateStateImageOnServer(indigo.kStateImageSel.SensorOn) - else: - indigo.devices[self.ahbDevId].updateStateImageOnServer(indigo.kStateImageSel.TimerOn) - else: - indigo.devices[self.ahbDevId].updateStateOnServer("onOffState", False, uiValue="Discovery: Off") - if self.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] == 0: - indigo.devices[self.ahbDevId].updateStateImageOnServer(indigo.kStateImageSel.SensorOff) - else: - indigo.devices[self.ahbDevId].updateStateImageOnServer(indigo.kStateImageSel.TimerOff) - except: - pass # Handle deleted Alexa-Hue Bridge devices by ignoring except SocketServer.socket.error as exc: if self.stopped: - retryLimit = 0 # Force Thread end - elif exc.args[0] != 48: + self.retryLimit = 0 # Force Thread end + elif exc.args[0] != 48: # 48 = Port In Use raise else: - retryCount += 1 - indigo.devices[self.ahbDevId].setErrorStateOnServer(u"port in use") # Default to 'port in use' status - PLUGIN.serverLogger.error("'{}' unable to access HTTP port {} as already in use - waiting 15 seconds to try again (will retry {} more times)".format(indigo.devices[self.ahbDevId].name, PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], retryLimit)) + self.retry = True + self.retryCount += 1 + PLUGIN.serverLogger.error("'{}' unable to access HTTP port {} as already in use - waiting 15 seconds to try again (will retry {} more times)".format(indigo.devices[self.ahbDevId].name, PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], self.retryLimit)) time.sleep(15) - PLUGIN.serverLogger.error("'{}' trying again to access HTTP port {} [attempt {}]".format(indigo.devices[self.ahbDevId].name, PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], retryCount)) - retryLimit -= 1 + PLUGIN.serverLogger.error("'{}' trying again to access HTTP port {} [attempt {}]".format(indigo.devices[self.ahbDevId].name, PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], self.retryCount)) + self.retryLimit -= 1 + except Exception, e: - PLUGIN.serverLogger.debug("Exception in HTTPD run method:\n%s" % str(e)) + PLUGIN.serverLogger.debug("Exception in HTTPD run method:\n{}".format(str(e))) raise if not self.stopped: - PLUGIN.serverLogger.error("'{}' failed to access HTTP port {} after {} attempts - This Alexa-Hue Bridge will be inoperable until the plugin is reloaded".format(indigo.devices[self.ahbDevId].name, PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], retryCount)) + PLUGIN.serverLogger.error("'{}' failed to access HTTP port {} after {} attempts - This Alexa-Hue Bridge will be inoperable until the plugin is reloaded".format(indigo.devices[self.ahbDevId].name, PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], self.retryCount)) indigo.devices[self.ahbDevId].setErrorStateOnServer(u"port in use") # Default to 'port in use' status else: PLUGIN.serverLogger.info("HTTP server stopped") def stop(self): PLUGIN.serverLogger.debug("Httpd.stop called") + if self.server: self.stopped = True self.server.shutdown() @@ -158,19 +141,19 @@ def stop(self): class HttpdRequestHandler(SocketServer.BaseRequestHandler): - def handle(self): + def handle(self): try: ahbDev = indigo.devices[self.server.alexaHueBridgeId] data = self.request.recv(1024) - PLUGIN.serverLogger.debug(str("HttpdRequestHandler.handle invoked for '{}' with data:\n{}\n\n".format(ahbDev.name, data))) + PLUGIN.serverLogger.debug(str("HttpdRequestHandler.handle invoked for '{}' by {} with data:\n{}\n\n".format(ahbDev.name, self.client_address, data))) - get_match = re.search(r'GET (.*?(\/[^\s^\/]*?))\s', data) + get_match = re.search(r'GET (.*?(/[^\s^/]*?))\s', data) if get_match: get_request_full=get_match.group(1).replace("..","") self.send_headers(get_request_full) self.request.sendall(self.get_response(self.server.alexaHueBridgeId, get_request_full)) - put_match = re.search(r'PUT (.*?(\/[^\s^\/]*?))\s', data) - put_data_match = re.search(r'(\{.*\})', data) + put_match = re.search(r'PUT (.*?(/[^\s^/]*?))\s', data) + put_data_match = re.search(r'({.*})', data) if put_match and put_data_match: put_request_full = put_match.group(1).replace("..","") put_data = put_data_match.group(1) @@ -197,10 +180,10 @@ def send_headers(self, file): def get_response(self, ahbDevId, request_string): try: ahbDev = indigo.devices[ahbDevId] - PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', request string: {}".format(ahbDev.name, request_string)) + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}' from {}, request string: {}".format(ahbDev.name, self.client_address, request_string)) # get device list - get_match = re.search(r'(\/[^\s^\/]+)$',request_string) + get_match = re.search(r'(/[^\s^/]+)$',request_string) if get_match: request_file=get_match.group(1) else: @@ -209,14 +192,14 @@ def get_response(self, ahbDevId, request_string): request_file = "/index.html" PLUGIN.serverLogger.debug("hue_listener.get_response request file: " + request_file) if re.search(r'/lights$',request_string): - PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', discovery request, returning the full list of devices in Hue JSON format".format(ahbDev.name)) + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}' from {}, discovery request, returning the full list of devices in Hue JSON format".format(ahbDev.name, self.client_address)) return self.getHueDeviceJSON(ahbDevId) # Get individual device status - I'm actually not sure what the last two cases are for, but this is taken directly # from the source script so I just left it in. get_device_match = re.search(r'/lights/([a-fA-F0-9]+)$',request_string) if get_device_match: - PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', found /lights/ in request string: {}".format(ahbDev.name, request_string)) + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}' from {}, found /lights/ in request string: {}".format(ahbDev.name, self.client_address, request_string)) return self.getHueDeviceJSON(ahbDevId, get_device_match.group(1)) # Hash key elif request_file in FILE_LIST: PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', serving from a local file: {}".format(ahbDev.name, request_file)) @@ -235,7 +218,7 @@ def get_response(self, ahbDevId, request_string): return INDEX_HTML else: return "HTTP/1.1 404 Not Found" - elif re.search(r'/api/[^\/]+$',request_string): + elif re.search(r'/api/[^/]+$',request_string): PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', found /api/ in request string: {}".format(ahbDev.name, request_string)) return "{}" else: @@ -243,7 +226,6 @@ def get_response(self, ahbDevId, request_string): except StandardError, e: PLUGIN.serverLogger.error(u"StandardError detected in get_response for '{}'. Line '{}' has error='{}'".format(ahbDev.name, sys.exc_traceback.tb_lineno, e)) - ######################################## def put_response(self, ahbDevId, request_string,request_data): try: @@ -266,7 +248,7 @@ def put_response(self, ahbDevId, request_string,request_data): return if alexaDeviceHashedKey not in PLUGIN.globals['alexaHueBridge'][ahbDevId]['hashKeys']: - PLUGIN.serverLogger.error(u"Alexa-Hue Bridge '%s' does not publish a device/action with Hash Key '{}'".format(ahbDev.name, alexaDeviceHashedKey)) + PLUGIN.serverLogger.error(u"Alexa-Hue Bridge '{}' does not publish a device/action with Hash Key '{}'".format(ahbDev.name, alexaDeviceHashedKey)) if alexaDeviceHashedKey in PLUGIN.globals['alexaHueBridge']['publishedHashKeys']: PLUGIN.serverLogger.error(u"Device/Action with Hash Key '{}' is published by Alexa-Hue Bridge '{}'".format(alexaDeviceHashedKey, indigo.devices[PLUGIN.globals['alexaHueBridge']['publishedHashKeys'][alexaDeviceHashedKey]].name)) PLUGIN.serverLogger.error(u"Re-run discovery to correct this problem.") @@ -332,14 +314,14 @@ def getHueDeviceJSON(self, ahbDevId, alexaDeviceHashedKey=None): # Return the JSON for all devices - called when discovering devices PLUGIN.serverLogger.debug(u"getHueDeviceJSON all-devices invocation for '{}'".format(self.ahbDevName)) deviceListDict = self._createFullDeviceDict(ahbDevId) - PLUGIN.serverLogger.debug('deviceListDict: %s' % str(deviceListDict)) + PLUGIN.serverLogger.debug('deviceListDict: {}'.format(str(deviceListDict))) PLUGIN.serverLogger.debug(u"'{}' json data: \n{}".format(self.ahbDevName, json.dumps(deviceListDict, indent=4))) if PLUGIN.globals['showDiscoveryInEventLog']: - PLUGIN.globals['queues']['discoveryLogging'].put([self.discoveryId, self.ahbDevName, PLUGIN.globals['discoveryLists'][self.discoveryId]]) + PLUGIN.globals['queues']['discoveryLogging'].put([self.discoveryId, self.client_address, self.ahbDevName, PLUGIN.globals['discoveryLists'][self.discoveryId]]) PLUGIN.serverLogger.debug(u"getHueDeviceJSON invocation completed for '{}'".format(self.ahbDevName)) return json.dumps(deviceListDict) except Exception, e: - PLUGIN.serverLogger.error(u"getHueDeviceJSON exception: \n%s" % str(traceback.format_exc(10))) + PLUGIN.serverLogger.error(u"getHueDeviceJSON exception: \n{}".format(str(traceback.format_exc(10)))) ################################################################################ # Utility methods to create the Hue dicts that will be converted to JSON @@ -365,7 +347,7 @@ def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDisc brightness = dev.states.get("brightness", 255) uniqueId = alexaDeviceHashedKey else: - PLUGIN.serverLogger.error(u"Unable to %s '%s' from '%s', associated device #%s not found" % (function, alexaDeviceName, ahbDevName, devId)) + PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated device #{} not found".format(function, alexaDeviceName, ahbDevName, devId)) return {} elif alexaDeviceData['mode'] == 'A': # Action onOffVariableId = int(alexaDeviceData["variableOnOffId"]) @@ -373,7 +355,7 @@ def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDisc if onOffVariableId in indigo.variables: onState = bool(indigo.variables[onOffVariableId].value) else: - PLUGIN.serverLogger.error(u"Unable to %s '%s' from '%s', associated On/Off variable #%s not found" % (function, alexaDeviceName, ahbDevName, onOffVariableId)) + PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated On/Off variable #{} not found".format(function, alexaDeviceName, ahbDevName, onOffVariableId)) return {} else: onState = True # Default to On ??? @@ -383,7 +365,7 @@ def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDisc if dimVariableId in indigo.variables: brightness = int(indigo.variables[dimVariableId].value) else: - PLUGIN.serverLogger.error(u"Unable to %s '%s' from '%s', associated Dim variable #%s not found" % (function, alexaDeviceName, ahbDevName, dimVariableId)) + PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated Dim variable #{} not found".format(function, alexaDeviceName, ahbDevName, dimVariableId)) return {} else: brightness = 255 # Default to 255 (max brightness) @@ -391,7 +373,7 @@ def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDisc else: return {} else: - PLUGIN.serverLogger.error(u"_createDeviceDict: alexaDeviceNameKey '%s' not in published devices; HashKey='%s'" % (alexaDeviceNameKey, alexaDeviceHashedKey)) + PLUGIN.serverLogger.error(u"_createDeviceDict: alexaDeviceNameKey '{}' not in published devices; HashKey='{}".format(alexaDeviceNameKey, alexaDeviceHashedKey)) return {} if isShowDiscoveryInEventLog: @@ -430,13 +412,13 @@ def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDisc # above return had line: "name": self.name.encode('ascii', 'ignore'), # Removed ascii encoding except Exception, e: - PLUGIN.serverLogger.error(u"_createDeviceDict exception: \n%s" % str(traceback.format_exc(10))) + PLUGIN.serverLogger.error(u"_createDeviceDict exception: \n{}".format(str(traceback.format_exc(10)))) def _createFullDeviceDict(self, ahbDevId): PLUGIN.serverLogger.debug(u"_createFullDeviceDict called") returnDict = dict() - PLUGIN.serverLogger.debug(u"_createFullDeviceDict: publishedAlexaDevices: \n%s" % str(PLUGIN.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices'])) + PLUGIN.serverLogger.debug(u"_createFullDeviceDict: publishedAlexaDevices: \n{}".format(str(PLUGIN.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices']))) ahbDev = indigo.devices[ahbDevId] publishedAlexaDevices = self.jsonLoadsProcess(ahbDev.pluginProps['alexaDevices']) @@ -444,7 +426,7 @@ def _createFullDeviceDict(self, ahbDevId): for alexaDeviceNameKey, AlexaDeviceData in publishedAlexaDevices.iteritems(): alexaDeviceHashKey = PLUGIN.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices'][alexaDeviceNameKey]['hashKey'] newDeviceDict = self._createDeviceDict('publish', ahbDevId, alexaDeviceHashKey, PLUGIN.globals['showDiscoveryInEventLog']) - PLUGIN.serverLogger.debug(u"_createFullDeviceDict: new device added: \n%s" % str(newDeviceDict)) + PLUGIN.serverLogger.debug(u"_createFullDeviceDict: new device added: \n{}".format(str(newDeviceDict))) returnDict[alexaDeviceHashKey] = newDeviceDict return returnDict diff --git a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/menuItems.xml b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/menuItems.xml index a9abc5b..849c262 100644 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/menuItems.xml +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/menuItems.xml @@ -12,4 +12,8 @@ Force Plugin Update forceUpdate + diff --git a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/plugin.py b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/plugin.py index 711eeb0..f20d1dc 100755 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/plugin.py +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/plugin.py @@ -11,14 +11,14 @@ import indigo except ImportError, e: pass -import inspect + import hashlib import json import logging import Queue import socket import sys -from time import localtime, time, sleep, strftime +from time import localtime, time, strftime import traceback import uuid @@ -36,7 +36,7 @@ def __init__(self, pluginId, pluginDisplayName, pluginVersion, pluginPrefs): indigo.PluginBase.__init__(self, pluginId, pluginDisplayName, pluginVersion, pluginPrefs) # Initialise dictionary to store plugin Globals - self.globals = {} + self.globals = dict() self.globals['networkAvailable'] = {} self.globals['networkAvailable']['checkUrl'] = NETWORK_AVAILABLE_CHECK_REMOTE_SERVER @@ -104,7 +104,7 @@ def __init__(self, pluginId, pluginDisplayName, pluginVersion, pluginPrefs): self.globals['portList'].append(int(dev.address)) # Do this regardless whether device enabled or not except: pass - self.generalLogger.debug(u'PORTLIST @Plugin INIT: %s' % self.globals['portList']) + self.generalLogger.debug(u"PORTLIST @Plugin INIT: {}".format(self.globals['portList'])) # Initialise dictionary for update checking self.globals['update'] = {} @@ -130,7 +130,7 @@ def forceUpdate(self): def checkRateLimit(self): limiter = self.globals['update']['updater'].getRateLimit() - self.generalLogger.info('RateLimit {limit:%d remaining:%d resetAt:%d}' % limiter) + self.generalLogger.info("RateLimit limit:{d[0]} remaining:{d[1]} resetAt:{d[2]}".format(d=limiter)) def startup(self): @@ -180,14 +180,14 @@ def validatePrefsConfigUi(self, valuesDict): errorDict = indigo.Dict() errorDict["overriddenHostIpAddress"] = "Host IP Address missing" errorDict["showAlertText"] = "You have elected to override the Host Ip Address but haven't specified it!" - return (False, valuesDict, errorDict) + return False, valuesDict, errorDict return True def closedPrefsConfigUi(self, valuesDict, userCancelled): self.methodTracer.threaddebug(u"CLASS: Plugin") - if userCancelled == True: + if userCancelled: return self.globals['networkAvailable']['checkUrl'] = valuesDict.get("networkCheckURL", NETWORK_AVAILABLE_CHECK_REMOTE_SERVER) @@ -245,7 +245,7 @@ def setDebuggingLevels(self, valuesDict): self.globals['debug']['debugBroadcaster'] = logging.INFO # For general debugging of the Broadcaster thread(s) self.globals['debug']['debugResponder'] = logging.INFO # For general debugging of the Responder thread(s) - if self.globals['debug']['debugEnabled'] == False: + if not self.globals['debug']['debugEnabled']: self.plugin_file_handler.setLevel(logging.INFO) else: self.plugin_file_handler.setLevel(logging.THREADDEBUG) @@ -284,7 +284,7 @@ def setDebuggingLevels(self, valuesDict): if debugMethodTrace: debugTypes.append('Method Trace') message = self.activeLoggingTypes(debugTypes) - self.generalLogger.warning(u"Debugging enabled for Alexa-Hue Bridge: %s" % (message)) + self.generalLogger.warning(u"Debugging enabled for Alexa-Hue Bridge: {}".format(message)) def activeLoggingTypes(self, debugTypes): self.methodTracer.threaddebug(u"CLASS: Plugin") @@ -315,7 +315,7 @@ def is_connected(): # connect to the host -- tells us if the host is actually # reachable s = socket.create_connection((host, 80), 2) - self.generalLogger.info(u"Alexa-Hue Bridge network access check to %s successfully completed." % self.globals['networkAvailable']['checkUrl']) + self.generalLogger.info(u"Alexa-Hue Bridge network access check to {} successfully completed.".format(self.globals['networkAvailable']['checkUrl'])) return True except: pass @@ -323,18 +323,18 @@ def is_connected(): isConnectedRetryCount = 0 self.globals['networkAvailable']['retryInterval'] = NETWORK_AVAILABLE_CHECK_RETRY_SECONDS_ONE - self.generalLogger.info(u"Alexa-Hue Bridge checking network access by attempting to access '%s'" % self.globals['networkAvailable']['checkUrl']) + self.generalLogger.info(u"Alexa-Hue Bridge checking network access by attempting to access '{}'".format(self.globals['networkAvailable']['checkUrl'])) while not is_connected(): isConnectedRetryCount += 1 if isConnectedRetryCount > NETWORK_AVAILABLE_CHECK_LIMIT_ONE: self.globals['networkAvailable']['retryInterval'] = NETWORK_AVAILABLE_CHECK_RETRY_SECONDS_TWO if isConnectedRetryCount < NETWORK_AVAILABLE_CHECK_LIMIT_TWO: - self.generalLogger.error(u"Alexa-Hue Bridge network access check failed - attempt %i - retrying in %i seconds" % (isConnectedRetryCount, self.globals['networkAvailable']['retryInterval'])) + self.generalLogger.error(u"Alexa-Hue Bridge network access check failed - attempt {} - retrying in {} seconds".format(isConnectedRetryCount, self.globals['networkAvailable']['retryInterval'])) elif isConnectedRetryCount == NETWORK_AVAILABLE_CHECK_LIMIT_TWO: self.globals['networkAvailable']['retryInterval'] = NETWORK_AVAILABLE_CHECK_RETRY_SECONDS_THREE - self.generalLogger.error(u"Alexa-Hue Bridge network access check failed - attempt %i - will now silently retry every %i seconds" % (isConnectedRetryCount, self.globals['networkAvailable']['retryInterval'])) + self.generalLogger.error(u"Alexa-Hue Bridge network access check failed - attempt {} - will now silently retry every {} seconds".format(isConnectedRetryCount, self.globals['networkAvailable']['retryInterval'])) elif isConnectedRetryCount > NETWORK_AVAILABLE_CHECK_LIMIT_TWO and isConnectedRetryCount % 12 == 0: - self.generalLogger.error(u"Alexa-Hue Bridge network access check failed - attempt %i - will continue to silently retry every %i seconds" % (isConnectedRetryCount, self.globals['networkAvailable']['retryInterval'])) + self.generalLogger.error(u"Alexa-Hue Bridge network access check failed - attempt {} - will continue to silently retry every {} seconds".format(isConnectedRetryCount, self.globals['networkAvailable']['retryInterval'])) self.sleep(self.globals['networkAvailable']['retryInterval']) # In seconds @@ -350,26 +350,19 @@ def is_connected(): self.globals['update']['updater'].checkForUpdate() nextCheckTime = strftime('%A, %Y-%b-%d at %H:%M', localtime(self.globals['update']['nextCheckTime'])) - self.generalLogger.info(u"Alexa-Hue Bridge next update check scheduled for: %s" % nextCheckTime) + self.generalLogger.info(u"Alexa-Hue Bridge next update check scheduled for: {}".format(nextCheckTime)) self.sleep(60) # in seconds except self.StopThread: self.generalLogger.info(u"Alexa-Hue Bridge shutdown requested") - - - - - - - ################################################ # start the Alexa-Hue Bridge device (aka ahbDev) ################################################ def deviceStartComm(self, ahbDev): try: self.methodTracer.threaddebug(u"CLASS: Plugin") - self.generalLogger.debug(u'DEVICE START: %s' % ahbDev.name) + self.generalLogger.debug(u"DEVICE START: {}".format(ahbDev.name)) if not ahbDev.id in self.globals['alexaHueBridge']: self.globals['alexaHueBridge'][ahbDev.id] = {} @@ -464,7 +457,7 @@ def deviceStartComm(self, ahbDev): props = ahbDev.pluginProps self.retrievePublishedDevices(props, ahbDev.id, True, False) # List Alexa devices in this Alexa-Hue Bridge + output info message + don't Check for V2 definitions - self.generalLogger.info(u"Starting Hue Bridge '%s' web server thread" % self.globals['alexaHueBridge'][ahbDev.id]['hubName']) + self.generalLogger.info(u"Starting Hue Bridge '{}' web server thread".format(self.globals['alexaHueBridge'][ahbDev.id]['hubName'])) start_webserver_required = False if not 'webServer' in self.globals['alexaHueBridge'][ahbDev.id]: @@ -475,16 +468,16 @@ def deviceStartComm(self, ahbDev): self.sleep(5) # wait 5 seconds (temporary fix?) del self.globals['alexaHueBridge'][ahbDev.id]['webServer'] start_webserver_required = True - if start_webserver_required == True: + if start_webserver_required: self.globals['alexaHueBridge'][ahbDev.id]['webServer'] = Httpd(self, ahbDev.id) self.globals['alexaHueBridge'][ahbDev.id]['webServer'].start() # Only start discovery if auto-start requested if not self.globals['alexaHueBridge'][ahbDev.id]['autoStartDiscovery']: - self.generalLogger.info(u"Hue Bridge '%s' 'Auto Start Discovery' NOT requested" % self.globals['alexaHueBridge'][ahbDev.id]['hubName']) + self.generalLogger.info(u"Hue Bridge '{}' 'Auto Start Discovery' NOT requested".format(self.globals['alexaHueBridge'][ahbDev.id]['hubName'])) self.setDeviceDiscoveryState(False, ahbDev.id) else: - self.generalLogger.info(u"Starting Hue Bridge '%s' discovery thread as 'Auto Start Discovery' requested" % self.globals['alexaHueBridge'][ahbDev.id]['hubName']) + self.generalLogger.info(u"Starting Hue Bridge '{}' discovery thread as 'Auto Start Discovery' requested".format(self.globals['alexaHueBridge'][ahbDev.id]['hubName'])) start_broadcaster_required = False if not 'broadcaster' in self.globals['alexaHueBridge'][ahbDev.id]: @@ -497,7 +490,7 @@ def deviceStartComm(self, ahbDev): self.globals['alexaHueBridge'][ahbDev.id]['broadcaster'].join(5) del self.globals['alexaHueBridge'][ahbDev.id]['broadcaster'] start_broadcaster_required = True - if start_broadcaster_required == True: + if start_broadcaster_required: self.globals['alexaHueBridge'][ahbDev.id]['broadcaster'] = Broadcaster(self, ahbDev.id) self.globals['alexaHueBridge'][ahbDev.id]['broadcaster'].start() @@ -512,7 +505,7 @@ def deviceStartComm(self, ahbDev): self.globals['alexaHueBridge'][ahbDev.id]['broadcaster'].join(5) del self.globals['alexaHueBridge'][ahbDev.id]['responder'] start_responder_required = True - if start_responder_required == True: + if start_responder_required: self.globals['alexaHueBridge'][ahbDev.id]['responder'] = Responder(self, ahbDev.id) self.globals['alexaHueBridge'][ahbDev.id]['responder'].start() @@ -521,7 +514,7 @@ def deviceStartComm(self, ahbDev): self.generalLogger.info(u"Alexa-Hue Bridge '{}' started: Host: {} Port: {}".format(self.globals['alexaHueBridge'][ahbDev.id]['hubName'], self.globals['alexaHueBridge'][ahbDev.id]['host'], self.globals['alexaHueBridge'][ahbDev.id]['port'])) except StandardError, e: - self.generalLogger.error(u"StandardError detected in deviceStartComm for '%s'. Line '%s' has error='%s'" % (indigo.devices[ahbDev.id].name, sys.exc_traceback.tb_lineno, e)) + self.generalLogger.error(u"StandardError detected in deviceStartComm for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDev.id].name, sys.exc_traceback.tb_lineno, e)) def deviceStopComm(self, ahbDev): self.methodTracer.threaddebug(u"CLASS: Plugin") @@ -540,19 +533,19 @@ def deviceStopComm(self, ahbDev): if self.globals['alexaHueBridge'][stoppedId]['responder']: self.globals['alexaHueBridge'][stoppedId]['responder'].stop() except StandardError, e: - self.generalLogger.error(u"StandardError detected in deviceStopComm for '%s'. Line '%s' has error='%s'" % (stoppedName, sys.exc_traceback.tb_lineno, e)) + self.generalLogger.error(u"StandardError detected in deviceStopComm for '{}'. Line '{}' has error='{}'".format(stoppedName, sys.exc_traceback.tb_lineno, e)) def didDeviceCommPropertyChange(self, origDev, newDev): self.methodTracer.threaddebug(u"CLASS: Plugin") - self.generalLogger.debug(u'DID-DEVICE-COMM-PROPERTY-CHANGE: Old [%s] vs New [%s]' % (origDev.name, newDev.name)) + self.generalLogger.debug(u"DID-DEVICE-COMM-PROPERTY-CHANGE: Old [{}] vs New [{}]".format(origDev.name, newDev.name)) if newDev.deviceTypeId == EMULATED_HUE_BRIDGE_TYPEID and origDev.enabled and newDev.enabled: # if newDev.pluginProps['port'] == "auto" or newDev.pluginProps['port'] != newDev.address: # self.generalLogger.debug(u'DID-DEVICE-COMM-PROPERTY-CHANGE: PORT AUTO OR CHANGED') # return True if 'discoveryExpiration' in origDev.pluginProps and 'discoveryExpiration' in newDev.pluginProps: if origDev.pluginProps['discoveryExpiration'] != newDev.pluginProps['discoveryExpiration']: - self.generalLogger.debug(u'DID-DEVICE-COMM-PROPERTY-CHANGE [EXPIRE MINUTES]: Old [%s] vs New [%s]' % (origDev.pluginProps['discoveryExpiration'], newDev.pluginProps['discoveryExpiration'])) - self.generalLogger.debug(u'DID-DEVICE-COMM-PROPERTY-CHANGE [AUTO START]: Old [%s] vs New [%s]' % (origDev.pluginProps['autoStartDiscovery'], newDev.pluginProps['autoStartDiscovery'])) + self.generalLogger.debug(u"DID-DEVICE-COMM-PROPERTY-CHANGE [EXPIRE MINUTES]: Old [{}] vs New [{}]".format(origDev.pluginProps['discoveryExpiration'], newDev.pluginProps['discoveryExpiration'])) + self.generalLogger.debug(u"DID-DEVICE-COMM-PROPERTY-CHANGE [AUTO START]: Old [{}] vs New [{}]".format(origDev.pluginProps['autoStartDiscovery'], newDev.pluginProps['autoStartDiscovery'])) return True if self.globals['alexaHueBridge'][newDev.id]['forceDeviceStopStart']: # If a force device stop start requested turn off request and action self.globals['alexaHueBridge'][newDev.id]['forceDeviceStopStart'] = False @@ -694,7 +687,7 @@ def retrievePublishedDevices(self, valuesDict, ahbDevId, infoMsg, convertVersion if versionTwoAlexaDeviceData['published'].lower() == 'true': # Do validity checks and discard (with message) if invalid if ('|' in versionTwoAlexaDeviceName) or (',' in versionTwoAlexaDeviceName) or (';' in versionTwoAlexaDeviceName): - self.generalLogger.error(u"Alexa Device (Plugin V2.x.x) '%s' definition detected in Indigo Device '%s': Unable to convert as Alexa Device Name cannot contain the vertical bar character i.e. '|', the comma character i.e. ',' or the semicolon character i.e. ';'." % (versionTwoAlexaDeviceName, dev.name)) + self.generalLogger.error(u"Alexa Device (Plugin V2.x.x) '{}' definition detected in Indigo Device '{}': Unable to convert as Alexa Device Name cannot contain the vertical bar character i.e. '|', the comma character i.e. ',' or the semicolon character i.e. ';'.".format(versionTwoAlexaDeviceName, dev.name)) continue duplicateDetected = False @@ -705,10 +698,10 @@ def retrievePublishedDevices(self, valuesDict, ahbDevId, infoMsg, convertVersion alexaDeviceName = AlexaDeviceData['name'] if ahbDevId == alexaHueBridgeData: # In theory this can't happen as this logic is only executed when the Alexa-Hue bridge has no Alexa devices! - self.generalLogger.error(u"Alexa Device (Plugin V2.x.x) '%s' definition detected in Indigo Device '%s': Unable to convert as Alexa Device Name this Alexa-Hue Bridge." % (alexaDeviceName, dev.name)) + self.generalLogger.error(u"Alexa Device (Plugin V2.x.x) '{}' definition detected in Indigo Device '{}': Unable to convert as Alexa Device Name this Alexa-Hue Bridge.".format(alexaDeviceName, dev.name)) else: alexaHueBridgeName = indigo.devices[alexaHueBridgeId].name - self.generalLogger.error(u"Alexa Device (Plugin V2.x.x) '%s' definition detected in Indigo Device '%s': Unable to convert as Alexa Device Name is already allocated on Alexa-Hue Bridge '%s'" % (alexaDeviceName, dev.name, alexaHueBridgeName)) + self.generalLogger.error(u"Alexa Device (Plugin V2.x.x) '{}' definition detected in Indigo Device '{}': Unable to convert as Alexa Device Name is already allocated on Alexa-Hue Bridge '{}'".format(alexaDeviceName, dev.name, alexaHueBridgeName)) if duplicateDetected: continue @@ -731,7 +724,7 @@ def retrievePublishedDevices(self, valuesDict, ahbDevId, infoMsg, convertVersion self.globals['alexaHueBridge']['publishedHashKeys'][hashKey] = ahbDevId - self.generalLogger.info(u"Alexa Device (Plugin V2.x.x) '%s' definition detected in Indigo Device '%s': Converting to V3 format." % (versionTwoAlexaDeviceName, dev.name)) + self.generalLogger.info(u"Alexa Device (Plugin V2.x.x) '{}' definition detected in Indigo Device '{}': Converting to V3 format.".format(versionTwoAlexaDeviceName, dev.name)) if len(valuesDict['alexaDevices']) > 0: valuesDict['alexaDevices'] = json.dumps(publishedAlexaDevices) @@ -744,17 +737,17 @@ def retrievePublishedDevices(self, valuesDict, ahbDevId, infoMsg, convertVersion elif numberPublished == 1: numberPublishedUI = 'one Alexa Device' else: - numberPublishedUI = str('%s Alexa Devices' % numberPublished) + numberPublishedUI = str("{} Alexa Devices".format(numberPublished)) if numberPublished <= DEVICE_LIMIT: - self.generalLogger.info(u"'%s' has %s published" % (self.globals['alexaHueBridge'][ahbDevId]['hubName'], numberPublishedUI)) + self.generalLogger.info(u"'{}' has {} published".format(self.globals['alexaHueBridge'][ahbDevId]['hubName'], numberPublishedUI)) else: - self.generalLogger.error(u"'%s' has %s published [LIMIT OF %s DEVICES EXCEEDED - DISCOVERY MAY NOT WORK!!!]" % (self.globals['alexaHueBridge'][ahbDevId]['hubName'], numberPublishedUI, DEVICE_LIMIT)) + self.generalLogger.error(u"'{}' has {} published [LIMIT OF {} DEVICES EXCEEDED - DISCOVERY MAY NOT WORK!!!]".format(self.globals['alexaHueBridge'][ahbDevId]['hubName'], numberPublishedUI, DEVICE_LIMIT)) self.generalLogger.error(u"Move excess Alexa devices to another existing or new Alexa-Hue Bridge") return valuesDict except StandardError, e: - self.generalLogger.error(u"StandardError detected in retrievePublishedDevices for '%s'. Line '%s' has error='%s'" % (indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) + self.generalLogger.error(u"StandardError detected in retrievePublishedDevices for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) @@ -795,40 +788,39 @@ def retrieveOtherPublishedDevices(self, ahbDevId): else: # Not used continue except StandardError, e: - self.generalLogger.error(u"StandardError detected in retrieveOtherPublishedDevices for '%s'. Line '%s' has error='%s'" % (indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) + self.generalLogger.error(u"StandardError detected in retrieveOtherPublishedDevices for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) def validateDeviceConfigUi(self, valuesDict, typeId, ahbDevId): self.methodTracer.threaddebug(u"CLASS: Plugin") if typeId == EMULATED_HUE_BRIDGE_TYPEID: self.generalLogger.debug(u"Validating Device config for type: " + typeId) - self.generalLogger.debug(u'validateDeviceConfigUi VALUESDICT = %s' % valuesDict) + self.generalLogger.debug(u"validateDeviceConfigUi VALUESDICT = {}".format(valuesDict)) errorsDict = indigo.Dict() try: amount = int(valuesDict["discoveryExpiration"]) if amount not in range(-1, 11): # -1 = No Discovery, 0 = Always Discover, 1 - 10 = Number of minutes to discover - raise - except: + raise ValueError("'Discovery Expiration' is invalid") + except ValueError: errorsDict["discoveryExpiration"] = "'Discovery Expiration' must be a positive integer from 1 to 10 (minutes) or 'No Discovery' or 'Discovery Permanently On'" errorsDict["showAlertText"] = "'Discovery Expiration' is invalid" - return (False, valuesDict, errorsDict) + return False, valuesDict, errorsDict try: disableAlexaVariableId = int(valuesDict.get("disableAlexaVariableList", "0")) if disableAlexaVariableId != 0: if indigo.variables[disableAlexaVariableId].value.lower() != 'true' and indigo.variables[disableAlexaVariableId].value.lower() != 'false': - raise - except: + raise ValueError("Selected variable is not valid") + except ValueError: errorsDict["disableAlexaVariableList"] = "'Disable Alexa Variable' must be 'true' or 'false' or '-- NO SELECTION --'" errorsDict["showAlertText"] = "Selected variable is not valid" - return (False, valuesDict, errorsDict) + return False, valuesDict, errorsDict alexaDeviceNameSorted, alexaDeviceName, alexaHueBridgeId = valuesDict["alexaDevicesList"].split("|") alexaHueBridgeId = int(alexaHueBridgeId) - alexaName = '' if alexaHueBridgeId == 0: alexaName = valuesDict['newAlexaName'] errorMessage = "'New Alexa Device Name' is present. Have you done an 'Add New Alexa Device' for the new Alexa device? Either Add the Alexa device or clear 'New Alexa Device Name' to enable Save. This check is to prevent any changes being lost." @@ -839,16 +831,16 @@ def validateDeviceConfigUi(self, valuesDict, typeId, ahbDevId): if alexaName != '': errorsDict["alexaDevicesList"] = errorMessage errorsDict["showAlertText"] = errorMessage - return (False, valuesDict, errorsDict) + return False, valuesDict, errorsDict - return (True, valuesDict) + return True, valuesDict def closedDeviceConfigUi(self, valuesDict, userCancelled, typeId, ahbDevId): self.methodTracer.threaddebug(u"CLASS: Plugin") try: - self.generalLogger.debug(u"'closePrefsConfigUi' called with userCancelled = %s" % (str(userCancelled))) + self.generalLogger.debug(u"'closePrefsConfigUi' called with userCancelled = {}".format(str(userCancelled))) - if userCancelled == True: + if userCancelled: return if typeId != EMULATED_HUE_BRIDGE_TYPEID: @@ -879,20 +871,20 @@ def closedDeviceConfigUi(self, valuesDict, userCancelled, typeId, ahbDevId): elif numberPublished == 1: numberPublishedUI = 'one Alexa Device' else: - numberPublishedUI = str('%s Alexa Devices' % numberPublished) + numberPublishedUI = str("{} Alexa Devices".format(numberPublished)) if numberPublished <= DEVICE_LIMIT: - self.generalLogger.info(u"'%s' updated and now has %s published" % (self.globals['alexaHueBridge'][ahbDevId]['hubName'], numberPublishedUI)) + self.generalLogger.info(u"'{}' updated and now has {} published".format(self.globals['alexaHueBridge'][ahbDevId]['hubName'], numberPublishedUI)) else: - self.generalLogger.error(u"'%s' updated and now has %s published [LIMIT OF %s DEVICES EXCEEDED - DISCOVERY MAY NOT WORK!!!]" % (self.globals['alexaHueBridge'][ahbDevId]['hubName'], numberPublishedUI, DEVICE_LIMIT)) + self.generalLogger.error(u"'{}' updated and now has {} published [LIMIT OF {} DEVICES EXCEEDED - DISCOVERY MAY NOT WORK!!!]".format(self.globals['alexaHueBridge'][ahbDevId]['hubName'], numberPublishedUI, DEVICE_LIMIT)) self.generalLogger.error(u"Move excess Alexa devices to another existing or new Alexa-Hue Bridge") - self.generalLogger.debug(u"'closePrefsConfigUi' completed for '%s'" % self.globals['alexaHueBridge'][ahbDevId]['hubName']) + self.generalLogger.debug(u"'closePrefsConfigUi' completed for '{}'".format(self.globals['alexaHueBridge'][ahbDevId]['hubName'])) return valuesDict except StandardError, e: - self.generalLogger.error(u"StandardError detected in closedDeviceConfigUi for '%s'. Line '%s' has error='%s'" % (indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) + self.generalLogger.error(u"StandardError detected in closedDeviceConfigUi for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) @@ -907,7 +899,7 @@ def deviceDeleted(self, dev): for ahbDevId in self.globals['alexaHueBridge']: if 'publishedAlexaDevices' in self.globals['alexaHueBridge'][ahbDevId]: if dev.id in self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices']: - self.generalLogger.info(u"A device (%s) that was published has been deleted - you'll probably want use the Alexa app to forget that device." % dev.name) + self.generalLogger.info(u"A device ({}) that was published has been deleted - you'll probably want use the Alexa app to forget that device.".format(dev.name)) self.refreshDeviceList(ahbDevId) super(Plugin, self).deviceDeleted(dev) @@ -979,8 +971,8 @@ def disableAlexaVariableList(self, filter="", valuesDict=None, typeId="", target disableAlexaVariableId = int(valuesDict.get("disableAlexaVariableList", "0")) if disableAlexaVariableId != 0: if indigo.variables[disableAlexaVariableId].value.lower() != 'true' and indigo.variables[disableAlexaVariableId].value.lower() != 'false': - raise - except: + raise ValueError("VARIABLE IS MISSING / INVALID") + except ValueError: if disableAlexaVariableId in indigo.variables: variableName = indigo.variables[disableAlexaVariableId].name else: @@ -1010,7 +1002,7 @@ def alexaDevicesListGlobal(self, filter, valuesDict, typeId, ahbDevId): alexaDeviceName = alexaDeviceData['name'].replace(',',' ').replace(';',' ') self.globals['alexaDevicesListGlobal'][alexaDeviceNameKey] = int(alexaHueBridgeId) alexaDeviceListKey = alexaDeviceNameKey + '|' + alexaDeviceName + '|' + str(alexaHueBridgeId) - alexaDeviceListKey = str('%s|%s|%s' %(alexaDeviceNameKey, alexaDeviceName, alexaHueBridgeId)) + alexaDeviceListKey = str('{}|{}|{}'.format(alexaDeviceNameKey, alexaDeviceName, alexaHueBridgeId)) allocatedAlexaDevicesListGlobal.append((alexaDeviceListKey, alexaDeviceName)) for alexaDeviceNameKey, alexaDeviceData in self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices'].iteritems(): @@ -1057,7 +1049,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if actionOnId in indigo.actionGroups: valuesDict["alexaNameIndigoOnAction"] = indigo.actionGroups[actionOnId].name else: - valuesDict["alexaNameIndigoOnAction"] = 'Action #%s not found' % actionOnId + valuesDict["alexaNameIndigoOnAction"] = 'Action #{} not found'.format(actionOnId) if actionOffId == 0: valuesDict["alexaNameIndigoOffAction"] = 'NO ACTION' @@ -1065,7 +1057,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if actionOffId in indigo.actionGroups: valuesDict["alexaNameIndigoOffAction"] = indigo.actionGroups[actionOffId].name else: - valuesDict["alexaNameIndigoOffAction"] = 'Action #%s not found' % actionOffId + valuesDict["alexaNameIndigoOffAction"] = 'Action #{} not found'.format(actionOffId) if variableOnOffId == 0: valuesDict["alexaNameIndigoOnOffActionVariable"] = 'NO VARIABLE' @@ -1073,7 +1065,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if variableOnOffId in indigo.variables: valuesDict["alexaNameIndigoOnOffActionVariable"] = indigo.variables[variableOnOffId].name else: - valuesDict["alexaNameIndigoOnOffActionVariable"] = 'Variable #%s not found' % variableOnOffId + valuesDict["alexaNameIndigoOnOffActionVariable"] = 'Variable #{} not found'.format(variableOnOffId) if actionDimId == 0: valuesDict["alexaNameIndigoDimAction"] = 'NO ACTION' @@ -1081,7 +1073,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if actionDimId in indigo.actionGroups: valuesDict["alexaNameIndigoDimAction"] = indigo.actionGroups[actionDimId].name else: - valuesDict["alexaNameIndigoDimAction"] = 'Action #%s not found' % actionDimId + valuesDict["alexaNameIndigoDimAction"] = 'Action #{} not found'.format(actionDimId) if variableDimId == 0: valuesDict["alexaNameIndigoDimActionVariable"] = 'NO VARIABLE' @@ -1089,7 +1081,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if variableDimId in indigo.variables: valuesDict["alexaNameIndigoDimActionVariable"] = indigo.variables[variableDimId].name else: - valuesDict["alexaNameIndigoDimActionVariable"] = 'Variable #%s not found' % variableDimId + valuesDict["alexaNameIndigoDimActionVariable"] = 'Variable #{} not found'.format(variableDimId) else: valuesDict["alexaNameActionDevice"] = "D" @@ -1098,7 +1090,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if deviceId in indigo.devices: valuesDict["alexaNameIndigoDevice"] = deviceName else: - valuesDict["alexaNameIndigoDevice"] = 'Device #%s not found (\'%s\' )' % (deviceId, deviceName) + valuesDict["alexaNameIndigoDevice"] = 'Device #{} not found (\'{}\' )'.format(deviceId, deviceName) else: mode = self.globals['alexaHueBridge'][alexaHueBridgeId]['publishedAlexaDevices'][alexaDeviceNameKey]['mode'] @@ -1118,7 +1110,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if actionOnId in indigo.actionGroups: valuesDict["alexaNameIndigoOnAction"] = indigo.actionGroups[actionOnId].name else: - valuesDict["alexaNameIndigoOnAction"] = 'Action #%s not found' % actionOnId + valuesDict["alexaNameIndigoOnAction"] = 'Action #{} not found'.format(actionOnId) if actionOffId == 0: valuesDict["alexaNameIndigoOffAction"] = 'NO ACTION' @@ -1126,7 +1118,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if actionOffId in indigo.actionGroups: valuesDict["alexaNameIndigoOffAction"] = indigo.actionGroups[actionOffId].name else: - valuesDict["alexaNameIndigoOffAction"] = 'Action #%s not found' % actionOffId + valuesDict["alexaNameIndigoOffAction"] = 'Action #{} not found'.format(actionOffId) if variableOnOffId == 0: valuesDict["alexaNameIndigoOnOffActionVariable"] = 'NO VARIABLE' @@ -1134,7 +1126,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if variableOnOffId in indigo.variables: valuesDict["alexaNameIndigoOnOffActionVariable"] = indigo.variables[variableOnOffId].name else: - valuesDict["alexaNameIndigoOnOffActionVariable"] = 'Variable #%s not found' % variableOnOffId + valuesDict["alexaNameIndigoOnOffActionVariable"] = 'Variable #{} not found'.format(variableOnOffId) if actionDimId == 0: valuesDict["alexaNameIndigoDimAction"] = 'NO ACTION' @@ -1142,7 +1134,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if actionDimId in indigo.actionGroups: valuesDict["alexaNameIndigoDimAction"] = indigo.actionGroups[actionDimId].name else: - valuesDict["alexaNameIndigoDimAction"] = 'Action #%s not found' % actionDimId + valuesDict["alexaNameIndigoDimAction"] = 'Action #{} not found'.format(actionDimId) if variableDimId == 0: valuesDict["alexaNameIndigoDimActionVariable"] = 'NO VARIABLE' @@ -1150,7 +1142,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if variableDimId in indigo.variables: valuesDict["alexaNameIndigoDimActionVariable"] = indigo.variables[variableDimId].name else: - valuesDict["alexaNameIndigoDimActionVariable"] = 'Variable #%s not found' % variableDimId + valuesDict["alexaNameIndigoDimActionVariable"] = 'Variable #{} not found'.format(variableDimId) else: valuesDict["alexaNameActionDevice"] = "D" deviceName = self.globals['alexaHueBridge'][alexaHueBridgeId]['publishedAlexaDevices'][alexaDeviceNameKey]['devName'].replace(',',' ').replace(';',' ') @@ -1158,7 +1150,7 @@ def alexaDevicesListGlobalSelection(self, valuesDict, typeId, ahbDevId): if deviceId in indigo.devices: valuesDict["alexaNameIndigoDevice"] = deviceName else: - valuesDict["alexaNameIndigoDevice"] = 'Device #%s not found (\'%s\' )' % (deviceId, deviceName) + valuesDict["alexaNameIndigoDevice"] = 'Device #{} not found (\'{}\' )'.format(deviceId, deviceName) valuesDict["alexaNameHueBridge"] = indigo.devices[int(alexaHueBridgeId)].name return valuesDict @@ -1266,35 +1258,35 @@ def addNewAlexaDevice(self, valuesDict, typeId, ahbDevId): self.methodTracer.threaddebug(u"CLASS: Plugin") if len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices']) >= DEVICE_LIMIT: - errorText = "You can't publish any more Alexa Devices - you've reached the maximum of %i imposed by the plugin on behalf of Amazon Alexa." % DEVICE_LIMIT + errorText = "You can't publish any more Alexa Devices - you've reached the maximum of {} imposed by the plugin on behalf of Amazon Alexa.".format(DEVICE_LIMIT) self.generalLogger.error(errorText) errorsDict = indigo.Dict() errorsDict["showAlertText"] = errorText - return (valuesDict, errorsDict) + return valuesDict, errorsDict if valuesDict["newAlexaName"] == '': errorsDict = indigo.Dict() errorsDict["newAlexaName"] = "New Alexa Name is missing and must be present." errorsDict["showAlertText"] = "New Alexa Name is missing and must be present." - return (valuesDict, errorsDict) + return valuesDict, errorsDict if '|' in valuesDict["newAlexaName"]: errorsDict = indigo.Dict() errorsDict["newAlexaName"] = "New Alexa Name cannot contain the vertical bar character i.e. '|'" errorsDict["showAlertText"] = "New Alexa Name cannot contain the vertical bar character i.e. '|'" - return (valuesDict, errorsDict) + return valuesDict, errorsDict if ',' in valuesDict["newAlexaName"]: errorsDict = indigo.Dict() errorsDict["newAlexaName"] = "New Alexa Name cannot contain the comma character i.e. ','" errorsDict["showAlertText"] = "New Alexa Name cannot contain the comma character i.e. ','" - return (valuesDict, errorsDict) + return valuesDict, errorsDict if ';' in valuesDict["newAlexaName"]: errorsDict = indigo.Dict() errorsDict["newAlexaName"] = "New Alexa Name cannot contain the semicolon character i.e. ';'" errorsDict["showAlertText"] = "New Alexa Name cannot contain the semicolon character i.e. ';'" - return (valuesDict, errorsDict) + return valuesDict, errorsDict newAlexaName = valuesDict["newAlexaName"] newAlexaNameKey = newAlexaName.lower() @@ -1303,29 +1295,29 @@ def addNewAlexaDevice(self, valuesDict, typeId, ahbDevId): if ahbDevId == alexaHueBridgeId: errorsDict = indigo.Dict() errorsDict["newAlexaName"] = "Duplicate Alexa Name" - errorsDict["showAlertText"] = "Alexa Device Name '%s' is already allocated on this Alexa-Hue Bridge" % newAlexaName + errorsDict["showAlertText"] = "Alexa Device Name '{}' is already allocated on this Alexa-Hue Bridge".format(newAlexaName) else: alexaHueBridgeName = indigo.devices[alexaHueBridgeId].name errorsDict = indigo.Dict() errorsDict["newAlexaName"] = "Duplicate Alexa Name" - errorsDict["showAlertText"] = "Alexa Device Name '%s' is already allocated on Alexa-Hue Bridge '%s'" % (newAlexaName, alexaHueBridgeName) - return (valuesDict, errorsDict) + errorsDict["showAlertText"] = "Alexa Device Name '{}' is already allocated on Alexa-Hue Bridge '{}'".format(newAlexaName, alexaHueBridgeName) + return valuesDict, errorsDict if valuesDict["actionOrDevice"] == 'D': devId = int(valuesDict["sourceDeviceMenu"]) if devId == 0: errorsDict = indigo.Dict() errorsDict["newAlexaName"] = "Indigo Device not selected" - errorsDict["showAlertText"] = "No Indigo device selected for Alexa Device Name '%s'" % (newAlexaName) - return (valuesDict, errorsDict) + errorsDict["showAlertText"] = "No Indigo device selected for Alexa Device Name '{}'".format(newAlexaName) + return valuesDict, errorsDict else: # Assume 'A' = Action actionOnId = int(valuesDict["sourceOnActionMenu"]) actionOffId = int(valuesDict["sourceOffActionMenu"]) if actionOnId == 0 or actionOffId == 0: errorsDict = indigo.Dict() errorsDict["newAlexaName"] = "Indigo Actions not selected for On or Off or both" - errorsDict["showAlertText"] = "Indigo Actions not selected for On or Off or both, for Alexa Device Name '%s'" % (newAlexaName) - return (valuesDict, errorsDict) + errorsDict["showAlertText"] = "Indigo Actions not selected for On or Off or both, for Alexa Device Name '{}'".format(newAlexaName) + return valuesDict, errorsDict @@ -1350,11 +1342,11 @@ def addNewAlexaDevice(self, valuesDict, typeId, ahbDevId): valuesDict['alexaDevices'] = json.dumps(publishedAlexaDevices) - self.generalLogger.debug(u'NUMBER OF DEVICES PRE UPDATE = %s' % len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices'])) + self.generalLogger.debug(u"NUMBER OF DEVICES PRE UPDATE = {}".format(len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices']))) self.retrievePublishedDevices(valuesDict, ahbDevId, False, False) # This picks up the add of the new device + don't output info message + don't Check for V2 definitions - self.generalLogger.debug(u'NUMBER OF DEVICES POST UPDATE = %s' % len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices'])) + self.generalLogger.debug(u"NUMBER OF DEVICES POST UPDATE = {}".format(len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices']))) valuesDict["newAlexaName"] = '' valuesDict["updatedAlexaDeviceName"] = '' @@ -1369,9 +1361,9 @@ def addNewAlexaDevice(self, valuesDict, typeId, ahbDevId): valuesDict["showLimitMessage"] = True except StandardError, e: - self.generalLogger.error(u"StandardError detected in updateAlexaDevice for '%s'. Line '%s' has error='%s'" % (indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) + self.generalLogger.error(u"StandardError detected in updateAlexaDevice for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) - self.generalLogger.debug(u'addNewAlexaDevice VALUESDICT = %s' % valuesDict) + self.generalLogger.debug(u"addNewAlexaDevice VALUESDICT = {}".format(valuesDict)) return valuesDict ######################################## @@ -1395,41 +1387,41 @@ def updateAlexaDevice(self, valuesDict, typeId, ahbDevId): errorsDict = indigo.Dict() errorsDict["updatedAlexaDeviceName"] = "Alexa Name is missing and must be present." errorsDict["showAlertText"] = "Alexa Name is missing and must be present." - return (valuesDict, errorsDict) + return valuesDict, errorsDict if '|' in updatedAlexaDeviceName: errorsDict = indigo.Dict() errorsDict["updatedAlexaDeviceName"] = "New Alexa Name cannot contain the vertical bar character i.e. '|'" errorsDict["showAlertText"] = "New Alexa Name cannot contain the vertical bar character i.e. '|'" - return (valuesDict, errorsDict) + return valuesDict, errorsDict if ',' in updatedAlexaDeviceName: errorsDict = indigo.Dict() errorsDict["updatedAlexaDeviceName"] = "New Alexa Name cannot contain the comma character i.e. ','" errorsDict["showAlertText"] = "New Alexa Name cannot contain the comma character i.e. ','" - return (valuesDict, errorsDict) + return valuesDict, errorsDict if ';' in updatedAlexaDeviceName: errorsDict = indigo.Dict() errorsDict["updatedAlexaDeviceName"] = "New Alexa Name cannot contain the semicolon character i.e. ';'" errorsDict["showAlertText"] = "New Alexa Name cannot contain the semicolon character i.e. ';'" - return (valuesDict, errorsDict) + return valuesDict, errorsDict if valuesDict["actionOrDevice"] == 'D': devId = int(valuesDict["sourceDeviceMenu"]) if devId == 0: errorsDict = indigo.Dict() errorsDict["updatedAlexaDeviceName"] = "Indigo Device not selected" - errorsDict["showAlertText"] = "No Indigo device selected for Alexa Device Name '%s'" % (updatedAlexaDeviceName) - return (valuesDict, errorsDict) + errorsDict["showAlertText"] = "No Indigo device selected for Alexa Device Name '{}'".format(updatedAlexaDeviceName) + return valuesDict, errorsDict else: # Assume 'A' = Action actionOnId = int(valuesDict["sourceOnActionMenu"]) actionOffId = int(valuesDict["sourceOffActionMenu"]) if actionOnId == 0 or actionOffId == 0: errorsDict = indigo.Dict() errorsDict["updatedAlexaDeviceName"] = "Indigo Actions not selected for On or Off or both" - errorsDict["showAlertText"] = "Indigo Actions not selected for On or Off or both, for Alexa Device Name '%s'" % (updatedAlexaDeviceName) - return (valuesDict, errorsDict) + errorsDict["showAlertText"] = "Indigo Actions not selected for On or Off or both, for Alexa Device Name '{}'".format(updatedAlexaDeviceName) + return valuesDict, errorsDict alexaDeviceNameKey, alexaDeviceName, alexaHueBridgeId = valuesDict["alexaDevicesList"].split("|") @@ -1439,19 +1431,19 @@ def updateAlexaDevice(self, valuesDict, typeId, ahbDevId): if ahbDevId == alexaHueBridgeId: errorsDict = indigo.Dict() errorsDict["updatedAlexaDeviceName"] = "Duplicate Alexa Name" - errorsDict["showAlertText"] = "Alexa Device Name '%s' is already allocated on this Alexa-Hue Bridge" % updatedAlexaDeviceName + errorsDict["showAlertText"] = "Alexa Device Name '{}' is already allocated on this Alexa-Hue Bridge".format(updatedAlexaDeviceName) else: alexaHueBridgeName = indigo.devices[alexaHueBridgeId].name errorsDict = indigo.Dict() errorsDict["updatedAlexaDeviceName"] = "Duplicate Alexa Name" - errorsDict["showAlertText"] = "Alexa Device Name '%s' is already allocated on Alexa-Hue Bridge '%s'" % (updatedAlexaDeviceName, alexaHueBridgeName) - return (valuesDict, errorsDict) + errorsDict["showAlertText"] = "Alexa Device Name '{}' is already allocated on Alexa-Hue Bridge '{}'".format(updatedAlexaDeviceName, alexaHueBridgeName) + return valuesDict, errorsDict try: publishedAlexaDevices = self.jsonLoadsProcess(valuesDict['alexaDevices']) - updatedAlexaDeviceData = {} + updatedAlexaDeviceData = dict() updatedAlexaDeviceData['hashKey'] = self.createHashKey(updatedAlexaDeviceNameKey) updatedAlexaDeviceData['name'] = updatedAlexaDeviceName if valuesDict["actionOrDevice"] == 'D': @@ -1476,11 +1468,11 @@ def updateAlexaDevice(self, valuesDict, typeId, ahbDevId): valuesDict['alexaDevices'] = json.dumps(publishedAlexaDevices) - self.generalLogger.debug(u'NUMBER OF DEVICES PRE UPDATE = %s' % len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices'])) + self.generalLogger.debug(u"NUMBER OF DEVICES PRE UPDATE = {}".format(len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices']))) self.retrievePublishedDevices(valuesDict, ahbDevId, False, False) # This picks up the update of the existing device + don't output info message + don't Check for V2 definitions - self.generalLogger.debug(u'NUMBER OF DEVICES POST UPDATE = %s' % len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices'])) + self.generalLogger.debug(u"NUMBER OF DEVICES POST UPDATE = {}".format(len(self.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices']))) valuesDict["newAlexaName"] = '' valuesDict["updatedAlexaDeviceName"] = '' @@ -1495,9 +1487,9 @@ def updateAlexaDevice(self, valuesDict, typeId, ahbDevId): valuesDict["showLimitMessage"] = True except StandardError, e: - self.generalLogger.error(u"StandardError detected in updateAlexaDevice for '%s'. Line '%s' has error='%s'" % (indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) + self.generalLogger.error(u"StandardError detected in updateAlexaDevice for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) - self.generalLogger.debug(u'updateAlexaDevice VALUESDICT = %s' % valuesDict) + self.generalLogger.debug(u"updateAlexaDevice VALUESDICT = {}".format(valuesDict)) return valuesDict ########################################################################################## @@ -1534,7 +1526,7 @@ def deleteDevices(self, valuesDict, typeId, ahbDevId): def publishedAlexaDevicesList(self, filter, valuesDict, typeId, ahbDevId): self.methodTracer.threaddebug(u"CLASS: Plugin") - self.generalLogger.debug(u"memberDevices called with filter: %s typeId: %s Hue Hub: %s" % (filter, typeId, str(ahbDevId))) + self.generalLogger.debug(u"memberDevices called with filter: {} typeId: {} Hue Hub: {}".format(filter, typeId, str(ahbDevId))) returnList = list() if 'publishedAlexaDevices' in self.globals['alexaHueBridge'][ahbDevId]: @@ -1546,12 +1538,12 @@ def publishedAlexaDevicesList(self, filter, valuesDict, typeId, ahbDevId): if alexaData['devId'] in indigo.devices: dev = indigo.devices[alexaData['devId']] if dev.name != alexaDeviceName: - listName += " = %s" % dev.name + listName += " = {}".format(dev.name) else: listName += " = MISSING!" else: # Assume 'A' = Action listName += " = ACTIONS" - alexaDeviceListKey = '%s|%s' % (alexaDeviceNameKey, alexaDeviceName) + alexaDeviceListKey = "{}|{}".format(alexaDeviceNameKey, alexaDeviceName) returnList.append((alexaDeviceListKey, listName)) returnList = sorted(returnList, key= lambda item: item[0]) return returnList @@ -1566,12 +1558,12 @@ def validateActionConfigUi(self, valuesDict, typeId, devId): try: amount = int(valuesDict["discoveryExpiration"]) if amount not in range(0, 11): - raise - except: + raise ValueError("Amount must be a positive integer from 0 to 10") + except ValueError: errorsDict["amount"] = "Amount must be a positive integer from 0 to 10" if len(errorsDict) > 0: - return (False, valuesDict, errorsDict) - return (True, valuesDict) + return False, valuesDict, errorsDict + return True, valuesDict ######################################## # Method called from bridge thread to turn on/off an Alexa device @@ -1583,7 +1575,7 @@ def validateActionConfigUi(self, valuesDict, typeId, devId): def turnOnOffDevice(self, ahbDevId, alexaDeviceNameKey, turnOn): ahbDev = indigo.devices[ahbDevId] - publishedAlexaDevices = self.jsonLoadsProcess(ahbDev.pluginProps['alexaDevices']) + publishedAlexaDevices = self.jsonLoadsProcess(ahbDev.pluginProps['alexaDevices']) alexaDeviceNameKey = alexaDeviceNameKey.lower() if alexaDeviceNameKey in publishedAlexaDevices: alexaDeviceData = publishedAlexaDevices[alexaDeviceNameKey] @@ -1593,13 +1585,13 @@ def turnOnOffDevice(self, ahbDevId, alexaDeviceNameKey, turnOn): devId = int(alexaDeviceData['devId']) name = indigo.devices[devId].name onOff = 'ON' if turnOn else 'OFF' - self.generalLogger.info(u"Set on state of Alexa device \"%s\" [\"%s\"] to %s" % (alexaDeviceName, name, onOff)) + self.generalLogger.info(u"Set on state of Alexa device \"{}\" [\"{}\"] to {}".format(alexaDeviceName, name, onOff)) if turnOn: indigo.device.turnOn(devId) else: indigo.device.turnOff(devId) except: - self.generalLogger.error(u"Indigo Device with id %i doesn't exist for Alexa Device \"%s\" - Edit Alexa Hue Bridge \"%s\" and correct error." % (devId, alexaDeviceName, ahbDev.name)) + self.generalLogger.error(u"Indigo Device with id {} doesn't exist for Alexa Device \"{}\" - Edit Alexa Hue Bridge \"{}\" and correct error.".format(devId, alexaDeviceName, ahbDev.name)) elif alexaDeviceData['mode'] == 'A': # Action onOffVarId = int(alexaDeviceData['variableOnOffId']) actionOnId = int(alexaDeviceData['actionOnId']) @@ -1614,9 +1606,9 @@ def turnOnOffDevice(self, ahbDevId, alexaDeviceNameKey, turnOn): indigo.actionGroup.execute(actionOnId) else: indigo.actionGroup.execute(actionOffId) - self.generalLogger.info(u"Set on state of Alexa device \"%s\" to %s" % (alexaDeviceName, onOff)) + self.generalLogger.info(u"Set on state of Alexa device \"{}\" to {}".format(alexaDeviceName, onOff)) except: - self.generalLogger.error(u"Alexa Device \"%s\" doesn't have supporting Indigo Actions." % alexaDeviceName) + self.generalLogger.error(u"Alexa Device \"{}\" doesn't have supporting Indigo Actions.".format(alexaDeviceName)) ######################################## @@ -1640,20 +1632,20 @@ def setDeviceBrightness(self, ahbDevId, alexaDeviceNameKey, brightness): dev = indigo.devices[devId] name = dev.name except: - self.generalLogger.error(u"Indigo Device with id %i doesn't exist for Alexa Device \"%s\" - Edit Alexa Hue Bridge \"%s\" and correct error." % (devId, alexaDeviceName, ahbDev.name)) + self.generalLogger.error(u"Indigo Device with id {} doesn't exist for Alexa Device \"{}\" - Edit Alexa Hue Bridge \"{}\" and correct error.".format(devId, alexaDeviceName, ahbDev.name)) return if isinstance(dev, indigo.DimmerDevice): - self.generalLogger.info(u"Set brightness of Alexa device \"%s\" [\"%s\"] to %i" % (alexaDeviceName, name, brightness)) + self.generalLogger.info(u"Set brightness of Alexa device \"{}\" [\"{}\"] to {}".format(alexaDeviceName, name, brightness)) indigo.dimmer.setBrightness(dev, value=brightness) else: - self.generalLogger.error(u"Alexa Device \"%s\" [\"%s\"] doesn't support dimming." % name) + self.generalLogger.error(u"Alexa Device \"{}\" [\"{}\"] doesn't support dimming.".format(alexaDeviceName, name)) elif alexaDevice['mode'] == 'A': # Action dimVarId = int(alexaDevice['variableDimId']) actionDimId = int(alexaDevice['actionDimId']) if dimVarId == 0 and actionDimId == 0: - self.generalLogger.error(u"Alexa Device \"%s\" doesn't support dimming." % alexaDeviceName) + self.generalLogger.error(u"Alexa Device \"{}\" doesn't support dimming.".format(alexaDeviceName)) else: - self.generalLogger.info(u"Set brightness of Alexa device \"%s\" to %i" % (alexaDeviceName, brightness)) + self.generalLogger.info(u"Set brightness of Alexa device \"{}\" to {}".format(alexaDeviceName, brightness)) if dimVarId != 0: brightness = str(brightness) indigo.variable.updateValue(dimVarId, value=brightness) @@ -1667,19 +1659,19 @@ def actionControlDimmerRelay(self, action, ahbDev): ###### TURN ON DISCOVERY ###### if action.deviceAction == indigo.kDimmerRelayAction.TurnOn: - self.generalLogger.info(u"sent \"%s\" %s" % (ahbDev.name, "Discovery on")) + self.generalLogger.info(u"sent \"{}\" {}".format(ahbDev.name, "Discovery on")) self.startDiscovery(action, ahbDev) ###### TURN OFF DISCOVERY ###### elif action.deviceAction == indigo.kDimmerRelayAction.TurnOff: - self.generalLogger.info(u"sent \"%s\" %s" % (ahbDev.name, "Discovery off")) + self.generalLogger.info(u"sent \"{}\" {}".format(ahbDev.name, "Discovery off")) self.stopDiscovery(action, ahbDev) ###### TOGGLE ###### elif action.deviceAction == indigo.kDimmerRelayAction.Toggle: - self.generalLogger.info(u"sent \"%s\" %s" % (ahbDev.name, "Discovery Toggle")) + self.generalLogger.info(u"sent \"{}\" {}".format(ahbDev.name, "Discovery Toggle")) desiredOnState = not ahbDev.onState - if desiredOnState == True: + if desiredOnState: self.startDiscovery(action, ahbDev) else: self.stopDiscovery(action, ahbDev) @@ -1695,7 +1687,7 @@ def startDiscovery(self, action, ahbDev): else: if not self.globals['alexaHueBridge'][ahbDev.id]['broadcaster'].is_alive(): start_broadcaster_required = True - if start_broadcaster_required == True: + if start_broadcaster_required: self.globals['alexaHueBridge'][ahbDev.id]['broadcaster'] = Broadcaster(self, ahbDev.id) try: self.globals['alexaHueBridge'][ahbDev.id]['broadcaster'].start() @@ -1703,10 +1695,10 @@ def startDiscovery(self, action, ahbDev): except StandardError, e: # the broadcaster won't start for some reason, so just tell them to try restarting the plugin - self.generalLogger.error(u"Start Discovery action failed for '%s': broadcaster thread couldn't start. Try restarting the plugin.'" % self.globals['alexaHueBridge'][ahbDev.id]['hubName']) + self.generalLogger.error(u"Start Discovery action failed for '{}': broadcaster thread couldn't start. Try restarting the plugin.'".format(self.globals['alexaHueBridge'][ahbDev.id]['hubName'])) errorLines = traceback.format_exc().splitlines() for errorLine in errorLines: - self.generalLogger.error(u"%s" % errorLine) + self.generalLogger.error(u"{}".format(errorLine)) return @@ -1716,19 +1708,19 @@ def startDiscovery(self, action, ahbDev): else: if not self.globals['alexaHueBridge'][ahbDev.id]['responder'].is_alive(): start_responder_required = True - if start_responder_required == True: + if start_responder_required: self.globals['alexaHueBridge'][ahbDev.id]['responder'] = Responder(self, ahbDev.id) try: self.globals['alexaHueBridge'][ahbDev.id]['responder'].start() self.setDeviceDiscoveryState(True, ahbDev.id) - self.generalLogger.info(u"Starting Hue Bridge '%s' discovery threads as 'Turn On Discovery' requested" % self.globals['alexaHueBridge'][ahbDev.id]['hubName']) + self.generalLogger.info(u"Starting Hue Bridge '{}' discovery threads as 'Turn On Discovery' requested".format(self.globals['alexaHueBridge'][ahbDev.id]['hubName'])) except: self.generalLogger.info(u"Start Discovery action failed") self.setDeviceDiscoveryState(False, ahbDev.id) # the responder won't start for some reason, so just tell them to try restarting the plugin - self.generalLogger.error(u"Start Discovery action failed for '%s': responder thread couldn't start. Try restarting the plugin." % self.globals['alexaHueBridge'][ahbDev.id]['hubName']) + self.generalLogger.error(u"Start Discovery action failed for '{}': responder thread couldn't start. Try restarting the plugin.".format(self.globals['alexaHueBridge'][ahbDev.id]['hubName'])) # If the broadcaster thread started correctly, then we need to shut it down since it won't work # without the responder thread. if self.globals['alexaHueBridge'][ahbDev.id]['broadcaster']: @@ -1747,13 +1739,13 @@ def stopDiscovery(self, action, ahbDev): if 'responder' in self.globals['alexaHueBridge'][ahbDev.id]: if self.globals['alexaHueBridge'][ahbDev.id]['responder']: self.globals['alexaHueBridge'][ahbDev.id]['responder'].stop() - self.generalLogger.info(u"Stopping Hue Bridge '%s' discovery threads as 'Turn Off Discovery' requested" % self.globals['alexaHueBridge'][ahbDev.id]['hubName']) + self.generalLogger.info(u"Stopping Hue Bridge '{}' discovery threads as 'Turn Off Discovery' requested".format(self.globals['alexaHueBridge'][ahbDev.id]['hubName'])) def setDeviceDiscoveryState(self, discoveryOn, ahbDevId): self.methodTracer.threaddebug(u"CLASS: Plugin") try: - self.generalLogger.debug(u'SET DEVICE DISCOVERY STATE = %s' % discoveryOn) + self.generalLogger.debug(u"SET DEVICE DISCOVERY STATE = {}".format(discoveryOn)) if discoveryOn: indigo.devices[ahbDevId].updateStateOnServer("onOffState", True, uiValue="Discovery: On") if self.globals['alexaHueBridge'][ahbDevId]['discoveryExpiration'] == 0: diff --git a/README.md b/README.md index 37dfb53..9c94dff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Overview -The Alexa-Hue Bridge is a plugin for version 7+ of the [Indigo Home Automation system][1]. Version 3.x of this plugin emulates multiple Philips Hue bridges to publish Indigo actions and devices (on/off and dimmer types only) to most Amazon Alexa devices (Echo, Dot, FireTV, etc.). +The Alexa-Hue Bridge is a plugin for version 7+ of the [Indigo Home Automation system][1]. Version 3.x of this plugin emulates multiple Philips Hue bridges to publish Indigo actions and devices (on/off and dimmer types only) to most Amazon Alexa devices (Echo [Gen 1], Dot [Gen 1 & 2], FireTV, etc.). Use the latest 1.x release for Indigo 6. @@ -10,8 +10,6 @@ Version 3 adds the ability to directly control Indigo Actions in addition to Ind It is **strongly recommended** to read the [Wiki Documentation][4] to familiarise yourself with the new way of working which is substantially different to earlier plugin versions (V1 and V2). -**The latest production release is available here: [https://github.com/IndigoDomotics/alexa-hue-bridge/releases][6]** - [1]: https://www.indigodomo.com [4]: http://wiki.indigodomo.com/doku.php?id=indigo_7_documentation:virtual_devices_interface#virtual_on_off_devices [6]: https://github.com/IndigoDomotics/alexa-hue-bridge/releases