示例#1
0
 def rollback(self):
     with self.__rlock:
         try:
             return self.__con.rollback()
         except Exception as e:
             Logger.log_error("Database.rollback ex:", e)
             traceback.print_exc()
示例#2
0
    def initialize(self):
        currentVersion = self.get_user_version()
        for updateToVersion, (__runOnce, __run) in enumerate(
                zip(self.__runOnce, self.__run),
                1):  # First version = 1, not 0.
            if updateToVersion > currentVersion:
                # Performs run once function call on later versions only.
                try:
                    __runOnce("/".join(
                        (Database.RESOURCE_PATH, str(updateToVersion))))
                except Exception as e:
                    Logger.log_error("Error on updating to version",
                                     updateToVersion, "ex:", e)
                    raise Exception(
                        "Failed to initialize database: error on run-once function for version "
                        + str(updateToVersion))

            # Executes all custom functions
            try:
                __run()
            except Exception as e:
                Logger.log_error("Error on version", updateToVersion,
                                 "function execution, ex:", e)
                raise Exception(
                    "Failed to initialize database: error on run-everytime function for version "
                    + str(updateToVersion))
        else:
            del (self.__runOnce)
            del (self.__run)

        self.set_user_version(updateToVersion)
示例#3
0
        def process_method_list(methodList):
            #===================================================================
            # Basic type validation
            #===================================================================
            if not isinstance(methodList, list):
                Logger.log_error(
                    "RuleService.set_rule: 'condition' and 'execution' must be type of list."
                )
                Logger.log_debug("type:", type(methodList), "value:",
                                 methodList)
                raise AutomationException(
                    11704,
                    "List is required for both 'condition' and 'execution'")

            #===================================================================
            # Check allowed size, raise error if exceeded.
            #===================================================================
            methodListLen = len(methodList)
            if methodListLen > AppConstants.MAX_METHOD_SIZE:
                Logger.log_error(
                    "RuleService.set_rule: 'condition' and 'execution' cannot have more than",
                    AppConstants.MAX_METHOD_SIZE, "items respectively.")
                raise AutomationException(11705, "Only a maximum of " + \
                                          str(AppConstants.MAX_METHOD_SIZE) + \
                                          " items is allowed for each 'condition' and 'execution' - given size " + \
                                          str(methodListLen),
                                          lambda text: str(AppConstants.MAX_METHOD_SIZE).join(text.split(":max_item_size:")))

            #===================================================================
            # Check if all kbxMethodIds are valid and all kbxMethodParams are list
            #===================================================================
            idValidator = NumberValidator(isRequired=True, decimalPoint=False)
            if not all([
                    idValidator.is_valid(eachMethod["kbxMethodId"])
                    and isinstance(eachMethod["kbxMethodParams"], list)
                    for eachMethod in methodList
            ]):
                raise AutomationException(
                    11704,
                    "'condition' and 'execution' have incorrect data structure."
                )

            #===================================================================
            # Check if all kbxParamName and kbxParamCurrentValue exists
            #===================================================================
            paramNameValidator = StringValidator(isRequired=True)
            for eachMethod in methodList:
                methodArgs = eachMethod["kbxMethodParams"]
                for methodArg in methodArgs:
                    if not paramNameValidator.is_valid(
                            methodArg[AppConstants.ARG_NAME]):
                        raise AutomationException(
                            11704,
                            "'condition' and 'execution' have invalid params structure"
                        )

                    if not AppConstants.ARG_CURRENT_VALUE in methodArg:
                        methodArg[AppConstants.ARG_CURRENT_VALUE] = None

            return methodList
示例#4
0
    def __date_time_range(self, request):
        try:
            dtVal = request.get_value(
                TimerModule._PARAM_DT_RANGE.get_kbx_param_name())
            startDateTime = dtVal.get_start_date_time()
            endDateTime = dtVal.get_end_date_time()

            execTime = request.get_arg(AppConstants.KEY_CONDITION_TIMESTAMP)
            execTime = int(execTime)

            if execTime > endDateTime:
                # Allow a time delta of 59 seconds
                response = bool(abs(execTime - endDateTime) <= 59)
            else:
                response = bool(startDateTime <= execTime <= endDateTime)

            if not response:
                raise AutomationException(11800)

            self.send_response({}, request.requestId)
        except AutomationException as ae:
            Logger.log_error(
                "TimerModule date_time range failed on comparison:", str(ae))
            self.send_response({}, request.requestId, ae.get_error_code(),
                               ae.get_error_message())
        except Exception as e:
            Logger.log_error(
                "TimerModule date_time range failed on comparison (unexpected):",
                str(e))
            ae = AutomationException(11099, str(e))
            self.send_response({}, request.requestId, ae.get_error_code(),
                               ae.get_error_message())
示例#5
0
    def delete_favorited_scene(self, sceneId):
        '''
        sceneId - must be a favorited scene.
        '''
        with self.__fav_lock:
            try:
                favSort = self.__sceneController.get_favsort_of(sceneId)
            except Exception as e:
                raise AutomationException(11092, "prevSceneId does not belongs to any scene - " + \
                                                "prevSceneId provided: " + str(sceneId) + ", error: " + str(e))
            else:
                if favSort is None:
                    raise AutomationException(13000, "sceneId does not belongs to any favorited scene - " + \
                                                    "sceneId provided: " + str(sceneId))

            # This method raise error and rollback automatically if failed, or commit once succeed.
            try:
                self.__sceneController.delete_favorited_scene(sceneId)
                self.__sceneController.commit()
            except Exception as e:
                self.__sceneController.rollback()
                Logger.log_error(
                    "SceneService.delete_favorited_scene failed to delete favorited scene, ex:",
                    str(e))
                raise AutomationException(13002, "unexpected error: " + str(e))

            #Broadcast event
            self.__broadcast_message__scene_updated(sceneId)
            self.__broadcast_message__favorited_scene_deleted(sceneId)
示例#6
0
        def __update_scene(scene):
            try:
                # Fire scene update start event
                sceneId = scene["sceneId"]
                sceneName = scene["sceneName"]

                # Add methods to subscribe list
                methodIds = [
                    kbxMethod["kbxMethodId"]
                    for kbxMethod in scene["execution"]
                ]
                self.__methodController.add(methodIds)

                # Update "scene" base table
                self.__sceneController.update(scene)
                self.__sceneController.commit()

            except Exception as e:
                self.__sceneController.rollback()
                self.__broadcast_message__scene_update_failed(
                    sceneId, sceneName)
                Logger.log_error("SceneService __update_scene failed:", e,
                                 "-- rolledback")
            else:
                # Broadcast message: completed updating a scene
                self.__broadcast_message__scene_updated(sceneId)
示例#7
0
 def __date_time_range(self, request):
     try:
         dtVal = request.get_value(TimerModule._PARAM_DT_RANGE.get_kbx_param_name())
         startDateTime = dtVal.get_start_date_time()
         endDateTime = dtVal.get_end_date_time()
         
         execTime = request.get_arg(AppConstants.KEY_CONDITION_TIMESTAMP)
         execTime = int(execTime)
         
         if execTime > endDateTime:
             # Allow a time delta of 59 seconds
             response = bool(abs(execTime - endDateTime) <= 59)
         else:
             response =  bool(startDateTime <= execTime <= endDateTime)
         
         if not response:
             raise AutomationException(11800)
             
         self.send_response({}, request.requestId)
     except AutomationException as ae:
         Logger.log_error("TimerModule date_time range failed on comparison:", str(ae))
         self.send_response({}, request.requestId, ae.get_error_code(), ae.get_error_message())
     except Exception as e:
         Logger.log_error("TimerModule date_time range failed on comparison (unexpected):", str(e))
         ae = AutomationException(11099, str(e))
         self.send_response({}, request.requestId, ae.get_error_code(), ae.get_error_message())
示例#8
0
 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()
示例#9
0
    def __day_of_week(self, request):
        try:
            dows = request.get_value(
                TimerModule._PARAM_DOW.get_kbx_param_name())

            execTime = request.get_arg(AppConstants.KEY_CONDITION_TIMESTAMP)
            execTime = datetime.datetime.fromtimestamp(execTime)
            execDow = execTime.isoweekday() % 7

            response = bool(execDow in dows)

            if not response:
                raise AutomationException(11800)

            self.send_response({}, request.requestId)
        except AutomationException as ae:
            Logger.log_error("TimerModule day_of_week failed on comparison:",
                             str(ae))
            self.send_response({}, request.requestId, ae.get_error_code(),
                               ae.get_error_message())
        except Exception as e:
            Logger.log_error(
                "TimerModule day_of_week failed on comparison (unexpected):",
                str(e))
            ae = AutomationException(11099, str(e))
            self.send_response({}, request.requestId, ae.get_error_code(),
                               ae.get_error_message())
示例#10
0
 def rollback(self):
     with self.__rlock:
         try:
             return self.__con.rollback()
         except Exception as e:
             Logger.log_error("Database.rollback ex:", e)
             traceback.print_exc()
示例#11
0
 def delete_favorited_scene(self, sceneId):
     '''
     sceneId - must be a favorited scene.
     '''
     with self.__fav_lock:
         try:
             favSort = self.__sceneController.get_favsort_of(sceneId)
         except Exception as e:
             raise AutomationException(11092, "prevSceneId does not belongs to any scene - " + \
                                             "prevSceneId provided: " + str(sceneId) + ", error: " + str(e))
         else:
             if favSort is None:
                 raise AutomationException(13000, "sceneId does not belongs to any favorited scene - " + \
                                                 "sceneId provided: " + str(sceneId))
         
         # This method raise error and rollback automatically if failed, or commit once succeed.
         try:
             self.__sceneController.delete_favorited_scene(sceneId)
             self.__sceneController.commit()
         except Exception as e:
             self.__sceneController.rollback()
             Logger.log_error("SceneService.delete_favorited_scene failed to delete favorited scene, ex:", str(e))
             raise AutomationException(13002, "unexpected error: " + str(e))
         
         #Broadcast event
         self.__broadcast_message__scene_updated(sceneId)
         self.__broadcast_message__favorited_scene_deleted(sceneId)
示例#12
0
 def __update_rule(rule):
     try:
         # Fire rule update start event
         ruleId = rule["ruleId"]
         
         # Add methods to subscribe list
         methodIds = [kbxMethod["kbxMethodId"] for kbxMethod in rule["condition"] + rule["execution"]]
         self.__methodController.add(methodIds)
         
         # Update "rule" base table
         self.__ruleController.update(rule)
         self.__ruleController.commit()
     
     except Exception as e:
         self.__ruleController.rollback()
         self.__broadcast_message__rule_update_failed(ruleId, ruleName)
         Logger.log_error("RuleService __update_rule failed:", e, "-- rolledback")
     else:
         self.__triggerController.register_listener(ruleId, rule["trigger"])
         
         # Process for Timer Module
         TimerModule.delete_scheduler(ruleId)
         
         timerModuleHandlers = {TimerModule.METHOD_ID_DATE_TIME_RANGE:TimerModule.handle_date_time_range,
                                TimerModule.METHOD_ID_DAY_OF_WEEK:TimerModule.handle_dow,
                                TimerModule.METHOD_ID_TIME_RANGE:TimerModule.handle_time_range}
         
         for kbxMethod in rule["condition"]:
             kbxMethodId = kbxMethod["kbxMethodId"]
             timerModuleHandler = timerModuleHandlers.get(kbxMethodId, None)
             if timerModuleHandler is not None:
                 timerModuleHandler(ruleId, kbxMethod["kbxMethodParams"])
             
         # Broadcast message: completed updating a rule
         self.__broadcast_message__rule_updated(ruleId)
示例#13
0
 def commit(self):
     with self.__rlock:
         try:
             return self.__con.commit()
         except Exception as e:
             Logger.log_error("Database.commit ex:", e)
             traceback.print_exc()
示例#14
0
 def commit(self):
     with self.__rlock:
         try:
             return self.__con.commit()
         except Exception as e:
             Logger.log_error("Database.commit ex:", e)
             traceback.print_exc()
示例#15
0
    def list_groups(self, language, section, parentId=None):
        try:
            def sort_group_list(value):
                name = value.get("kbxGroupLabel")
                if name is None:
                    return ""
                else:
                    return str(name).lower()
                
            
            unknownGroupDict = {}
            unknownGroupId = self.__get_group_ids()
                
            parentId = AppConstants.GROUP_ID_AUTOMATION if parentId is None else parentId

            result = SharedMethod.list_shared_method_groups(kbxGroupParentId=parentId, kbxMethodTag=section,
                                                            enableTagCount=True, language=language)
            
            groupList = result["groupList"]
            
            # Level 1 groups which contain of SERVICES and LOCATIONS.
            if parentId == AppConstants.GROUP_ID_AUTOMATION:
                services = deque()
                groups =  deque()
                
                for groupDict in groupList:
                    kbxGroupId = groupDict["kbxGroupId"]
                    
                    # Add indicator for UI
                    groupDict["kbxGroupHasChild"] = True

                    # Reordering
                    if kbxGroupId == AppConstants.GROUP_ID_NOTIFICATION:
                        groupDict["kbxGroupDesc"] = KBXLang("group_notification_" + section)
                        services.appendleft(groupDict)
                    elif kbxGroupId == AppConstants.GROUP_ID_SERVICE:
                        groupDict["kbxGroupDesc"] = KBXLang("group_service_" + section)
                        services.append(groupDict)
                    elif kbxGroupId == unknownGroupId:
                        #append the group dict
                        unknownGroupDict = groupDict
                    else:
                        groups.append(groupDict)
                groups = sorted(groups, key=sort_group_list)
                if len(unknownGroupDict) > 0:
                    groups.append(unknownGroupDict)
                services.extend(groups)
                groupList = services
                parentGroup = None
                
            # Level 2 groups which are DEVICES or SERVICES.
            else:
                parentGroup = SharedMethod.get_shared_method_group_by_id(kbxGroupId=parentId, language=language)

            return parentGroup, groupList

        except Exception as e:
            Logger.log_error("APIService.list_groups ex:", e)
            raise AutomationException(11601, "Unexpected error - " + str(e))
示例#16
0
 def __on_shared_method_updated(self, eventObject):
     '''
     Triggered based on event broadcasted by system app.
     '''
     try:
         kbxMethod = json.loads(eventObject["eventData"]) # eventData = kbxMethod
         self.update(kbxMethod)
     except Exception as e:
         Logger.log_error("MethodController.__on_shared_method_updated ex:", e)
         traceback.print_exc()
示例#17
0
 def enable_rule(self, ruleId, enabled):
     self.__check_rule_process_status(ruleId)
     try:
         self.__ruleController.enable(ruleId, enabled)
         self.__ruleController.commit()
     except Exception as e:
         self.__ruleController.rollback()
         Logger.log_error("RuleService enable_rule ex:", e, "-- rolled back")
     else:
         self.__broadcast_message__rule_updated(ruleId)
示例#18
0
 def enable_rule(self, ruleId, enabled):
     self.__check_rule_process_status(ruleId)
     try:
         self.__ruleController.enable(ruleId, enabled)
         self.__ruleController.commit()
     except Exception as e:
         self.__ruleController.rollback()
         Logger.log_error("RuleService enable_rule ex:", e,
                          "-- rolled back")
     else:
         self.__broadcast_message__rule_updated(ruleId)
示例#19
0
 def __on_shared_method_group_updated(self, eventObject):
     '''
     Triggered based on event broadcasted by system app.
     '''
     try:
         eventData = json.loads(eventObject["eventData"])
         self.update(eventData)  # eventData = kbxGroup
     except Exception as e:
         Logger.log_error(
             "GroupController.__on_shared_method_group_updated ex:", e)
         traceback.print_exc()
示例#20
0
    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"])
示例#21
0
 def __on_shared_method_deleted(self, eventObject):
     '''
     Triggered based on event broadcasted by system app.
     '''
     try:
         eventData = json.loads(eventObject["eventData"])
         kbxMethodId = eventData["kbxMethodId"]
         self.delete(kbxMethodId)
     except Exception as e:
         Logger.log_error("MethodController.__on_shared_method_deleted ex:",
                          e)
         traceback.print_exc()
示例#22
0
 def __add_scene_execution_result(self, serUrl, serStartTime, serEndTime, sceneName, sceneProtected, sceneId, execution, language):
         try:
             SceneExecutionResultService.instance().add_scene_execution_result(serUrl=serUrl, 
                                                                               serStartTime=serStartTime, 
                                                                               serEndTime=serEndTime, 
                                                                               sceneName=sceneName, 
                                                                               sceneProtected=sceneProtected, 
                                                                               sceneId=sceneId, 
                                                                               execution=execution, 
                                                                               language=language)
         except Exception as e:
             Logger.log_error("SceneService.__add_scene_execution_result ex:", e)
示例#23
0
    def set_favorited_scene(self, sceneId, prevSceneId=None):
        '''
        sceneId - can be either favorited/non-favorited scene, but must be a valid scene id.
        prevSceneId - must be another favorited scene or error is raised.
        
        Both updating and executing doesn't blocks a scene from adding to/removing from favorited list.
        '''
        with self.__fav_lock:
            # Validation for sceneId.
            if not self.__sceneController.has(sceneId):
                raise AutomationException(
                    11092,
                    "sceneId does not belongs to any scene - sceneId provided: "
                    + str(sceneId))

            # Because UI display in reversed order, hence their prevSceneId == our nextSceneId
            nextSceneId = prevSceneId or None

            # Get favSort before sceneId of nextSceneId
            if nextSceneId is None:
                maxFavSort = self.__sceneController.get_largest_favsort_num(
                )  # If len of favorited list is 0, maxFavSort = 0
                # favSort stores number to be assigned to sceneId.
                favSort = maxFavSort + 1
            else:
                try:
                    # favSort stores number to be assigned to sceneId.
                    # current favSort of prevSceneId will becomes favSort of sceneId.
                    favSort = self.__sceneController.get_favsort_of(
                        nextSceneId)
                except Exception as e:
                    raise AutomationException(11092, "prevSceneId does not belongs to any scene - " + \
                                                    "prevSceneId provided: " + str(nextSceneId) + ", error: " + str(e))
                else:
                    if favSort is None:
                        raise AutomationException(13000, "prevSceneId does not belongs to any favorited scene - " + \
                                                        "prevSceneId provided: " + str(nextSceneId) + ", error: " + str(e))

            # Update favSort of the scene
            try:
                self.__sceneController.update_favorited_scene(sceneId, favSort)
                self.__sceneController.commit()
            except Exception as e:
                self.__sceneController.rollback()
                Logger.log_error(
                    "SceneService.set_favorited_scene failed to update favorited scene, ex:",
                    str(e))
                raise AutomationException(13001, "unexpected error: " + str(e))

            # Broadcast events
            self.__broadcast_message__scene_updated(sceneId)
            self.__broadcast_message__favorited_scene_added(
                sceneId, prevSceneId)
示例#24
0
 def delete_rule(self, ruleId):
     self.__check_rule_process_status(ruleId)
     try:
         self.__ruleController.delete(ruleId)
         self.__ruleController.commit()
     except Exception as e:
         self.__ruleController.rollback()
         Logger.log_error("RuleService delete_rule ex:", e, "-- rolled back")
     else:
         self.__broadcast_message__rule_deleted(ruleId)
         self.__triggerController.unregister_listener(ruleId)
         TimerModule.delete_scheduler(ruleId)
示例#25
0
    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"])
示例#26
0
 def delete_rule(self, ruleId):
     self.__check_rule_process_status(ruleId)
     try:
         self.__ruleController.delete(ruleId)
         self.__ruleController.commit()
     except Exception as e:
         self.__ruleController.rollback()
         Logger.log_error("RuleService delete_rule ex:", e,
                          "-- rolled back")
     else:
         self.__broadcast_message__rule_deleted(ruleId)
         self.__triggerController.unregister_listener(ruleId)
         TimerModule.delete_scheduler(ruleId)
示例#27
0
    def __on_shared_method_group_deleted(self, eventObject):
        '''
        Triggered based on event broadcasted by system app.
        '''
        try:
            eventData = json.loads(eventObject["eventData"])
            kbxGroupId = eventData["kbxGroupId"]
            self.delete(kbxGroupId)
        except Exception as e:
            Logger.log_error("GroupController.__on_shared_method_group_deleted ex:", e)
            traceback.print_exc()

            
示例#28
0
    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"])
示例#29
0
    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"])
示例#30
0
    def __parse_section(self, section):
        '''
        Convert if/then into correlated automation tags.
        '''
        section = str(section).lower()

        mapDict = {AppConstants.SECTION_CONDITION:AppConstants.TAG_CONDITION,
                   AppConstants.SECTION_EXECUTION:AppConstants.TAG_ACTION}
        
        try:
            return mapDict[section]
        
        except:
            Logger.log_error("__parse_section ex: given value(%s), type(%s), allowed values(%s)" % (str(section), str(type(section)), str(mapDict.keys())))
            raise AutomationException(11097, "section param must be either value from " + str(mapDict.keys())) # invalid parameter
示例#31
0
 def __add_scene_execution_result(self, serUrl, serStartTime, serEndTime,
                                  sceneName, sceneProtected, sceneId,
                                  execution, language):
     try:
         SceneExecutionResultService.instance().add_scene_execution_result(
             serUrl=serUrl,
             serStartTime=serStartTime,
             serEndTime=serEndTime,
             sceneName=sceneName,
             sceneProtected=sceneProtected,
             sceneId=sceneId,
             execution=execution,
             language=language)
     except Exception as e:
         Logger.log_error("SceneService.__add_scene_execution_result ex:",
                          e)
示例#32
0
 def delete_scene(self, sceneId):
     self.__verify_scene_updated(sceneId)
     
     try:
         favSort = self.__sceneController.get_favsort_of(sceneId) # To determine should favorited_Scene_deleted broadcasted
         self.__sceneController.delete(sceneId)
         self.__sceneController.commit()
     except Exception as e:
         self.__sceneController.rollback()
         traceback.print_exc()
         Logger.log_error("SceneService delete_scene ex:", e, "-- rolled back")
         raise AutomationException(11906, "Unable to delete scene, problem - " + str(e))
     else:
         self.__broadcast_message__scene_deleted(sceneId)
         if favSort is not None:
             self.__broadcast_message__favorited_scene_deleted(sceneId)
示例#33
0
        def __update_rule(rule):
            try:
                # Fire rule update start event
                ruleId = rule["ruleId"]

                # Add methods to subscribe list
                methodIds = [
                    kbxMethod["kbxMethodId"]
                    for kbxMethod in rule["condition"] + rule["execution"]
                ]
                self.__methodController.add(methodIds)

                # Update "rule" base table
                self.__ruleController.update(rule)
                self.__ruleController.commit()

            except Exception as e:
                self.__ruleController.rollback()
                self.__broadcast_message__rule_update_failed(ruleId, ruleName)
                Logger.log_error("RuleService __update_rule failed:", e,
                                 "-- rolledback")
            else:
                self.__triggerController.register_listener(
                    ruleId, rule["trigger"])

                # Process for Timer Module
                TimerModule.delete_scheduler(ruleId)

                timerModuleHandlers = {
                    TimerModule.METHOD_ID_DATE_TIME_RANGE:
                    TimerModule.handle_date_time_range,
                    TimerModule.METHOD_ID_DAY_OF_WEEK: TimerModule.handle_dow,
                    TimerModule.METHOD_ID_TIME_RANGE:
                    TimerModule.handle_time_range
                }

                for kbxMethod in rule["condition"]:
                    kbxMethodId = kbxMethod["kbxMethodId"]
                    timerModuleHandler = timerModuleHandlers.get(
                        kbxMethodId, None)
                    if timerModuleHandler is not None:
                        timerModuleHandler(ruleId,
                                           kbxMethod["kbxMethodParams"])

                # Broadcast message: completed updating a rule
                self.__broadcast_message__rule_updated(ruleId)
示例#34
0
 def execute(self, stmt, bindings=None):
     '''
     Execute only the statement without any return value.
     '''
     with self.__rlock:
         cursor = self.__con.cursor()
         try:
             if bindings is None:
                 cursor.execute(str(stmt))
             else:
                 cursor.execute(str(stmt), tuple(bindings))
         except Exception as e:
             Logger.log_error("Database.execute ex:", e)
             traceback.print_exc()
             raise e
         finally:
             cursor.close()
示例#35
0
    def __get_default_group_ids(self):
        try:
            systemId = SharedMethod.get_system_id()

            results = SharedMethod.list_shared_method_groups(kbxGroupAppId=[systemId],
                                                             kbxGroupName=["automation_app", "notification", "service"])

            groups = {group.get("kbxGroupName", "_"):group.get("kbxGroupId") for group in results["groupList"]}

            AppConstants.GROUP_ID_AUTOMATION = groups["automation_app"]
            AppConstants.GROUP_ID_NOTIFICATION = groups["notification"]
            AppConstants.GROUP_ID_SERVICE = groups["service"]

        except Exception as e:
            Logger.log_error("AutomationApp on_system_connected retrying __get_default_group_ids, ex:", e)
            traceback.print_exc()
            raise e
示例#36
0
 def insert(self, stmt, bindings):
     '''
     The only different from "execute" is that this function returns lastrowid.
     '''
     with self.__rlock:
         cursor = self.__con.cursor()
         try:
             cursor.execute(stmt, bindings)
             lastrowid = cursor.lastrowid
             return lastrowid
         except Exception as e:
             Logger.log_error("Database.insert ex:", e)
             Logger.log_debug("Statement:", stmt, "bindings:", bindings)
             traceback.print_exc()
             raise e
         finally:
             cursor.close()
示例#37
0
 def insert(self, stmt, bindings):
     '''
     The only different from "execute" is that this function returns lastrowid.
     '''
     with self.__rlock:
         cursor = self.__con.cursor()
         try:
             cursor.execute(stmt, bindings)
             lastrowid = cursor.lastrowid
             return lastrowid
         except Exception as e:
             Logger.log_error("Database.insert ex:", e)
             Logger.log_debug("Statement:", stmt, "bindings:", bindings)
             traceback.print_exc()
             raise e
         finally:
             cursor.close()
示例#38
0
 def execute(self, stmt, bindings=None):
     '''
     Execute only the statement without any return value.
     '''
     with self.__rlock:
         cursor = self.__con.cursor()
         try:
             if bindings is None:
                 cursor.execute(str(stmt))
             else:
                 cursor.execute(str(stmt), tuple(bindings))
         except Exception as e:
             Logger.log_error("Database.execute ex:", e)
             traceback.print_exc()
             raise e
         finally:
             cursor.close()
示例#39
0
 def set_favorited_scene(self, sceneId, prevSceneId=None):
     '''
     sceneId - can be either favorited/non-favorited scene, but must be a valid scene id.
     prevSceneId - must be another favorited scene or error is raised.
     
     Both updating and executing doesn't blocks a scene from adding to/removing from favorited list.
     '''
     with self.__fav_lock:
         # Validation for sceneId.
         if not self.__sceneController.has(sceneId):
             raise AutomationException(11092, "sceneId does not belongs to any scene - sceneId provided: " + str(sceneId))
         
         # Because UI display in reversed order, hence their prevSceneId == our nextSceneId
         nextSceneId = prevSceneId or None
         
         # Get favSort before sceneId of nextSceneId
         if nextSceneId is None:
             maxFavSort = self.__sceneController.get_largest_favsort_num() # If len of favorited list is 0, maxFavSort = 0
             # favSort stores number to be assigned to sceneId.
             favSort = maxFavSort + 1
         else:
             try:
                 # favSort stores number to be assigned to sceneId.
                 # current favSort of prevSceneId will becomes favSort of sceneId.
                 favSort = self.__sceneController.get_favsort_of(nextSceneId)
             except Exception as e:
                 raise AutomationException(11092, "prevSceneId does not belongs to any scene - " + \
                                                 "prevSceneId provided: " + str(nextSceneId) + ", error: " + str(e))
             else:
                 if favSort is None:
                     raise AutomationException(13000, "prevSceneId does not belongs to any favorited scene - " + \
                                                     "prevSceneId provided: " + str(nextSceneId) + ", error: " + str(e))
             
         # Update favSort of the scene
         try:
             self.__sceneController.update_favorited_scene(sceneId, favSort)
             self.__sceneController.commit()
         except Exception as e:
             self.__sceneController.rollback()
             Logger.log_error("SceneService.set_favorited_scene failed to update favorited scene, ex:", str(e))
             raise AutomationException(13001, "unexpected error: " + str(e))
 
         # Broadcast events
         self.__broadcast_message__scene_updated(sceneId)
         self.__broadcast_message__favorited_scene_added(sceneId, prevSceneId)
示例#40
0
    def __time_range(self, request):
        try:
            try:
                tVal = request.get_value(
                    TimerModule._PARAM_TIME_RANGE.get_kbx_param_name())
                startTime = tVal.get_start_time()
                endTime = tVal.get_end_time()
            except:
                # Backward compatible to daily_task
                kbxTime = KBXTime(kbxParamName="time")
                startTime = endTime = kbxTime.cast(request.get_arg("time"))

            execTime = request.get_arg(AppConstants.KEY_CONDITION_TIMESTAMP)
            execTime = datetime.datetime.fromtimestamp(execTime)
            execTime = (execTime.hour * 3600) + (execTime.minute *
                                                 60) + (execTime.second)

            if endTime < startTime:
                checkRange = [(startTime, 86400), (0, endTime + 59)]
            else:
                checkRange = [(startTime, endTime + 59)]

            for startVal, endVal in checkRange:
                if startVal <= execTime <= endVal:
                    response = True
                    break
            else:
                response = False

            if not response:
                raise AutomationException(11800)

            self.send_response({}, request.requestId)
        except AutomationException as ae:
            Logger.log_error("TimerModule time range failed on comparison:",
                             str(ae))
            self.send_response({}, request.requestId, ae.get_error_code(),
                               ae.get_error_message())
        except Exception as e:
            Logger.log_error(
                "TimerModule time range failed on comparison (unexpected):",
                str(e))
            ae = AutomationException(11099, str(e))
            self.send_response({}, request.requestId, ae.get_error_code(),
                               ae.get_error_message())
示例#41
0
        def process_method_list(methodList):
            #===================================================================
            # Basic type validation
            #===================================================================
            if not isinstance(methodList, list):
                Logger.log_error("RuleService.set_rule: 'condition' and 'execution' must be type of list.")
                Logger.log_debug("type:", type(methodList), "value:", methodList)
                raise AutomationException(11704, "List is required for both 'condition' and 'execution'")

            #===================================================================
            # Check allowed size, raise error if exceeded.
            #===================================================================
            methodListLen = len(methodList)
            if methodListLen > AppConstants.MAX_METHOD_SIZE:
                Logger.log_error("RuleService.set_rule: 'condition' and 'execution' cannot have more than", AppConstants.MAX_METHOD_SIZE, "items respectively.")
                raise AutomationException(11705, "Only a maximum of " + \
                                          str(AppConstants.MAX_METHOD_SIZE) + \
                                          " items is allowed for each 'condition' and 'execution' - given size " + \
                                          str(methodListLen),
                                          lambda text: str(AppConstants.MAX_METHOD_SIZE).join(text.split(":max_item_size:")))

            #===================================================================
            # Check if all kbxMethodIds are valid and all kbxMethodParams are list
            #===================================================================
            idValidator = NumberValidator(isRequired=True, decimalPoint=False)
            if not all([idValidator.is_valid(eachMethod["kbxMethodId"])
                        and isinstance(eachMethod["kbxMethodParams"], list)
                        for eachMethod in methodList]):
                raise AutomationException(11704, "'condition' and 'execution' have incorrect data structure.")

            #===================================================================
            # Check if all kbxParamName and kbxParamCurrentValue exists
            #===================================================================
            paramNameValidator = StringValidator(isRequired=True)
            for eachMethod in methodList:
                methodArgs = eachMethod["kbxMethodParams"]
                for methodArg in methodArgs:
                    if not paramNameValidator.is_valid(methodArg[AppConstants.ARG_NAME]):
                        raise AutomationException(11704, "'condition' and 'execution' have invalid params structure")

                    if not AppConstants.ARG_CURRENT_VALUE in methodArg:
                        methodArg[AppConstants.ARG_CURRENT_VALUE] = None
            
            return methodList
示例#42
0
 def execute_and_fetch_all(self, stmt, bindings=None):
     '''
     Returns a list of sqlite.Row instances.
     The "list" if empty if no result was fetched.
     '''
     with self.__rlock:
         cursor = self.__con.cursor()
         try:
             if bindings is None:
                 cursor.execute(str(stmt))
             else:
                 cursor.execute(str(stmt), tuple(bindings))
                 
             return cursor.fetchall()
         except Exception as e:
             Logger.log_error("Database.execute_and_fetch_all ex:", e)
             traceback.print_exc()
             raise e
         finally:
             cursor.close()
示例#43
0
    def execute_and_fetch_one(self, stmt, bindings=None):
        '''
        Returns an sqlite.Row instance.
        Return value is None if the statement fetch no result.
        '''
        with self.__rlock:
            cursor = self.__con.cursor()
            try:
                if bindings is None:
                    cursor.execute(str(stmt))
                else:
                    cursor.execute(str(stmt), tuple(bindings))

                return cursor.fetchone()
            except Exception as e:
                Logger.log_error("Database.execute_and_fetch_all ex:", e)
                traceback.print_exc()
                raise e
            finally:
                cursor.close()
示例#44
0
 def execute_and_fetch_one(self, stmt, bindings=None):
     '''
     Returns an sqlite.Row instance.
     Return value is None if the statement fetch no result.
     '''
     with self.__rlock:
         cursor = self.__con.cursor()
         try:
             if bindings is None:
                 cursor.execute(str(stmt))
             else:
                 cursor.execute(str(stmt), tuple(bindings))
                 
             return cursor.fetchone()
         except Exception as e:
             Logger.log_error("Database.execute_and_fetch_all ex:", e)
             traceback.print_exc()
             raise e
         finally:
             cursor.close()
示例#45
0
    def delete_scene(self, sceneId):
        self.__verify_scene_updated(sceneId)

        try:
            favSort = self.__sceneController.get_favsort_of(
                sceneId
            )  # To determine should favorited_Scene_deleted broadcasted
            self.__sceneController.delete(sceneId)
            self.__sceneController.commit()
        except Exception as e:
            self.__sceneController.rollback()
            traceback.print_exc()
            Logger.log_error("SceneService delete_scene ex:", e,
                             "-- rolled back")
            raise AutomationException(
                11906, "Unable to delete scene, problem - " + str(e))
        else:
            self.__broadcast_message__scene_deleted(sceneId)
            if favSort is not None:
                self.__broadcast_message__favorited_scene_deleted(sceneId)
示例#46
0
    def execute_and_fetch_all(self, stmt, bindings=None):
        '''
        Returns a list of sqlite.Row instances.
        The "list" if empty if no result was fetched.
        '''
        with self.__rlock:
            cursor = self.__con.cursor()
            try:
                if bindings is None:
                    cursor.execute(str(stmt))
                else:
                    cursor.execute(str(stmt), tuple(bindings))

                return cursor.fetchall()
            except Exception as e:
                Logger.log_error("Database.execute_and_fetch_all ex:", e)
                traceback.print_exc()
                raise e
            finally:
                cursor.close()
示例#47
0
    def __retry_seri_implementation(self, serId, serisWithError, seriIndexes):
        try:
            # Update statuses of all items to be retried to "busy".
            self.__serController.update_seri_status(serId=serId, seriIndexes=seriIndexes, seriStatus="busy", seriError=None)
            
            # Broadcast event.
            self.__broadcast_message__seri_retry_started(serId, seriIndexes=seriIndexes)
            
            # Retry process starts here.
            for seri in serisWithError:
                try:
                    kbxMethodId = seri["kbxMethodId"]
                    if kbxMethodId != -291: # Skips all -291 and declare as "ok" immediately.
                        params = {kbxMethodParam["kbxParamName"]:kbxMethodParam["kbxParamCurrentValue"] 
                                  for kbxMethodParam in seri["kbxMethodParams"]}
                        result = SharedMethod.call_by_method_id(kbxMethodId, **params)
                        seriError = str(result)
                    else:
                        seriError = None
                    
                    seriStatus = "ok"
                    
                except Exception as e:
                    seriStatus = "error"
                    seriError = str(e)
                    
                finally:
                    seriIndex = seri["seriIndex"]
                    
                    if not self.__serLock.is_deleted(serId):
                        # Update statuses and broadcast events only if ser is not deleted.
                        self.__serController.update_seri_status(serId=serId, seriIndexes=[seriIndex], 
                                                                seriStatus=seriStatus, seriError=seriError)
                        self.__broadcast_message__seri_retry_completed(serId, seriIndex, seriStatus, seriError)
                    
        except Exception as e:
            ''' THIS PORTION SHOULD NEVER RUN. (it's bug if this portion is executed) '''
            Logger.log_error("SceneExecutionResultService.retry_scene_execution_result_item ex:", e)

        finally:
            self.__serLock.unlock(serId)
示例#48
0
        def __update_scene(scene):
            try:
                # Fire scene update start event
                sceneId = scene["sceneId"]
                sceneName = scene["sceneName"]
                    
                # Add methods to subscribe list
                methodIds = [kbxMethod["kbxMethodId"] for kbxMethod in scene["execution"]]
                self.__methodController.add(methodIds)
                    
                # Update "scene" base table
                self.__sceneController.update(scene)
                self.__sceneController.commit()

            except Exception as e:
                self.__sceneController.rollback()
                self.__broadcast_message__scene_update_failed(sceneId, sceneName)
                Logger.log_error("SceneService __update_scene failed:", e, "-- rolledback")
            else:
                # Broadcast message: completed updating a scene
                self.__broadcast_message__scene_updated(sceneId)
示例#49
0
 def __day_of_week(self, request):
     try:
         dows = request.get_value(TimerModule._PARAM_DOW.get_kbx_param_name())
         
         execTime = request.get_arg(AppConstants.KEY_CONDITION_TIMESTAMP)
         execTime = datetime.datetime.fromtimestamp(execTime)
         execDow = execTime.isoweekday() % 7
         
         response = bool(execDow in dows)
         
         if not response:
             raise AutomationException(11800)
         
         self.send_response({}, request.requestId)
     except AutomationException as ae:
         Logger.log_error("TimerModule day_of_week failed on comparison:", str(ae))
         self.send_response({}, request.requestId, ae.get_error_code(), ae.get_error_message())
     except Exception as e:
         Logger.log_error("TimerModule day_of_week failed on comparison (unexpected):", str(e))
         ae = AutomationException(11099, str(e))
         self.send_response({}, request.requestId, ae.get_error_code(), ae.get_error_message())
示例#50
0
 def __time_range(self, request):
     try:
         try:
             tVal = request.get_value(TimerModule._PARAM_TIME_RANGE.get_kbx_param_name())
             startTime = tVal.get_start_time()
             endTime = tVal.get_end_time()
         except:
             # Backward compatible to daily_task
             kbxTime = KBXTime(kbxParamName="time")
             startTime = endTime = kbxTime.cast(request.get_arg("time"))
         
         execTime = request.get_arg(AppConstants.KEY_CONDITION_TIMESTAMP)
         execTime = datetime.datetime.fromtimestamp(execTime)
         execTime = (execTime.hour * 3600) + (execTime.minute * 60) + (execTime.second)
         
         if endTime < startTime:
             checkRange = [(startTime, 86400), (0, endTime + 59)]
         else:
             checkRange = [(startTime, endTime + 59)]
             
         for startVal, endVal in checkRange:
             if startVal <= execTime <= endVal:
                 response = True
                 break
         else:
             response = False
             
         if not response:
             raise AutomationException(11800)
         
         self.send_response({}, request.requestId)
     except AutomationException as ae:
         Logger.log_error("TimerModule time range failed on comparison:", str(ae))
         self.send_response({}, request.requestId, ae.get_error_code(), ae.get_error_message())
     except Exception as e:
         Logger.log_error("TimerModule time range failed on comparison (unexpected):", str(e))
         ae = AutomationException(11099, str(e))
         self.send_response({}, request.requestId, ae.get_error_code(), ae.get_error_message())
示例#51
0
    def __get_default_group_ids(self):
        try:
            systemId = SharedMethod.get_system_id()

            results = SharedMethod.list_shared_method_groups(
                kbxGroupAppId=[systemId],
                kbxGroupName=["automation_app", "notification", "service"])

            groups = {
                group.get("kbxGroupName", "_"): group.get("kbxGroupId")
                for group in results["groupList"]
            }

            AppConstants.GROUP_ID_AUTOMATION = groups["automation_app"]
            AppConstants.GROUP_ID_NOTIFICATION = groups["notification"]
            AppConstants.GROUP_ID_SERVICE = groups["service"]

        except Exception as e:
            Logger.log_error(
                "AutomationApp on_system_connected retrying __get_default_group_ids, ex:",
                e)
            traceback.print_exc()
            raise e
示例#52
0
 def initialize(self):
     currentVersion = self.get_user_version()
     for updateToVersion, (__runOnce, __run) in enumerate(zip(self.__runOnce, self.__run), 1): # First version = 1, not 0.
         if updateToVersion > currentVersion:
             # Performs run once function call on later versions only.
             try:
                 __runOnce("/".join((Database.RESOURCE_PATH, str(updateToVersion))))
             except Exception as e:
                 Logger.log_error("Error on updating to version", updateToVersion, "ex:", e)
                 raise Exception("Failed to initialize database: error on run-once function for version " +
                                 str(updateToVersion))
             
         # Executes all custom functions
         try:
             __run()
         except Exception as e:
             Logger.log_error("Error on version", updateToVersion, "function execution, ex:", e)
             raise Exception("Failed to initialize database: error on run-everytime function for version " +
                             str(updateToVersion))
     else:
         del(self.__runOnce)
         del(self.__run)
             
     self.set_user_version(updateToVersion)
示例#53
0
    def list_methods(self, language, section, groupId):
        try:
            result = SharedMethod.list_shared_methods(kbxGroupId=groupId,
                                                      kbxMethodTag=section,
                                                      kbxMethodStatus=[SharedMethod.METHOD_STATUS_ACTIVE, SharedMethod.METHOD_STATUS_INACTIVE],
                                                      language=language)

            methodList = result["methodList"]

            #===================================================================
            # Get group information
            #===================================================================
            groupDict = SharedMethod.get_shared_method_group_by_id(kbxGroupId=groupId, language=language)
            
            # Append "kbxMethodHasEvent" indicator.
            for kbxMethod in methodList:
                kbxMethodEvent = kbxMethod.get("kbxMethodEvent")
                kbxMethodIdentifier = kbxMethod.get("kbxMethodIdentifier")
                kbxMethod["kbxMethodHasEvent"] = not Util.is_empty(kbxMethodEvent) and not Util.is_empty(kbxMethodIdentifier)

            return methodList, groupDict
        except Exception as e:
            Logger.log_error("APIService.list_methods ex:", e)
            raise AutomationException(11601, "Unexpected error - " + str(e))
示例#54
0
 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()
示例#55
0
    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()