int wpm_encode_apdu_object_property( uint8_t * apdu, BACNET_WRITE_PROPERTY_DATA * wpdata) { int apdu_len = 0; /* total length of the apdu, return value */ int len = 0; if (apdu) { apdu_len = encode_context_enumerated(&apdu[0], 0, wpdata->object_property); /* optional array index */ if (wpdata->array_index != BACNET_ARRAY_ALL) { apdu_len += encode_context_unsigned(&apdu[apdu_len], 1, wpdata->array_index); } apdu_len += encode_opening_tag(&apdu[apdu_len], 2); for (len = 0; len < wpdata->application_data_len; len++) { apdu[apdu_len] = wpdata->application_data[len]; apdu_len++; } apdu_len += encode_closing_tag(&apdu[apdu_len], 2); if (wpdata->priority != BACNET_NO_PRIORITY) { encode_context_unsigned(&apdu[apdu_len], 3, wpdata->priority); } } return apdu_len; }
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; }
/* encode service */ int rd_encode_apdu( uint8_t * apdu, uint8_t invoke_id, BACNET_REINITIALIZED_STATE state, BACNET_CHARACTER_STRING * password) { 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_REINITIALIZE_DEVICE; apdu_len = 4; len = encode_context_enumerated(&apdu[apdu_len], 0, state); apdu_len += len; /* optional password */ if (password) { /* FIXME: must be at least 1 character, limited to 20 characters */ len = encode_context_character_string(&apdu[apdu_len], 1, password); apdu_len += len; } } return apdu_len; }
int bacapp_encode_access_rule( uint8_t * apdu, BACNET_ACCESS_RULE * rule) { int len; int apdu_len = 0; len = encode_context_enumerated(&apdu[0], 0, rule->time_range_specifier); apdu_len += len; if (rule->time_range_specifier == TIME_RANGE_SPECIFIER_SPECIFIED) { len = bacapp_encode_context_device_obj_property_ref(&apdu[apdu_len], 1, &rule->time_range); if (len > 0) apdu_len += len; else return -1; } len = encode_context_enumerated(&apdu[apdu_len], 2, rule->location_specifier); apdu_len += len; if (rule->location_specifier == LOCATION_SPECIFIER_SPECIFIED) { len = bacapp_encode_context_device_obj_property_ref(&apdu[apdu_len], 3, &rule->location); if (len > 0) apdu_len += len; else return -1; } len = encode_context_boolean(&apdu[apdu_len], 4, rule->enable); apdu_len += len; return apdu_len; }
/* 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; }
int rpm_encode_apdu_object_property( uint8_t * apdu, BACNET_PROPERTY_ID object_property, uint32_t array_index) { int apdu_len = 0; /* total length of the apdu, return value */ if (apdu) { apdu_len = encode_context_enumerated(&apdu[0], 0, object_property); /* optional array index */ if (array_index != BACNET_ARRAY_ALL) apdu_len += encode_context_unsigned(&apdu[apdu_len], 1, array_index); } return apdu_len; }
int Lighting_Output_Encode_Lighting_Command( uint8_t * apdu, BACNET_LIGHTING_COMMAND * data) { int apdu_len = 0; /* total length of the apdu, return value */ int len = 0; /* total length of the apdu, return value */ float real_value = 0.0; uint32_t unsigned_value = 0; if (apdu) { len = encode_context_enumerated(&apdu[apdu_len], 0, data->operation); apdu_len += len; /* optional level? */ if (data->level != 255) { real_value = data->level; len = encode_context_real(&apdu[apdu_len], 1, real_value); apdu_len += len; } /* optional ramp-rate */ if (data->ramp_rate != 255) { real_value = data->ramp_rate; len = encode_context_real(&apdu[apdu_len], 2, real_value); apdu_len += len; } /* optional step increment */ if (data->step_increment != 255) { real_value = data->step_increment; len = encode_context_real(&apdu[apdu_len], 3, real_value); apdu_len += len; } /* optional fade time */ if (data->fade_time != 0) { real_value = data->fade_time; len = encode_context_real(&apdu[apdu_len], 4, real_value); apdu_len += len; } /* optional duration */ if (data->duration != 0) { unsigned_value = data->duration; len = encode_context_unsigned(&apdu[apdu_len], 5, unsigned_value); apdu_len += len; } } return apdu_len; }
/** * Encodes into bytes from the lighting-command structure * * @param apdu - buffer to hold the bytes * @param value - lighting command value to encode * * @return number of bytes encoded, or 0 if unable to encode. */ int lighting_command_encode( uint8_t * apdu, BACNET_LIGHTING_COMMAND * data) { int apdu_len = 0; /* total length of the apdu, return value */ int len = 0; /* total length of the apdu, return value */ if (apdu) { len = encode_context_enumerated(&apdu[apdu_len], 0, data->operation); apdu_len += len; /* optional target-level */ if (data->use_target_level) { len = encode_context_real(&apdu[apdu_len], 1, data->target_level); apdu_len += len; } /* optional ramp-rate */ if (data->use_ramp_rate) { len = encode_context_real(&apdu[apdu_len], 2, data->ramp_rate); apdu_len += len; } /* optional step increment */ if (data->use_step_increment) { len = encode_context_real(&apdu[apdu_len], 3, data->step_increment); apdu_len += len; } /* optional fade time */ if (data->use_fade_time) { len = encode_context_unsigned(&apdu[apdu_len], 4, data->fade_time); apdu_len += len; } /* optional priority */ if (data->use_priority) { len = encode_context_unsigned(&apdu[apdu_len], 5, data->priority); apdu_len += len; } } return apdu_len; }
int rpm_ack_encode_apdu_object_property( uint8_t * apdu, BACNET_PROPERTY_ID object_property, uint32_t array_index) { int apdu_len = 0; /* total length of the apdu, return value */ if (apdu) { /* Tag 2: propertyIdentifier */ apdu_len = encode_context_enumerated(&apdu[0], 2, object_property); /* Tag 3: optional propertyArrayIndex */ if (array_index != BACNET_ARRAY_ALL) apdu_len += encode_context_unsigned(&apdu[apdu_len], 3, array_index); } return apdu_len; }
/*************************************************** ** ** 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; }
/* 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; }
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; }
/* 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; }
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; }
/** 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; }
int bacapp_encode_property_state( uint8_t * apdu, BACNET_PROPERTY_STATE * value) { int len = 0; /* length of each encoding */ if (value && apdu) { switch (value->tag) { case BOOLEAN_VALUE: len = encode_context_boolean(&apdu[0], 0, value->state.booleanValue); break; case BINARY_VALUE: len = encode_context_enumerated(&apdu[0], 1, value->state.binaryValue); break; case EVENT_TYPE: len = encode_context_enumerated(&apdu[0], 2, value->state.eventType); break; case POLARITY: len = encode_context_enumerated(&apdu[0], 3, value->state.polarity); break; case PROGRAM_CHANGE: len = encode_context_enumerated(&apdu[0], 4, value->state.programChange); break; case PROGRAM_STATE: len = encode_context_enumerated(&apdu[0], 5, value->state.programState); break; case REASON_FOR_HALT: len = encode_context_enumerated(&apdu[0], 6, value->state.programError); break; case RELIABILITY: len = encode_context_enumerated(&apdu[0], 7, value->state.reliability); break; case STATE: len = encode_context_enumerated(&apdu[0], 8, value->state.state); break; case SYSTEM_STATUS: len = encode_context_enumerated(&apdu[0], 9, value->state.systemStatus); break; case UNITS: len = encode_context_enumerated(&apdu[0], 10, value->state.units); break; case UNSIGNED_VALUE: len = encode_context_unsigned(&apdu[0], 11, value->state.unsignedValue); break; case LIFE_SAFETY_MODE: len = encode_context_enumerated(&apdu[0], 12, value->state.lifeSafetyMode); break; case LIFE_SAFETY_STATE: len = encode_context_enumerated(&apdu[0], 13, value->state.lifeSafetyState); break; default: assert(0); break; } } return len; }
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; }