Ejemplo n.º 1
0
int bacapp_encode_device_obj_ref(
    uint8_t * apdu,
    BACNET_DEVICE_OBJECT_REFERENCE * value)
{
    int len;
    int apdu_len = 0;

    /* Device id is optional so see if needed
     * (set type to BACNET_NO_DEV_TYPE or something other than OBJECT_DEVICE to
	 * omit */

    if (value->deviceIndentifier.type == OBJECT_DEVICE) {
        len =
            encode_context_object_id(&apdu[apdu_len], 0,
            (int) value->deviceIndentifier.type,
            value->deviceIndentifier.instance);
        apdu_len += len;
    }

    len =
        encode_context_object_id(&apdu[apdu_len], 1,
        (int) value->objectIdentifier.type, value->objectIdentifier.instance);
    apdu_len += len;

    return apdu_len;
}
Ejemplo n.º 2
0
int wpm_error_ack_encode_apdu(
    uint8_t * apdu,
    uint8_t invoke_id,
    BACNET_WRITE_PROPERTY_DATA * wp_data)
{
    int len = 0;

    if (apdu) {
        apdu[len++] = PDU_TYPE_ERROR;
        apdu[len++] = invoke_id;
        apdu[len++] = SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE;

        len += encode_opening_tag(&apdu[len], 0);
        len += encode_application_enumerated(&apdu[len], wp_data->error_class);
        len += encode_application_enumerated(&apdu[len], wp_data->error_code);
        len += encode_closing_tag(&apdu[len], 0);

        len += encode_opening_tag(&apdu[len], 1);
        len +=
            encode_context_object_id(&apdu[len], 0, wp_data->object_type,
            wp_data->object_instance);
        len +=
            encode_context_enumerated(&apdu[len], 1, wp_data->object_property);

        if (wp_data->array_index != BACNET_ARRAY_ALL)
            len +=
                encode_context_unsigned(&apdu[len], 2, wp_data->array_index);
        len += encode_closing_tag(&apdu[len], 1);
    }
    return len;
}
Ejemplo n.º 3
0
int bacapp_encode_device_obj_property_ref(
    uint8_t * apdu,
    BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
{
    int len;
    int apdu_len = 0;

    len =
        encode_context_object_id(&apdu[apdu_len], 0,
        (int) value->objectIdentifier.type, value->objectIdentifier.instance);
    apdu_len += len;

    len =
        encode_context_enumerated(&apdu[apdu_len], 1,
        value->propertyIdentifier);
    apdu_len += len;

    /* Array index is optional so check if needed before inserting */
    if (value->arrayIndex != BACNET_ARRAY_ALL) {
        len = encode_context_unsigned(&apdu[apdu_len], 2, value->arrayIndex);
        apdu_len += len;
    }

    /* Likewise, device id is optional so see if needed
     * (set type to BACNET_NO_DEV_TYPE or something other than OBJECT_DEVICE to
	 * omit */

    if (value->deviceIndentifier.type == OBJECT_DEVICE) {
        len =
            encode_context_object_id(&apdu[apdu_len], 3,
            (int) value->deviceIndentifier.type,
            value->deviceIndentifier.instance);
        apdu_len += len;
    }
    return apdu_len;
}
Ejemplo n.º 4
0
/* encode service */
int wp_encode_apdu(
    uint8_t * apdu,
    uint8_t invoke_id,
    BACNET_WRITE_PROPERTY_DATA * wpdata)
{
    int apdu_len = 0;   /* total length of the apdu, return value */
    int len = 0;        /* total length of the apdu, return value */

    if (apdu) {
        apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
        apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
        apdu[2] = invoke_id;
        apdu[3] = SERVICE_CONFIRMED_WRITE_PROPERTY;     /* service choice */
        apdu_len = 4;
        len =
            encode_context_object_id(&apdu[apdu_len], 0, wpdata->object_type,
            wpdata->object_instance);
        apdu_len += len;
        len =
            encode_context_enumerated(&apdu[apdu_len], 1,
            wpdata->object_property);
        apdu_len += len;
        /* optional array index; ALL is -1 which is assumed when missing */
        if (wpdata->array_index != BACNET_ARRAY_ALL) {
            len =
                encode_context_unsigned(&apdu[apdu_len], 2,
                wpdata->array_index);
            apdu_len += len;
        }
        /* propertyValue */
        len = encode_opening_tag(&apdu[apdu_len], 3);
        apdu_len += len;
        for (len = 0; len < wpdata->application_data_len; len++) {
            apdu[apdu_len + len] = wpdata->application_data[len];
        }
        apdu_len += wpdata->application_data_len;
        len = encode_closing_tag(&apdu[apdu_len], 3);
        apdu_len += len;
        /* optional priority - 0 if not set, 1..16 if set */
        if (wpdata->priority != BACNET_NO_PRIORITY) {
            len =
                encode_context_unsigned(&apdu[apdu_len], 4, wpdata->priority);
            apdu_len += len;
        }
    }

    return apdu_len;
}
Ejemplo n.º 5
0
int wpm_encode_apdu_object_begin(
    uint8_t * apdu,
    BACNET_OBJECT_TYPE object_type,
    uint32_t object_instance)
{
    int apdu_len = 0;   /* total length of the apdu, return value */

    if (apdu) {
        apdu_len =
            encode_context_object_id(&apdu[0], 0, object_type,
            object_instance);
        /* Tag 1: sequence of WriteAccessSpecification */
        apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
    }

    return apdu_len;
}
Ejemplo n.º 6
0
int rpm_ack_encode_apdu_object_begin(
    uint8_t * apdu,
    BACNET_RPM_DATA * rpmdata)
{
    int apdu_len = 0;   /* total length of the apdu, return value */

    if (apdu) {
        /* Tag 0: objectIdentifier */
        apdu_len =
            encode_context_object_id(&apdu[0], 0, rpmdata->object_type,
            rpmdata->object_instance);
        /* Tag 1: listOfResults */
        apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
    }

    return apdu_len;
}
Ejemplo n.º 7
0
/***************************************************
**
** Encodes the service data part of Event Notification
**
****************************************************/
int alarm_ack_encode_service_request(
    uint8_t * apdu,
    BACNET_ALARM_ACK_DATA * data)
{
    int len = 0;        /* length of each encoding */
    int apdu_len = 0;   /* total length of the apdu, return value */

    if (apdu) {
        len =
            encode_context_unsigned(&apdu[apdu_len], 0,
                                    data->ackProcessIdentifier);
        apdu_len += len;

        len =
            encode_context_object_id(&apdu[apdu_len], 1,
                                     (int) data->eventObjectIdentifier.type,
                                     data->eventObjectIdentifier.instance);
        apdu_len += len;

        len =
            encode_context_enumerated(&apdu[apdu_len], 2,
                                      data->eventStateAcked);
        apdu_len += len;

        len =
            bacapp_encode_context_timestamp(&apdu[apdu_len], 3,
                                            &data->eventTimeStamp);
        apdu_len += len;

        len =
            encode_context_character_string(&apdu[apdu_len], 4,
                                            &data->ackSource);
        apdu_len += len;

        len =
            bacapp_encode_context_timestamp(&apdu[apdu_len], 5,
                                            &data->ackTimeStamp);
        apdu_len += len;
    }

    return apdu_len;
}
Ejemplo n.º 8
0
/* encode service */
int rp_encode_apdu(
    uint8_t * apdu,
    uint8_t invoke_id,
    BACNET_READ_PROPERTY_DATA * rpdata)
{
    int len = 0;        /* length of each encoding */
    int apdu_len = 0;   /* total length of the apdu, return value */

    if (apdu) {
        apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
        apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
        apdu[2] = invoke_id;
        apdu[3] = SERVICE_CONFIRMED_READ_PROPERTY;      /* service choice */
        apdu_len = 4;
        if (rpdata->object_type <= BACNET_MAX_OBJECT) {
            /* check bounds so that we could create malformed
               messages for testing */
            len =
                encode_context_object_id(&apdu[apdu_len], 0,
                rpdata->object_type, rpdata->object_instance);
            apdu_len += len;
        }
        if (rpdata->object_property <= 4194303) {
            /* check bounds so that we could create malformed
               messages for testing */
            len =
                encode_context_enumerated(&apdu[apdu_len], 1,
                rpdata->object_property);
            apdu_len += len;
        }
        /* optional array index */
        if (rpdata->array_index != BACNET_ARRAY_ALL) {
            len =
                encode_context_unsigned(&apdu[apdu_len], 2,
                rpdata->array_index);
            apdu_len += len;
        }
    }

    return apdu_len;
}
Ejemplo n.º 9
0
int lso_encode_apdu(
    uint8_t * apdu,
    uint8_t invoke_id,
    BACNET_LSO_DATA * data)
{
    int len = 0;        /* length of each encoding */
    int apdu_len = 0;   /* total length of the apdu, return value */

    if (apdu && data) {
        apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
        apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
        apdu[2] = invoke_id;
        apdu[3] = SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION;
        apdu_len = 4;
        /* tag 0 - requestingProcessId */
        len = encode_context_unsigned(&apdu[apdu_len], 0, data->processId);
        apdu_len += len;
        /* tag 1 - requestingSource */
        len =
            encode_context_character_string(&apdu[apdu_len], 1,
            &data->requestingSrc);
        apdu_len += len;
        /*
           Operation
         */
        len = encode_context_enumerated(&apdu[apdu_len], 2, data->operation);
        apdu_len += len;
        /*
           Object ID
         */

        len =
            encode_context_object_id(&apdu[apdu_len], 3,
            (int) data->targetObject.type, data->targetObject.instance);

        apdu_len += len;
    }

    return apdu_len;
}
Ejemplo n.º 10
0
int whohas_encode_apdu(
    uint8_t * apdu,
    BACNET_WHO_HAS_DATA * data)
{
    int len = 0;        /* length of each encoding */
    int apdu_len = 0;   /* total length of the apdu, return value */

    if (apdu && data) {
        apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
        apdu[1] = SERVICE_UNCONFIRMED_WHO_HAS;  /* service choice */
        apdu_len = 2;
        /* optional limits - must be used as a pair */
        if ((data->low_limit >= 0)
            && (data->low_limit <= BACNET_MAX_INSTANCE)
            && (data->high_limit >= 0)
            && (data->high_limit <= BACNET_MAX_INSTANCE)) {
            len = encode_context_unsigned(&apdu[apdu_len], 0, data->low_limit);
            apdu_len += len;
            len =
                encode_context_unsigned(&apdu[apdu_len], 1, data->high_limit);
            apdu_len += len;
        }
        if (data->object_name) {
            len =
                encode_context_character_string(&apdu[apdu_len], 3,
                &data->object.name);
            apdu_len += len;
        } else {
            len =
                encode_context_object_id(&apdu[apdu_len], 2,
                (int) data->object.identifier.type,
                data->object.identifier.instance);
            apdu_len += len;
        }
    }

    return apdu_len;
}
Ejemplo n.º 11
0
/* alternate method to encode the ack without extra buffer */
int rp_ack_encode_apdu_init(
    uint8_t * apdu,
    uint8_t invoke_id,
    BACNET_READ_PROPERTY_DATA * rpdata)
{
    int len = 0;        /* length of each encoding */
    int apdu_len = 0;   /* total length of the apdu, return value */

    if (apdu) {
        apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */
        apdu[1] = invoke_id;    /* original invoke id from request */
        apdu[2] = SERVICE_CONFIRMED_READ_PROPERTY;      /* service choice */
        apdu_len = 3;

        /* service ack follows */
        len =
            encode_context_object_id(&apdu[apdu_len], 0, rpdata->object_type,
            rpdata->object_instance);
        apdu_len += len;
        len =
            encode_context_enumerated(&apdu[apdu_len], 1,
            rpdata->object_property);
        apdu_len += len;
        /* context 2 array index is optional */
        if (rpdata->array_index != BACNET_ARRAY_ALL) {
            len =
                encode_context_unsigned(&apdu[apdu_len], 2,
                rpdata->array_index);
            apdu_len += len;
        }
        len = encode_opening_tag(&apdu[apdu_len], 3);
        apdu_len += len;
    }

    return apdu_len;
}
Ejemplo n.º 12
0
static int cov_encode_subscription(
    uint8_t * apdu,
    int max_apdu,
    BACNET_COV_SUBSCRIPTION * cov_subscription)
{
    int len = 0;
    int apdu_len = 0;
    BACNET_OCTET_STRING octet_string;

    /* FIXME: unused parameter */
    max_apdu = max_apdu;
    /* Recipient [0] BACnetRecipientProcess - opening */
    len = encode_opening_tag(&apdu[apdu_len], 0);
    apdu_len += len;
    /*  recipient [0] BACnetRecipient - opening */
    len = encode_opening_tag(&apdu[apdu_len], 0);
    apdu_len += len;
    /* CHOICE - address [1] BACnetAddress - opening */
    len = encode_opening_tag(&apdu[apdu_len], 1);
    apdu_len += len;
    /* network-number Unsigned16, */
    /* -- A value of 0 indicates the local network */
    len =
        encode_application_unsigned(&apdu[apdu_len],
        cov_subscription->dest.net);
    apdu_len += len;
    /* mac-address OCTET STRING */
    /* -- A string of length 0 indicates a broadcast */
    if (cov_subscription->dest.net) {
        octetstring_init(&octet_string, &cov_subscription->dest.adr[0],
            cov_subscription->dest.len);
    } else {
        octetstring_init(&octet_string, &cov_subscription->dest.mac[0],
            cov_subscription->dest.mac_len);
    }
    len = encode_application_octet_string(&apdu[apdu_len], &octet_string);
    apdu_len += len;
    /* CHOICE - address [1] BACnetAddress - closing */
    len = encode_closing_tag(&apdu[apdu_len], 1);
    apdu_len += len;
    /*  recipient [0] BACnetRecipient - closing */
    len = encode_closing_tag(&apdu[apdu_len], 0);
    apdu_len += len;
    /* processIdentifier [1] Unsigned32 */
    len =
        encode_context_unsigned(&apdu[apdu_len], 1,
        cov_subscription->subscriberProcessIdentifier);
    apdu_len += len;
    /* Recipient [0] BACnetRecipientProcess - closing */
    len = encode_closing_tag(&apdu[apdu_len], 0);
    apdu_len += len;
    /*  MonitoredPropertyReference [1] BACnetObjectPropertyReference, */
    len = encode_opening_tag(&apdu[apdu_len], 1);
    apdu_len += len;
    /* objectIdentifier [0] */
    len =
        encode_context_object_id(&apdu[apdu_len], 0,
        cov_subscription->monitoredObjectIdentifier.type,
        cov_subscription->monitoredObjectIdentifier.instance);
    apdu_len += len;
    /* propertyIdentifier [1] */
    /* FIXME: we are monitoring 2 properties! How to encode? */
    len = encode_context_enumerated(&apdu[apdu_len], 1, PROP_PRESENT_VALUE);
    apdu_len += len;
    /* MonitoredPropertyReference [1] - closing */
    len = encode_closing_tag(&apdu[apdu_len], 1);
    apdu_len += len;
    /* IssueConfirmedNotifications [2] BOOLEAN, */
    len =
        encode_context_boolean(&apdu[apdu_len], 2,
        cov_subscription->flag.issueConfirmedNotifications);
    apdu_len += len;
    /* TimeRemaining [3] Unsigned, */
    len =
        encode_context_unsigned(&apdu[apdu_len], 3,
        cov_subscription->lifetime);
    apdu_len += len;

    return apdu_len;
}
Ejemplo n.º 13
0
/** Encode an RPM request, to be sent.
 *
 * @param apdu [in,out] Buffer to hold encoded bytes.
 * @param max_apdu [in] Length of apdu buffer.
 * @param invoke_id [in] The Invoke ID to use for this message.
 * @param read_access_data [in] The RPM data to be requested.
 * @return Length of encoded bytes, or 0 on failure.
 */
int rpm_encode_apdu(
    uint8_t * apdu,
    size_t max_apdu,
    uint8_t invoke_id,
    BACNET_READ_ACCESS_DATA * read_access_data)
{
    int apdu_len = 0;   /* total length of the apdu, return value */
    int len = 0;        /* length of the data */
    BACNET_READ_ACCESS_DATA *rpm_object;        /* current object */
    uint8_t apdu_temp[16];      /* temp for data before copy */
    BACNET_PROPERTY_REFERENCE *rpm_property;    /* current property */

    len = rpm_encode_apdu_init(&apdu_temp[0], invoke_id);
    len =
        (int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len, (size_t) len,
        (size_t) max_apdu);
    if (len == 0) {
        return 0;
    }
    apdu_len += len;
    rpm_object = read_access_data;
    while (rpm_object) {
        len =
            encode_context_object_id(&apdu_temp[0], 0, rpm_object->object_type,
            rpm_object->object_instance);
        len =
            (int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
            (size_t) len, (size_t) max_apdu);
        if (len == 0) {
            return 0;
        }
        apdu_len += len;
        /* Tag 1: sequence of ReadAccessSpecification */
        len = encode_opening_tag(&apdu_temp[0], 1);
        len =
            (int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
            (size_t) len, (size_t) max_apdu);
        if (len == 0) {
            return 0;
        }
        apdu_len += len;
        rpm_property = rpm_object->listOfProperties;
        while (rpm_property) {
            /* stuff as many properties into it as APDU length will allow */
            len =
                encode_context_enumerated(&apdu_temp[0], 0,
                rpm_property->propertyIdentifier);
            len =
                (int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
                (size_t) len, (size_t) max_apdu);
            if (len == 0) {
                return 0;
            }
            apdu_len += len;
            /* optional array index */
            if (rpm_property->propertyArrayIndex != BACNET_ARRAY_ALL) {
                len =
                    encode_context_unsigned(&apdu_temp[0], 1,
                    rpm_property->propertyArrayIndex);
                len =
                    (int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
                    (size_t) len, (size_t) max_apdu);
                if (len == 0) {
                    return 0;
                }
                apdu_len += len;
            }
            rpm_property = rpm_property->next;
        }
        len = encode_closing_tag(&apdu_temp[0], 1);
        len =
            (int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
            (size_t) len, (size_t) max_apdu);
        if (len == 0) {
            return 0;
        }
        apdu_len += len;
        rpm_object = rpm_object->next;
    }

    return apdu_len;
}
Ejemplo n.º 14
0
int Notification_Class_Read_Property(
    BACNET_READ_PROPERTY_DATA * rpdata)
{
    NOTIFICATION_CLASS_INFO *CurrentNotify;
    BACNET_CHARACTER_STRING char_string;
    BACNET_OCTET_STRING octet_string;
    BACNET_BIT_STRING bit_string;
    uint8_t *apdu = NULL;
    uint8_t u8Val;
    int idx;
    int apdu_len = 0;   /* return value */


    if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
        (rpdata->application_data_len == 0)) {
        return 0;
    }

    apdu = rpdata->application_data;
    CurrentNotify =
        &NC_Info[Notification_Class_Instance_To_Index(rpdata->
            object_instance)];

    switch (rpdata->object_property) {
        case PROP_OBJECT_IDENTIFIER:
            apdu_len =
                encode_application_object_id(&apdu[0],
                OBJECT_NOTIFICATION_CLASS, rpdata->object_instance);
            break;

        case PROP_OBJECT_NAME:
        case PROP_DESCRIPTION:
            Notification_Class_Object_Name(rpdata->object_instance,
                &char_string);
            apdu_len =
                encode_application_character_string(&apdu[0], &char_string);
            break;

        case PROP_OBJECT_TYPE:
            apdu_len =
                encode_application_enumerated(&apdu[0],
                OBJECT_NOTIFICATION_CLASS);
            break;

        case PROP_NOTIFICATION_CLASS:
            apdu_len +=
                encode_application_unsigned(&apdu[0], rpdata->object_instance);
            break;

        case PROP_PRIORITY:
            if (rpdata->array_index == 0)
                apdu_len += encode_application_unsigned(&apdu[0], 3);
            else {
                if (rpdata->array_index == BACNET_ARRAY_ALL) {
                    apdu_len +=
                        encode_application_unsigned(&apdu[apdu_len],
                        CurrentNotify->Priority[TRANSITION_TO_OFFNORMAL]);
                    apdu_len +=
                        encode_application_unsigned(&apdu[apdu_len],
                        CurrentNotify->Priority[TRANSITION_TO_FAULT]);
                    apdu_len +=
                        encode_application_unsigned(&apdu[apdu_len],
                        CurrentNotify->Priority[TRANSITION_TO_NORMAL]);
                } else if (rpdata->array_index <= MAX_BACNET_EVENT_TRANSITION) {
                    apdu_len +=
                        encode_application_unsigned(&apdu[apdu_len],
                        CurrentNotify->Priority[rpdata->array_index - 1]);
                } else {
                    rpdata->error_class = ERROR_CLASS_PROPERTY;
                    rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
                    apdu_len = -1;
                }
            }
            break;

        case PROP_ACK_REQUIRED:
            u8Val = CurrentNotify->Ack_Required;

            bitstring_init(&bit_string);
            bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
                (u8Val & TRANSITION_TO_OFFNORMAL_MASKED) ? true : false);
            bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
                (u8Val & TRANSITION_TO_FAULT_MASKED) ? true : false);
            bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
                (u8Val & TRANSITION_TO_NORMAL_MASKED) ? true : false);
            /* encode bitstring */
            apdu_len +=
                encode_application_bitstring(&apdu[apdu_len], &bit_string);
            break;

        case PROP_RECIPIENT_LIST:
            /* encode all entry of Recipient_List */
            for (idx = 0; idx < NC_MAX_RECIPIENTS; idx++) {
                BACNET_DESTINATION *RecipientEntry;
                int i = 0;

                /* get pointer of current element for Recipient_List  - easier for use */
                RecipientEntry = &CurrentNotify->Recipient_List[idx];
                if (RecipientEntry->Recipient.RecipientType !=
                    RECIPIENT_TYPE_NOTINITIALIZED) {
                    /* Valid Days - BACnetDaysOfWeek - [bitstring] monday-sunday */
                    u8Val = 0x01;
                    bitstring_init(&bit_string);

                    for (i = 0; i < MAX_BACNET_DAYS_OF_WEEK; i++) {
                        if (RecipientEntry->ValidDays & u8Val)
                            bitstring_set_bit(&bit_string, i, true);
                        else
                            bitstring_set_bit(&bit_string, i, false);
                        u8Val <<= 1;    /* next day */
                    }
                    apdu_len +=
                        encode_application_bitstring(&apdu[apdu_len],
                        &bit_string);

                    /* From Time */
                    apdu_len +=
                        encode_application_time(&apdu[apdu_len],
                        &RecipientEntry->FromTime);

                    /* To Time */
                    apdu_len +=
                        encode_application_time(&apdu[apdu_len],
                        &RecipientEntry->ToTime);

                    /*
                       BACnetRecipient ::= CHOICE {
                       device [0] BACnetObjectIdentifier,
                       address [1] BACnetAddress
                       } */

                    /* CHOICE - device [0] BACnetObjectIdentifier */
                    if (RecipientEntry->Recipient.RecipientType ==
                        RECIPIENT_TYPE_DEVICE) {
                        apdu_len +=
                            encode_context_object_id(&apdu[apdu_len], 0,
                            OBJECT_DEVICE,
                            RecipientEntry->Recipient._.DeviceIdentifier);
                    }
                    /* CHOICE - address [1] BACnetAddress */
                    else if (RecipientEntry->Recipient.RecipientType ==
                        RECIPIENT_TYPE_ADDRESS) {
                        /* opening tag 1 */
                        apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
                        /* network-number Unsigned16, */
                        apdu_len +=
                            encode_application_unsigned(&apdu[apdu_len],
                            RecipientEntry->Recipient._.Address.net);

                        /* mac-address OCTET STRING */
                        if (RecipientEntry->Recipient._.Address.net) {
                            octetstring_init(&octet_string,
                                RecipientEntry->Recipient._.Address.adr,
                                RecipientEntry->Recipient._.Address.len);
                        } else {
                            octetstring_init(&octet_string,
                                RecipientEntry->Recipient._.Address.mac,
                                RecipientEntry->Recipient._.Address.mac_len);
                        }
                        apdu_len +=
                            encode_application_octet_string(&apdu[apdu_len],
                            &octet_string);

                        /* closing tag 1 */
                        apdu_len += encode_closing_tag(&apdu[apdu_len], 1);

                    } else {;
                    }   /* shouldn't happen */

                    /* Process Identifier - Unsigned32 */
                    apdu_len +=
                        encode_application_unsigned(&apdu[apdu_len],
                        RecipientEntry->ProcessIdentifier);

                    /* Issue Confirmed Notifications - boolean */
                    apdu_len +=
                        encode_application_boolean(&apdu[apdu_len],
                        RecipientEntry->ConfirmedNotify);

                    /* Transitions - BACnet Event Transition Bits [bitstring] */
                    u8Val = RecipientEntry->Transitions;

                    bitstring_init(&bit_string);
                    bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
                        (u8Val & TRANSITION_TO_OFFNORMAL_MASKED) ? true :
                        false);
                    bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
                        (u8Val & TRANSITION_TO_FAULT_MASKED) ? true : false);
                    bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
                        (u8Val & TRANSITION_TO_NORMAL_MASKED) ? true : false);

                    apdu_len +=
                        encode_application_bitstring(&apdu[apdu_len],
                        &bit_string);
                }
            }
            break;

        default:
            rpdata->error_class = ERROR_CLASS_PROPERTY;
            rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
            apdu_len = -1;
            break;
    }

    /*  only array properties can have array options */
    if ((apdu_len >= 0) && (rpdata->object_property != PROP_PRIORITY) &&
        (rpdata->array_index != BACNET_ARRAY_ALL)) {
        rpdata->error_class = ERROR_CLASS_PROPERTY;
        rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
        apdu_len = BACNET_STATUS_ERROR;
    }

    return apdu_len;
}