def executeRule(self, rule): actionManager = ActionManager() action, originalModel, parameters = actionManager.getActionAndTemplateAndParameterValues(rule.consequent) parameters.update({'buildingName' : rule.buildingName}) if rule.roomName: parameters.update({'roomName' : rule.roomName}) if rule.groupId: parameters.update({'groupId' : rule.groupId}) if self.simulationParameters: localSimulationParameters = self.simulationParameters.copy() localSimulationParameters.update({'ruleId' : rule.id, 'ruleText' : rule.getFullRepresentation()}) parameters.update({'simulationParameters' : localSimulationParameters}) driver = actionManager.getActionDriver(action, parameters) message = "Rule " + str(rule.id) + " (" + str(rule.buildingName) if rule.groupId: message += ".g[" + str(rule.groupId) + "]" if rule.roomName: message += ".r[" + str(rule.roomName) + "]" flash(message + ") actuated; consequent is '" + rule.consequent + "'...") try: driver.actuate() except Exception as e: flash(message + ") Erro while actuating the consequent '" + rule.consequent + "'... " + str(e), 'red') if not self.simulationParameters: rules = Rules() rules.setActiveRule(buildingName = rule.buildingName, roomName = rule.roomName, ruleId = rule.id)
def getConflictingRules(self, roomName, buildingName, ruleBody): checkData(locals()) ruleBody = ruleBody.strip() from app.backend.controller.triggerManager import TriggerManager from app.backend.controller.actionManager import ActionManager triggerManager = TriggerManager() actionManager = ActionManager() room = Room(buildingName = buildingName, roomName = roomName) room.retrieve() ruleList = room.getRules( includeGroupsRules = True, includeDisabled = False) ruleAntecedent = ruleBody.split("then")[0].replace("if", "").strip() ruleConsequent = ruleBody.split("then")[1].strip() newRuleTranslatedTriggers = triggerManager.translateTrigger(ruleAntecedent) newRuleAction, originalModel, parameterValues = actionManager.getActionAndTemplateAndParameterValues(ruleConsequent) conflictingRuleList = [] for rule in ruleList: currentRuleAction, originalModel, parameterValues = actionManager.getActionAndTemplateAndParameterValues(rule.consequent) savedRuleTranslatedTriggers = triggerManager.translateTrigger(rule.antecedent) conflictingAntecedentFound = False for newRuleTrigger in newRuleTranslatedTriggers["triggers"]: for savedRuleTrigger in savedRuleTranslatedTriggers["triggers"]: if "between" not in newRuleTrigger["antecedent"]: if newRuleTrigger["antecedent"] == savedRuleTrigger["antecedent"] and (newRuleAction.category == currentRuleAction.category): conflictingAntecedentFound = True else: # In the case of range based antecedent I cannot just check if it is equal but I have to see the trigger name if newRuleTrigger["trigger"].triggerName == savedRuleTrigger["trigger"].triggerName and (newRuleAction.category == currentRuleAction.category): conflictingAntecedentFound = True if conflictingAntecedentFound: break if conflictingAntecedentFound: break if conflictingAntecedentFound: conflictingRuleList.append({"ruleId" : rule.id, "ruleBody" : rule.getFullRepresentation()}) return {"conflictingRules" : conflictingRuleList}
def test1(self): from app.backend.controller.triggerManager import TriggerManager from app.backend.controller.actionManager import ActionManager triggerManager = TriggerManager() print triggerManager.getTrigger("it is between 10.00 AM and 8.00 PM") print triggerManager.translateTrigger("it is between 10.00 AM and 8.00 PM") actionManager = ActionManager() print actionManager.getAction("turn on the heating")
def translateAction(): if request.method == "POST": sessionKey = validateInput(request.form["sessionKey"]) userUuid = validateInput(request.form["userUuid"]) consequent = validateInput(request.form["consequent"]) try: session = SessionManager() session.checkSessionValidity(sessionKey, userUuid) actionManager = ActionManager() return returnResult(actionManager.translateAction(ruleConsequent=consequent, getDict=True)) except Exception as e: return returnError(e)
def ruleCategories(username=None): if request.method == "POST": sessionKey = validateInput(request.form["sessionKey"]) userUuid = validateInput(request.form["userUuid"]) try: session = SessionManager() session.checkSessionValidity(sessionKey, userUuid) userManager = UsersManager() from app.backend.controller.actionManager import ActionManager actionManager = ActionManager() categories = actionManager.getActionCategories() result = {"categories": categories} return returnResult(result) except Exception as e: return returnError(e)
def __addOrModifyRule(self, priority = None, buildingName = None, roomName = None, authorUuid = None, ruleBody = None, ruleId = None, antecedent = None, consequent = None, enabled = True): checkData(locals()) import time,datetime startTimeMilliseconds = long((time.time() + 0.5) * 1000) if ruleBody: try: antecedent = ruleBody.split("then")[0].replace("if ", "").strip() consequent = ruleBody.split("then")[1].strip() except Exception as e: raise NotWellFormedRuleError("There is a syntax error in the rule you are trying to save") # Detecting rule category (by the rule-consequent) from app.backend.controller.actionManager import ActionManager actionManager = ActionManager() category = actionManager.getAction(consequent).category from app.backend.model.user import User author = User(uuid = authorUuid) author.retrieve() if int(str(priority)) < 0 or int(str(priority)) > author.getMaxRoomPriority(): raise RulePriorityError("You can specify rules for rooms with a priority value between 0 and " + str(author.getMaxRoomPriority()) + ". You inserted " + str(priority)) from app.backend.model.rule import Rule from app.backend.model.room import Room if not ruleId: rule = Rule(priority = priority, category = category, buildingName = buildingName, roomName = roomName, authorUuid = authorUuid, antecedent = antecedent, consequent = consequent, enabled = True) else: rule = Rule(id = ruleId) rule.retrieve() author = rule.getAuthor() rule.antecedent = antecedent rule.consequent = consequent rule.authorUuid = authorUuid rule.authorUuid = authorUuid rule.enabled = enabled editor = rule.getAuthor() if editor.level < rule.getPriority(): raise UserCredentialError("You cannot modify this rule since it has a too high priority for your user level") room = Room(buildingName = buildingName, roomName = roomName) room.retrieve() if not ruleId and not rule.checkIfUnique(): raise DuplicatedRuleError("The submitted rule is already been saved for the considered room.") # excludedRuleId is needed to ignore the rule that the user want to edit excludedRuleId = ruleId if ruleId else None roomRules = room.getRules(author = False, includeGroupsRules = True, excludedRuleId = excludedRuleId) # Checking that a priority is unique over the same category for r in roomRules: if str(r.category) == str(category) and int(r.getPriority()) == int(priority): raise AlredyAssignedPriorityError("In room " + roomName + " the priority " + str(priority) + " has alredy been assigned to another rule with the same category!") temporaryRuleSet = [] temporaryRuleSet.extend(roomRules) temporaryRuleSet.append(rule) #### OPTMIZATION ######################################################################################## # Removing rules with a trigger that is different form the one of the rule I'm trying to insert or modify from app.backend.controller.triggerManager import TriggerManager triggerManager = TriggerManager() newRuleTriggers = triggerManager.translateTrigger(rule.antecedent)["triggers"] for i in range(0, len(temporaryRuleSet)): otherRuleTriggers = triggerManager.translateTrigger(temporaryRuleSet[i].antecedent)["triggers"] deleteRule = False if rule.category == temporaryRuleSet[i].category: for t1 in newRuleTriggers: for t2 in otherRuleTriggers: if t1 == t2: deleteRule = True break; if deleteRule: break; if deleteRule: del temporaryRuleSet[i] #### OPTMIZATION ######################################################################################## for i in range(0, len(temporaryRuleSet)): temporaryRuleSet[i].groupId = None temporaryRuleSet[i].roomName = roomName from app.backend.controller.rulesetChecker import RulesetChecker rulesetChecker = RulesetChecker(temporaryRuleSet) ruleCheckErrorList = rulesetChecker.check() if len(ruleCheckErrorList) == 0: if ruleId: rule.id = ruleId rule.setPriority(priority) from app.backend.commons.console import flash endTimeMilliseconds = long((time.time() + 0.5) * 1000) opTimeMilliseconds = endTimeMilliseconds - startTimeMilliseconds flash("RoomRuleVerification [SUCCESS]: roomName = " + str(roomName) +" #rules=" + str(len(temporaryRuleSet)) + " - opTimeMilliseconds:" + str(opTimeMilliseconds)) return room.addRule(rule).getDict() else: from app.backend.commons.console import flash logMessage = "authorUuid = " + str(authorUuid) + ", " logMessage += "buildingName = " + str(buildingName) + ", " logMessage += "roomName = " + str(roomName) + ", " logMessage += "ruleSetDescr = " + str(temporaryRuleSet) + ", " logMessage += "newRule = " + str(rule) flash("RuleValidationError: " + logMessage) endTimeMilliseconds = long((time.time() + 0.5) * 1000) opTimeMilliseconds = endTimeMilliseconds - startTimeMilliseconds flash("RoomRuleVerification [FAILED]: roomName = " + str(roomName) +" #rules=" + str(len(temporaryRuleSet)) + " - opTimeMilliseconds:" + str(opTimeMilliseconds)) raise RuleValidationError(ruleCheckErrorList)
def check(self): triggerManager = TriggerManager() actionManager = ActionManager() assertionTemplate = "(assert (=> @@RULE_ANTECEDENT@@ @@RULE_CONSEQUENT@@))" finalAssertionTemplate = "(assert (and @@FIRST_ARG@@ @@SECOND_ARG@@ ))" rangeTriggersName = {"EXT_TEMPERATURE_RANGE" : "(extTempInRoom 1)", "ROOM_TEMPERATURE_RANGE" : "(tempInRoom 1)", "DATE_RANGE" : "(day 1)", "TIME_RANGE" : "(time 1)"} theoremBody = [] theoremAssertions = [] parametersIntervals = {} for rule in self.ruleList: translatedTriggers = triggerManager.translateTrigger(rule.antecedent) translatedConsequent, action, parameters = actionManager.translateAction(rule.consequent) translatedAntecedent = translatedTriggers["translation"] currentRuleAssertion = assertionTemplate.replace("@@RULE_ANTECEDENT@@", translatedAntecedent) currentRuleAssertion = currentRuleAssertion.replace("@@RULE_CONSEQUENT@@", translatedConsequent) # Adding the current rule to the theorem body theoremBody.append(currentRuleAssertion) # Now saving, in case of range based trigger, which intervals has to be checked for translatedTrigger in translatedTriggers["triggers"]: trigger = translatedTrigger["trigger"] parameters = translatedTrigger["translatedParams"] if trigger.triggerName in rangeTriggersName.keys(): if trigger.triggerName not in parametersIntervals.keys(): parametersIntervals[trigger.triggerName] = [] parametersIntervals[trigger.triggerName].append(int(parameters['0'])) parametersIntervals[trigger.triggerName].append(int(parameters['1'])) else: theoremAssertions.append('(assert ' + translatedAntecedent + ')') for triggerName in parametersIntervals.keys(): intervals = sorted(parametersIntervals[triggerName]) #theoremAssertions.append('(assert (< ' + rangeTriggersName[triggerName] + ' ' + str(intervals[0]) + '))') for i in range(1, len(intervals)): firstArg = '(>= ' + rangeTriggersName[triggerName] + ' ' + str(intervals[i-1]) + ')' secondArg = '(<= ' + rangeTriggersName[triggerName] + ' ' + str(intervals[i]) + ')' theoremAssertions.append(finalAssertionTemplate.replace("@@FIRST_ARG@@", firstArg).replace("@@SECOND_ARG@@", secondArg)) for i in intervals: theoremAssertions.append('(assert (= ' + rangeTriggersName[triggerName] + ' ' + str(i) + '))') partialOutputFile = "" #File Header and Settings f = open(self.__MAIN_PATH + "header_template.txt") lines = f.readlines() f.close() for line in lines: partialOutputFile += line for assertion in theoremBody: partialOutputFile += assertion + "\n" for assertion in theoremAssertions: outputFile = partialOutputFile + assertion + "\n" outputFile += "(check-sat)" + "\n" temporaryFilePath = self.__MAIN_PATH + self.__addPrefixToFileName("test_smt.z3") theOutFile = open(temporaryFilePath,"w") theOutFile.write(outputFile) theOutFile.close() execStr = self.__MAIN_PATH + "z3/bin/z3 -smt2 " + temporaryFilePath #print execStr try: z3Output = subprocess.check_output(execStr, shell=True) os.remove(temporaryFilePath) if "unsat" in z3Output: error = "There is a conflict in the rules! " + assertion print error self.errorList.append(error) return self.errorList except Exception as e : raise RuleValidationEngineError("The rule validation engine failed during rule checking.") return []
def __addOrModifyRule(self, priority = None, buildingName = None, groupId = None, authorUuid = None, ruleBody = None, ruleId = None): checkData(locals()) import time,datetime startTimeMilliseconds = long((time.time() + 0.5) * 1000) try: antecedent = ruleBody.split("then")[0].replace("if ", "").strip() consequent = ruleBody.split("then")[1].strip() except Exception as e: raise NotWellFormedRuleError("There is a syntax error in the rule you are trying to save") from app.backend.controller.actionManager import ActionManager actionManager = ActionManager() category = actionManager.getAction(consequent).category from app.backend.model.user import User author = User(uuid = authorUuid) author.retrieve() if int(str(priority)) < 0 or int(str(priority)) > author.getMaxGroupPriority(): raise RulePriorityError("You can specify rules for groups with a priority value between 0 and " + str(author.getMaxRoomPriority()) + ". You inserted " + str(priority)) from app.backend.model.rule import Rule from app.backend.model.group import Group if not ruleId: rule = Rule(priority = priority, category = category, buildingName = buildingName, groupId = groupId, authorUuid = authorUuid, antecedent = antecedent, consequent = consequent, enabled = True) else: rule = Rule(id = ruleId) rule.retrieve() author = rule.getAuthor() rule.antecedent = antecedent rule.consequent = consequent rule.authorUuid = authorUuid editor = rule.getAuthor() if editor.level < rule.getPriority(): raise UserCredentialError("You cannot modify this rule since it has a too high priority for your user level") group = Group(buildingName = buildingName, id = groupId) group.retrieve() if not ruleId and not rule.checkIfUnique(): raise DuplicatedRuleError("The submitted rule is already been saved for the considered group.") # excludedRuleId is needed to ignore the rule that the user want to edit excludedRuleId = ruleId if ruleId else None ruleCheckErrorList = [] groupRoomList = group.getRooms() for room in groupRoomList: groupRules = group.getRules(excludedRuleId = excludedRuleId) # Checking that a priority is unique over the same category for r in groupRules: if str(r.category) == str(category) and int(r.getPriority()) == int(priority): raise AlredyAssignedPriorityError("In group " + str(groupId) + " the priority " + str(priority) + " has alredy been assigned to another rule with the same category!") temporaryRuleSet = [] temporaryRuleSet.extend(room.getRules(author = False, includeGroupsRules = True, excludedRuleId = False, excludeCrossRoomValidationRules = True)) temporaryRuleSet.extend(groupRules) temporaryRuleSet.append(rule) from app.backend.controller.rulesetChecker import RulesetChecker rulesetChecker = RulesetChecker(temporaryRuleSet) ruleCheckErrorList.extend(rulesetChecker.check()) if len(ruleCheckErrorList) == 0: if ruleId: #if i'm in edit mode rule.id = ruleId rule.setPriority(priority) # Disabling rules in all the groups rooms since they have to be validated again for room in groupRoomList: from app.backend.controller.notificationsManager import NotificationsManager notifications = NotificationsManager() messageSubject = "Group " + str(groupId) + " changed your room " + str(room.roomName) + " policy." messageText = "Some rules in group " + str(groupId) + " have been changed." notifications.sendNotification(buildingName = buildingName, roomName = room.roomName, messageSubject = messageSubject, messageText = messageText) #for r in room.getRules(includeGroupsRules = False, excludeCrossRoomValidationRules = True): # r.disable() from app.backend.commons.console import flash endTimeMilliseconds = long((time.time() + 0.5) * 1000) opTimeMilliseconds = endTimeMilliseconds - startTimeMilliseconds flash("GroupsRuleVerification [SUCCESS]: groupId = " + str(groupId) +" #rules=" + str(len(temporaryRuleSet)) + " - opTimeMilliseconds:" + str(opTimeMilliseconds)) return group.addRule(rule).getDict() else: from app.backend.commons.console import flash logMessage = "authorUuid = " + str(authorUuid) + ", " logMessage += "buildingName = " + str(buildingName) + ", " logMessage += "gropuId = " + str(groupId) + ", " logMessage += "ruleSetDescr = " + str(temporaryRuleSet) + ", " logMessage += "newRule = " + str(rule) flash("RuleValidationError: " + logMessage) endTimeMilliseconds = long((time.time() + 0.5) * 1000) opTimeMilliseconds = endTimeMilliseconds - startTimeMilliseconds flash("GroupsRuleVerification [FAILED]: groupId = " + str(groupId) +" #rules=" + str(len(temporaryRuleSet)) + " - opTimeMilliseconds:" + str(opTimeMilliseconds)) raise RuleValidationError(ruleCheckErrorList + " Error in room " + room.roomName)