def read_property_multiple_g3(device, properties, timeout=3.0, no_fallback=0): # Some device's do not properly answer multiple properties to multiple # objects. This method first tries RPM, then RPM(singular) and finially RP # to retrieve a list of properties. # A readPropertyFallback attribute remembers which mode was successful and # that is used in subsequent reads. if (not (_device_table.has_key(device)) or \ (_device_table[device].readPropertyFallback < BACNET_RPM_SINGLE_OK)): results = _read_property_multiple_g3(device,properties, timeout) if (results != None): if (len(results) == len(properties)): _device_table[device].readPropertyFallback=1 # No fallback needed. return results elif no_fallback != 0: return results else: # Broken device? _device_table[device].readPropertyFallback=0 results = [] properties = copy.copy(properties) while properties: property = properties.pop(0) try: rp_result = read_property_g3(device, property) if (rp_result is not None): #remember this worked if (_device_table[device].readPropertyFallback == BACNET_RPM_UNKNOWN): msglog.log('broadway', msglog.types.WARN, 'read_property fallback for device = ' + str(device)) _device_table[device].readPropertyFallback = BACNET_RPM_NOT_SUPPORTED #convert result to RPM style result = sequence.ReadAccessResult() result.object_identifier = rp_result.object_identifier result.list_of_results = [ sequence._ReadPropertyMultipleResult( property_identifier=rp_result.property_identifier, property_array_index=rp_result.property_array_index, property_value=rp_result.property_value) ] else: # Place holder... result = ReadAccessResult() except BACnetError, e: # Simulate RPMs behaviour when a subset of reads fail. error = sequence.Error(decode=tag.decode(e.npdu.data).value) result = sequence.ReadAccessResult() result.object_identifier = data.BACnetObjectIdentifier(property[0], property[1]) if len(property) > 3 and property[3] != -1: index = property[3] else: index = -1 result.list_of_results = [ sequence._ReadPropertyMultipleResult( property_identifier=property[2], property_array_index=index, property_access_error=error) ] results.append(result)
def read_property_multiple_g3(device, properties, timeout=3.0, no_fallback=0): # Some device's do not properly answer multiple properties to multiple # objects. This method first tries RPM, then RPM(singular) and finially RP # to retrieve a list of properties. # A readPropertyFallback attribute remembers which mode was successful and # that is used in subsequent reads. if not (_device_table.has_key(device)) or (_device_table[device].readPropertyFallback < BACNET_RPM_SINGLE_OK): results = _read_property_multiple_g3(device, properties, timeout) if results != None: if len(results) == len(properties): _device_table[device].readPropertyFallback = 1 # No fallback needed. return results elif no_fallback != 0: return results else: # Broken device? _device_table[device].readPropertyFallback = 0 results = [] properties = copy.copy(properties) while properties: property = properties.pop(0) try: rp_result = read_property_g3(device, property) if rp_result is not None: # remember this worked if _device_table[device].readPropertyFallback == BACNET_RPM_UNKNOWN: msglog.log("broadway", msglog.types.WARN, "read_property fallback for device = " + str(device)) _device_table[device].readPropertyFallback = BACNET_RPM_NOT_SUPPORTED # convert result to RPM style result = sequence.ReadAccessResult() result.object_identifier = rp_result.object_identifier result.list_of_results = [ sequence._ReadPropertyMultipleResult( property_identifier=rp_result.property_identifier, property_array_index=rp_result.property_array_index, property_value=rp_result.property_value, ) ] else: # Place holder... result = ReadAccessResult() except BACnetError, e: # Simulate RPMs behaviour when a subset of reads fail. error = sequence.Error(decode=tag.decode(e.npdu.data).value) result = sequence.ReadAccessResult() result.object_identifier = data.BACnetObjectIdentifier(property[0], property[1]) if len(property) > 3 and property[3] != -1: index = property[3] else: index = -1 result.list_of_results = [ sequence._ReadPropertyMultipleResult( property_identifier=property[2], property_array_index=index, property_access_error=error ) ] results.append(result)
def cov_notification_msg(server_device, msg, confirmed): notif = tag.decode(msg.data) if DEBUG: print "COV NOTIFICATION: ", notif # convert request into a list of cov specifications ss = sequence.CovNotification(decode=notif.value) if DEBUG: print "COV NOTIFICATION sequence: ", ss pid = ss.pid if DEBUG: print "COV NOTIFICATION pid: ", pid device_id = ss.device_identifier.instance_number if DEBUG: print "COV NOTIFICATION device_id: ", device_id time_remaining = ss.time_remaining if DEBUG: print "COV NOTIFICATION time_remaining: ", time_remaining if _device_table.has_key(device_id): device = _device_table[device_id] else: # Unknown device. return error_pdu(msg, 5, 25) try: if device.node is None: dnode = as_node("/services/network/BACnet/internetwork/Devices/" + str(device_id)) device.node = dnode o = device.node.as_node( (str(ss.object_identifier.object_type)) + "/" + (str(ss.object_identifier.instance_number)) ) except: return error_pdu(msg, 5, 25) if DEBUG: print "COV NOTIFICATION object: ", o for pv in ss.list_of_property_values: try: p = o.get_child(str(pv.property_identifier), auto_discover=0) except ENoSuchName: if DEBUG: print "COV NOTIFICATION ENOSUCHNAME" # This can happen if the property we are refering to is # not instantiated (because it isn't polled/monitored/not-of- # interest. Example: We are only monitoring present-value # property, but not status-flags. Ignore for now. else: p.cov_notif_processing(pv.value, pid, time_remaining) return simple_ack_pdu(msg)
def cov_notification_msg(server_device, msg, confirmed): notif = tag.decode(msg.data) if DEBUG: print 'COV NOTIFICATION: ', notif #convert request into a list of cov specifications ss = sequence.CovNotification(decode=notif.value) if DEBUG: print 'COV NOTIFICATION sequence: ', ss pid = ss.pid if DEBUG: print 'COV NOTIFICATION pid: ', pid device_id = ss.device_identifier.instance_number if DEBUG: print 'COV NOTIFICATION device_id: ', device_id time_remaining = ss.time_remaining if DEBUG: print 'COV NOTIFICATION time_remaining: ', time_remaining if _device_table.has_key(device_id): device = _device_table[device_id] else: # Unknown device. return error_pdu(msg, 5, 25) try: if device.node is None: dnode = as_node('/services/network/BACnet/internetwork/Devices/' + str(device_id)) device.node = dnode o = device.node.as_node((str(ss.object_identifier.object_type)) \ + '/'+ (str(ss.object_identifier.instance_number))) except: return error_pdu(msg, 5, 25) if DEBUG: print 'COV NOTIFICATION object: ', o for pv in ss.list_of_property_values: try: p = o.get_child(str(pv.property_identifier), auto_discover=0) except ENoSuchName: if DEBUG: print 'COV NOTIFICATION ENOSUCHNAME' # This can happen if the property we are refering to is # not instantiated (because it isn't polled/monitored/not-of- # interest. Example: We are only monitoring present-value # property, but not status-flags. Ignore for now. else: p.cov_notif_processing(pv.value, pid, time_remaining) return simple_ack_pdu(msg)
def read_property_multiple(device, properties): # this hack is back in now because Trane's onsite bridge (device 11) # does not properly answer multiple properties # This method first tries RPM, then RPM(singular) and finially RP to retrieve # a list of properties # A readPropertyFallback attribute remembers which mode was successful and # that is used in subsequent reads results = [] if not (_device_table.has_key(device)) or (_device_table[device].readPropertyFallback < 2): results = read_property_multiple_real2(device, properties) if results != None: if len(results) == len(properties): _device_table[device].readPropertyFallback = 1 # No fallback needed. return results # we did not get the result we expected, try to fall back to a different # method this function breaks the read_property_multiple into groups of # GroupSize results = [] Groupsize = 1 while properties: group = properties[0:Groupsize] ilen = len(group) result = None if (_device_table[device].readPropertyFallback == 0) or (_device_table[device].readPropertyFallback == 2): result = read_property_multiple_real2(device, group) if result != None: # remember this worked if _device_table[device].readPropertyFallback == 0: msglog.log( "broadway", msglog.types.WARN, "read_property_multiple fallback for device = " + str(device) ) _device_table[device].readPropertyFallback = 2 # Use single RPM. if (_device_table[device].readPropertyFallback == 0) or (_device_table[device].readPropertyFallback == 3): result = read_property(device, group[0]) if result != None: # remember this worked if _device_table[device].readPropertyFallback == 0: msglog.log("broadway", msglog.types.WARN, "read_property fallback for device = " + str(device)) _device_table[device].readPropertyFallback = 3 rp_result = result # convert result to RPM style result = ((None, None),) for p in rp_result.value: # Again, if we felt like it, we could extract the property # ID from tag.number 2. But we won't because we don't use # it. If we wrote code to match the request to response, # we would need it. if p.number == 4: # Property value list p_value = p.value[0].value p_bacnet_value_type = p.value[0].number result = ((p_value, p_bacnet_value_type),) elif p.number == 3: # Property value list p_value = p.value[0].value p_bacnet_value_type = p.value[0].number result = ((p_value, p_bacnet_value_type),) elif p.number == 5: # error code result = ((None, None),) properties = properties[Groupsize:] if result is None: if DEBUG: print "No results..." result = (None, None) for i in range(0, ilen): results.append(result) else: for i in range(0, ilen): if i < len(result): results.append(result[i]) else: raise BACnetException("Too few results...") return results
def read_property_multiple(device, properties): # this hack is back in now because Trane's onsite bridge (device 11) # does not properly answer multiple properties # This method first tries RPM, then RPM(singular) and finially RP to retrieve # a list of properties # A readPropertyFallback attribute remembers which mode was successful and # that is used in subsequent reads results=[] if (not (_device_table.has_key(device)) or \ (_device_table[device].readPropertyFallback < 2)): results = read_property_multiple_real2(device,properties) if (results != None): if (len(results) == len(properties)): _device_table[device].readPropertyFallback=1 # No fallback needed. return results # we did not get the result we expected, try to fall back to a different # method this function breaks the read_property_multiple into groups of # GroupSize results=[] Groupsize = 1 while properties: group = properties[0:Groupsize] ilen = len(group) result = None if (_device_table[device].readPropertyFallback == 0) or \ (_device_table[device].readPropertyFallback == 2): result = read_property_multiple_real2(device, group) if (result != None): #remember this worked if (_device_table[device].readPropertyFallback == 0): msglog.log('broadway', msglog.types.WARN, 'read_property_multiple fallback for device = ' + str(device)) _device_table[device].readPropertyFallback = 2 # Use single RPM. if (_device_table[device].readPropertyFallback == 0) or \ (_device_table[device].readPropertyFallback == 3): result = read_property(device, group[0]) if (result != None): #remember this worked if (_device_table[device].readPropertyFallback == 0): msglog.log('broadway', msglog.types.WARN, 'read_property fallback for device = ' + str(device)) _device_table[device].readPropertyFallback = 3 rp_result = result #convert result to RPM style result = ((None, None),) for p in rp_result.value: # Again, if we felt like it, we could extract the property # ID from tag.number 2. But we won't because we don't use # it. If we wrote code to match the request to response, # we would need it. if p.number == 4: # Property value list p_value = p.value[0].value p_bacnet_value_type = p.value[0].number result = ((p_value, p_bacnet_value_type),) elif p.number == 3: # Property value list p_value = p.value[0].value p_bacnet_value_type = p.value[0].number result = ((p_value, p_bacnet_value_type),) elif p.number == 5: # error code result = ((None, None),) properties = properties[Groupsize:] if result is None: if DEBUG: print 'No results...' result = (None,None) for i in range(0,ilen): results.append(result) else: for i in range(0,ilen): if i < len(result): results.append(result[i]) else: raise BACnetException('Too few results...') return results