def db_3_update(self, resourcePath): ''' convert all "rgb" to "hsb" ''' from com.cloudMedia.theKuroBox.sdk.util.colorUtils import ColorUtils for idCol, tableName in [("reId", "rule_execution"), ("seId", "scene_execution")]: toBeUpdateds = deque() rows = self.__con.execute('SELECT "' + idCol + '", "kbxMethodParams" ' + \ 'FROM "' + tableName + '" ' + \ 'WHERE "kbxMethodParams" LIKE ?', ('%"r"%', )).fetchall() for row in rows: methodRow = dict(row) kbxMethodParams = methodRow["kbxMethodParams"] for kbxMethodParam in kbxMethodParams: kbxParamCurrentValue = kbxMethodParam["kbxParamCurrentValue"] if isinstance(kbxParamCurrentValue, dict): if not {"r", "g", "b"}.difference(kbxParamCurrentValue): hsbDict = ColorUtils.rgb_to_hsb(kbxParamCurrentValue["r"], kbxParamCurrentValue["g"], kbxParamCurrentValue["b"]) kbxMethodParam["kbxParamCurrentValue"] = hsbDict toBeUpdateds.append(methodRow) for methodRow in toBeUpdateds: self.__con.execute('UPDATE "' + tableName + '" SET "kbxMethodParams"=? WHERE "' + idCol + '"=?', (methodRow["kbxMethodParams"], methodRow[idCol])) Logger.log_info("Database v3 update: RGB -> HSB (%i entries from %s migrated)" % (len(toBeUpdateds), str(tableName))) Logger.log_info("Database v3 update completed")
def __broadcast_message__favorited_scene_added(self, sceneId, prevSceneId): eventTag = AppConstants.EVENT_FAVORITED_SCENE_ADDED eventData = {"sceneId": sceneId, "prevSceneId": prevSceneId} self.__broadcast_message(eventTag, eventData) Logger.log_info("Favorited scene added/updated: Id", sceneId, "prevId:", prevSceneId)
def start(self): ''' Initialize all services required by automation app. ''' MethodController.instance() # Must listen to groups and methods added event before bootstrap. # Bootstrap try: bs = BootstrapService() Logger.log_info("Bootstrap update kbx method ...") bs.update_kbx_method() Logger.log_info("Bootstrap update kbx group ...") bs.update_kbx_group() Logger.log_info("Bootstrap register trigger schedulers ...") bs.register_trigger_schedulers() Logger.log_info("Bootstrap register timer module schedulers ...") bs.register_timer_module_schedulers() except Exception as e: bs.rollback() Logger.log_error("AutomationModuleWrapper.start bootstrap ex:", e) traceback.print_exc() raise e else: bs.commit() Logger.log_info("Bootstrap process completed!") self.__apiService = APIService() self.__ruleService = RuleService() self.__sceneService = SceneService() self.__serService = SceneExecutionResultService.instance()
def __broadcast_message__scene_update_started(self, sceneId, sceneName=None): eventTag = AppConstants.EVENT_SCENE_UPDATE_STARTED eventData = {"sceneId": sceneId, "newSceneName": sceneName} self.__broadcast_message(eventTag, eventData) Logger.log_info("Scene Start Update:", sceneName)
def post_system_connected(self): super().post_system_connected() Logger.log_info("post_system_connected starts...") DebugModule.DEBUG_POST_SYSTEM_CONNECTED.append(time.time()) self.__automationModule.start() Logger.log_info("post_system_connected ends...")
def __broadcast_message__scene_updated(self, sceneId): try: scene = self.__sceneController.get_summary(sceneId) except Exception as e: Logger.log_error("SceneService.__broadcast_message__scene_updated get_summary ex:", e) scene = None eventTag = AppConstants.EVENT_SCENE_UPDATED eventData = {"sceneId":sceneId, "newSceneSummary":scene} self.__broadcast_message(eventTag, eventData) Logger.log_info("Scene Updated:", scene["sceneName"])
def __broadcast_message__rule_updated(self, ruleId): try: rule = self.__ruleController.get_summary(ruleId) except Exception as e: Logger.log_error("RuleService.__broadcast_message__rule_updated get_summary ex:", e) return eventTag = AppConstants.EVENT_RULE_UPDATED eventData = rule self.__broadcast_message(eventTag, eventData) Logger.log_info("Rule Updated:", rule["ruleName"])
def __broadcast_message__scene_updated(self, sceneId): try: scene = self.__sceneController.get_summary(sceneId) except Exception as e: Logger.log_error( "SceneService.__broadcast_message__scene_updated get_summary ex:", e) scene = None eventTag = AppConstants.EVENT_SCENE_UPDATED eventData = {"sceneId": sceneId, "newSceneSummary": scene} self.__broadcast_message(eventTag, eventData) Logger.log_info("Scene Updated:", scene["sceneName"])
def __broadcast_message__scene_update_failed(self, sceneId, sceneName=None): ''' sceneName - For debugging purpose. ''' try: scene = self.__sceneController.get_summary(sceneId) except Exception: scene = None eventTag = AppConstants.EVENT_SCENE_UPDATE_FAILED eventData = {"sceneId": sceneId, "oldSceneSummary":scene} self.__broadcast_message(eventTag, eventData) Logger.log_info("Scene Update Failed:", sceneName)
def __broadcast_message__rule_update_failed(self, ruleId, ruleName=None): ''' ruleName - For debugging purpose. ''' try: rule = self.__ruleController.get_summary(ruleId) except Exception: rule = None eventTag = AppConstants.EVENT_RULE_UPDATE_FAILED eventData = {"ruleId": ruleId, "oldRuleSummary": rule} self.__broadcast_message(eventTag, eventData) Logger.log_info("Rule Update Failed:", ruleName)
def __broadcast_message__rule_updated(self, ruleId): try: rule = self.__ruleController.get_summary(ruleId) except Exception as e: Logger.log_error( "RuleService.__broadcast_message__rule_updated get_summary ex:", e) return eventTag = AppConstants.EVENT_RULE_UPDATED eventData = rule self.__broadcast_message(eventTag, eventData) Logger.log_info("Rule Updated:", rule["ruleName"])
def __broadcast_message__rule_update_failed(self, ruleId, ruleName=None): ''' ruleName - For debugging purpose. ''' try: rule = self.__ruleController.get_summary(ruleId) except Exception: rule = None eventTag = AppConstants.EVENT_RULE_UPDATE_FAILED eventData = {"ruleId": ruleId, "oldRuleSummary":rule} self.__broadcast_message(eventTag, eventData) Logger.log_info("Rule Update Failed:", ruleName)
def __broadcast_message__scene_update_failed(self, sceneId, sceneName=None): ''' sceneName - For debugging purpose. ''' try: scene = self.__sceneController.get_summary(sceneId) except Exception: scene = None eventTag = AppConstants.EVENT_SCENE_UPDATE_FAILED eventData = {"sceneId": sceneId, "oldSceneSummary": scene} self.__broadcast_message(eventTag, eventData) Logger.log_info("Scene Update Failed:", sceneName)
def db_3_update(self, resourcePath): ''' convert all "rgb" to "hsb" ''' from com.cloudMedia.theKuroBox.sdk.util.colorUtils import ColorUtils for idCol, tableName in [("reId", "rule_execution"), ("seId", "scene_execution")]: toBeUpdateds = deque() rows = self.__con.execute('SELECT "' + idCol + '", "kbxMethodParams" ' + \ 'FROM "' + tableName + '" ' + \ 'WHERE "kbxMethodParams" LIKE ?', ('%"r"%', )).fetchall() for row in rows: methodRow = dict(row) kbxMethodParams = methodRow["kbxMethodParams"] for kbxMethodParam in kbxMethodParams: kbxParamCurrentValue = kbxMethodParam[ "kbxParamCurrentValue"] if isinstance(kbxParamCurrentValue, dict): if not {"r", "g", "b" }.difference(kbxParamCurrentValue): hsbDict = ColorUtils.rgb_to_hsb( kbxParamCurrentValue["r"], kbxParamCurrentValue["g"], kbxParamCurrentValue["b"]) kbxMethodParam["kbxParamCurrentValue"] = hsbDict toBeUpdateds.append(methodRow) for methodRow in toBeUpdateds: self.__con.execute( 'UPDATE "' + tableName + '" SET "kbxMethodParams"=? WHERE "' + idCol + '"=?', (methodRow["kbxMethodParams"], methodRow[idCol])) Logger.log_info( "Database v3 update: RGB -> HSB (%i entries from %s migrated)" % (len(toBeUpdateds), str(tableName))) Logger.log_info("Database v3 update completed")
def db_2_update(self, resourcePath): self.__execute_script("/".join([resourcePath, "tablestructure.sql"])) Logger.log_info("Database v2 update: Table structures built") Logger.log_info("Database v2 update completed")
def db_1_update(self, resourcePath): Logger.log_info("Database v1 update started") self.__execute_script("/".join([resourcePath, "tablestructure.sql"])) Logger.log_info("Database v1 update: Table structures built") # #################### Migration codes #################### try: from automationApp.migration.storage import Storage allGroups = Storage.list_all_groups() if len(allGroups) > 0: # Probably no rule is set. ''' All Groups: e.g. {25: 'Yeelight Blue II'} ''' for kbxGroupId, kbxGroupLabel in allGroups.items(): self.__con.execute('INSERT INTO "kbx_group"("kbxGroupId", "kbxGroupLabel", "kbxGroupStatus") VALUES (?, ?, ?)', (kbxGroupId, kbxGroupLabel, -1)) del(allGroups) ''' All Groups Methods: e.g. {69: 25, 71: 25} ''' allMethodGroups = Storage.list_all_method_groups() for kbxMethodId, kbxGroupId in allMethodGroups.items(): self.__con.execute('INSERT INTO "kbx_method"("kbxMethodId", "kbxGroupId", "kbxMethodStatus") ' + \ 'VALUES (?, ?, ?)', (kbxMethodId, kbxGroupId, -1)) ''' All Rules: e.g. [{ 'execution': [{'kbxMethodId': 71, 'kbxMethodParams': [{'kbxParamCurrentValue': '4', 'kbxParamName': 'pairedDeviceId'},{'kbxParamCurrentValue': [False], 'kbxParamName': 'on'}]}], 'trigger': {'type': 0, 'value': None}, 'ruleId': '1425284835.0756288', 'enabled': True, 'condition': [{'kbxMethodId': 69, 'kbxMethodParams': [{'kbxParamCurrentValue': '4', 'kbxParamName': 'pairedDeviceId'}, {'kbxParamCurrentValue': [True], 'kbxParamName': 'on'}]}], 'ruleName': 'ReTestet' }] ''' allRules = Storage.list_all_rules() cursor = self.__con.cursor() createdTime = updatedTime = time.time() triggerController = TriggerController.instance() for sort, rule in enumerate(allRules): trigger = triggerController.parse_to_trigger_dto(rule["trigger"]) cursor.execute('INSERT INTO "rule"("ruleName", "ruleProtected", "trigger", "enabled", "statusProcessed", "createdTime", "updatedTime", "sort") ' + \ 'VALUES (?, ?, ?, ?, ?, ?, ?, ?)', (rule["ruleName"], False, json.dumps(trigger), rule["enabled"], "updated", createdTime, updatedTime, sort)) ruleId = cursor.lastrowid for vals in (["execution", "rule_execution", "reRuleId"], ["condition", "rule_condition", "rcRuleId"]): for kbxMethodSort, kbxMethodWithCurrentValue in enumerate(rule[vals[0]]): self.__con.execute('INSERT INTO "' + vals[1] + '"("' + vals[2] + '", "kbxMethodId", "kbxMethodParams", "createdTime", "sort") ' + \ 'VALUES (?, ?, ?, ?, ?)', (ruleId, kbxMethodWithCurrentValue["kbxMethodId"], json.dumps(kbxMethodWithCurrentValue["kbxMethodParams"]), createdTime, kbxMethodSort)) cursor.close() del(allRules) self.__con.commit() except Exception as e: self.__con.rollback() Logger.log_warning("Database failed to migrate rules from system, ex:", e , "---- rolled back") else: Logger.log_info("Database v1 update: Rules migrated") try: Storage.delete_all_rules() Storage.delete_all_method_groups() Storage.delete_all_groups() except Exception as e: Logger.log_warning("Database failed to remove rules from system after migration, ex:", e) # #################### End of migration codes #################### self.__execute_script("/".join([resourcePath, "triggers.sql"])) Logger.log_info("Database v1 update: Triggers built") self.__execute_script("/".join([resourcePath, "indexes.sql"])) Logger.log_info("Database v1 update: Indexes built") Logger.log_info("Database v1 update completed")
def on_system_connected(self): super().on_system_connected() Logger.log_info("on_system_connected begins...") DebugModule.DEBUG_ON_SYSTEM_CONNECTED.append(time.time()) self.__automationModule = AutomationModuleWrapper() # ID must be retrieved before timer module register groups. self.__get_default_group_ids() # ===== Register methods ===== # APIs paramSection = KBXString(kbxParamName="section") paramLimit = KBXNumber(kbxParamName="limit", kbxParamIsRequired=False, kbxParamMinValue=0, \ kbxParamMaxValue=200) paramOffset = KBXNumber(kbxParamName="offset", kbxParamIsRequired=False, kbxParamMinValue=0) self.register_method(kbxMethodName="list_groups", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_groups, kbxMethodParams=[KBXNumber(kbxParamName="parentId", kbxParamIsRequired=False, kbxParamMinValue=1), paramSection]) self.register_method(kbxMethodName="list_methods", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_methods, kbxMethodParams=[KBXNumber(kbxParamName="groupId", kbxParamMinValue=1), paramSection]) self.register_method(kbxMethodName="update_kbx_method", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.update_kbx_method, kbxMethodParams=[KBXNumber(kbxParamName="kbxMethodId", kbxParamMinValue=1)]) self.register_method(kbxMethodName="update_kbx_group", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.update_kbx_group, kbxMethodParams=[KBXNumber(kbxParamName="kbxGroupId", kbxParamMinValue=1)]) self.register_method(kbxMethodName="list_kbx_methods", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_kbx_methods, kbxMethodParams=[paramLimit, paramOffset]) self.register_method(kbxMethodName="list_kbx_groups", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_kbx_groups, kbxMethodParams=[paramLimit, paramOffset]) # Rules paramRuleId = KBXNumber(kbxParamName="ruleId", kbxParamDecimal=0, kbxParamMinValue=1) self.register_method(kbxMethodName="set_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.set_rule) self.register_method(kbxMethodName="list_rules", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_rules, kbxMethodParams=[paramLimit, paramOffset]) self.register_method(kbxMethodName="get_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.get_rule, kbxMethodParams=[paramRuleId]) self.register_method(kbxMethodName="delete_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.delete_rule, kbxMethodParams=[paramRuleId]) self.register_method(kbxMethodName="trigger_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.trigger_rule, kbxMethodParams=[paramRuleId, KBXBoolean(kbxParamName="checkCondition", kbxParamIsRequired=False)]) self.register_method(kbxMethodName="enable_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.enable_rule, kbxMethodParams=[paramRuleId, KBXBoolean(kbxParamName="enabled", kbxParamIsRequired=True)]) # Scenes paramSceneId = KBXNumber(kbxParamName="sceneId", kbxParamDecimal=0, kbxParamMinValue=1) self.register_method(kbxMethodName="set_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.set_scene) self.register_method(kbxMethodName="execute_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.execute_scene, kbxMethodParams=[paramSceneId, KBXString(kbxParamName="serUrl", kbxParamIsRequired=False)]) self.register_method(kbxMethodName="stop_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.stop_scene, kbxMethodParams=[paramSceneId]) self.register_method(kbxMethodName="delete_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.delete_scene, kbxMethodParams=[paramSceneId]) self.register_method(kbxMethodName="get_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.get_scene, kbxMethodParams=[paramSceneId]) self.register_method(kbxMethodName="list_scenes", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_scenes, kbxMethodParams=[paramOffset, paramLimit]) # Scene Execution Results paramSerId = KBXString(kbxParamName="serId") self.register_method(kbxMethodName="get_scene_execution_result", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.get_scene_execution_result, kbxMethodParams=[paramSerId]) self.register_method(kbxMethodName="retry_scene_execution_result_item", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.retry_scene_execution_result_item, kbxMethodParams=[paramSerId, KBXNumber(kbxParamName="seriIndex", kbxParamIsRequired=False, kbxParamMinValue=0)]) self.register_method(kbxMethodName="list_scene_execution_results", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_scene_execution_results, kbxMethodParams=[paramOffset, paramLimit]) self.register_method(kbxMethodName="delete_scene_execution_result", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.delete_scene_execution_result, kbxMethodParams=[paramSerId]) # Favorited Scenes self.register_method(kbxMethodName="set_favorited_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.set_favorited_scene, kbxMethodParams=[paramSceneId, KBXNumber(kbxParamName="prevSceneId", kbxParamIsRequired=False, kbxParamDecimal=0, kbxParamMinValue=1)]) self.register_method(kbxMethodName="delete_favorited_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.delete_favorited_scene, kbxMethodParams=[paramSceneId]) self.register_method(kbxMethodName="list_favorited_scenes", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_favorited_scenes, kbxMethodParams=[paramLimit, paramOffset]) Logger.log_info("on_system_connected ends...")
def on_start(self): Logger.log_info("on_start begins...") AppInfo.JSON_ENCODER_CLS = AutomationJSONEncoder Database.instance().initialize() self.register_module(DebugModule("debug_module", None)) Logger.log_info("registered module: debug_module") self.register_module(ControllerModule("controller_module", None)) Logger.log_info("registered module: debug_module") self.register_module(TimerModule("timer_module", None)) Logger.log_info("registered module: debug_module") self.register_module(DeviceManagerModule("device_manager", None)) Logger.log_info("registered module: debug_module") self.register_module(ZWaveModule("zwave_module", None)) Logger.log_info("registered module: zwave_module") self.register_module(LocationManagerModule("location_manager", None)) Logger.log_info("registered module: location_manager") Logger.log_info("on_start ends...")
def __broadcast_message__favorited_scene_deleted(self, sceneId): eventTag = AppConstants.EVENT_FAVORITED_SCENE_DELETED eventData = {"sceneId": sceneId} self.__broadcast_message(eventTag, eventData) Logger.log_info("Favorited scene deleted: Id", sceneId)
def __broadcast_message__rule_deleted(self, ruleId): eventTag = AppConstants.EVENT_RULE_DELETED eventData = {"ruleId": ruleId} self.__broadcast_message(eventTag, eventData) Logger.log_info("Rule Deleted: Id -", ruleId)
def __broadcast_message__scene_deleted(self, sceneId): eventTag = AppConstants.EVENT_SCENE_DELETED eventData = {"sceneId": sceneId} self.__broadcast_message(eventTag, eventData) Logger.log_info("Scene Deleted: Id -", sceneId)
def __execute_scene_implementation(self, sceneId, execution, serObj, language): ''' ** Call execute_scene; DO NOT call this function directly. ''' Logger.log_info("execute scene id:", sceneId) def execution_func(sceneThreadEvent, kbxMethodId, seri, **kwargs): try: if kbxMethodId == -291: # Delay Timer delayInSec = kwargs["delayInSec"] sceneThreadEvent.wait(delayInSec) seri["seriError"] = None else: # Execute method result = SharedMethod.call(**kwargs) seri["seriError"] = str(result) seri["seriStatus"] = "ok" except Exception as e: seri["seriStatus"] = "error" seri["seriError"] = str(e) Logger.log_debug("Execution failed, method:", kwargs["kbxMethodName"]) finally: sceneThreadEvent.set() try: # Record for debugging purpose serStartTime = time.time() #=================================================================== # Prepare to execute execution methods #=================================================================== sceneExecLock = self.__sceneExecLocks.get(sceneId) sceneThreadEvent = sceneExecLock.get_thread_event() seris = deque() methodExecTime = int(time.time()) isLoopCompleted = True for row in execution: kbxMethodId = row["kbxMethodId"] kbxMethodName = row["kbxMethodName"] kbxGroupId = row["kbxGroupId"] kbxMethodStatus = row["kbxMethodStatus"] methodParamsWithCurrentValues = row["kbxMethodParams"] seri = {"kbxMethodId":kbxMethodId, "kbxGroupId":kbxGroupId, "kbxMethodName":kbxMethodName, "kbxMethodParams":methodParamsWithCurrentValues} seris.append(seri) # Check is stop if sceneExecLock.is_stop(): if not isLoopCompleted: serEndTime = time.time() isLoopCompleted = False # === Execution interrupted === continue # Check is method not removed elif kbxMethodStatus not in (SharedMethod.METHOD_STATUS_ACTIVE, SharedMethod.METHOD_STATUS_INACTIVE): seri["seriStatus"] = "error" seri["seriError"] = "method is removed" continue kwargs = {methodParam[AppConstants.ARG_NAME]: methodParam[AppConstants.ARG_CURRENT_VALUE] for methodParam in methodParamsWithCurrentValues} if AppInfo.REQUEST_KEY_LANGUAGE not in kwargs: kwargs[AppInfo.REQUEST_KEY_LANGUAGE] = AppInfo.DEFAULT_API_LANGUAGE kwargs["kbxMethodName"] = kbxMethodName kwargs["kbxGroupId"] = kbxGroupId kwargs["kbxModuleName"] = row["kbxModuleName"] kwargs["kbxMethodAppId"] = row["kbxMethodAppId"] kwargs[AppConstants.KEY_ACTION_TIMESTAMP] = methodExecTime #=========================================================== # Execute method #=========================================================== sceneThreadEvent.clear() execThread = threading.Thread(target=execution_func, args=[sceneThreadEvent, row["kbxMethodId"], seri], kwargs=kwargs) execThread.daemon = False execThread.start() sceneThreadEvent.wait() # Event will be set by "stop_scene" or SharedMethod.call returns. # Check is stop if sceneExecLock.is_stop(): if not isLoopCompleted: serEndTime = time.time() isLoopCompleted = False # === Execution interrupted === continue if isLoopCompleted: # Record for debugging purpose serEndTime = time.time() # === Execution completed === except Exception as e: # This is unexpected error. Execution will not be recorded by Scene Execution Result. Logger.log_error("SceneService.__execute_scene_implementation ex:", e) # === Execution completed with errors === else: if serObj is not None: # Log to sceneExecutionResultService self.__sceneExecutionResultThreadPool.submit(self.__add_scene_execution_result, serUrl=serObj["serUrl"], serStartTime=serStartTime, serEndTime=serEndTime, sceneName=serObj["sceneName"], sceneProtected=serObj["sceneProtected"], sceneId=sceneId, execution=seris, language=language) finally: del(self.__sceneExecLocks[sceneId]) # Delete exec lock sceneExecLock.release()
def db_1_update(self, resourcePath): Logger.log_info("Database v1 update started") self.__execute_script("/".join([resourcePath, "tablestructure.sql"])) Logger.log_info("Database v1 update: Table structures built") # #################### Migration codes #################### try: from automationApp.migration.storage import Storage allGroups = Storage.list_all_groups() if len(allGroups) > 0: # Probably no rule is set. ''' All Groups: e.g. {25: 'Yeelight Blue II'} ''' for kbxGroupId, kbxGroupLabel in allGroups.items(): self.__con.execute( 'INSERT INTO "kbx_group"("kbxGroupId", "kbxGroupLabel", "kbxGroupStatus") VALUES (?, ?, ?)', (kbxGroupId, kbxGroupLabel, -1)) del (allGroups) ''' All Groups Methods: e.g. {69: 25, 71: 25} ''' allMethodGroups = Storage.list_all_method_groups() for kbxMethodId, kbxGroupId in allMethodGroups.items(): self.__con.execute('INSERT INTO "kbx_method"("kbxMethodId", "kbxGroupId", "kbxMethodStatus") ' + \ 'VALUES (?, ?, ?)', (kbxMethodId, kbxGroupId, -1)) ''' All Rules: e.g. [{ 'execution': [{'kbxMethodId': 71, 'kbxMethodParams': [{'kbxParamCurrentValue': '4', 'kbxParamName': 'pairedDeviceId'},{'kbxParamCurrentValue': [False], 'kbxParamName': 'on'}]}], 'trigger': {'type': 0, 'value': None}, 'ruleId': '1425284835.0756288', 'enabled': True, 'condition': [{'kbxMethodId': 69, 'kbxMethodParams': [{'kbxParamCurrentValue': '4', 'kbxParamName': 'pairedDeviceId'}, {'kbxParamCurrentValue': [True], 'kbxParamName': 'on'}]}], 'ruleName': 'ReTestet' }] ''' allRules = Storage.list_all_rules() cursor = self.__con.cursor() createdTime = updatedTime = time.time() triggerController = TriggerController.instance() for sort, rule in enumerate(allRules): trigger = triggerController.parse_to_trigger_dto( rule["trigger"]) cursor.execute('INSERT INTO "rule"("ruleName", "ruleProtected", "trigger", "enabled", "statusProcessed", "createdTime", "updatedTime", "sort") ' + \ 'VALUES (?, ?, ?, ?, ?, ?, ?, ?)', (rule["ruleName"], False, json.dumps(trigger), rule["enabled"], "updated", createdTime, updatedTime, sort)) ruleId = cursor.lastrowid for vals in (["execution", "rule_execution", "reRuleId"], ["condition", "rule_condition", "rcRuleId"]): for kbxMethodSort, kbxMethodWithCurrentValue in enumerate( rule[vals[0]]): self.__con.execute('INSERT INTO "' + vals[1] + '"("' + vals[2] + '", "kbxMethodId", "kbxMethodParams", "createdTime", "sort") ' + \ 'VALUES (?, ?, ?, ?, ?)', (ruleId, kbxMethodWithCurrentValue["kbxMethodId"], json.dumps(kbxMethodWithCurrentValue["kbxMethodParams"]), createdTime, kbxMethodSort)) cursor.close() del (allRules) self.__con.commit() except Exception as e: self.__con.rollback() Logger.log_warning( "Database failed to migrate rules from system, ex:", e, "---- rolled back") else: Logger.log_info("Database v1 update: Rules migrated") try: Storage.delete_all_rules() Storage.delete_all_method_groups() Storage.delete_all_groups() except Exception as e: Logger.log_warning( "Database failed to remove rules from system after migration, ex:", e) # #################### End of migration codes #################### self.__execute_script("/".join([resourcePath, "triggers.sql"])) Logger.log_info("Database v1 update: Triggers built") self.__execute_script("/".join([resourcePath, "indexes.sql"])) Logger.log_info("Database v1 update: Indexes built") Logger.log_info("Database v1 update completed")
def __broadcast_message__rule_update_started(self, ruleId, ruleName=None): eventTag = AppConstants.EVENT_RULE_UPDATE_STARTED eventData = {"ruleId": ruleId, "newRuleName": ruleName} self.__broadcast_message(eventTag, eventData) Logger.log_info("Rule Start Update:", ruleName)
def __execute_scene_implementation(self, sceneId, execution, serObj, language): ''' ** Call execute_scene; DO NOT call this function directly. ''' Logger.log_info("execute scene id:", sceneId) def execution_func(sceneThreadEvent, kbxMethodId, seri, **kwargs): try: if kbxMethodId == -291: # Delay Timer delayInSec = kwargs["delayInSec"] sceneThreadEvent.wait(delayInSec) seri["seriError"] = None else: # Execute method result = SharedMethod.call(**kwargs) seri["seriError"] = str(result) seri["seriStatus"] = "ok" except Exception as e: seri["seriStatus"] = "error" seri["seriError"] = str(e) Logger.log_debug("Execution failed, method:", kwargs["kbxMethodName"]) finally: sceneThreadEvent.set() try: # Record for debugging purpose serStartTime = time.time() #=================================================================== # Prepare to execute execution methods #=================================================================== sceneExecLock = self.__sceneExecLocks.get(sceneId) sceneThreadEvent = sceneExecLock.get_thread_event() seris = deque() methodExecTime = int(time.time()) isLoopCompleted = True for row in execution: kbxMethodId = row["kbxMethodId"] kbxMethodName = row["kbxMethodName"] kbxGroupId = row["kbxGroupId"] kbxMethodStatus = row["kbxMethodStatus"] methodParamsWithCurrentValues = row["kbxMethodParams"] seri = { "kbxMethodId": kbxMethodId, "kbxGroupId": kbxGroupId, "kbxMethodName": kbxMethodName, "kbxMethodParams": methodParamsWithCurrentValues } seris.append(seri) # Check is stop if sceneExecLock.is_stop(): if not isLoopCompleted: serEndTime = time.time() isLoopCompleted = False # === Execution interrupted === continue # Check is method not removed elif kbxMethodStatus not in ( SharedMethod.METHOD_STATUS_ACTIVE, SharedMethod.METHOD_STATUS_INACTIVE): seri["seriStatus"] = "error" seri["seriError"] = "method is removed" continue kwargs = { methodParam[AppConstants.ARG_NAME]: methodParam[AppConstants.ARG_CURRENT_VALUE] for methodParam in methodParamsWithCurrentValues } if AppInfo.REQUEST_KEY_LANGUAGE not in kwargs: kwargs[AppInfo. REQUEST_KEY_LANGUAGE] = AppInfo.DEFAULT_API_LANGUAGE kwargs["kbxMethodName"] = kbxMethodName kwargs["kbxGroupId"] = kbxGroupId kwargs["kbxModuleName"] = row["kbxModuleName"] kwargs["kbxMethodAppId"] = row["kbxMethodAppId"] kwargs[AppConstants.KEY_ACTION_TIMESTAMP] = methodExecTime #=========================================================== # Execute method #=========================================================== sceneThreadEvent.clear() execThread = threading.Thread( target=execution_func, args=[sceneThreadEvent, row["kbxMethodId"], seri], kwargs=kwargs) execThread.daemon = False execThread.start() sceneThreadEvent.wait( ) # Event will be set by "stop_scene" or SharedMethod.call returns. # Check is stop if sceneExecLock.is_stop(): if not isLoopCompleted: serEndTime = time.time() isLoopCompleted = False # === Execution interrupted === continue if isLoopCompleted: # Record for debugging purpose serEndTime = time.time() # === Execution completed === except Exception as e: # This is unexpected error. Execution will not be recorded by Scene Execution Result. Logger.log_error("SceneService.__execute_scene_implementation ex:", e) # === Execution completed with errors === else: if serObj is not None: # Log to sceneExecutionResultService self.__sceneExecutionResultThreadPool.submit( self.__add_scene_execution_result, serUrl=serObj["serUrl"], serStartTime=serStartTime, serEndTime=serEndTime, sceneName=serObj["sceneName"], sceneProtected=serObj["sceneProtected"], sceneId=sceneId, execution=seris, language=language) finally: del (self.__sceneExecLocks[sceneId]) # Delete exec lock sceneExecLock.release()
def __broadcast_message__favorited_scene_added(self, sceneId, prevSceneId): eventTag = AppConstants.EVENT_FAVORITED_SCENE_ADDED eventData = {"sceneId":sceneId, "prevSceneId":prevSceneId} self.__broadcast_message(eventTag, eventData) Logger.log_info("Favorited scene added/updated: Id", sceneId, "prevId:", prevSceneId)
def __broadcast_message__rule_update_started(self, ruleId, ruleName=None): eventTag = AppConstants.EVENT_RULE_UPDATE_STARTED eventData = {"ruleId":ruleId, "newRuleName":ruleName} self.__broadcast_message(eventTag, eventData) Logger.log_info("Rule Start Update:", ruleName)
def on_system_connected(self): super().on_system_connected() Logger.log_info("on_system_connected begins...") DebugModule.DEBUG_ON_SYSTEM_CONNECTED.append(time.time()) self.__automationModule = AutomationModuleWrapper() # ID must be retrieved before timer module register groups. self.__get_default_group_ids() # ===== Register methods ===== # APIs paramSection = KBXString(kbxParamName="section") paramLimit = KBXNumber(kbxParamName="limit", kbxParamIsRequired=False, kbxParamMinValue=0, \ kbxParamMaxValue=200) paramOffset = KBXNumber(kbxParamName="offset", kbxParamIsRequired=False, kbxParamMinValue=0) self.register_method(kbxMethodName="list_groups", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_groups, kbxMethodParams=[ KBXNumber(kbxParamName="parentId", kbxParamIsRequired=False, kbxParamMinValue=1), paramSection ]) self.register_method( kbxMethodName="list_methods", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_methods, kbxMethodParams=[ KBXNumber(kbxParamName="groupId", kbxParamMinValue=1), paramSection ]) self.register_method( kbxMethodName="update_kbx_method", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.update_kbx_method, kbxMethodParams=[ KBXNumber(kbxParamName="kbxMethodId", kbxParamMinValue=1) ]) self.register_method( kbxMethodName="update_kbx_group", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.update_kbx_group, kbxMethodParams=[ KBXNumber(kbxParamName="kbxGroupId", kbxParamMinValue=1) ]) self.register_method( kbxMethodName="list_kbx_methods", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_kbx_methods, kbxMethodParams=[paramLimit, paramOffset]) self.register_method( kbxMethodName="list_kbx_groups", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_kbx_groups, kbxMethodParams=[paramLimit, paramOffset]) # Rules paramRuleId = KBXNumber(kbxParamName="ruleId", kbxParamDecimal=0, kbxParamMinValue=1) self.register_method(kbxMethodName="set_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.set_rule) self.register_method(kbxMethodName="list_rules", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_rules, kbxMethodParams=[paramLimit, paramOffset]) self.register_method(kbxMethodName="get_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.get_rule, kbxMethodParams=[paramRuleId]) self.register_method(kbxMethodName="delete_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.delete_rule, kbxMethodParams=[paramRuleId]) self.register_method( kbxMethodName="trigger_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.trigger_rule, kbxMethodParams=[ paramRuleId, KBXBoolean(kbxParamName="checkCondition", kbxParamIsRequired=False) ]) self.register_method(kbxMethodName="enable_rule", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.enable_rule, kbxMethodParams=[ paramRuleId, KBXBoolean(kbxParamName="enabled", kbxParamIsRequired=True) ]) # Scenes paramSceneId = KBXNumber(kbxParamName="sceneId", kbxParamDecimal=0, kbxParamMinValue=1) self.register_method(kbxMethodName="set_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.set_scene) self.register_method( kbxMethodName="execute_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.execute_scene, kbxMethodParams=[ paramSceneId, KBXString(kbxParamName="serUrl", kbxParamIsRequired=False) ]) self.register_method(kbxMethodName="stop_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.stop_scene, kbxMethodParams=[paramSceneId]) self.register_method( kbxMethodName="delete_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.delete_scene, kbxMethodParams=[paramSceneId]) self.register_method(kbxMethodName="get_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.get_scene, kbxMethodParams=[paramSceneId]) self.register_method(kbxMethodName="list_scenes", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_scenes, kbxMethodParams=[paramOffset, paramLimit]) # Scene Execution Results paramSerId = KBXString(kbxParamName="serId") self.register_method( kbxMethodName="get_scene_execution_result", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.get_scene_execution_result, kbxMethodParams=[paramSerId]) self.register_method(kbxMethodName="retry_scene_execution_result_item", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule. retry_scene_execution_result_item, kbxMethodParams=[ paramSerId, KBXNumber(kbxParamName="seriIndex", kbxParamIsRequired=False, kbxParamMinValue=0) ]) self.register_method( kbxMethodName="list_scene_execution_results", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_scene_execution_results, kbxMethodParams=[paramOffset, paramLimit]) self.register_method(kbxMethodName="delete_scene_execution_result", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule. delete_scene_execution_result, kbxMethodParams=[paramSerId]) # Favorited Scenes self.register_method( kbxMethodName="set_favorited_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.set_favorited_scene, kbxMethodParams=[ paramSceneId, KBXNumber(kbxParamName="prevSceneId", kbxParamIsRequired=False, kbxParamDecimal=0, kbxParamMinValue=1) ]) self.register_method( kbxMethodName="delete_favorited_scene", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.delete_favorited_scene, kbxMethodParams=[paramSceneId]) self.register_method( kbxMethodName="list_favorited_scenes", kbxMethodIsPrivate=True, kbxMethodFunc=self.__automationModule.list_favorited_scenes, kbxMethodParams=[paramLimit, paramOffset]) Logger.log_info("on_system_connected ends...")
def __broadcast_message__favorited_scene_deleted(self, sceneId): eventTag = AppConstants.EVENT_FAVORITED_SCENE_DELETED eventData = {"sceneId":sceneId} self.__broadcast_message(eventTag, eventData) Logger.log_info("Favorited scene deleted: Id", sceneId)
def __trigger_rule_implementation(self, ruleId, checkCondition=False, eventTag=None, eventData=None, eventMethodId=None): ''' Triggers a rule by given ruleId. ''' Logger.log_info("trigger rule id:", ruleId) # Check if rule is "updated" AND enabled. statusProcessed, enabled = self.__ruleController.get_status_processed_and_enabled(ruleId) if statusProcessed != AppConstants.RULE_STATUS_UPDATED or enabled != True: return self.__ruleExecInfos.setdefault(ruleId, RuleExecInfo()) ruleExecInfo = self.__ruleExecInfos.get(ruleId) ruleExecInfo.increase_trigger_count() triggerCountInThisSession = ruleExecInfo.get_trigger_count() with ruleExecInfo.get_rlock(): #======================================================================= # Check conditions #======================================================================= if checkCondition is True: # Check if we should proceed (stop if there is another pending request on the same ruleId). if triggerCountInThisSession != ruleExecInfo.get_trigger_count(): return methodListToCheck = deque() result = self.__ruleController.list_conditions(ruleId) methodCheckingTime = int(time.time()) for row in result: if row["kbxMethodStatus"] not in (SharedMethod.METHOD_STATUS_ACTIVE, SharedMethod.METHOD_STATUS_INACTIVE): return else: methodArgs = row["kbxMethodParams"] kwargs = {methodArg[AppConstants.ARG_NAME]:methodArg[AppConstants.ARG_CURRENT_VALUE] for methodArg in methodArgs} if eventTag is not None and eventMethodId == row["kbxMethodId"]: kwargs[AppConstants.KEY_CONDITION_EVENT_TAG] = eventTag kwargs[AppConstants.KEY_CONDITION_EVENT_DATA] = eventData if AppInfo.REQUEST_KEY_LANGUAGE not in kwargs: kwargs[AppInfo.REQUEST_KEY_LANGUAGE] = AppInfo.DEFAULT_API_LANGUAGE kwargs["kbxMethodName"] = row["kbxMethodName"] kwargs["kbxModuleName"] = row["kbxModuleName"] kwargs["kbxGroupId"] = row["kbxGroupId"] kwargs["kbxMethodAppId"] = row["kbxMethodAppId"] # Update ruleId if it is required by the method if "ruleId" in kwargs: kwargs["ruleId"] = str(ruleId) callId = hash(str(kwargs)) # Generate condition checking ID kwargs[AppConstants.KEY_CONDITION_TIMESTAMP] = methodCheckingTime # So that timestamp will not caused the generated id to be different methodListToCheck.append({"callId":callId, "callFn":SharedMethod.call, "callKwargs":kwargs}) #=============================================================== # Submit all conditions for checking #=============================================================== methodListToCheckLen = len(methodListToCheck) if methodListToCheckLen > 0: ruleExecResult = RuleExecResult(methodListToCheckLen) for methodItem in methodListToCheck: self.__condCallGroup.submit(callbackFn=self.__on_method_call_complete, ruleExecResult=ruleExecResult, **methodItem) result = ruleExecResult.wait(40.0) if result is False or ruleExecResult.get_result() is False: return # Failed at condition checking. # Clear cache del(methodListToCheck) del(methodCheckingTime) del(methodListToCheckLen) # Check if we should proceed (stop if there is another pending request on the same ruleId). if triggerCountInThisSession != ruleExecInfo.get_trigger_count(): return #======================================================================= # Execute executions #======================================================================= methodListToExec = deque() result = self.__ruleController.list_executions(ruleId) methodExecTime = int(time.time()) for row in result: if row["kbxMethodStatus"] not in (SharedMethod.METHOD_STATUS_ACTIVE, SharedMethod.METHOD_STATUS_INACTIVE): continue else: methodArgs = row["kbxMethodParams"] kwargs = {methodArg[AppConstants.ARG_NAME]:methodArg[AppConstants.ARG_CURRENT_VALUE] for methodArg in methodArgs} if AppInfo.REQUEST_KEY_LANGUAGE not in kwargs: kwargs[AppInfo.REQUEST_KEY_LANGUAGE] = AppInfo.DEFAULT_API_LANGUAGE kwargs["kbxMethodName"] = row["kbxMethodName"] kwargs["kbxModuleName"] = row["kbxModuleName"] kwargs["kbxGroupId"] = row["kbxGroupId"] kwargs["kbxMethodAppId"] = row["kbxMethodAppId"] # Update ruleId if it is required by the method if "ruleId" in kwargs: kwargs["ruleId"] = str(ruleId) callId = hash(str(kwargs)) # Generate execution id kwargs[AppConstants.KEY_ACTION_TIMESTAMP] = methodExecTime methodListToExec.append({"callId":callId, "callFn":SharedMethod.call, "callKwargs":kwargs}) #=============================================================== # Submit all methods for executions #=============================================================== methodListToExecLen = len(methodListToExec) if methodListToExecLen > 0: ruleExecResult = RuleExecResult(methodListToExecLen) for methodItem in methodListToExec: self.__execCallGroup.submit(callbackFn=self.__on_method_call_complete, ruleExecResult=ruleExecResult, **methodItem) result = ruleExecResult.wait(30.0) return
def __trigger_rule_implementation(self, ruleId, checkCondition=False, eventTag=None, eventData=None, eventMethodId=None): ''' Triggers a rule by given ruleId. ''' Logger.log_info("trigger rule id:", ruleId) # Check if rule is "updated" AND enabled. statusProcessed, enabled = self.__ruleController.get_status_processed_and_enabled( ruleId) if statusProcessed != AppConstants.RULE_STATUS_UPDATED or enabled != True: return self.__ruleExecInfos.setdefault(ruleId, RuleExecInfo()) ruleExecInfo = self.__ruleExecInfos.get(ruleId) ruleExecInfo.increase_trigger_count() triggerCountInThisSession = ruleExecInfo.get_trigger_count() with ruleExecInfo.get_rlock(): #======================================================================= # Check conditions #======================================================================= if checkCondition is True: # Check if we should proceed (stop if there is another pending request on the same ruleId). if triggerCountInThisSession != ruleExecInfo.get_trigger_count( ): return methodListToCheck = deque() result = self.__ruleController.list_conditions(ruleId) methodCheckingTime = int(time.time()) for row in result: if row["kbxMethodStatus"] not in ( SharedMethod.METHOD_STATUS_ACTIVE, SharedMethod.METHOD_STATUS_INACTIVE): return else: methodArgs = row["kbxMethodParams"] kwargs = { methodArg[AppConstants.ARG_NAME]: methodArg[AppConstants.ARG_CURRENT_VALUE] for methodArg in methodArgs } if eventTag is not None and eventMethodId == row[ "kbxMethodId"]: kwargs[AppConstants. KEY_CONDITION_EVENT_TAG] = eventTag kwargs[AppConstants. KEY_CONDITION_EVENT_DATA] = eventData if AppInfo.REQUEST_KEY_LANGUAGE not in kwargs: kwargs[ AppInfo. REQUEST_KEY_LANGUAGE] = AppInfo.DEFAULT_API_LANGUAGE kwargs["kbxMethodName"] = row["kbxMethodName"] kwargs["kbxModuleName"] = row["kbxModuleName"] kwargs["kbxGroupId"] = row["kbxGroupId"] kwargs["kbxMethodAppId"] = row["kbxMethodAppId"] # Update ruleId if it is required by the method if "ruleId" in kwargs: kwargs["ruleId"] = str(ruleId) callId = hash( str(kwargs)) # Generate condition checking ID kwargs[ AppConstants. KEY_CONDITION_TIMESTAMP] = methodCheckingTime # So that timestamp will not caused the generated id to be different methodListToCheck.append({ "callId": callId, "callFn": SharedMethod.call, "callKwargs": kwargs }) #=============================================================== # Submit all conditions for checking #=============================================================== methodListToCheckLen = len(methodListToCheck) if methodListToCheckLen > 0: ruleExecResult = RuleExecResult(methodListToCheckLen) for methodItem in methodListToCheck: self.__condCallGroup.submit( callbackFn=self.__on_method_call_complete, ruleExecResult=ruleExecResult, **methodItem) result = ruleExecResult.wait(40.0) if result is False or ruleExecResult.get_result() is False: return # Failed at condition checking. # Clear cache del (methodListToCheck) del (methodCheckingTime) del (methodListToCheckLen) # Check if we should proceed (stop if there is another pending request on the same ruleId). if triggerCountInThisSession != ruleExecInfo.get_trigger_count( ): return #======================================================================= # Execute executions #======================================================================= methodListToExec = deque() result = self.__ruleController.list_executions(ruleId) methodExecTime = int(time.time()) for row in result: if row["kbxMethodStatus"] not in ( SharedMethod.METHOD_STATUS_ACTIVE, SharedMethod.METHOD_STATUS_INACTIVE): continue else: methodArgs = row["kbxMethodParams"] kwargs = { methodArg[AppConstants.ARG_NAME]: methodArg[AppConstants.ARG_CURRENT_VALUE] for methodArg in methodArgs } if AppInfo.REQUEST_KEY_LANGUAGE not in kwargs: kwargs[ AppInfo. REQUEST_KEY_LANGUAGE] = AppInfo.DEFAULT_API_LANGUAGE kwargs["kbxMethodName"] = row["kbxMethodName"] kwargs["kbxModuleName"] = row["kbxModuleName"] kwargs["kbxGroupId"] = row["kbxGroupId"] kwargs["kbxMethodAppId"] = row["kbxMethodAppId"] # Update ruleId if it is required by the method if "ruleId" in kwargs: kwargs["ruleId"] = str(ruleId) callId = hash(str(kwargs)) # Generate execution id kwargs[AppConstants.KEY_ACTION_TIMESTAMP] = methodExecTime methodListToExec.append({ "callId": callId, "callFn": SharedMethod.call, "callKwargs": kwargs }) #=============================================================== # Submit all methods for executions #=============================================================== methodListToExecLen = len(methodListToExec) if methodListToExecLen > 0: ruleExecResult = RuleExecResult(methodListToExecLen) for methodItem in methodListToExec: self.__execCallGroup.submit( callbackFn=self.__on_method_call_complete, ruleExecResult=ruleExecResult, **methodItem) result = ruleExecResult.wait(30.0) return
def __broadcast_message__scene_update_started(self, sceneId, sceneName=None): eventTag = AppConstants.EVENT_SCENE_UPDATE_STARTED eventData = {"sceneId": sceneId, "newSceneName":sceneName} self.__broadcast_message(eventTag, eventData) Logger.log_info("Scene Start Update:", sceneName)