Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
def cov_subscription_request(device, prop_tuple, subscription_type, \
               lifetime, subscription_pid, **keywords):
    object = prop_tuple[0]
    instance = prop_tuple[1]

    rp = APDU()
    rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU
    rp.choice = 5 # Subscribe COV Request

    rp.data = tag.Context(0,data.\
              encode_unsigned_integer(subscription_pid)).encoding
    objID =   tag.Context(1,data.BACnetObjectIdentifier(object,instance))
    rp.data = rp.data + objID.encoding
    rp.data = rp.data + \
              tag.Context(2,data.\
              encode_boolean(subscription_type)).encoding
    rp.data = rp.data + \
              tag.Context(3,data.\
              encode_unsigned_integer(lifetime)).encoding
    if keywords.has_key('callback'):
        keywords['callback'].callback(_cov_subscription_callback)
        request_id = network.send_request(device, rp, **keywords)
        return keywords['callback']
    else: #block until answer else let tsm handle callback
        request_id = network.send_request(device, rp)
        r = recv_response(request_id)
        return r
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
 def test_encode_bacnet_object_identifier(self):
     t = tag.BACnetObjectIdentifier(data.BACnetObjectIdentifier(0x3,0xf))
     if t.name != 'BACnetObjectIdentifier':
         raise 'Encoded BACnetObjectIdentifier incorrectly as', t.name
     b = t.value
     if b.id != 0xc0000f:
         raise 'Incorrect BACnetObjectIdentifier id'
     if b.object_type != 0x3:
         raise 'Incorrect BACnetObjectIdentifier object_type'
     if b.instance_number != 0xf:
         raise 'Incorrect BACnetObjectIdentifier instance_number'
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
def write_property_multiple_g3(device, prop_vals, no_fall_back=0):
    obj_ids = {}
    for pv in prop_vals:
        prop_tuple = pv[0]
        prop_val = pv[1]        
        object = prop_tuple[0]
        instance = prop_tuple[1]
        k = (object, instance) # use tuple as key into object map
        if not obj_ids.has_key(k): # if necy, add a map entry for the given object ID
            was = sequence.WriteAccessSpecification()
            was.list_of_properties = [] # populated on this pass, and poss'ly subsequent passes
            was.object_identifier = data.BACnetObjectIdentifier(object, instance)
            obj_ids[k] = was
        property_id = prop_tuple[2]
        property_array_index = None # default
        priority = None             # default
        # If valid index and/or priority is/are available, add it/them to extended tuple:
        if len(prop_tuple) > 3 and prop_tuple[3] != -1:
            property_array_index = prop_tuple[3]
            if len(prop_tuple) > 4:
                priority = prop_tuple[4]
        # Create and init a new BACnetPropertyValue instance (using given value), and add
        # that new instance to the corresponding object map entry:
        kw = {'property_identifier':property_id,\
              'value':prop_val,\
              'property_array_index':property_array_index}
        if not property_array_index is None:
            kw['property_array_index'] = property_array_index
        if not priority is None:
            kw['priority'] = priority
        obj_ids[k].list_of_properties.append(sequence.BACnetPropertyValue(*(),**kw))
    rp = APDU()
    rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU
    rp.choice = 16
    for obj_v in obj_ids.values():
        obj_v_enc = obj_v.encoding
        t = tag.encode(obj_v_enc)
        rp.data.fromstring(t)
    request_id = network.send_request(device, rp)
    r = recv_response(request_id)
    
    # @fixme Decode the BACnet-SimpleACK-PDU? and/or handle error rtns by defaulting to
    # write_prop_mults on each "obj_v" above, and then to indiv write_props on elems of
    # obj_v.list_of_properties...
    return r
Ejemplo n.º 8
0
def write_property(device, object, instance, property, arrayidx, priority,
                   value, btype):
    rp = APDU()
    rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU
    rp.choice = 15
    objectIdentifier = tag.Context(0,data.BACnetObjectIdentifier(object,instance))
    propertyIdentifier = tag.Context(1,data.encode_enumerated(property))
    propertyArrayIndex = None # @fixme Support arrayidx
    propertyValue = tag.Construct(3)
    if (priority):
        priorityTag = tag.Context(4,data.encode_enumerated(priority))
    
    if btype == 0:    propertyValue.value.append(tag.Null())
    elif btype == 1:  propertyValue.value.append(tag.Boolean(int(value)))
    elif btype == 2:  propertyValue.value.append(tag.UnsignedInteger(int(value)))
    elif btype == 3:  propertyValue.value.append(tag.SignedInteger(int(value)))
    elif btype == 4:  propertyValue.value.append(tag.Real(float(value)))
    elif btype == 5:  propertyValue.value.append(tag.Double(float(value)))
    elif btype == 6:  propertyValue.value.append(tag.OctetString(value))
    elif btype == 7:
        if type(value) == types.StringValue or type(value) == array.ArrayType:
            propertyValue.value.append(tag.CharacterString(data.ANSI_String(value)))
        else:
            propertyValue.value.append(tag.CharacterString(value))
    elif btype == 8:  propertyValue.value.append(tag.BitString(value))
    elif btype == 9:  propertyValue.value.append(tag.Enumerated(int(value)))
    elif btype == 10: propertyValue.value.append(tag.Date(value))
    elif btype == 11: propertyValue.value.append(tag.Time(value))
    elif btype == 12: propertyValue.value.append(tag.BACnetObjectIdentifier(value))
    else: raise EInvalidValue("btype", btype)

    if propertyArrayIndex is None:
        rp.data = objectIdentifier.encoding + propertyIdentifier.encoding + \
                  propertyValue.encoding
    else:
        rp.data = objectIdentifier.encoding + propertyIdentifier.encoding + \
                  propertyArrayIndex.encoding + propertyValue.encoding

    if (priority):  #optional priority tag
        rp.data = rp.data + priorityTag.encoding
        
    request_id = network.send_request(device, rp)
    r = recv_response(request_id)
    return r
Ejemplo n.º 9
0
def write_property_g3(device, prop_tuple, value_tag_list, priority=None):
    object = prop_tuple[0]
    instance = prop_tuple[1]
    property = prop_tuple[2]

    wpr = sequence.WritePropertyRequest()
    wpr.object_identifier = data.BACnetObjectIdentifier(object, instance)
    wpr.property_identifier = property
    if len(prop_tuple) > 3 and prop_tuple[3] != -1:
        wpr.property_array_index = prop_tuple[3]
    wpr.property_value = value_tag_list
    if priority is not None:
        wpr.priority = priority
    rp = APDU()
    rp.pdu_type = BACNET_CONFIRMED_SERVICE_REQUEST_PDU
    rp.choice = 15
    rp.data = tag.encode(wpr.encoding)
    request_id = network.send_request(device, rp)
    r = recv_response(request_id)
    return r
Ejemplo n.º 10
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
Ejemplo n.º 11
0
 def object_identifier(self):
     if debug: print 'return boid'
     return data.BACnetObjectIdentifier(self.object_type,
                                        self.instance_number)
Ejemplo n.º 12
0
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))