def who_is_request_received(msg, network): if not the_devices: if debug: print 'who is received but we have no device(s)' return if len(msg.data) == 0: #device limits tags len==0 means global request if debug: print 'who are' for the_device in the_devices.values(): i_am(the_device, network) else: if debug: print 'check if we are who is' tags = tag.decode(msg.data).value if debug: print tags if len(tags) == 2: if debug: print tags[0] print tags[1] lower_limit = data.decode_unsigned_integer(tags[0].data) #Device Instance Range Low Limit upper_limit = data.decode_unsigned_integer(tags[1].data) if debug: print 'is it between: %s and %s' % (lower_limit, upper_limit) # From bacnet plugfest, we were filtering out anyone not on our network from test for # address limits. We were responding ok to global whoisall # if network == the_device.network: for the_device in the_devices.values(): if the_device.instance_number >= lower_limit: if the_device.instance_number <= upper_limit: if debug: print 'i am the mo-fo' i_am(the_device, network)
def read_property_g3(device, prop, timeout=3.0, **keywords): object = prop[0] instance = prop[1] property = prop[2] arrayidx = None if len(prop) > 3 : arrayidx = prop[3] rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 12 objID = tag.Context(0,data.BACnetObjectIdentifier(object,instance)) propID = tag.Context(1,data.encode_enumerated(property)) rp.data = objID.encoding + propID.encoding if arrayidx is not None and arrayidx != -1: rp.data = rp.data + \ tag.Context(2,data.encode_unsigned_integer(arrayidx)).\ encoding if keywords.has_key('callback'): keywords['callback'].callback(_read_property_callback) request_id = network.send_request(device, rp, timeout, **keywords) return keywords['callback'] else: #block until answer else let tsm handle callback request_id = network.send_request(device, rp, timeout) r = recv_response(request_id, timeout) response = tag.decode(r.data) return sequence.ReadPropertyACK(decode=response.value)
def read_property_g3(device, prop, timeout=3.0, **keywords): object = prop[0] instance = prop[1] property = prop[2] arrayidx = None if len(prop) > 3: arrayidx = prop[3] rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 12 objID = tag.Context(0, data.BACnetObjectIdentifier(object, instance)) propID = tag.Context(1, data.encode_enumerated(property)) rp.data = objID.encoding + propID.encoding if arrayidx is not None and arrayidx != -1: rp.data = rp.data + tag.Context(2, data.encode_unsigned_integer(arrayidx)).encoding if keywords.has_key("callback"): keywords["callback"].callback(_read_property_callback) request_id = network.send_request(device, rp, timeout, **keywords) return keywords["callback"] else: # block until answer else let tsm handle callback request_id = network.send_request(device, rp, timeout) r = recv_response(request_id, timeout) response = tag.decode(r.data) return sequence.ReadPropertyACK(decode=response.value)
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 who_is_request_received(msg, network): if not the_devices: if debug: print 'who is received but we have no device(s)' return if len(msg.data) == 0: #device limits tags len==0 means global request if debug: print 'who are' for the_device in the_devices.values(): i_am(the_device, network) else: if debug: print 'check if we are who is' tags = tag.decode(msg.data).value if debug: print tags if len(tags) == 2: if debug: print tags[0] print tags[1] lower_limit = data.decode_unsigned_integer( tags[0].data) #Device Instance Range Low Limit upper_limit = data.decode_unsigned_integer(tags[1].data) if debug: print 'is it between: %s and %s' % (lower_limit, upper_limit) # From bacnet plugfest, we were filtering out anyone not on our network from test for # address limits. We were responding ok to global whoisall # if network == the_device.network: for the_device in the_devices.values(): if the_device.instance_number >= lower_limit: if the_device.instance_number <= upper_limit: if debug: print 'i am the mo-fo' i_am(the_device, network)
def server_read_property(device, msg): s = None o = None ss = None p = None try: # device.time_rp.begin() request = tag.decode(msg.data) if DEBUG: print "SERVER READ PROPERTY request: ", request s = sequence.ReadPropertyRequest(decode=request.value) if DEBUG: print "SERVER READ PROPERTY sequence: ", s o = device.find_bacnet_object(s.object_identifier) if o is None: # object not found raise ENotFound( "BACnet Server Read, Object not found, Type: %d Instance: %d propID: %d" % (s.object_identifier.object_type, s.object_identifier.instance_number, s.property_identifier) ) if DEBUG: print "SERVER READ PROPERTY object: ", o ss = s.property_identifier if DEBUG: print "ss = ", ss p = o.find_property(ss) if o is None: # object not found raise ENotFound( "BACnet Server Read, Prop not found, Type: %d Instance: %d propID: %d" % (s.object_identifier.object_type, s.object_identifier.instance_number, s.property_identifier) ) if DEBUG: print "SERVER READ PROPERTY property: ", p i = None answer = sequence.ReadPropertyACK() if s.property_array_index != OPTIONAL: if DEBUG: print "_bacnet.serverreadproperty ", s.property_array_index i = s.property_array_index answer.property_array_index = i if DEBUG: print i answer.object_identifier = s.object_identifier answer.property_identifier = s.property_identifier answer.property_value = p.as_tags(i) # this is where we retrieve the value from the node answer = complex_ack_pdu(msg, answer.encoding) # device.time_rp.end() return answer except: # @fixme use literals not numbers msglog.log("mpx:bacnet", msglog.types.ERR, str(msg)) msglog.exception() if p: return error_pdu(msg, 2, 25) # operational-problem if o: return error_pdu(msg, 2, 32) # unknown-property if s: return error_pdu(msg, 1, 31) # unknown-object return error_pdu(msg, 2, 0) # other
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_real2(device, properties): results = [] rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 14 rp.data = array.array("c") for prop in properties: object = prop[0] instance = prop[1] property = prop[2] objID = tag.Context(0, data.BACnetObjectIdentifier(object, instance)) if len(prop) < 4 or prop[3] == -1: propID = tag.Construct(1, [tag.Context(0, data.encode_enumerated(property))]) else: arrayidx = prop[3] propID = tag.Construct( 1, [ tag.Context(0, data.encode_enumerated(property)), tag.Context(1, data.encode_unsigned_integer(arrayidx)), ], ) rp.data.fromstring(objID.encoding) rp.data.fromstring(propID.encoding) request_id = network.send_request(device, rp) r = recv_response(request_id) responses = tag.decode(r.data) for response in responses.value: # Now if we felt like it, we could extract the BACnetIdentifierObject from # the response data, at response.number 0. But we won't because # we don't need it at the moment. if response.number == 1: # Property id/value list. for p in response.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 if p_value is None: pass p_bacnet_value_type = p.value[0].number results.append((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 results.append((p_value, p_bacnet_value_type)) elif p.number == 5: # error code results.append((None, None)) return results
def _read_property_multiple_callback(tsm): try: if tsm.exception: raise tsm.exception r = tsm.response recv_callback_helper(r) responses = tag.decode(r.data) return sequence.context_read_access_result_list(responses) except Exception, e: return e
def _read_property_callback(tsm): try: if tsm.exception: raise tsm.exception r = tsm.response recv_callback_helper(r) response = tag.decode(r.data) return sequence.ReadPropertyACK(decode=response.value) except Exception, e: return e
def read_property_multiple_real2(device, properties): results = [] rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 14 rp.data = array.array('c') for prop in properties: object = prop[0] instance = prop[1] property = prop[2] objID = tag.Context(0,data.BACnetObjectIdentifier(object,instance)) if len(prop) < 4 or prop[3] == -1: propID = tag.Construct( 1,[tag.Context(0,data.encode_enumerated(property))] ) else: arrayidx = prop[3] propID = tag.Construct( 1,[tag.Context(0, data.encode_enumerated(property)), tag.Context(1, data.encode_unsigned_integer(arrayidx))] ) rp.data.fromstring(objID.encoding) rp.data.fromstring(propID.encoding) request_id = network.send_request(device, rp) r = recv_response(request_id) responses = tag.decode(r.data) for response in responses.value: # Now if we felt like it, we could extract the BACnetIdentifierObject from # the response data, at response.number 0. But we won't because # we don't need it at the moment. if response.number == 1: # Property id/value list. for p in response.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 if p_value is None: pass p_bacnet_value_type = p.value[0].number results.append((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 results.append((p_value, p_bacnet_value_type)) elif p.number == 5: # error code results.append((None, None)) return results
def server_write_property_multiple(device, msg): request = tag.decode(msg.data) if DEBUG: print "SERVER WRITE PROPERTY MULTIPLE request: ", request results = None # convert request into a list of read access specifications ss = sequence.context_write_access_specification_list(request) o = None p = None if DEBUG: print "SERVER WRITE PROPERTY sequence: ", ss for s in ss: # do each write access specification o = device.find_bacnet_object(s.object_identifier) if DEBUG: print "SERVER WRITE PROPERTY object: ", o for pv in s.list_of_properties: i = None if pv.property_array_index != OPTIONAL: i = pv.property_array_index priority = None if pv.priority != OPTIONAL: priority = pv.priority try: p = o.find_property(pv.property_identifier) p.write(pv.value, i, priority) # index? except EPermission: if DEBUG: print "SERVER WRITE PROPERTY EPERMISSION ERROR" result = sequence.WritePropertyMultipleError() result.error_type = sequence.Error(2, 40) # write access denied bopr = BACnetObjectPropertyReference() bopr.object_identifier = s.object_identifier bopr.property_identifier = pv.property_identifier bopr.property_index = pv.property_array_index result.first_failed_write_attempt = bopr return complex_ack_pdu(result.encoding) except: if DEBUG: print "SERVER WRITE PROPERTY ERROR" result = sequence.WritePropertyMultipleError() if p: result.error_type = sequence.Error(2, 25) # operational error elif o: result.error_type = sequence.Error(2, 32) # unknown property else: # unkown object result.error_type = sequence.Error(1, 31) # unknown object bopr = BACnetObjectPropertyReference() bopr.object_identifier = s.object_identifier bopr.property_identifier = pv.property_identifier bopr.property_index = pv.property_array_index result.first_failed_write_attempt = bopr return complex_ack_pdu(result.encoding) if DEBUG: print "SERVER WRITE PROPERTY property: ", p 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 server_read_property_multiple(device, msg): request = tag.decode(msg.data) if DEBUG: print "SERVER READ PROPERTY MULTIPLE request: ", request results = [] # convert request into a list of read access specifications ss = sequence.context_read_access_specification_list(request) o = None p = None if DEBUG: print "SERVER READ PROPERTY sequence: ", ss # device.time_rpm.begin() for s in ss: o = device.find_bacnet_object(s.object_identifier) if DEBUG: print "SERVER READ PROPERTY object: ", o result = sequence.ReadAccessResult() result.object_identifier = s.object_identifier props = [] for spec in s.list_of_specs: prop_result = sequence._ReadPropertyMultipleResult() prop_result.property_identifier = spec.property_identifier i = None if spec.property_index != OPTIONAL: i = spec.property_index prop_result.property_array_index = i try: p = o.find_property(spec.property_identifier) prop_result.property_value = p.as_tags(i) except: if p: prop_result.property_access_error = sequence.Error(2, 25) # operational error elif o: prop_result.property_access_error = sequence.Error(2, 32) # unknown property else: # unkown object prop_result.property_access_error = sequence.Error(1, 31) # unknown object if DEBUG: print "SERVER property_access_error: ", str( prop_result.property_access_error ), s.object_identifier.object_type, s.object_identifier.instance_number, str( spec.property_identifier ) if DEBUG: print "SERVER READ PROPERTY property: ", p props.append(prop_result.encoding) result.list_of_results = props results.extend(result.encoding) if DEBUG: print "SERVER READ PROPERTY MULTIPLE request results: ", results answer = complex_ack_pdu(msg, results) # device.time_rpm.end() return answer
def server_read_property(device, msg): s = None o = None ss = None p = None try: #device.time_rp.begin() request = tag.decode(msg.data) if DEBUG: print 'SERVER READ PROPERTY request: ', request s = sequence.ReadPropertyRequest(decode=request.value) if DEBUG: print 'SERVER READ PROPERTY sequence: ', s o = device.find_bacnet_object(s.object_identifier) if o is None: # object not found raise ENotFound('BACnet Server Read, Object not found, Type: %d Instance: %d propID: %d' % \ (s.object_identifier.object_type, s.object_identifier.instance_number, s.property_identifier)) if DEBUG: print 'SERVER READ PROPERTY object: ', o ss = s.property_identifier if DEBUG: print 'ss = ', ss p = o.find_property(ss) if o is None: # object not found raise ENotFound('BACnet Server Read, Prop not found, Type: %d Instance: %d propID: %d' % \ (s.object_identifier.object_type, s.object_identifier.instance_number, s.property_identifier)) if DEBUG: print 'SERVER READ PROPERTY property: ', p i = None answer = sequence.ReadPropertyACK() if s.property_array_index != OPTIONAL: if DEBUG: print '_bacnet.serverreadproperty ', s.property_array_index i = s.property_array_index answer.property_array_index = i if DEBUG: print i answer.object_identifier = s.object_identifier answer.property_identifier = s.property_identifier answer.property_value = p.as_tags(i) #this is where we retrieve the value from the node answer = complex_ack_pdu(msg, answer.encoding) #device.time_rp.end() return answer except: #@fixme use literals not numbers msglog.log('mpx:bacnet',msglog.types.ERR,str(msg)) msglog.exception() if p: return error_pdu(msg, 2, 25) # operational-problem if o: return error_pdu(msg, 2, 32) # unknown-property if s: return error_pdu(msg, 1, 31) # unknown-object return error_pdu(msg, 2, 0) # other
def _read_property_multiple_g3(device, properties, timeout=3.0, **keywords): rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 14 rp.data = array.array("c") for prop in properties: object = prop[0] instance = prop[1] property = prop[2] objID = tag.Context(0, data.BACnetObjectIdentifier(object, instance)) if isinstance(property, types.TupleType): tags = [] for pid in property: # loop through list of properties if isinstance(pid, types.TupleType): # may have index if len(pid) > 1: # index tags.append(tag.Context(0, data.encode_enumerated(pid[0]))) tags.append(tag.Context(1, data.encode_unsigned_integer(pid[1]))) continue pid = pid[0] # doen't need to be tuple tags.append(tag.Context(0, data.encode_enumerated(pid))) propID = tag.Construct(1, tags) # frame it in contruct tags else: if len(prop) < 4 or prop[3] == -1: propID = tag.Construct(1, [tag.Context(0, data.encode_enumerated(property))]) else: arrayidx = prop[3] propID = tag.Construct( 1, [ tag.Context(0, data.encode_enumerated(property)), tag.Context(1, data.encode_unsigned_integer(arrayidx)), ], ) rp.data.fromstring(objID.encoding) rp.data.fromstring(propID.encoding) # return rp if DEBUG: for c in rp.data: print hex(ord(c)), " ", print "" if keywords.has_key("callback"): keywords["callback"].callback(_read_property_multiple_callback) network.send_request(device, rp, timeout, **keywords) return keywords["callback"] # used as flag request_id = network.send_request(device, rp, timeout) r = recv_response(request_id, timeout) responses = tag.decode(r.data) return sequence.context_read_access_result_list(responses)
def _read_property_multiple_g3(device, properties, timeout=3.0, **keywords): rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 14 rp.data = array.array('c') for prop in properties: object = prop[0] instance = prop[1] property = prop[2] objID = tag.Context(0,data.BACnetObjectIdentifier(object,instance)) if isinstance(property, types.TupleType): tags = [] for pid in property: #loop through list of properties if isinstance(pid, types.TupleType): #may have index if len(pid) > 1: #index tags.append(tag.Context(0, data.encode_enumerated(pid[0]))) tags.append(tag.Context(1, data.encode_unsigned_integer(pid[1]))) continue pid = pid[0] #doen't need to be tuple tags.append(tag.Context(0,data.encode_enumerated(pid))) propID = tag.Construct(1,tags) #frame it in contruct tags else: if len(prop) < 4 or prop[3] == -1: propID = tag.Construct( 1,[tag.Context(0,data.encode_enumerated(property))] ) else: arrayidx = prop[3] propID = tag.Construct( 1,[tag.Context(0, data.encode_enumerated(property)), tag.Context(1, data.encode_unsigned_integer(arrayidx))] ) rp.data.fromstring(objID.encoding) rp.data.fromstring(propID.encoding) #return rp if DEBUG: for c in rp.data: print hex(ord(c)),' ', print '' if keywords.has_key('callback'): keywords['callback'].callback(_read_property_multiple_callback) network.send_request(device, rp, timeout, **keywords) return keywords['callback'] #used as flag request_id = network.send_request(device, rp, timeout) r = recv_response(request_id, timeout) responses = tag.decode(r.data) return sequence.context_read_access_result_list(responses)
def server_write_property_multiple(device, msg): request = tag.decode(msg.data) if DEBUG: print 'SERVER WRITE PROPERTY MULTIPLE request: ', request results = None #convert request into a list of read access specifications ss = sequence.context_write_access_specification_list(request) o = None p = None if DEBUG: print 'SERVER WRITE PROPERTY sequence: ', ss for s in ss: #do each write access specification o = device.find_bacnet_object(s.object_identifier) if DEBUG: print 'SERVER WRITE PROPERTY object: ', o for pv in s.list_of_properties: i = None if pv.property_array_index != OPTIONAL: i = pv.property_array_index priority = None if pv.priority != OPTIONAL: priority = pv.priority try: p = o.find_property(pv.property_identifier) p.write(pv.value, i, priority) #index? except EPermission: if DEBUG: print 'SERVER WRITE PROPERTY EPERMISSION ERROR' result = sequence.WritePropertyMultipleError() result.error_type = sequence.Error(2,40) #write access denied bopr = BACnetObjectPropertyReference() bopr.object_identifier = s.object_identifier bopr.property_identifier = pv.property_identifier bopr.property_index = pv.property_array_index result.first_failed_write_attempt = bopr return complex_ack_pdu(result.encoding) except: if DEBUG: print 'SERVER WRITE PROPERTY ERROR' result = sequence.WritePropertyMultipleError() if p: result.error_type = sequence.Error(2,25) #operational error elif o: result.error_type = sequence.Error(2,32) #unknown property else: #unkown object result.error_type = sequence.Error(1,31) #unknown object bopr = BACnetObjectPropertyReference() bopr.object_identifier = s.object_identifier bopr.property_identifier = pv.property_identifier bopr.property_index = pv.property_array_index result.first_failed_write_attempt = bopr return complex_ack_pdu(result.encoding) if DEBUG: print 'SERVER WRITE PROPERTY property: ', p return simple_ack_pdu(msg)
def server_write_property(device, msg): try: # device.time_wp.begin() request = tag.decode(msg.data) if DEBUG: print "SERVER WRITE PROPERTY request: ", request s = sequence.WritePropertyRequest(decode=request.value) if DEBUG: print "SERVER WRITE PROPERTY sequence: ", s o = device.find_bacnet_object(s.object_identifier) if o is None: # object not found raise ENotFound( "BACnet Server Write, Object not found, Type: %d Instance: %d propID: %d" % (s.object_identifier.object_type, s.object_identifier.instance_number, s.property_identifier) ) if DEBUG: print "SERVER WRITE PROPERTY object: ", o p = o.find_property(s.property_identifier) if p is None: # object not found raise ENotFound( "BACnet Server Write Prop not found, Type: %d Instance: %d propID: %d" % (s.object_identifier.object_type, s.object_identifier.instance_number, s.property_identifier) ) if DEBUG: print "SERVER WRITE PROPERTY property: ", p priority = None if s.priority != OPTIONAL: priority = s.priority i = None if s.property_array_index != OPTIONAL: i = s.property_array_index if DEBUG: print "SERVER WRITE PROPERTY value: ", s.property_value[0].value, priority p.write(s.property_value, i, priority) answer = simple_ack_pdu(msg) # device.time_wp.end() return answer except EPermission: if DEBUG: print "Permission error on write propety" return error_pdu(msg, 2, 40) except: msglog.exception() if DEBUG: print "ERROR on Write Property" print "device: ", str(device) return error_pdu(msg, 2, 0)
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 server_read_property_multiple(device, msg): request = tag.decode(msg.data) if DEBUG: print 'SERVER READ PROPERTY MULTIPLE request: ', request results = [] #convert request into a list of read access specifications ss = sequence.context_read_access_specification_list(request) o = None p = None if DEBUG: print 'SERVER READ PROPERTY sequence: ', ss #device.time_rpm.begin() for s in ss: o = device.find_bacnet_object(s.object_identifier) if DEBUG: print 'SERVER READ PROPERTY object: ', o result = sequence.ReadAccessResult() result.object_identifier = s.object_identifier props = [] for spec in s.list_of_specs: prop_result = sequence._ReadPropertyMultipleResult() prop_result.property_identifier = spec.property_identifier i = None if spec.property_index != OPTIONAL: i = spec.property_index prop_result.property_array_index = i try: p = o.find_property(spec.property_identifier) prop_result.property_value = p.as_tags(i) except: if p: prop_result.property_access_error = sequence.Error(2,25) #operational error elif o: prop_result.property_access_error = sequence.Error(2,32) #unknown property else: #unkown object prop_result.property_access_error = sequence.Error(1,31) #unknown object if DEBUG: print 'SERVER property_access_error: ', str(prop_result.property_access_error), \ s.object_identifier.object_type, s.object_identifier.instance_number, \ str(spec.property_identifier) if DEBUG: print 'SERVER READ PROPERTY property: ', p props.append(prop_result.encoding) result.list_of_results = props results.extend(result.encoding) if DEBUG: print 'SERVER READ PROPERTY MULTIPLE request results: ', results answer = complex_ack_pdu(msg, results) #device.time_rpm.end() return answer
def server_write_property(device, msg): try: #device.time_wp.begin() request = tag.decode(msg.data) if DEBUG: print 'SERVER WRITE PROPERTY request: ', request s = sequence.WritePropertyRequest(decode=request.value) if DEBUG: print 'SERVER WRITE PROPERTY sequence: ', s o = device.find_bacnet_object(s.object_identifier) if o is None: # object not found raise ENotFound('BACnet Server Write, Object not found, Type: %d Instance: %d propID: %d' % \ (s.object_identifier.object_type, s.object_identifier.instance_number, s.property_identifier)) if DEBUG: print 'SERVER WRITE PROPERTY object: ', o p = o.find_property(s.property_identifier) if p is None: # object not found raise ENotFound('BACnet Server Write Prop not found, Type: %d Instance: %d propID: %d' % \ (s.object_identifier.object_type, s.object_identifier.instance_number, s.property_identifier)) if DEBUG: print 'SERVER WRITE PROPERTY property: ', p priority = None if s.priority != OPTIONAL: priority = s.priority i = None if s.property_array_index != OPTIONAL: i = s.property_array_index if DEBUG: print 'SERVER WRITE PROPERTY value: ', s.property_value[0].value, priority p.write(s.property_value, i, priority) answer = simple_ack_pdu(msg) #device.time_wp.end() return answer except EPermission: if DEBUG: print 'Permission error on write propety' return error_pdu(msg, 2, 40) except: msglog.exception() if DEBUG: print 'ERROR on Write Property' print 'device: ', str(device) return error_pdu(msg, 2, 0)
def read_property(device, prop): object = prop[0] instance = prop[1] property = prop[2] arrayidx = None if len(prop) > 3: arrayidx = prop[3] rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 12 objID = tag.Context(0, data.BACnetObjectIdentifier(object, instance)) propID = tag.Context(1, data.encode_enumerated(property)) rp.data = objID.encoding + propID.encoding if arrayidx is not None and arrayidx != -1: rp.data = rp.data + tag.Context(2, data.encode_unsigned_integer(arrayidx)).encoding request_id = network.send_request(device, rp) r = recv_response(request_id) response = tag.decode(r.data) return response
def read_property(device, prop): object = prop[0] instance = prop[1] property = prop[2] arrayidx = None if len(prop) > 3 : arrayidx = prop[3] rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 12 objID = tag.Context(0,data.BACnetObjectIdentifier(object,instance)) propID = tag.Context(1,data.encode_enumerated(property)) rp.data = objID.encoding + propID.encoding if arrayidx is not None and arrayidx != -1: rp.data = rp.data + \ tag.Context(2,data.encode_unsigned_integer(arrayidx)).\ encoding request_id = network.send_request(device, rp) r = recv_response(request_id) response = tag.decode(r.data) return response
def read_private_object_list(device, vendor, object_type, start_index=0): """## # Return a list of lists of object names and identifiers. # @param device address number, vendor number, object type number. # @return A list, each element of which is a list with the first item an object name, # the second item a BacnetObjectIndentifier object.""" results = [] identifier_list = [] answer = [] last_instance = 0 max_tags = 0 rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 18 # ConfirmedPrivateTransferRequest rp.data = array.array("c") vendorID = tag.Context(0, data.encode_unsigned_integer(vendor)) service = tag.Context(1, data.encode_unsigned_integer(0x81)) instanceTag = tag.Construct( 2, [ tag.Context(0, data.encode_unsigned_integer(object_type)), tag.Context(1, data.encode_unsigned_integer(start_index)), tag.Context(2, data.encode_unsigned_integer(50)), ], ) rp.data.fromstring(vendorID.encoding) rp.data.fromstring(service.encoding) rp.data.fromstring(instanceTag.encoding) request_id = network.send_request(device, rp) r = recv_response(request_id) responses = tag.decode(r.data) for response in responses.value: # Now if we felt like it, we could extract the BACnetIdentifierObject from # the response data, at response.number 0. But we won't because # we don't need it at the moment. if response.number == 2: # context 2 contains instance tag replay parameters # reply parameters list. for p in response.value: # we could match tag 0 with requested object type if p.number == 1: # last Instance retrieved last_instance = data.BACnetObjectIdentifier(decode=p.data).instance_number if p.number == 2: # Max tags returned. If equals 50, ask for more max_tags = ord(p.data) if p.number == 3: # yet another open context # Identifier list for i in p.value: if i.number == 4: # this is the bacnet object identifier # bnoi = data.data_decode_bacnet_object_identifier(i.data) bnoi = data.BACnetObjectIdentifier(decode=i.data) # finially we get to add one to the list identifier_list.append(bnoi) # tag 5 would be theNVMTag, whatever that is # tag 6 would be the VMTag # now create a read property multiple to request all the names of these collected id's properties = [] if len(identifier_list) > 0: for id in identifier_list: properties.append([object_type, id.instance_number, 77]) try: answer = read_property_multiple(device, properties) except BACnetError, e: # @fixme Remove after we figure out the error. print e.npdu raise e if len(answer) != len(identifier_list): raise BACnetException("Identifier list and answer list are different lengths") for i in range(len(identifier_list)): results.append( [ device, identifier_list[i].object_type, identifier_list[i].instance_number, answer[i][0].character_string, ] ) if max_tags == 50: results = results.append(read_private_object_list(device, vendor, object_type, last_instance))
def read_private_object_list(device, vendor, object_type, start_index=0): """## # Return a list of lists of object names and identifiers. # @param device address number, vendor number, object type number. # @return A list, each element of which is a list with the first item an object name, # the second item a BacnetObjectIndentifier object.""" results = [] identifier_list = [] answer = [] last_instance = 0 max_tags = 0 rp = APDU() rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU rp.choice = 18 #ConfirmedPrivateTransferRequest rp.data = array.array('c') vendorID = tag.Context(0,data.encode_unsigned_integer(vendor)) service = tag.Context(1,data.encode_unsigned_integer(0x81)) instanceTag = tag.Construct(2,[ tag.Context(0,data.encode_unsigned_integer(object_type)), tag.Context(1,data.encode_unsigned_integer(start_index)), tag.Context(2,data.encode_unsigned_integer(50))]) rp.data.fromstring(vendorID.encoding) rp.data.fromstring(service.encoding) rp.data.fromstring(instanceTag.encoding) request_id = network.send_request(device, rp) r = recv_response(request_id) responses = tag.decode(r.data) for response in responses.value: # Now if we felt like it, we could extract the BACnetIdentifierObject from # the response data, at response.number 0. But we won't because # we don't need it at the moment. if response.number == 2: #context 2 contains instance tag replay parameters # reply parameters list. for p in response.value: # we could match tag 0 with requested object type if p.number == 1: # last Instance retrieved last_instance = data.BACnetObjectIdentifier(decode=p.data).instance_number if p.number == 2: # Max tags returned. If equals 50, ask for more max_tags = ord(p.data) if p.number == 3: #yet another open context # Identifier list for i in p.value: if i.number == 4: #this is the bacnet object identifier # bnoi = data.data_decode_bacnet_object_identifier(i.data) bnoi = data.BACnetObjectIdentifier(decode=i.data) #finially we get to add one to the list identifier_list.append(bnoi) #tag 5 would be theNVMTag, whatever that is #tag 6 would be the VMTag #now create a read property multiple to request all the names of these collected id's properties = [] if len(identifier_list) > 0: for id in identifier_list: properties.append([object_type,id.instance_number,77]) try: answer = read_property_multiple(device, properties) except BACnetError, e: # @fixme Remove after we figure out the error. print e.npdu raise e if len(answer) != len(identifier_list): raise BACnetException('Identifier list and answer list are different lengths') for i in range(len(identifier_list)): results.append([device,identifier_list[i].object_type, identifier_list[i].instance_number, answer[i][0].character_string]) if max_tags == 50: results = results.append(read_private_object_list(device, vendor, object_type, last_instance))