def validate_batch(self, seq): # Validate each command for seqRow in seq.iterrows(): zone = seqRow[1]['zone'] actuType = seqRow[1]['actuator_type'] setVal = seqRow[1]['set_value'] uuid = self.get_actuator_uuid(zone, actuType) name= self.get_actuator_name(zone, actuType) seqRow[1]['uuid'] = uuid seqRow[1]['name'] = name if not uuid in self.actuDict.keys(): actuator = metaactuators.make_actuator(uuid, name, zone, actuType) if actuator == None: logging.error("Incorrect actuator type: %s", actuType) raise QRError('Incorrect actuator type', actuType) self.actuDict[uuid] = actuator actuator = self.actuDict[uuid] # Validation 1: Check input range if not actuator.validate_input(setVal): logging.error("Input value is not in correct range: %s", repr(seqRow[1])) raise QRError("Input value is not in correct range", seqRow[1]) # Validation 2: Check if there is a dependent command in given batch for otherSeqRow in seq.iterrows(): if seqRow[0]!=otherSeqRow[0]: if actuator.check_dependency(otherSeqRow[1], self.now()): logging.error("A command is dependent on a command in the given sequence: %s", repr(seqRow[1]) + repr(otherSeqRow[1])) raise QRError("A command is dependent on a command in the given sequence", repr(seqRow[1]) + repr(otherSeqRow[1])) elif otherSeqRow[1]['uuid'] == uuid: logging.error('A command has same target equipment with another: %s', repr(seqRow[1])+ repr(otherSeqRow[1])) raise QRError('A command has same target equipment with another', repr(seqRow[1])+ repr(otherSeqRow[1])) # Validation 3: Check if there is a dependent command in current status queryDep = {'set_time':{'$gte':self.now()-actuator.minLatency}} depCommands = self.statColl.load_dataframe(queryDep) for commRow in depCommands.iterrows(): if actuator.check_dependency(commRow[1], self.now()): logging.error("A command is dependent on current status: %s", repr(seqRow[1])+repr(commRow[1])) raise QRError("A command is dependent on current status", repr(seqRow[1])+repr(commRow[1])) seq.loc[seqRow[0]] = seqRow[1]
def emergent_rollback(self): queryAll = {"under_control":True} resetQueue = self.statColl.load_dataframe(queryAll) resetQueue = resetQueue.sort(columns='set_time', axis='index') maxConcurrentResetNum = 10 resetInterval = 10*60 # 10 minutes if len(resetQueue)==0: return None resetSeq= defaultdict(dict) #resetSeq = [[]] # Make actuators to reset and get earliest set time dependent on reset_queue earliestDepTime = self.dummyEndTime for row in resetQueue.iterrows(): uuid = row[1]['uuid'] name = row[1]['name'] actuType = row[1]['actuator_type'] if not uuid in self.actuDict.keys(): actuator = metaactuators.make_actuator(uuid,name,actuType=actuType) if actuator == None: #raise QRError('Incorrect actuator type', actuType) print("Incorrect actuator type: ", actuType) continue self.actuDict[uuid] = actuator setTime = row[1]['set_time'] dependentTime = setTime - actuator.get_longest_dependency() if earliestDepTime > dependentTime: earliestDepTime = dependentTime # Construct Reset Sequence # Filter redundant controls and align with dependency for row in resetQueue.iterrows(): uuid = row[1]['uuid'] inQFlag = False for l in resetSeq.values(): if uuid in l.keys(): inQFlag = True if inQFlag == True: continue actuator = self.actuDict[uuid] lastKey = 0 now = self.now() row[1]['original_value'] = actuator.get_value(now-timedelta(hours=1), now).tail(1)[0] insertedFlag = False for k,l in resetSeq.iteritems(): depList = actuator.get_dependent_actu_list() if not bool(set(depList) & set(l.keys())) and len(l)<maxConcurrentResetNum: resetSeq[k][uuid] = row[1].to_dict() insertedFlag = True lastKey = k lastKey += 1 if not insertedFlag: resetSeq[lastKey][uuid] = row[1].to_dict() for key, stats in resetSeq.iteritems(): oneResetSeq = pd.DataFrame() for uuid, stat in stats.iteritems(): oneResetSeq = pd.concat([oneResetSeq, pd.DataFrame(stat, index=[0])]) resetSeq[key] = oneResetSeq #TODO: need to add checking acknowledgement # Rollback for k, l in resetSeq.iteritems(): for key, stat in l.iterrows(): # stat = row[1] uuid = stat['uuid'] name = stat['name'] actuType = stat['actuator_type'] if actuType in [self.actuNames.commonSetpoint]: setVal = stat['reset_value'] else: setVal = -1 actuator = self.actuDict[uuid] now = self.now() origVal = stat['original_value'] setTime = self.now() expLogRow = ExpLogRow(uuid, name, setTime=setTime, setVal=setVal, origVal=origVal) actuator.reset_value(setVal, setTime) self.ack_issue(l) time.sleep(resetInterval)