From d8b78101d4502e1ad5dccf7a4f833542cc9e92f6 Mon Sep 17 00:00:00 2001 From: aashe Date: Sat, 14 May 2022 22:31:46 -0500 Subject: [PATCH] Code cleanup --- .../Contents/Server Plugin/domoPadDevices.py | 15 +- .../Server Plugin/googleHomeDevices.py | 127 +++---- .../Contents/Server Plugin/plugin.py | 317 +++++++++--------- 3 files changed, 227 insertions(+), 232 deletions(-) diff --git a/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/domoPadDevices.py b/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/domoPadDevices.py index bde41ac..caabcc7 100644 --- a/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/domoPadDevices.py +++ b/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/domoPadDevices.py @@ -2,8 +2,7 @@ # -*- coding: utf-8 -*- # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// -# Domotics Pad Google Client Plugin by RogueProeliator -# See plugin.py for more plugin details and information +# Domotics Pad Client Plugin by RogueProeliator # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// @@ -12,11 +11,10 @@ # ///////////////////////////////////////////////////////////////////////////////////////// import RPFramework + # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// # DomoPadAndroidClient -# Handles the information related to a specific Android client connected/talking to -# Indigo and HousePad Plugins # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// class DomoPadAndroidClient(RPFramework.RPFrameworkNonCommChildDevice): @@ -48,10 +46,9 @@ def initiateCommunications(self): super(DomoPadAndroidClient, self).initiateCommunications() # update the state of the device to reflect the pairing status... - currentPairingState = self.indigoDevice.states.get("isPaired", False) - currentPairingProp = self.indigoDevice.pluginProps.get("deviceRegistrationId", "") + current_pairing_prop = self.indigoDevice.pluginProps.get("deviceRegistrationId", "") - if currentPairingProp == "": + if current_pairing_prop == "": self.indigoDevice.updateStateOnServer("isPaired", False, uiValue="Not Paired") else: self.indigoDevice.updateStateOnServer("isPaired", True, uiValue="Paired") @@ -60,8 +57,8 @@ def initiateCommunications(self): # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// # VideoCameraFeed -# Handles the specification of a video feed that can be shown within HousePad, such as -# to show live security camera feeds +# Handles the specification of a video feed that can be shown within HousePad, such as +# to show live security camera feeds # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// class VideoCameraFeed(RPFramework.RPFrameworkNonCommChildDevice): diff --git a/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/googleHomeDevices.py b/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/googleHomeDevices.py index baa98e5..aa02aaf 100644 --- a/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/googleHomeDevices.py +++ b/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/googleHomeDevices.py @@ -2,8 +2,7 @@ # -*- coding: utf-8 -*- # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// -# Domotics Pad Google Client Plugin by RogueProeliator -# See plugin.py for more plugin details and information +# Domotics Pad Client Plugin by RogueProeliator # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// @@ -15,9 +14,9 @@ # ///////////////////////////////////////////////////////////////////////////////////////// # GoogleDeviceTypesDefinition -# Dictionary which defines the available Google Home device types and stores the -# recommended traits to support for the device type in order to allow the most complete -# control/user experience "out of the box" +# Dictionary which defines the available Google Home device types and stores the +# recommended traits to support for the device type in order to allow the most complete +# control/user experience "out of the box" # ///////////////////////////////////////////////////////////////////////////////////////// googleDeviceTypesDefn = { 'action.devices.types.DOOR': @@ -74,6 +73,7 @@ def mapIndigoDeviceToGoogleType(device): else: return '' + # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # Builds a Google Device sync definition for the given device utilizing the Global Props # defined by the user as well as the Indigo type @@ -81,25 +81,25 @@ def mapIndigoDeviceToGoogleType(device): def buildGoogleHomeDeviceDefinition(device): # do not check the published flag so that this routine may be used without explicit # options... full implementations should only pass in published devices - globalProps = device.sharedProps + global_props = device.sharedProps # retrieve the device type for the Google Assistant device - googleDevType = globalProps.get('googleClientAsstType', '') - if googleDevType == '': - googleDevType = mapIndigoDeviceToGoogleType(device) + google_dev_type = global_props.get('googleClientAsstType', '') + if google_dev_type == '': + google_dev_type = mapIndigoDeviceToGoogleType(device) # retrieve the name of the device as defined by the user - googleDevName = globalProps.get('googleClientAsstName', '') - if googleDevName == '': - googleDevName = device.name + google_dev_name = global_props.get('googleClientAsstName', '') + if google_dev_name == '': + google_dev_name = device.name - deviceDefnDict = { + device_defn_dict = { 'id': RPFramework.RPFrameworkUtils.to_unicode(device.id), - 'type': googleDeviceTypesDefn[googleDevType]['DeviceType'], - 'traits': list(googleDeviceTypesDefn[googleDevType]['Traits']), + 'type': googleDeviceTypesDefn[google_dev_type]['DeviceType'], + 'traits': list(googleDeviceTypesDefn[google_dev_type]['Traits']), 'name': { - 'defaultNames': [googleDevName], - 'name': googleDevName + 'defaultNames': [google_dev_name], + 'name': google_dev_name }, 'willReportState': False, 'deviceInfo': { @@ -107,7 +107,8 @@ def buildGoogleHomeDeviceDefinition(device): 'model': device.model } } - return deviceDefnDict + return device_defn_dict + # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # Builds the response for Google Assistant in the format required for updating the @@ -115,33 +116,33 @@ def buildGoogleHomeDeviceDefinition(device): # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def buildGoogleHomeDeviceStatusUpdate(device): # configuration information is found in the global properties collection - globalProps = device.sharedProps + global_props = device.sharedProps # retrieve the device type for the Google Assistant device - googleDevType = globalProps.get('googleClientAsstType', '') - if googleDevType == '': - googleDevType = mapIndigoDeviceToGoogleType(device) + google_dev_type = global_props.get('googleClientAsstType', '') + if google_dev_type == '': + google_dev_type = mapIndigoDeviceToGoogleType(device) # the status returned depends on the traits that are defined for this # device (dependent upon the device type) - deviceStatusTraits = {} - for trait in googleDeviceTypesDefn[googleDevType]['Traits']: + device_status_traits = {} + for trait in googleDeviceTypesDefn[google_dev_type]['Traits']: if trait == 'action.devices.traits.Brightness': - deviceStatusTraits['brightness'] = device.states.get('brightnessLevel', 0) + device_status_traits['brightness'] = device.states.get('brightnessLevel', 0) elif trait == 'action.devices.traits.ColorSetting': # not yet implemented... could be added to Light type as an RGB state, such # as for Hue lights pass elif trait == 'action.devices.traits.OnOff': - deviceStatusTraits['on'] = device.states.get('onOffState', False) + device_status_traits['on'] = device.states.get('onOffState', False) # the online status will simply be if the device is enabled; should we look at a status # value? - deviceStatusTraits['online'] = device.configured and device.enabled and device.states.get('errorState', '') == '' + device_status_traits['online'] = device.configured and device.enabled and device.states.get('errorState', '') == '' # return the trait/state dictionary back... note that the device ID will need # to be set as the key to this by the calling procedure - return deviceStatusTraits + return device_status_traits # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # Processes the EXECUTE intent against the given device IDs; note that multiple @@ -151,69 +152,69 @@ def buildGoogleHomeDeviceStatusUpdate(device): def processExecuteRequest(commandsList): # the response object contains a list of devices that fall into each status; this will # be a dictionary of status with a value being the list of devices - deviceStatusResults = {} + device_status_results = {} # there may be multiple commands to execute in the array for commandDefn in commandsList: # build the list of devices against which we must execute the # command(s) provided - devicesList = [] + devices_list = [] for deviceId in commandDefn['devices']: - indigoDevice = indigo.devices[int(deviceId['id'])] - devicesList.append(indigoDevice) - if not indigoDevice.id in deviceStatusResults: - deviceStatusResults[indigoDevice.id] = '' + indigo_device = indigo.devices[int(deviceId['id'])] + devices_list.append(indigo_device) + if indigo_device.id not in device_status_results: + device_status_results[indigo_device.id] = '' # loop through each device, executing the requested commands only if they are # valid for the device type found - for device in devicesList: + for device in devices_list: # determine if the device is online and configured; otherwise it cannot accept the command - isDeviceOnline = device.configured and device.enabled and device.states.get('errorState', '') == '' + is_device_online = device.configured and device.enabled and device.states.get('errorState', '') == '' # execute the requested command, if available - if isDeviceOnline == False: - deviceStatusResults[device.id] = 'OFFLINE' + if not is_device_online: + device_status_results[device.id] = 'OFFLINE' else: for execCommand in commandDefn['execution']: - commandId = execCommand['command'] - if commandId == 'action.devices.commands.OnOff': - if execCommand['params']['on'] == True: + command_id = execCommand['command'] + if command_id == 'action.devices.commands.OnOff': + if execCommand['params']['on']: indigo.device.turnOn(device.id) else: indigo.device.turnOff(device.id) # mark the execution as pending since the commands are generally asynchronous in # nature... the statuses will be updated when the device changes - if deviceStatusResults[device.id] == '': - deviceStatusResults[device.id] = 'PENDING' + if device_status_results[device.id] == '': + device_status_results[device.id] = 'PENDING' - # formulate the return... this is an arry with a new result dictionary for each + # formulate the return... this is an array with a new result dictionary for each # status within the devices results - commandReturn = [] - successDevices = {'ids': [], 'status': 'SUCCESS' } - pendingDevices = {'ids': [], 'status': 'PENDING' } - errorDevices = {'ids': [], 'status': 'ERROR' } - offlineDevices = {'ids': [], 'status': 'OFFLINE' } + command_return = [] + success_devices = {'ids': [], 'status': 'SUCCESS'} + pending_devices = {'ids': [], 'status': 'PENDING'} + error_devices = {'ids': [], 'status': 'ERROR'} + offline_devices = {'ids': [], 'status': 'OFFLINE'} # add each device result to the appropriate list - for deviceId, result in deviceStatusResults.items(): + for deviceId, result in device_status_results.items(): if result == 'SUCCESS': - successDevices['ids'].append(str(deviceId)) + success_devices['ids'].append(str(deviceId)) elif result == 'PENDING': - pendingDevices['ids'].append(str(deviceId)) + pending_devices['ids'].append(str(deviceId)) elif result == 'ERROR': - errorDevices['ids'].append(str(deviceId)) + error_devices['ids'].append(str(deviceId)) elif result == 'offlineDevices': - offlineDevices['ids'].append(str(deviceId)) + offline_devices['ids'].append(str(deviceId)) # build the composite results array - if len(successDevices['ids']) > 0: - commandReturn.append(successDevices) - if len(pendingDevices['ids']) > 0: - commandReturn.append(pendingDevices) - if len(errorDevices['ids']) > 0: - commandReturn.append(errorDevices) - if len(offlineDevices['ids']) > 0: - commandReturn.append(offlineDevices) + if len(success_devices['ids']) > 0: + command_return.append(success_devices) + if len(pending_devices['ids']) > 0: + command_return.append(pending_devices) + if len(error_devices['ids']) > 0: + command_return.append(error_devices) + if len(offline_devices['ids']) > 0: + command_return.append(offline_devices) - return commandReturn \ No newline at end of file + return command_return diff --git a/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/plugin.py b/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/plugin.py index 481abbb..e6a4641 100644 --- a/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/plugin.py +++ b/DomoPad Mobile Client Plugin.indigoPlugin/Contents/Server Plugin/plugin.py @@ -2,9 +2,7 @@ # -*- coding: utf-8 -*- # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// -# Domotics Pad Client Plugin by RogueProeliator -# Indigo plugin designed to interface with the various Google services supported by -# Domotics Pad, such as mobile clients and Google Home devices +# Domotics Pad Client Plugin by RogueProeliator # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// @@ -12,7 +10,6 @@ # ///////////////////////////////////////////////////////////////////////////////////////// # Python imports # ///////////////////////////////////////////////////////////////////////////////////////// -import cgi from distutils.dir_util import copy_tree import os import re @@ -25,24 +22,21 @@ import RPFramework import domoPadDevices -import googleHomeDevices # ///////////////////////////////////////////////////////////////////////////////////////// # Constants and configuration variables # ///////////////////////////////////////////////////////////////////////////////////////// INCLUDED_IWS_VERSION = (1, 5) -DOMOPADCOMMAND_SENDNOTIFICATION = u'SendNotification' -DOMOPADCOMMAND_SPEAKANNOUNCEMENTNOTIFICATION = u'SendTextToSpeechNotification' -DOMOPADCOMMAND_CPDISPLAYNOTIFICATION = u'SendCPDisplayRequest' -DOMOPADCOMMAND_DEVICEUPDATEREQUESTNOTIFICATION = u'RequestDeviceStatusUpdate' +DOMOPADCOMMAND_SENDNOTIFICATION = "SendNotification" +DOMOPADCOMMAND_SPEAKANNOUNCEMENTNOTIFICATION = "SendTextToSpeechNotification" +DOMOPADCOMMAND_CPDISPLAYNOTIFICATION = "SendCPDisplayRequest" +DOMOPADCOMMAND_DEVICEUPDATEREQUESTNOTIFICATION = "RequestDeviceStatusUpdate" # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// # Plugin -# Primary Indigo plugin class that is universal for all devices (receivers) to be -# controlled # ///////////////////////////////////////////////////////////////////////////////////////// # ///////////////////////////////////////////////////////////////////////////////////////// class Plugin(RPFramework.RPFrameworkPlugin): @@ -57,6 +51,8 @@ class Plugin(RPFramework.RPFrameworkPlugin): def __init__(self, pluginId, pluginDisplayName, pluginVersion, pluginPrefs): # RP framework base class's init method super().__init__(pluginId, pluginDisplayName, pluginVersion, pluginPrefs, managedDeviceClassModule=domoPadDevices) + self.socket_server = None + self.socket_server_thread = None # ///////////////////////////////////////////////////////////////////////////////////// # Indigo control methods @@ -75,16 +71,16 @@ def startup(self): # create the socket listener server that will listen for incoming commands to # be sent to the Plugin try: - host = u'' + host = "" port = int(self.getGUIConfigValue(RPFramework.GUI_CONFIG_PLUGINSETTINGS, "remoteCommandPort", "9176")) - self.socketServer = ThreadedTCPServer((host, port), ThreadedTCPRequestHandler) + self.socket_server = ThreadedTCPServer((host, port), ThreadedTCPRequestHandler) self.logger.debug("Starting up connection listener") - self.socketServerThread = threading.Thread(target=self.socketServer.serve_forever) - self.socketServerThread.daemon = True - self.socketServerThread.start() + self.socket_server_thread = threading.Thread(target=self.socket_server.serve_forever) + self.socket_server_thread.daemon = True + self.socket_server_thread.start() except: - self.exceptionLog() + self.logger.exception("Failed to start up the threaded listener; incoming requests from clients may be affected") # tell the Indigo server that we want to be notificed of all device # updates (so we can push to Google) @@ -96,8 +92,8 @@ def startup(self): # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def shutdown(self): super(Plugin, self).shutdown() - if not (self.socketServer is None): - self.socketServer.shutdown() + if not (self.socket_server is None): + self.socket_server.shutdown() # ///////////////////////////////////////////////////////////////////////////////////// # Action/command processing routines @@ -115,31 +111,32 @@ def handleUnknownPluginCommand(self, rpCommand, reQueueCommandsList): else: self.logger.threaddebug(f"Push Notification Send Command: DevicePairID={rpCommand.commandPayload[0]}; Type={rpCommand.commandPayload[2]}; Message={rpCommand.commandPayload[1]}") - # setup the defaults so that we know all of the parameters have a value... - queryStringParams = {"devicePairingId": rpCommand.commandPayload[0], + # set up the defaults so that we know all the parameters have a value... + query_params = { + "devicePairingId" : rpCommand.commandPayload[0], "notificationType": "Alert", "priority" : rpCommand.commandPayload[2], "message" : rpCommand.commandPayload[1], "action1Name" : "", "action1Group" : "", "action2Name" : "", - "action2Group" : ""} + "action2Group" : "" + } # build the query string as it must be URL encoded if rpCommand.commandPayload[3] != "" and rpCommand.commandPayload[4] != "": self.logger.threaddebug(f"Push Notification Send Action 1: {rpCommand.commandPayload[3]} => {rpCommand.commandPayload[4]}") - queryStringParams["action1Name"] = f"{rpCommand.commandPayload[3]}" - queryStringParams["action1Group"] = f"{rpCommand.commandPayload[4]}" - queryStringParams["notificationType"] = "ActionAlert" - targetApiMethod = "sendActionablePushNotification" + query_params["action1Name"] = f"{rpCommand.commandPayload[3]}" + query_params["action1Group"] = f"{rpCommand.commandPayload[4]}" + query_params["notificationType"] = "ActionAlert" if rpCommand.commandPayload[5] != "" and rpCommand.commandPayload[6] != "": self.logger.threaddebug(f"Push Notification Send Action 2: {rpCommand.commandPayload[5]} => {rpCommand.commandPayload[6]}") - queryStringParams["action2Name"] = f"{rpCommand.commandPayload[5]}" - queryStringParams["action2Group"] = f"{rpCommand.commandPayload[6]}" - queryStringParams["notificationType"] = "ActionAlert" + query_params["action2Name"] = f"{rpCommand.commandPayload[5]}" + query_params["action2Group"] = f"{rpCommand.commandPayload[6]}" + query_params["notificationType"] = "ActionAlert" push_url = "https://com-duncanware-domopad.appspot.com/_ah/api/messaging/v1/sendActionablePushNotification" - response = requests.post(push_url, data=queryStringParams) + response = requests.post(push_url, data=query_params) response_code = response.status_code response_text = response.text @@ -154,9 +151,9 @@ def handleUnknownPluginCommand(self, rpCommand, reQueueCommandsList): self.logger.exception("Error sending push notification.") elif rpCommand.commandName == DOMOPADCOMMAND_SPEAKANNOUNCEMENTNOTIFICATION: - self.logger.threaddebug(f"Speak Announcement Notification Send Command: DevicePairID={RPFramework.RPFrameworkUtils.to_unicode(rpCommand.commandPayload[0])}; Msg={RPFramework.RPFrameworkUtils.to_unicode(rpCommand.commandPayload[1])}") + self.logger.threaddebug(f"Speak Announcement Notification Send Command: DevicePairID={rpCommand.commandPayload[0]}; Msg={rpCommand.commandPayload[1]}") - message_expanded = self.substituteIndigoValues(RPFramework.RPFrameworkUtils.to_unicode(rpCommand.commandPayload[1]), rpCommand.commandPayload[2], []) + message_expanded = self.substituteIndigoValues(f"{rpCommand.commandPayload[1]}", rpCommand.commandPayload[2], []) data_params = {"devicePairingId": rpCommand.commandPayload[0], "message": message_expanded} push_url = "https://com-duncanware-domopad.appspot.com/_ah/api/messaging/v1/sendAnnounceTextRequest" response = requests.post(push_url, data=data_params) @@ -174,12 +171,12 @@ def handleUnknownPluginCommand(self, rpCommand, reQueueCommandsList): self.logger.exception("Error sending speak announcement notification.") elif rpCommand.commandName == DOMOPADCOMMAND_CPDISPLAYNOTIFICATION: - self.logger.threaddebug(f"Control Page Display Notification Send Command: DevicePairID={RPFramework.RPFrameworkUtils.to_unicode(rpCommand.commandPayload[0])}; Page={RPFramework.RPFrameworkUtils.to_unicode(rpCommand.commandPayload[1])}") + self.logger.threaddebug(f"Control Page Display Notification Send Command: DevicePairID={rpCommand.commandPayload[0]}; Page={rpCommand.commandPayload[1]}") # load the control page name so that we may pass it along to the deviceId - # (may be needed for notification purposes) - requestedPage = indigo.rawServerRequest("GetControlPage", {"ID" : rpCommand.commandPayload[1]}) - cpPageName = requestedPage["Name"] + # (this may be needed for notification purposes) + requested_page = indigo.rawServerRequest("GetControlPage", {"ID" : rpCommand.commandPayload[1]}) + cpPageName = requested_page["Name"] data_params = {"devicePairingId": rpCommand.commandPayload[0], "pageRequested": rpCommand.commandPayload[1], "pageName": cpPageName} push_url = "https://com-duncanware-domopad.appspot.com/_ah/api/messaging/v1/sendControlPageDisplayRequest" @@ -202,54 +199,54 @@ def handleUnknownPluginCommand(self, rpCommand, reQueueCommandsList): # command for the plugin to process asynchronously # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def processSendNotification(self, action): - rpDevice = self.managedDevices[action.deviceId] - deviceRegistrationId = rpDevice.indigoDevice.pluginProps.get("deviceRegistrationId", "") - messageToSend = self.substitute(action.props.get("message")) - importanceLevel = action.props.get("importanceLevel") + device = self.managedDevices[action.deviceId] + registration_id = device.indigoDevice.pluginProps.get("deviceRegistrationId", "") + message_to_send = self.substitute(action.props.get("message")) + importance_level = action.props.get("importanceLevel") - action1Name = action.props.get("action1Name" , "") - action1Group = action.props.get("action1Group", "") - action2Name = action.props.get("action2Name" , "") - action2Group = action.props.get("action2Group", "") + action1_name = action.props.get("action1Name" , "") + action1_group = action.props.get("action1Group", "") + action2_name = action.props.get("action2Name" , "") + action2_group = action.props.get("action2Group", "") - if deviceRegistrationId == "": - self.logger.error(f"Unable to send push notification to {rpDevice.indigoDevice.deviceId}; the device is not paired.") + if registration_id == "": + self.logger.error(f"Unable to send push notification to {device.indigoDevice.deviceId}; the device is not paired.") else: self.logger.threaddebug(f"Queuing push notification command for {action.deviceId}") - self.pluginCommandQueue.put(RPFramework.RPFrameworkCommand(DOMOPADCOMMAND_SENDNOTIFICATION, commandPayload=(deviceRegistrationId, messageToSend, importanceLevel, action1Name, action1Group, action2Name, action2Group))) + self.pluginCommandQueue.put(RPFramework.RPFrameworkCommand(DOMOPADCOMMAND_SENDNOTIFICATION, commandPayload=(registration_id, message_to_send, importance_level, action1_name, action1_group, action2_name, action2_group))) # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # This routine will send the Speak Announcement command to an Android Device # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def processSpeakAnnouncementNotification(self, action): - rpDevice = self.managedDevices[action.deviceId] - deviceRegistrationId = rpDevice.indigoDevice.pluginProps.get("deviceRegistrationId", "") - announcementMsg = action.props.get("announcement", "") + device = self.managedDevices[action.deviceId] + registration_id = device.indigoDevice.pluginProps.get("deviceRegistrationId", "") + announcement_msg = action.props.get("announcement", "") - if deviceRegistrationId == "": - self.logger.error(f"Unable to send speak announcement request notification to {rpDevice.indigoDevice.deviceId}; the device is not paired.") - elif announcementMsg == "": - self.logger.error(f"Unable to send speak announcement request notification to {rpDevice.indigoDevice.deviceId}; no announcement text was entered.") + if registration_id == "": + self.logger.error(f"Unable to send speak announcement request notification to {device.indigoDevice.deviceId}; the device is not paired.") + elif announcement_msg == "": + self.logger.error(f"Unable to send speak announcement request notification to {device.indigoDevice.deviceId}; no announcement text was entered.") else: self.logger.threaddebug(f"Queuing peak announcement request notification command for {action.deviceId}") - self.pluginCommandQueue.put(RPFramework.RPFrameworkCommand(DOMOPADCOMMAND_SPEAKANNOUNCEMENTNOTIFICATION, commandPayload=(deviceRegistrationId, announcementMsg, rpDevice))) + self.pluginCommandQueue.put(RPFramework.RPFrameworkCommand(DOMOPADCOMMAND_SPEAKANNOUNCEMENTNOTIFICATION, commandPayload=(registration_id, announcement_msg, device))) # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # This routine will send the Control Page Display Command to a Android device (in # order to request that a specific control page be shown on the device) # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def processControlPageDisplayNotification(self, action): - rpDevice = self.managedDevices[action.deviceId] - deviceRegistrationId = rpDevice.indigoDevice.pluginProps.get("deviceRegistrationId", "") - controlPageId = int(action.props.get("controlPageId", "0")) + device = self.managedDevices[action.deviceId] + registration_id = device.indigoDevice.pluginProps.get("deviceRegistrationId", "") + control_page_id = int(action.props.get("controlPageId", "0")) - if deviceRegistrationId == "": - self.logger.error(f"Unable to send control page display request notification to {rpDevice.indigoDevice.deviceId}; the device is not paired.") - elif controlPageId <= 0: - self.logger.error(f"Unable to send control page display request notification to {rpDevice.indigoDevice.deviceId}; no control page was selected.") + if registration_id == "": + self.logger.error(f"Unable to send control page display request notification to {device.indigoDevice.deviceId}; the device is not paired.") + elif control_page_id <= 0: + self.logger.error(f"Unable to send control page display request notification to {device.indigoDevice.deviceId}; no control page was selected.") else: self.logger.threaddebug(f"Queuing control page display request notification command for {action.deviceId}") - self.pluginCommandQueue.put(RPFramework.RPFrameworkCommand(DOMOPADCOMMAND_CPDISPLAYNOTIFICATION, commandPayload=(deviceRegistrationId, controlPageId))) + self.pluginCommandQueue.put(RPFramework.RPFrameworkCommand(DOMOPADCOMMAND_CPDISPLAYNOTIFICATION, commandPayload=(registration_id, control_page_id))) # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # This routine will send the Update Device Status request notification in order to ask @@ -307,11 +304,11 @@ def clearNotificationAction2(self, valuesDict, typeId, devId): def processIWSUpdateCheck(self): # check the IWS plugin currently installed and see if we need to install or upgrade # to the version included with this plugin - currentIWSPluginVersion = self.getIWSPluginVersion() - self.logger.debug(f"Current IWS Plugin: v{currentIWSPluginVersion[0]}.{currentIWSPluginVersion[1]}") + iws_plugin_ver = self.getIWSPluginVersion() + self.logger.debug(f"Current IWS Plugin: v{iws_plugin_ver[0]}.{iws_plugin_ver[1]}") self.logger.debug(f"Included IWS Plugin: v{INCLUDED_IWS_VERSION[0]}.{INCLUDED_IWS_VERSION[1]}") - if INCLUDED_IWS_VERSION[0] > currentIWSPluginVersion[0] or (INCLUDED_IWS_VERSION[0] == currentIWSPluginVersion[0] and INCLUDED_IWS_VERSION[1] > currentIWSPluginVersion[1]): + if INCLUDED_IWS_VERSION[0] > iws_plugin_ver[0] or (INCLUDED_IWS_VERSION[0] == iws_plugin_ver[0] and INCLUDED_IWS_VERSION[1] > iws_plugin_ver[1]): # we need to perform the IWS upgrade now self.updateIWSPlugin() @@ -321,18 +318,18 @@ def processIWSUpdateCheck(self): # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def getIWSPluginVersion(self): try: - versionUrl = "http://localhost:{self.pluginPrefs.get(u'indigoPort')}/AndroidClientHelper/getVersionInfo" - response = requests.get(versionUrl, auth=HTTPDigestAuth(self.pluginPrefs.get("indigoUsername"), self.pluginPrefs.get("indigoPassword"))) - responseTText = response.text + version_url = f"http://localhost:{self.pluginPrefs.get(u'indigoPort')}/AndroidClientHelper/getVersionInfo" + response = requests.get(version_url, auth=HTTPDigestAuth(self.pluginPrefs.get("indigoUsername"), self.pluginPrefs.get("indigoPassword"))) + response_text = response.text regex = re.compile("^v(?P\d+)\.(?P\d+)$") - match = regex.search(responseTText) + match = regex.search(response_text) if match is None: - self.logger.warning(f"Connected to IWS, but current version not returned: {responseTText}") - return (0,0) + self.logger.warning(f"Connected to IWS, but current version not returned: {response_text}") + return 0, 0 else: - return (int(match.groupdict().get("major")), int(match.groupdict().get("minor"))) + return int(match.groupdict().get("major")), int(match.groupdict().get("minor")) except: # when an exception occurs we are going to have to assume that we need to copy # the plugin over... @@ -340,7 +337,7 @@ def getIWSPluginVersion(self): self.logger.error("Failed to retrieve current IWS plugin version:") else: self.logger.warning("Failed to retrieve current IWS plugin version:") - return (0,0) + return 0, 0 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # This routine will perform an update to the current IWS plugin by copying over the @@ -360,7 +357,7 @@ def updateIWSPlugin(self): self.logger.info(f"Target IWS directory: {iwsPluginHome}") # ensure that we have the correct source directory... - if os.path.exists(mainPluginHome) == False: + if not os.path.exists(mainPluginHome): self.logger.error("ERROR: Source directory not found! AndroidClientHelper IWS plugin install could not complete.") return @@ -377,9 +374,9 @@ def updateIWSPlugin(self): # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def restartIWS(self): try: - baseUrl = f"http://localhost:{self.pluginPrefs.get('indigoPort')}/" - restartUrl = baseUrl + "indigocommand?name=restart" - response = requests.get(restartUrl, auth=HTTPDigestAuth(self.pluginPrefs.get("indigoUsername"), self.pluginPrefs.get("indigoPassword"))) + base_url = f"http://localhost:{self.pluginPrefs.get('indigoPort')}/" + restart_url = base_url + "indigocommand?name=restart" + requests.get(restart_url, auth=HTTPDigestAuth(self.pluginPrefs.get("indigoUsername"), self.pluginPrefs.get("indigoPassword"))) except: pass @@ -389,14 +386,14 @@ def restartIWS(self): # minute update interval) # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def requestDeviceStatusNotification(self, deviceId): - rpDevice = self.managedDevices[deviceId] - deviceRegistrationId = rpDevice.indigoDevice.pluginProps.get("deviceRegistrationId", "") + rp_device = self.managedDevices[deviceId] + registration_id = rp_device.indigoDevice.pluginProps.get("deviceRegistrationId", "") - if deviceRegistrationId == "": - self.logger.error(f"Unable to send status update request notification to {rpDevice.indigoDevice.deviceId}; the device is not paired.") + if registration_id == "": + self.logger.error(f"Unable to send status update request notification to {rp_device.indigoDevice.deviceId}; the device is not paired.") else: self.logger.threaddebug(f"Queuing device status update request notification command for {RPFramework.RPFrameworkUtils.to_unicode(deviceId)}") - self.pluginCommandQueue.put(RPFramework.RPFrameworkCommand(DOMOPADCOMMAND_DEVICEUPDATEREQUESTNOTIFICATION, commandPayload=deviceRegistrationId)) + self.pluginCommandQueue.put(RPFramework.RPFrameworkCommand(DOMOPADCOMMAND_DEVICEUPDATEREQUESTNOTIFICATION, commandPayload=registration_id)) # ///////////////////////////////////////////////////////////////////////////////////////// @@ -413,122 +410,122 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): def handle(self): try: # self.request.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) - requestReceived = self.request.recv(1024).decode('utf-8') + request_received = self.request.recv(1024).decode('utf-8') # attempt to parse the request to determine how to proceed from here - commandParser = re.compile("GET (/{0,1}AndroidClientHelper){0,1}/{0,1}(?P\w+)(\?(?P.+)){0,1}\s+HTTP") - commandMatch = commandParser.search(requestReceived) + command_parser = re.compile("GET (/{0,1}AndroidClientHelper){0,1}/{0,1}(?P\w+)(\?(?P.+)){0,1}\s+HTTP") + command_match = command_parser.search(request_received) # send back the proper HTML headers so that the browser knows the connection is good... self.request.sendall(b"HTTP/1.0 200 OK\nContent-Type: text/html\n\n") - commandResponse = "" - if commandMatch is None: - commandResponse = "ERROR: No command received" + command_response = "" + if command_match is None: + command_response = "ERROR: No command received" else: - commandName = commandMatch.groupdict().get("commandName") - indigo.server.log(f"Process command: {commandName}") + command_name = command_match.groupdict().get("commandName") + indigo.server.log(f"Process command: {command_name}") - if commandName == "executePluginAction": - commandArguments = self.parseArguments(commandMatch.groupdict().get("arguments")) + if command_name == "executePluginAction": + command_arguments = self.parseArguments(command_match.groupdict().get("arguments")) # TODO: the plugin action parameters will be encrypted on the action line as an argument # required parameters are the plugin ID and device ID - pluginId = commandArguments.get("pluginId")[0] - deviceId = commandArguments.get("deviceId")[0] - actionId = commandArguments.get("actionId")[0] - actionProps = commandArguments.get("actionProps")[0] - indigo.server.log(actionProps) + plugin_id = command_arguments.get("pluginId")[0] + device_id = command_arguments.get("deviceId")[0] + action_id = command_arguments.get("actionId")[0] + action_props = command_arguments.get("actionProps")[0] + indigo.server.log(action_props) # get the plugin that was requested from the indigo server... if this is a domoPadMobileClient then we need # to access the plugin object directly to avoid an error dispatching the executeAction - if pluginId == "com.duncanware.domoPadMobileClient": - indigoPlugin = indigo.activePlugin + if plugin_id == "com.duncanware.domoPadMobileClient": + indigo_plugin = indigo.activePlugin - if actionId == "sendUpdateStatusRequestNotification": - indigoPlugin.requestDeviceStatusNotification(int(deviceId)) + if action_id == "sendUpdateStatusRequestNotification": + indigo_plugin.requestDeviceStatusNotification(int(device_id)) else: - indigo.server.log(f"Unknown action received for domoPadMobileClient: {actionId}") + indigo.server.log(f"Unknown action received for domoPadMobileClient: {action_id}") else: - indigoPlugin = indigo.server.getPlugin(pluginId) - if indigoPlugin is None: - commandResponse = "ERROR: Invalid plugin specified" - elif (actionProps is None) or (len(actionProps) == 0): - indigoPlugin.executeAction(actionId, deviceId=int(deviceId)) - commandResponse = "OK" + indigo_plugin = indigo.server.getPlugin(plugin_id) + if indigo_plugin is None: + command_response = "ERROR: Invalid plugin specified" + elif (action_props is None) or (len(action_props) == 0): + indigo_plugin.executeAction(action_id, deviceId=int(device_id)) + command_response = "OK" else: - actionPropDict = eval(actionProps) - indigoPlugin.executeAction(actionId, deviceId=int(deviceId), props=actionPropDict) - commandResponse = "OK" + action_prop_dict = eval(action_props) + indigo_plugin.executeAction(action_id, deviceId=int(device_id), props=action_prop_dict) + command_response = "OK" - elif commandName == "registerAndroidDevice": - commandArguments = self.parseArguments(commandMatch.groupdict().get("arguments")) - deviceId = commandArguments.get("deviceId")[0] - pairingId = commandArguments.get("pairingId")[0] - allowOverwrite = int(commandArguments.get("allowOverwrite")[0]) + elif command_name == "registerAndroidDevice": + command_arguments = self.parseArguments(command_match.groupdict().get("arguments")) + device_id = command_arguments.get("deviceId")[0] + pairing_id = command_arguments.get("pairingId")[0] + allow_overwrite = int(command_arguments.get("allowOverwrite")[0]) - indigoAndroidDev = indigo.devices[int(deviceId)] - pluginProps = indigoAndroidDev.pluginProps; + android_dev = indigo.devices[int(device_id)] + plugin_props = android_dev.pluginProps; - if pluginProps.get("deviceRegistrationId", "") == "" or allowOverwrite == 1: - pluginProps["deviceRegistrationId"] = pairingId - indigoAndroidDev.replacePluginPropsOnServer(pluginProps) - indigoAndroidDev.updateStateOnServer("isPaired", True, uiValue="Paired") - commandResponse = "OK" - indigo.server.log(f"Successfully paired Android device to Indigo Device {deviceId}") + if plugin_props.get("deviceRegistrationId", "") == "" or allow_overwrite == 1: + plugin_props["deviceRegistrationId"] = pairing_id + android_dev.replacePluginPropsOnServer(plugin_props) + android_dev.updateStateOnServer("isPaired", True, uiValue="Paired") + command_response = "OK" + indigo.server.log(f"Successfully paired Android device to Indigo Device {device_id}") else: indigo.server.log("Rejected device pairing - Indigo Device already paired to another Android device.", isError=True) - commandResponse = "ERROR: Exception Processing Request" + command_response = "ERROR: Exception Processing Request" - elif commandName == "unregisterAndroidDevice": - commandArguments = self.parseArguments(commandMatch.groupdict().get("arguments")) - deviceId = commandArguments.get("deviceId")[0] - pairingId = commandArguments.get("pairingId")[0] + elif command_name == "unregisterAndroidDevice": + command_arguments = self.parseArguments(command_match.groupdict().get("arguments")) + device_id = command_arguments.get("deviceId")[0] + pairing_id = command_arguments.get("pairingId")[0] - indigoAndroidDev = indigo.devices[int(deviceId)] - pluginProps = indigoAndroidDev.pluginProps + android_dev = indigo.devices[int(device_id)] + plugin_props = android_dev.pluginProps # only de-register if the pairing IDs currently match... - if pluginProps.get("deviceRegistrationId", "") == pairingId: - pluginProps["deviceRegistrationId"] = "" - indigoAndroidDev.replacePluginPropsOnServer(pluginProps) - indigoAndroidDev.updateStateOnServer("isPaired", False, uiValue="Not Paired") - commandResponse = "OK" - indigo.server.log(f"Successfully un-paired Android device to Indigo Device {deviceId}") + if plugin_props.get("deviceRegistrationId", "") == pairing_id: + plugin_props["deviceRegistrationId"] = "" + android_dev.replacePluginPropsOnServer(plugin_props) + android_dev.updateStateOnServer("isPaired", False, uiValue="Not Paired") + command_response = "OK" + indigo.server.log(f"Successfully un-paired Android device to Indigo Device {device_id}") else: indigo.server.log(f"Rejected device un-pairing - Indigo Device does not match Android device.", isError=True) - commandResponse = "ERROR: Exception Processing Request" + command_response = "ERROR: Exception Processing Request" - elif commandName == u'updateMobileDeviceStates': - commandArguments = self.parseArguments(commandMatch.groupdict().get("arguments")) - pairingId = commandArguments.get("pairingId")[0] - modelName = commandArguments.get("deviceModel")[0] - batteryStatus = commandArguments.get("batteryStatus")[0] - batteryLevel = int(commandArguments.get("batteryLevel")[0]) - longitude = commandArguments.get("longitude")[0] - latitude = commandArguments.get("latitude")[0] - locationFixTime = commandArguments.get("locationFix", (""))[0] + elif command_name == u'updateMobileDeviceStates': + command_arguments = self.parseArguments(command_match.groupdict().get("arguments")) + pairing_id = command_arguments.get("pairingId")[0] + model_name = command_arguments.get("deviceModel")[0] + battery_status = command_arguments.get("batteryStatus")[0] + battery_level = int(command_arguments.get("batteryLevel")[0]) + longitude = command_arguments.get("longitude")[0] + latitude = command_arguments.get("latitude")[0] + location_fix_time = command_arguments.get("locationFix", (""))[0] # we need to find the proper devices based upon the pairing id; the default response will be # that the device was not found - commandResponse = "ERROR: Device not found" - devIter = indigo.devices.iter(filter="com.duncanware.domoPadMobileClient.domoPadAndroidClient") - for dev in devIter: - if dev.pluginProps.get("deviceRegistrationId", "") == pairingId: - dev.updateStateOnServer("modelName", modelName) - dev.updateStateOnServer("batteryStatus", batteryStatus) - dev.updateStateOnServer("batteryLevel", batteryLevel) + command_response = "ERROR: Device not found" + dev_iter = indigo.devices.iter(filter="com.duncanware.domoPadMobileClient.domoPadAndroidClient") + for dev in dev_iter: + if dev.pluginProps.get("deviceRegistrationId", "") == pairing_id: + dev.updateStateOnServer("modelName", model_name) + dev.updateStateOnServer("batteryStatus", battery_status) + dev.updateStateOnServer("batteryLevel", battery_level) dev.updateStateOnServer("longitude", longitude) dev.updateStateOnServer("latitude", latitude) - dev.updateStateOnServer("locationFixTime", locationFixTime) + dev.updateStateOnServer("locationFixTime", location_fix_time) - commandResponse = "OK" + command_response = "OK" - if commandResponse != "OK": - indigo.server.log(f"Received status update for unknown device with Pairing ID: {pairingId}", isError=True) + if command_response != "OK": + indigo.server.log(f"Received status update for unknown device with Pairing ID: {pairing_id}", isError=True) # send whatever response was generated back to the caller - self.request.sendall(commandResponse) + self.request.sendall(command_response) except Exception as e: indigo.server.log(f"DomoPad Plugin Exception: Error processing remote request: {e}")