diff --git a/Alexa-Hue Bridge.indigoPlugin/Contents/Info.plist b/Alexa-Hue Bridge.indigoPlugin/Contents/Info.plist index 71fb2e1..238541a 100755 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Info.plist +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Info.plist @@ -3,7 +3,7 @@ PluginVersion - 3.0.26 + 3.0.27 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 7341f95..a052012 100755 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery.py +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/discovery.py @@ -73,35 +73,35 @@ def __init__(self, plugin, ahbDevId): self.interrupted = False - broadcast_data = {"broadcast_ip": BCAST_IP, - "upnp_port": UPNP_PORT, - "server_ip": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['host'], - "server_port": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], - "uuid": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['uuid']} - self.broadcast_packet = broadcast_packet % broadcast_data + self.broadcast_data = {"broadcast_ip": BCAST_IP, + "upnp_port": UPNP_PORT, + "server_ip": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['host'], + "server_port": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['port'], + "uuid": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['uuid']} + self.broadcast_packet = broadcast_packet % self.broadcast_data except StandardError, e: PLUGIN.broadcasterLogger.error(u"StandardError detected in Broadcaster.Init for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) def run(self): try: PLUGIN.broadcasterLogger.debug("Broadcaster.run called") - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) - sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20) - start_time = time.time() - end_time = start_time + (PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] * 60) + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20) + self.start_time = time.time() + self.end_time = self.start_time + (PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] * 60) PLUGIN.broadcasterLogger.debug("Broadcaster.run: sending first broadcast:\n{}".format(self.broadcast_packet)) while True: - sock.sendto(self.broadcast_packet, (BCAST_IP, UPNP_PORT)) + self.sock.sendto(self.broadcast_packet, (BCAST_IP, UPNP_PORT)) for x in range(BROADCAST_INTERVAL): time.sleep(1.5) # Following code will only time out the Broadcaster Thread if PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] > 0 (valid values 0 thru 10 inclusive) # A value of zero means 'always on' - if PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] and time.time() > end_time: + if PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] and time.time() > self.end_time: PLUGIN.broadcasterLogger.debug("Broadcaster thread timed out") self.stop() if self.interrupted: PLUGIN.setDeviceDiscoveryState(False, self.ahbDevId) - sock.close() + self.sock.close() return except StandardError, e: @@ -122,45 +122,46 @@ def __init__(self, plugin, ahbDevId): try: self.ahbDevId = ahbDevId + self.ahbName = indigo.devices[self.ahbDevId].name 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'], - "uuid": PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['uuid']} - self.response_packet = response_packet % response_data + self.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 % self.response_data except StandardError, e: PLUGIN.responderLogger.error(u"StandardError detected in Responder.Init for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDevId].name, sys.exc_traceback.tb_lineno, e)) def run(self): try: PLUGIN.responderLogger.debug("Responder.run called") - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) try: - sock.bind(('', UPNP_PORT)) - sock.setsockopt(socket.IPPROTO_IP, + self.sock.bind(('', UPNP_PORT)) + self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(BCAST_IP) + socket.inet_aton(PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['host'])) - sock.settimeout(1) - start_time = time.time() - end_time = start_time + (PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] * 60) + self.sock.settimeout(1) + self.start_time = time.time() + self.end_time = self.start_time + (PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] * 60) while True: try: - data, addr = sock.recvfrom(1024) + self.data, self.addr = self.sock.recvfrom(1024) # Following code discards non-Echo network traffic if option set in plugin config if PLUGIN.globals['amazonEchoDeviceFilterActive']: - if addr[0] not in PLUGIN.globals['amazonEchoDevices'].values(): + if self.addr[0] not in PLUGIN.globals['amazonEchoDevices']: if PLUGIN.globals['debug']['filter']: - PLUGIN.responderLogger.debug("Responder.respond called from SKIPPED address '{}'".format(str(addr[0]))) + PLUGIN.responderLogger.debug("Responder.respond called from SKIPPED address '{}'".format(str(self.addr[0]))) continue # Following code will only time out the Broadcaster Thread if PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] > 0 (valid values 0 thru 10 inclusive) # A value of zero means 'always on' - if PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] and time.time() > end_time: + if PLUGIN.globals['alexaHueBridge'][self.ahbDevId]['discoveryExpiration'] and time.time() > self.end_time: PLUGIN.responderLogger.debug("Responder.run thread timed out") self.stop() raise socket.error @@ -168,12 +169,12 @@ def run(self): if self.interrupted: PLUGIN.responderLogger.debug("Responder.run: self.interrupted: True") PLUGIN.setDeviceDiscoveryState(False, self.ahbDevId) - sock.close() + self.sock.close() return else: - if M_SEARCH_REQ_MATCH in data: - PLUGIN.responderLogger.debug("Responder.run: received: {}".format(str(data))) - self.respond(addr) + if M_SEARCH_REQ_MATCH in self.data: + PLUGIN.responderLogger.debug("Responder.run: received from {}: {}".format(self.addr, str(self.data))) + self.respond(self.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 # stop the thread (which really isn't needed, but it logs a nice stop debug message). @@ -197,13 +198,13 @@ def stop(self): PLUGIN.responderLogger.debug("Responder thread stopped") self.interrupted = True - def respond(self, addr): - time.sleep(1.5) - PLUGIN.responderLogger.debug("Responder.respond called from address {}\n{}".format(str(addr), self.response_packet)) - PLUGIN.responderLogger.debug("Responder.respond: creating output_socket") - output_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - PLUGIN.responderLogger.debug("Responder.respond: calling output_socket.sendto") - 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 {}".format(str(addr))) + def respond(self, p1_addr, ): + #time.sleep(1.5) + PLUGIN.responderLogger.debug("Responder.respond for {}, called from address {}\n{}".format(self.ahbName, str(p1_addr), self.response_packet)) + PLUGIN.responderLogger.debug("Responder.respond: for {}, creating output_socket".format(self.ahbName)) + self.output_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + PLUGIN.responderLogger.debug("Responder.respond: for {}, calling output_socket.sendto".format(self.ahbName)) + self.output_socket.sendto(self.response_packet, p1_addr) + PLUGIN.responderLogger.debug("Responder.respond: for {}, closing output_socket".format(self.ahbName)) + self.output_socket.close() + PLUGIN.responderLogger.debug("Responder.respond: for {}, UDP Response sent to {}".format(self.ahbName, str(p1_addr))) 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 a73356b..dfa6bd0 100755 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/hue_listener.py +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/hue_listener.py @@ -22,8 +22,6 @@ import time import traceback -from constants import * - FILE_LIST = ["/description.xml", "/index.html", "/hue_logo_0.png", "/hue_logo_3.png"] DESCRIPTION_XML = """ @@ -80,6 +78,7 @@ PLUGIN = None + class Httpd(threading.Thread): def __init__(self, plugin, ahbDevId): threading.Thread.__init__(self) @@ -148,198 +147,192 @@ class HttpdRequestHandler(SocketServer.BaseRequestHandler): def handle(self): try: - client_ip = self.client_address[0] - client_port = self.client_address[1] - self.client_name_address = u"{}:{}".format(self.client_address[0],self.client_address[1]) - knownEchoaddress = False - for aeDevId, aeIpAddress in PLUGIN.globals['amazonEchoDevices'].iteritems(): - if aeIpAddress == self.client_address[0]: - knownEchoaddress = True - self.client_name_address = u"'{}':{}".format(indigo.devices[aeDevId].name, self.client_address[1]) - datetimeNowUi = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - keyValueList = [ - {'key': 'activityDetected', 'value': True, 'uiValue': 'Active'}, - {'key': 'lastActiveDateTime', 'value': datetimeNowUi} - ] - indigo.devices[aeDevId].updateStatesOnServer(keyValueList) - - indigo.devices[aeDevId].updateStateImageOnServer(indigo.kStateImageSel.SensorOn) - - PLUGIN.globals['queues']['amazonEchoDeviceTimer'].put(aeDevId) # Queue a message to set a timer to set device inactive after a short period of time - break + self.client_ip = self.client_address[0] + self.client_port = self.client_address[1] + self.client_name_address = u"{}:{}".format(self.client_ip, self.client_port) + + # Following code checks to see whether device is a known Amazon Echo + self.knownEchoAddress = False + if self.client_ip in PLUGIN.globals['amazonEchoDevices']: + self.knownEchoAddress = True + self.aeDevId = PLUGIN.globals['amazonEchoDevices'][self.client_ip] + self.client_name_address = u"'{}':{}".format(indigo.devices[self.aeDevId].name, self.client_port) + self.datetimeNowUi = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + self.keyValueList = [ + {'key': 'activityDetected', 'value': True, 'uiValue': 'Active'}, + {'key': 'lastActiveDateTime', 'value': self.datetimeNowUi} + ] + indigo.devices[self.aeDevId].updateStatesOnServer(self.keyValueList) + indigo.devices[self.aeDevId].updateStateImageOnServer(indigo.kStateImageSel.SensorOn) + + PLUGIN.globals['queues']['amazonEchoDeviceTimer'].put(self.aeDevId) # Queue a message to set a timer to set device inactive after a short period of time # Following code discards non-Echo network traffic if option set in plugin config - if PLUGIN.globals['amazonEchoDeviceFilterActive'] and not knownEchoaddress: - if addr[0] not in PLUGIN.globals['amazonEchoDevices'].values(): + if PLUGIN.globals['amazonEchoDeviceFilterActive'] and not self.knownEchoAddress: + if self.client_ip not in PLUGIN.globals['amazonEchoDevices']: if PLUGIN.globals['debug']['filter']: - PLUGIN.responderLogger.debug("HttpdRequestHandler.handle called from SKIPPED address '{}'".format(str(addr[0]))) + PLUGIN.responderLogger.debug("HttpdRequestHandler.handle called from SKIPPED address '{}'".format(str(self.client_ip))) return - ahbDev = indigo.devices[self.server.alexaHueBridgeId] - data = self.request.recv(1024) - PLUGIN.serverLogger.debug(str("HttpdRequestHandler.handle invoked for '{}' by {} with data:\n{}\n\n".format(ahbDev.name, self.client_name_address, 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) - if put_match and put_data_match: - put_request_full = put_match.group(1).replace("..","") - put_data = put_data_match.group(1) - - put_reponse_data = self.put_response(self.server.alexaHueBridgeId, put_request_full, put_data) - if put_reponse_data is not None: + self.ahbDev = indigo.devices[self.server.alexaHueBridgeId] + self.data = self.request.recv(1024) + PLUGIN.serverLogger.debug(str("HttpdRequestHandler.handle invoked for '{}' by {} with data:\n{}\n\n".format(self.ahbDev.name, self.client_name_address, self.data))) + + self.get_match = re.search(r'GET (.*?(/[^\s^/]*?))\s', self.data) + if self.get_match: + self.get_request_full = self.get_match.group(1).replace(".." ,"") + self.send_headers(self.get_request_full) + self.request.sendall(self.get_response(self.server.alexaHueBridgeId, self.client_name_address, self.get_request_full, )) + self.put_match = re.search(r'PUT (.*?(/[^\s^/]*?))\s', self.data) + self.put_data_match = re.search(r'({.*})', self.data) + if self.put_match and self.put_data_match: + self.put_request_full = self.put_match.group(1).replace(".." ,"") + self.put_data = self.put_data_match.group(1) + + self.put_reponse_data = self.put_response(self.server.alexaHueBridgeId, self.client_name_address, self.put_request_full, self.put_data) + if self.put_reponse_data is not None: self.send_headers("file.json") - self.request.sendall(put_reponse_data) + self.request.sendall(self.put_reponse_data) - a = 1 - b = 2 - c = a + b except StandardError, e: - PLUGIN.serverLogger.error(u"StandardError detected in HttpdRequestHandler for '{}'. Line '{}' has error='{}'".format(ahbDev.name, sys.exc_traceback.tb_lineno, e)) + PLUGIN.serverLogger.error(u"StandardError detected in HttpdRequestHandler for '{}'. Line '{}' has error='{}'".format('self.ahbDev.name', sys.exc_traceback.tb_lineno, e)) + PLUGIN.serverLogger.error(u"StandardError detected in HttpdRequestHandler for '{}'. Line '{}' has error='{}'".format(self.ahbDev.name, sys.exc_traceback.tb_lineno, e)) - def send_headers(self, file): - self.request.sendall("HTTP/1.1 200 OK\r\n") - self.request.sendall("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n") - (type,encoding) = mimetypes.guess_type(file) - if type is None: - type = "application/json" - self.request.sendall("Content-type: "+type+"\r\n\r\n") - PLUGIN.serverLogger.debug("HttpdRequestHandler.send_headers: Sent content type: {}".format(type)) + def send_headers(self, p1_file): + try: + self.request.sendall("HTTP/1.1 200 OK\r\n") + self.request.sendall("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n") + (self.mimeType, self.mimeEncoding) = mimetypes.guess_type(p1_file) + if self.mimeType is None: + self.mimeType = "application/json" + self.request.sendall("Content-type: " + self.mimeType + "\r\n\r\n") + PLUGIN.serverLogger.debug("HttpdRequestHandler.send_headers: Sent content type: {}".format(self.mimeType)) + except StandardError, e: + PLUGIN.serverLogger.error(u"StandardError detected in HttpdRequestHandler for '{}'. Line '{}' has error='{}'".format('self.ahbDev.name', sys.exc_traceback.tb_lineno, e)) ######################################## # Utility methods ######################################## - def get_response(self, ahbDevId, request_string): + def get_response(self, p1_ahbDevId, p2_client_name_address, p3_request_string): try: - ahbDev = indigo.devices[ahbDevId] - PLUGIN.serverLogger.debug("hue_listener.get_response for '{}' from {}, request string: {}".format(ahbDev.name, self.client_name_address, request_string)) + self.ahbDev = indigo.devices[p1_ahbDevId] + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}' from {}, request string: {}".format(self.ahbDev.name, p2_client_name_address, p3_request_string)) # get device list - get_match = re.search(r'(/[^\s^/]+)$',request_string) - if get_match: - request_file=get_match.group(1) + self.get_match = re.search(r'(/[^\s^/]+)$', p3_request_string) + if self.get_match: + self.request_file = self.get_match.group(1) else: - request_file="" - if request_file == "" or request_file == "/": - 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 '{}' from {}, discovery request, returning the full list of devices in Hue JSON format".format(ahbDev.name, self.client_name_address)) - return self.getHueDeviceJSON(ahbDevId) + self.request_file = "" + if self.request_file == "" or self.request_file == "/": + self.request_file = "/index.html" + PLUGIN.serverLogger.debug("hue_listener.get_response request file: " + self.request_file) + if re.search(r'/lights$', p3_request_string): + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}' from {}, discovery request, returning the full list of devices in Hue JSON format".format(self.ahbDev.name, p2_client_name_address)) + return self.getHueDeviceJSON(p1_ahbDevId, p2_client_name_address) # 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 '{}' from {}, found /lights/ in request string: {}".format(ahbDev.name, self.client_name_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)) - if request_file == "/description.xml": - hostXml = PLUGIN.globals['alexaHueBridge'][ahbDevId]['host'] - portXml = PLUGIN.globals['alexaHueBridge'][ahbDevId]['port'] - uuidXml = PLUGIN.globals['alexaHueBridge'][ahbDevId]['uuid'] - desc_xml = DESCRIPTION_XML % {'host': hostXml, 'port': portXml, 'uuid': uuidXml} - PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', returning file description.xml with data:\n{}".format(ahbDev.name, desc_xml)) - return desc_xml - elif request_file == "/hue_logo_0.png": + self.get_device_match = re.search(r'/lights/([a-fA-F0-9]+)$', p3_request_string) + if self.get_device_match: + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}' from {}, found /lights/ in request string: {}".format(self.ahbDev.name, p2_client_name_address, p3_request_string)) + return self.getHueDeviceJSON(p1_ahbDevId, p2_client_name_address, self.get_device_match.group(1)) # Hash key + elif self.request_file in FILE_LIST: + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', serving from a local file: {}".format(self.ahbDev.name, self.request_file)) + if self.request_file == "/description.xml": + self.hostXml = PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['host'] + self.portXml = PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['port'] + self.uuidXml = PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['uuid'] + self.desc_xml = DESCRIPTION_XML % {'host': self.hostXml, 'port': self.portXml, 'uuid': self.uuidXml} + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', returning file description.xml with data:\n{}".format(self.ahbDev.name, self.desc_xml)) + return self.desc_xml + elif self.request_file == "/hue_logo_0.png": return ICON_SMALL.decode('base64') - elif request_file == "/hue_logo_3.png": + elif self.request_file == "/hue_logo_3.png": return ICON_BIG.decode('base64') - elif request_file == "/index.html": + elif self.request_file == "/index.html": return INDEX_HTML else: return "HTTP/1.1 404 Not Found" - 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)) + elif re.search(r'/api/[^/]+$', p3_request_string): + PLUGIN.serverLogger.debug("hue_listener.get_response for '{}', found /api/ in request string: {}".format(self.ahbDev.name, p3_request_string)) return "{}" else: return "{}" 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)) + PLUGIN.serverLogger.error(u"StandardError detected in get_response for '{}'. Line '{}' has error='{}'".format('self.ahbDev.name', sys.exc_traceback.tb_lineno, e)) ######################################## - def put_response(self, ahbDevId, request_string,request_data): + def put_response(self, p1_ahbDevId, p2_client_name_address, p3_request_string, p4_request_data): try: - ahbDev = indigo.devices[ahbDevId] - PLUGIN.serverLogger.debug("put_response for '{}', request_string:\n{}\nrequest_data:\n{}\n\n".format(ahbDev.name, request_string, request_data)) + self.ahbDev = indigo.devices[p1_ahbDevId] + PLUGIN.serverLogger.debug("put_response for '{}', p3_request_string:\n{}\np4_request_data:\n{}\n\n".format(self.ahbDev.name, p3_request_string, p4_request_data)) - put_device_match = re.search(r'/lights/([a-fA-F0-9]+)/state$',request_string) - if put_device_match: - alexaDeviceHashedKey = str(put_device_match.group(1)) + self.put_device_match = re.search(r'/lights/([a-fA-F0-9]+)/state$', p3_request_string) + if self.put_device_match: + self.alexaDeviceHashedKey = str(self.put_device_match.group(1)) - # if alexaDeviceHashedKey == "c3202b3cd2301f75d371c0c660d1c06ecb49f4198036ff7c085810fef5a7f57d": # TESTING - # alexaDeviceHashedKey = 420025267 # TESTING - - if str(alexaDeviceHashedKey).isdigit(): + if str(self.alexaDeviceHashedKey).isdigit(): try: - name = indigo.devices[int(alexaDeviceHashedKey)].name + self.name = indigo.devices[int(self.alexaDeviceHashedKey)].name except: - name = "unknown device with ID {}".format(alexaDeviceHashedKey) - PLUGIN.serverLogger.error(u"Unable to process Alexa request on '{}' : Alexa key {} is not a valid hash key for '{}'".format(ahbDev.name, alexaDeviceHashedKey, name)) + self.name = "unknown device with ID {}".format(self.alexaDeviceHashedKey) + PLUGIN.serverLogger.error(u"Unable to process Alexa request on '{}' : Alexa key {} is not a valid hash key for '{}'".format(self.ahbDev.name, self.alexaDeviceHashedKey, self.name)) return - if alexaDeviceHashedKey not in PLUGIN.globals['alexaHueBridge'][ahbDevId]['hashKeys']: - 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)) + if self.alexaDeviceHashedKey not in PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['hashKeys']: + PLUGIN.serverLogger.error(u"Alexa-Hue Bridge '{}' does not publish a device/action with Hash Key '{}'".format(self.ahbDev.name, self.alexaDeviceHashedKey)) + if self.alexaDeviceHashedKey in PLUGIN.globals['alexaHueBridge']['publishedHashKeys']: + PLUGIN.serverLogger.error(u"Device/Action with Hash Key '{}' is published by Alexa-Hue Bridge '{}'".format(self.alexaDeviceHashedKey, indigo.devices[PLUGIN.globals['alexaHueBridge']['publishedHashKeys'][self.alexaDeviceHashedKey]].name)) PLUGIN.serverLogger.error(u"Re-run discovery to correct this problem.") return else: - alexaDeviceNameKey = PLUGIN.globals['alexaHueBridge'][ahbDevId]['hashKeys'][alexaDeviceHashedKey] + self.alexaDeviceNameKey = PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['hashKeys'][self.alexaDeviceHashedKey] - disableAlexaVariableId = PLUGIN.globals['alexaHueBridge'][ahbDevId]['disableAlexaVariableId'] + self.disableAlexaVariableId = PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['disableAlexaVariableId'] - if disableAlexaVariableId in indigo.variables and indigo.variables[disableAlexaVariableId].value == 'true': - if not PLUGIN.globals['alexaHueBridge'][ahbDevId]['hideDisableAlexaVariableMessages']: - PLUGIN.serverLogger.info(u"Alexa-Hue Bridge '{}' Alexa commands disabled (by variable): Alexa command for device/ action '{}' ignored.".format(ahbDev.name, alexaDeviceNameKey)) + if self.disableAlexaVariableId in indigo.variables and indigo.variables[self.disableAlexaVariableId].value == 'true': + if not PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['hideDisableAlexaVariableMessages']: + PLUGIN.serverLogger.info(u"Alexa-Hue Bridge '{}' Alexa commands disabled (by variable): Alexa command for device/ action '{}' ignored.".format(self.ahbDev.name, self.alexaDeviceNameKey)) return - request = json.loads(request_data) - if "bri" in request: - PLUGIN.setDeviceBrightness(self.client_name_address, ahbDevId, alexaDeviceNameKey, int(round((float(request["bri"]) * 100.0 ) / 255.0))) # 2017-AUG-15 - elif "on" in request: + self.requestData = json.loads(p4_request_data) + if "bri" in self.requestData: + PLUGIN.setDeviceBrightness(p2_client_name_address, p1_ahbDevId, self.alexaDeviceNameKey, int(round((float(self.requestData["bri"]) * 100.0) / 255.0))) # 2017-AUG-15 + elif "on" in self.requestData: # ON == TRUE, OFF == FALSE - PLUGIN.turnOnOffDevice(self.client_name_address, ahbDevId, alexaDeviceNameKey, request["on"]) - list = [] - for key in request: - list.append({"success":{key:request[key]}}) - return json.dumps(list) + PLUGIN.turnOnOffDevice(p2_client_name_address, p1_ahbDevId, self.alexaDeviceNameKey, self.requestData["on"]) + self.list = [] + for self.key in self.requestData: + self.list.append({"success":{self.key:self.requestData[self.key]}}) + return json.dumps(self.list) except StandardError, e: - PLUGIN.serverLogger.error(u"StandardError detected in put_response for device '{}'. Line '{}' has error='{}'".format(ahbDev.name, sys.exc_traceback.tb_lineno, e)) - + PLUGIN.serverLogger.error(u"StandardError detected in put_response for device '{}'. Line '{}' has error='{}'".format(self.ahbDev.name, sys.exc_traceback.tb_lineno, e)) ######################################## # This is the method that's called to build the member device list. Note # that valuesDict is read-only so any changes you make to it will be discarded. ######################################## - def getHueDeviceJSON(self, ahbDevId, alexaDeviceHashedKey=None): + def getHueDeviceJSON(self, p1_ahbDevId, p2_client_name_address, p3_alexaDeviceHashedKey=None): try: - self.ahbDevName = indigo.devices[ahbDevId].name - PLUGIN.serverLogger.debug(u"getHueDeviceJSON invoked for '{}' with #Key '{}'".format(self.ahbDevName, alexaDeviceHashedKey)) - if alexaDeviceHashedKey: - # if alexaDeviceHashedKey == "c3202b3cd2301f75d371c0c660d1c06ecb49f4198036ff7c085810fef5a7f57d": # TESTING - # alexaDeviceHashedKey = 420025261 # TESTING - - if str(alexaDeviceHashedKey).isdigit(): + self.ahbDevName = indigo.devices[p1_ahbDevId].name + PLUGIN.serverLogger.debug(u"getHueDeviceJSON invoked for '{}' with #Key '{}'".format(self.ahbDevName, p3_alexaDeviceHashedKey)) + if p3_alexaDeviceHashedKey: + if str(p3_alexaDeviceHashedKey).isdigit(): try: - name = indigo.devices[int(alexaDeviceHashedKey)].name + self.name = indigo.devices[int(p3_alexaDeviceHashedKey)].name except: - name = "unknown device with ID {}".format(alexaDeviceHashedKey) - PLUGIN.serverLogger.error(u"Unable to process Alexa request for '{}' : Alexa key {} is not a valid hash key for '{}'".format(self.ahbDevName, alexaDeviceHashedKey, name)) + self.name = "unknown device with ID {}".format(p3_alexaDeviceHashedKey) + PLUGIN.serverLogger.error(u"Unable to process Alexa request for '{}' : Alexa key {} is not a valid hash key for '{}'".format(self.ahbDevName, p3_alexaDeviceHashedKey, self.name)) return json.dumps({}) # Return the JSON for a single device - alexaDeviceNameKey = PLUGIN.globals['alexaHueBridge'][ahbDevId]['hashKeys'][alexaDeviceHashedKey] - PLUGIN.serverLogger.debug(u"getHueDeviceJSON single-device invocation for '{}' and called with Alexa Device Hash Key [Name]: {} [{}]".format(self.ahbDevName, alexaDeviceHashedKey, alexaDeviceNameKey)) - deviceDict = self._createDeviceDict('access', ahbDevId, alexaDeviceHashedKey, False) - PLUGIN.serverLogger.debug(u"'{}' json data: \n{}".format(self.ahbDevName, json.dumps(deviceDict, indent=4))) - return json.dumps(deviceDict) + self.alexaDeviceNameKey = PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['hashKeys'][p3_alexaDeviceHashedKey] + PLUGIN.serverLogger.debug(u"getHueDeviceJSON single-device invocation for '{}' and called with Alexa Device Hash Key [Name]: {} [{}]".format(self.ahbDevName, p3_alexaDeviceHashedKey, self.alexaDeviceNameKey)) + self.deviceDict = self._createDeviceDict('access', p1_ahbDevId, p3_alexaDeviceHashedKey, False) + PLUGIN.serverLogger.debug(u"'{}' json data: \n{}".format(self.ahbDevName, json.dumps(self.deviceDict, indent=4))) + return json.dumps(self.deviceDict) else: if PLUGIN.globals['showDiscoveryInEventLog']: PLUGIN.globals['discoveryId'] += 1 @@ -348,71 +341,71 @@ def getHueDeviceJSON(self, ahbDevId, alexaDeviceHashedKey=None): PLUGIN.serverLogger.debug(u"getHueDeviceJSON all-devices invocation for '{}: Discovery Count = {}".format(self.ahbDevName, self.discoveryId)) # 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: {}'.format(str(deviceListDict))) - PLUGIN.serverLogger.debug(u"'{}' json data: \n{}".format(self.ahbDevName, json.dumps(deviceListDict, indent=4))) + self.deviceListDict = self._createFullDeviceDict(p1_ahbDevId) + PLUGIN.serverLogger.debug('deviceListDict: {}'.format(str(self.deviceListDict))) + PLUGIN.serverLogger.debug(u"'{}' json data: \n{}".format(self.ahbDevName, json.dumps(self.deviceListDict, indent=4))) if PLUGIN.globals['showDiscoveryInEventLog']: - PLUGIN.globals['queues']['discoveryLogging'].put([self.discoveryId, self.client_name_address, self.ahbDevName, PLUGIN.globals['discoveryLists'][self.discoveryId]]) + PLUGIN.globals['queues']['discoveryLogging'].put([self.discoveryId, p2_client_name_address, self.ahbDevName, PLUGIN.globals['discoveryLists'][self.discoveryId]]) PLUGIN.serverLogger.debug(u"getHueDeviceJSON invocation completed for '{}'".format(self.ahbDevName)) - return json.dumps(deviceListDict) + return json.dumps(self.deviceListDict) except Exception, e: 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 ################################################################################ - def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDiscoveryInEventLog): + def _createDeviceDict(self, p1_function, p2_ahbDevId, p3_alexaDeviceHashedKey, p4_isShowDiscoveryInEventLog): PLUGIN.serverLogger.debug(u"_createDeviceDict called") try: - ahbDev = indigo.devices[ahbDevId] - ahbDevName = ahbDev.name - publishedAlexaDevices = self.jsonLoadsProcess(ahbDev.pluginProps['alexaDevices']) - - alexaDeviceNameKey = PLUGIN.globals['alexaHueBridge'][ahbDevId]['hashKeys'][alexaDeviceHashedKey] - if alexaDeviceNameKey in publishedAlexaDevices: - alexaDeviceData = publishedAlexaDevices[alexaDeviceNameKey] - alexaDeviceName = alexaDeviceData['name'] - if alexaDeviceData['mode'] == 'D': # Device - devId = int(alexaDeviceData['devId']) - if devId in indigo.devices: - dev = indigo.devices[devId] - onState = dev.onState - reachable = dev.enabled - brightness = dev.states.get("brightness", 255) - uniqueId = alexaDeviceHashedKey + self.ahbDev = indigo.devices[p2_ahbDevId] + self.ahbDevName = self.ahbDev.name + self.publishedAlexaDevices = self.jsonLoadsProcess(self.ahbDev.pluginProps['alexaDevices']) + + self.alexaDeviceNameKey = PLUGIN.globals['alexaHueBridge'][p2_ahbDevId]['hashKeys'][p3_alexaDeviceHashedKey] + if self.alexaDeviceNameKey in self.publishedAlexaDevices: + self.alexaDeviceData = self.publishedAlexaDevices[self.alexaDeviceNameKey] + self.alexaDeviceName = self.alexaDeviceData['name'] + if self.alexaDeviceData['mode'] == 'D': # Device + self.devId = int(self.alexaDeviceData['devId']) + if self.devId in indigo.devices: + self.dev = indigo.devices[self.devId] + self.onState = self.dev.onState + self.reachable = self.dev.enabled + self.brightness = self.dev.states.get("brightness", 255) + self.uniqueId = p3_alexaDeviceHashedKey else: - PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated device #{} not found".format(function, alexaDeviceName, ahbDevName, devId)) + PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated device #{} not found".format(p1_function, self.alexaDeviceName, self.ahbDevName, self.devId)) return {} - elif alexaDeviceData['mode'] == 'A': # Action - onOffVariableId = int(alexaDeviceData["variableOnOffId"]) - if onOffVariableId != 0: - if onOffVariableId in indigo.variables: - onState = bool(indigo.variables[onOffVariableId].value) + elif self.alexaDeviceData['mode'] == 'A': # Action + self.onOffVariableId = int(self.alexaDeviceData["variableOnOffId"]) + if self.onOffVariableId != 0: + if self.onOffVariableId in indigo.variables: + self.onState = bool(indigo.variables[self.onOffVariableId].value) else: - PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated On/Off variable #{} not found".format(function, alexaDeviceName, ahbDevName, onOffVariableId)) + PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated On/Off variable #{} not found".format(p1_function, self.alexaDeviceName, self.ahbDevName, self.onOffVariableId)) return {} else: - onState = True # Default to On ??? - reachable = True - dimVariableId = int(alexaDeviceData["variableDimId"]) - if dimVariableId != 0: - if dimVariableId in indigo.variables: - brightness = int(indigo.variables[dimVariableId].value) + self.onState = True # Default to On ??? + self.reachable = True + self.dimVariableId = int(self.alexaDeviceData["variableDimId"]) + if self.dimVariableId != 0: + if self.dimVariableId in indigo.variables: + self.brightness = int(indigo.variables[self.dimVariableId].value) else: - PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated Dim variable #{} not found".format(function, alexaDeviceName, ahbDevName, dimVariableId)) + PLUGIN.serverLogger.error(u"Unable to {} '{}' from '{}', associated Dim variable #{} not found".format(p1_function, self.alexaDeviceName, self.ahbDevName, self.dimVariableId)) return {} else: - brightness = 255 # Default to 255 (max brightness) - uniqueId = alexaDeviceHashedKey + self.brightness = 255 # Default to 255 (max brightness) + self.uniqueId = p3_alexaDeviceHashedKey else: return {} else: - PLUGIN.serverLogger.error(u"_createDeviceDict: alexaDeviceNameKey '{}' not in published devices; HashKey='{}".format(alexaDeviceNameKey, alexaDeviceHashedKey)) + PLUGIN.serverLogger.error(u"_createDeviceDict: alexaDeviceNameKey '{}' not in published devices; HashKey='{}".format(self.alexaDeviceNameKey, p3_alexaDeviceHashedKey)) return {} - if isShowDiscoveryInEventLog: - PLUGIN.globals['discoveryLists'][self.discoveryId].append(alexaDeviceName) + if p4_isShowDiscoveryInEventLog: + PLUGIN.globals['discoveryLists'][self.discoveryId].append(self.alexaDeviceName) return { "pointsymbol": { @@ -426,11 +419,11 @@ def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDisc "8": "none", }, "state": { - "on": onState, + "on": self.onState, "xy": [0.4589, 0.4103], "alert": "none", - "reachable": reachable, - "bri": brightness, + "reachable": self.reachable, + "bri": self.brightness, "hue": 14924, "colormode": "hs", "ct": 365, @@ -438,9 +431,9 @@ def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDisc "sat": 143 }, "swversion": "6601820", - "name": alexaDeviceName, + "name": self.alexaDeviceName, "manufacturername": "Philips", - "uniqueid": uniqueId, + "uniqueid": self.uniqueId, "type": "Extended color light", "modelid": "LCT001" } @@ -449,40 +442,39 @@ def _createDeviceDict(self, function, ahbDevId, alexaDeviceHashedKey, isShowDisc except Exception, e: PLUGIN.serverLogger.error(u"_createDeviceDict exception: \n{}".format(str(traceback.format_exc(10)))) - - def _createFullDeviceDict(self, ahbDevId): + def _createFullDeviceDict(self, p1_ahbDevId): PLUGIN.serverLogger.debug(u"_createFullDeviceDict called") - returnDict = dict() - PLUGIN.serverLogger.debug(u"_createFullDeviceDict: publishedAlexaDevices: \n{}".format(str(PLUGIN.globals['alexaHueBridge'][ahbDevId]['publishedAlexaDevices']))) + self.returnDict = dict() + PLUGIN.serverLogger.debug(u"_createFullDeviceDict: publishedAlexaDevices: \n{}".format(str(PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['publishedAlexaDevices']))) - ahbDev = indigo.devices[ahbDevId] - publishedAlexaDevices = self.jsonLoadsProcess(ahbDev.pluginProps['alexaDevices']) + self.ahbDev = indigo.devices[p1_ahbDevId] + self.publishedAlexaDevices = self.jsonLoadsProcess(self.ahbDev.pluginProps['alexaDevices']) - 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{}".format(str(newDeviceDict))) - returnDict[alexaDeviceHashKey] = newDeviceDict - return returnDict + for self.alexaDeviceNameKey, self.AlexaDeviceData in self.publishedAlexaDevices.iteritems(): + self.alexaDeviceHashKey = PLUGIN.globals['alexaHueBridge'][p1_ahbDevId]['publishedAlexaDevices'][self.alexaDeviceNameKey]['hashKey'] + self.newDeviceDict = self._createDeviceDict('publish', p1_ahbDevId, self.alexaDeviceHashKey, PLUGIN.globals['showDiscoveryInEventLog']) + PLUGIN.serverLogger.debug(u"_createFullDeviceDict: new device added: \n{}".format(str(self.newDeviceDict))) + self.returnDict[self.alexaDeviceHashKey] = self.newDeviceDict + return self.returnDict ######################################## # This method is called to load the stored json data and make sure the Alexa Name keys are valid before returning data # i.e. remove leading/trailing spaces, remove caharcters ',', ';', replace multiple concurrent spaces with one space, force to lower case ######################################## - def jsonLoadsProcess(self, dataToLoad): + def jsonLoadsProcess(self, p1_dataToLoad): - publishedAlexaDevices = json.loads(dataToLoad) + self.publishedAlexaDevices = json.loads(p1_dataToLoad) - alexaDeviceNameKeyList = [] - for alexaDeviceNameKey, alexaDeviceData in publishedAlexaDevices.iteritems(): - alexaDeviceNameKeyList.append(alexaDeviceNameKey) + self.alexaDeviceNameKeyList = [] + for self.alexaDeviceNameKey, self.alexaDeviceData in self.publishedAlexaDevices.iteritems(): + self.alexaDeviceNameKeyList.append(self.alexaDeviceNameKey) - for alexaDeviceNameKey in alexaDeviceNameKeyList: - alexaDeviceNameKeyProcessed = ' '. join((alexaDeviceNameKey.strip().lower().replace(',',' ').replace(';',' ')).split()) - if alexaDeviceNameKeyProcessed != alexaDeviceNameKey: - publishedAlexaDevices[alexaDeviceNameKeyProcessed] = publishedAlexaDevices.pop(alexaDeviceNameKey) + for self.alexaDeviceNameKey in self.alexaDeviceNameKeyList: + self.alexaDeviceNameKeyProcessed = ' '. join((self.alexaDeviceNameKey.strip().lower().replace(',', ' ').replace(';', ' ')).split()) + if self.alexaDeviceNameKeyProcessed != self.alexaDeviceNameKey: + self.publishedAlexaDevices[self.alexaDeviceNameKeyProcessed] = self.publishedAlexaDevices.pop(self.alexaDeviceNameKey) - return publishedAlexaDevices + return self.publishedAlexaDevices diff --git a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/plugin.py b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/plugin.py index 2156d00..8a5ec16 100755 --- a/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/plugin.py +++ b/Alexa-Hue Bridge.indigoPlugin/Contents/Server Plugin/plugin.py @@ -400,7 +400,8 @@ def deviceStartCommAe(self, aeDev): aeDev.updateStateImageOnServer(indigo.kStateImageSel.SensorOff) - self.globals['amazonEchoDevices'][aeDev.id] = aeDev.address + if aeDev.address != '- none -': + self.globals['amazonEchoDevices'][aeDev.address] = aeDev.id except StandardError, e: self.generalLogger.error(u"StandardError detected in deviceStartComm [AE] for '{}'. Line '{}' has error='{}'".format(indigo.devices[aeDev.id].name, sys.exc_traceback.tb_lineno, e)) @@ -565,25 +566,27 @@ def deviceStartCommAhb(self, ahbDev): except StandardError, e: self.generalLogger.error(u"StandardError detected in deviceStartComm [AHB] for '{}'. Line '{}' has error='{}'".format(indigo.devices[ahbDev.id].name, sys.exc_traceback.tb_lineno, e)) - def deviceStopComm(self, ahbDev): + def deviceStopComm(self, dev): self.methodTracer.threaddebug(u"CLASS: Plugin") try: - if ahbDev.deviceTypeId != EMULATED_HUE_BRIDGE_TYPEID: - return - - stoppedId = ahbDev.id - stoppedName = ahbDev.name - - if 'webServer' in self.globals['alexaHueBridge'][stoppedId]: - if self.globals['alexaHueBridge'][stoppedId]['webServer']: - self.globals['alexaHueBridge'][stoppedId]['webServer'].stop() - if 'broadcaster' in self.globals['alexaHueBridge'][stoppedId]: - if self.globals['alexaHueBridge'][stoppedId]['broadcaster']: - self.globals['alexaHueBridge'][stoppedId]['broadcaster'].stop() - if 'responder' in self.globals['alexaHueBridge'][stoppedId]: - if self.globals['alexaHueBridge'][stoppedId]['responder']: - self.globals['alexaHueBridge'][stoppedId]['responder'].stop() + stoppedId = dev.id + stoppedAddress = dev.address + stoppedName = dev.name + + if dev.deviceTypeId == ECHO_DEVICE_TYPEID: + if dev.address in self.globals['amazonEchoDevices']: + del self.globals['amazonEchoDevices'][stoppedAddress] + elif dev.deviceTypeId == EMULATED_HUE_BRIDGE_TYPEID: + if 'webServer' in self.globals['alexaHueBridge'][stoppedId]: + if self.globals['alexaHueBridge'][stoppedId]['webServer']: + self.globals['alexaHueBridge'][stoppedId]['webServer'].stop() + if 'broadcaster' in self.globals['alexaHueBridge'][stoppedId]: + if self.globals['alexaHueBridge'][stoppedId]['broadcaster']: + self.globals['alexaHueBridge'][stoppedId]['broadcaster'].stop() + if 'responder' in self.globals['alexaHueBridge'][stoppedId]: + if self.globals['alexaHueBridge'][stoppedId]['responder']: + self.globals['alexaHueBridge'][stoppedId]['responder'].stop() except StandardError, e: self.generalLogger.error(u"StandardError detected in deviceStopComm for '{}'. Line '{}' has error='{}'".format(stoppedName, sys.exc_traceback.tb_lineno, e)) @@ -917,7 +920,9 @@ def closedDeviceConfigUi(self, valuesDict, userCancelled, typeId, devId): def closedAeDeviceConfigUi(self, valuesDict, userCancelled, typeId, aeDevId): self.methodTracer.threaddebug(u"CLASS: Plugin") try: - self.globals['amazonEchoDevices'][aeDevId] = valuesDict.get("address", '- none -') + echoAddress = valuesDict.get("address", '- none -') + if echoAddress != '- none -': + self.globals['amazonEchoDevices'][echoAddress] = aeDevId return valuesDict except StandardError, e: @@ -981,8 +986,8 @@ def deviceDeleted(self, dev): 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) elif dev.deviceTypeId == ECHO_DEVICE_TYPEID: - if dev.id in self.globals['amazonEchoDevices']: - del self.globals['amazonEchoDevices'][dev.id] + if dev.address in self.globals['amazonEchoDevices']: + del self.globals['amazonEchoDevices'][dev.address] super(Plugin, self).deviceDeleted(dev)