def doActions( self, actions, inEvent ): #self._log.debug( "doActions %s : %s" % ( actions, inEvent ) ) od = inEvent.getPayload() # first do all updates newEvents = list() updated = dict() # keys are updated values, content is whether value changed. for action in actions: variableName = self.stringSub(inEvent.getPayload(),action["name"]) if action.has_key("value"): # has value updated[variableName] = self.doUpdate( variableName, action["value"], action.has_key("transient") ) elif od.has_key( action["key"] ): # has key updated[variableName] = self.doUpdate( variableName, od[ action["key"] ], action.has_key("transient") ) #self._log.debug( "doActions %s" % ( self._values ) ) # then check the compounds. # TODO may be need to reevaluate the compounds based on the newState updates. # for cmp in self._compounds: # test to see whether we always retest compound even if no change in value for key in updated: if cmp.uses(key) and (updated[key] or cmp._alwaysReDo): #self._log.debug( "cmp uses %s : %s (%s)" % ( name, cmp, str(self._values) ) ) if cmp.match(self._values): self._log.debug( "compound matches %s" % ( cmp ) ) if cmp.state(): for ns in cmp.state(): if ns.has_key("value"): self._values[ns["name"]] = ns["value"] elif ns.has_key("key"): # update from event or localstate if self._values.has_key(ns["key"]): self._values[ns["name"]] = self._values[ns["key"]] elif od and od.has_key(ns["key"]): self._values[ns["name"]] = od[ns["key"]] else: # error self._log.error( "newState missing value or key2 %s" % ( ns ) ) if cmp.events(): for ne in cmp.events(): #pass in incoming event so we can support string substitution in our variable names newEvents.append( makeNewEvent( ne, inEvent, self._values ) ) # and then break from for loop. break # finally remove transients for action in actions: # may of allready been deleted? if action.has_key("transient") and self._values.has_key(action["name"]): del self._values[action["name"]] for evnt in newEvents: self.sendEvent( evnt )
def doActions(self, delays, inEvent): if delays: for delay in delays: _log.debug("createDelay %s" % (delay)) # a delay entry has delayMinutes or delaySeconds attribute # a newEvent list/entry. secs = 0 if delay.has_key("delayMinutes"): secs = int(delay["delayMinutes"]) * 60 if delay.has_key("delaySeconds"): secs = secs + int(delay["delaySeconds"]) if delay.has_key("delayHours"): secs = secs + int(delay["delayHours"]) * 3600 newEvents = list() if isinstance(delay["newEvent"], list): for newEvent in delay["newEvent"]: newEvents.append(makeNewEvent(newEvent, inEvent, None)) else: newEvents.append(makeNewEvent(delay["newEvent"], inEvent, None)) # insert into list at correct point ntry = DelayedEventEntry(secs, newEvents) idx = 0 # _log.debug( 'insert into %s self %s ' % (self._waiting, ntry) ) while idx < len(self._waiting): # _log.debug( 'insert %i Test self %i against %i ' % (idx, ntry.delta(), self._waiting[idx].delta()) ) if self._waiting[idx].delta() > ntry.delta(): # insert here self._waiting[idx].decrement(ntry.delta()) self._waiting.insert(idx, ntry) break else: ntry.decrement(self._waiting[idx].delta()) idx = idx + 1 if idx >= len(self._waiting): # onto end of list self._waiting.append(ntry) _log.info("createdDelay %s" % (ntry))
def doActions( self, actions, inEvent ): _log.debug( 'doActions %s %s' % ( actions, inEvent ) ) if actions and inEvent.getPayload(): for action in actions: _log.debug( 'Generate event %s' % ( action ) ) evOd = inEvent.getPayload() # ensure backward compatibility and default to scaling conversion = "scale" if action.has_key( "conversion" ): conversion = action["conversion"] self._log.debug("Conversion is %s" %conversion) # scaling conversion required if conversion == "scale": preoffset = 0.0 postoffset = 0.0 multiplier = 1.0 divisor = 1.0 val = 1.0 od = dict() # get the conversion parameters from the eventdespatch, # if these are specified if action.has_key( "preoffset" ): preoffset = float(action["preoffset"]) elif action.has_key( "offset" ): preoffset = float(action["offset"]) if action.has_key( "postoffset" ): postoffset = float(action["postoffset"]) if action.has_key( "multiplier" ): multiplier = float(action["multiplier"]) if action.has_key( "divisor" ): divisor = float(action["divisor"]) # get the conversion parameters from payload of incoming # event, if these are specified if evOd.has_key( "preoffset" ): preoffset = float(evOd["preoffset"]) _log.info( 'Using preoffset from payload: %s' % ( preoffset ) ) if evOd.has_key( "postoffset" ): postoffset = float(evOd["postoffset"]) _log.info( 'Using postoffset from payload: %s' % ( postoffset ) ) if evOd.has_key( "multiplier" ): multiplier = float(evOd["multiplier"]) _log.info( 'Using multiplier from payload: %s' % ( multiplier ) ) if evOd.has_key( "divisor" ): divisor = float(evOd["divisor"]) _log.info( 'Using divisor from payload: %s' % ( divisor ) ) # get the value to be scaled from the payload of incoming # event (has to be specified) if evOd.has_key( "val" ): val = float(evOd["val"]) else: _log.debug( 'No Payload "val" in: %s' % ( action ) ) if action.has_key( "copy_other_data" ): od['newVal'] = ( (val - preoffset)*multiplier/divisor) + postoffset self.sendEvent( makeNewEvent( action, inEvent, od ) ) # hex to decimal conversion required if conversion == "hex_to_dec": # setting default input and output types informat = "string" outformat = "int" value = "00" od = dict() if action.has_key( "informat" ): informat = action["informat"] if action.has_key( "outformat" ): outformat = action["outformat"] if evOd.has_key( "val" ): value = evOd["val"] if action.has_key( "attr" ): if informat == "string": if outformat == "int": od[action["attr"]] = int( value, 16 ) elif outformat == "string": od[action["attr"]] = string(int( value, 16 )) self.sendEvent( makeNewEvent( action, inEvent, None, od ) ) # integer to decimal conversion required if conversion == "dec_to_hex": # setting default input and output types informat = "int" outformat = "string" value = 0 od = dict() if action.has_key( "informat" ): informat = action["informat"] if action.has_key( "outformat" ): outformat = action["outformat"] if evOd.has_key( "val" ): value = int(evOd["val"]) if action.has_key( "attr" ): if informat == "int": if outformat == "string": od[action["attr"]] = hex(value) elif outformat == "bytes_dec": od[action["attr"]+"1"] = ord(hex(value)[2:3]) if hex(value)[3:4]: od[action["attr"]+"2"] = ord(hex(value)[3:4]) else: od[action["attr"]+"2"] = ord('0') self.sendEvent( makeNewEvent( action, inEvent, None, od ) ) if action.has_key( "attr" )!= True: action["attr"] = "val" if conversion == "NAD_to_dec": #this converts the list of bytes recieved from a NAD products RS232 port into the bytes that represent the actual payload, this should work for the NAD Viso Five and Four #see nad_rs232_1.03.doc for protocol definition if action.has_key( "incommingattr" ): attrkey = action["incommingattr"] else: attrkey = "val" value = 0 od = dict() if evOd.has_key( attrkey ): value = str(evOd[attrkey]) x = 0 # we should be recieving a string with bytes as their decimal value seperated by a ; and terminated by a : splt = value.rstrip(':') splt = splt.split(';') od[action["attr"]] = '' # go through our list of bytes in decimal format while x < len(splt): if x == len(splt)-1: #we should not have got here as that means we never encountered the checksum byte #so we assume the data must be mangled somehow _log.error("NAD_to_int : Did not find checksum, data is invalid" %(checksum,value[x+1])) od = '' break elif int(float(splt[x])) == 94: #94 is the flag byte which means the next byte is reserved keyword bitwise ORed with 64 # to get the value back we bitwise AND it with 191 # unless the next value is 94 in which we just take 94 as the value if splt[x+1] == '94': od[action["attr"]] += '94;' x +=2 else: od[action["attr"]] += str(int(float(splt[x+1])) & 191) + ';' x+= 2 continue elif int(float(splt[x])) == 1: #1 is the control byte to indicate the start of an update so we ignore it and jump to the next one x+=1 continue elif int(float(splt[x])) == 2: # 2 means the next byte will be the checksum for the data so we verify it then finish checksum = 0 for y in od[action["attr"]].split(';'): if y != '': checksum+= int(y) checksum = checksum % 256 checksum = checksum ^ 255 if checksum == int(float(splt[x+1])): od[action["attr"]] = od[action["attr"]].rstrip(';') od[action["attr"]] += ':' #we break here as we have reached the end of what we should be parsing break else: _log.error("NAD_to_int : Checksum failure , is %i expected %s" %(checksum,splt[x+1])) od = '' #we break here as we have reached the end of what we should be parsing break elif int(float(splt[x])) == 0 | ((int(float(splt[x])) >= 3) & (int(float(splt[x])) <= 19)): #Currently none of the reserved control bytes are actually used so if we get any we ignore them _log.error("NAD_to_int : Unlisted control character '%s' , ignoring" %splt[x]) else: #not a control byte so it must be part of the data we are trying to read od[action["attr"]] += splt[x] + ';' x+=1 #dont send the event if we have nothing to send if od != '': self.sendEvent( makeNewEvent( action, inEvent, None, od ) ) if conversion == "dec_to_NAD": #this converts a command into a format for transmission to a NAD product via RS232 #see nad_rs232_1.03.doc for protocol definition value = 0 od = dict() if evOd.has_key( "val" ): value = evOd["val"] x = 0 if value != '': splt = value.rstrip(':') splt = splt.split(';') #nad packets always start with 1 od[action["attr"]] = '1;' while x < len(splt): if int(float(splt[x])) == 94: #we want to represent 94 which is a special control byte so in our outgoing packet so we insert two of them od[action["attr"]] += '94;94' x+=1 continue elif (int(float(splt[x])) >= 0) & (int(float(splt[x])) <= 19): #all control characters must have a 94 preceeding them and they must be bitwise ORed with 64 od[action["attr"]] += '94;' + str(int(float(splt[x]))|64) + ';' x+= 1 else: od[action["attr"]] += ('%i'%int(float(splt[x]))) + ';' x+= 1 #we need to add the 8 bit checksum , we do not include the first byte in the checksum and we use the original unencoded values for the data checksum = 0 for y in splt: checksum+= int(float(y)) checksum = checksum % 256 checksum = checksum ^ 255 od[action["attr"]] += '2;%i:' %checksum self.sendEvent( makeNewEvent( action, inEvent, None, od ) ) else: self._log.error("int_to_NAD payload was empty! We cant encode a blank payload!")