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; }
int ptransfer_error_encode_apdu( uint8_t * apdu, uint8_t invoke_id, BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code, BACNET_PRIVATE_TRANSFER_DATA * private_data) { int apdu_len = 0; /* total length of the apdu, return value */ int len = 0; /* length of the part of the encoding */ if (apdu) { apdu[0] = PDU_TYPE_ERROR; apdu[1] = invoke_id; apdu[2] = SERVICE_CONFIRMED_PRIVATE_TRANSFER; apdu_len = 3; /* service parameters */ /* ConfirmedPrivateTransfer-Error ::= SEQUENCE { errorType [0] Error, vendorID [1] Unsigned, serviceNumber [2] Unsigned, errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL } */ len = encode_opening_tag(&apdu[apdu_len], 0); apdu_len += len; len = encode_application_enumerated(&apdu[apdu_len], error_class); apdu_len += len; len = encode_application_enumerated(&apdu[apdu_len], error_code); apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], 0); apdu_len += len; len = encode_context_unsigned(&apdu[apdu_len], 1, private_data->vendorID); apdu_len += len; len = encode_context_unsigned(&apdu[apdu_len], 2, private_data->serviceNumber); apdu_len += len; len = encode_opening_tag(&apdu[apdu_len], 3); apdu_len += len; for (len = 0; len < private_data->serviceParametersLen; len++) { apdu[apdu_len] = private_data->serviceParameters[len]; apdu_len++; } len = encode_closing_tag(&apdu[apdu_len], 3); apdu_len += len; } return apdu_len; }
/* encode service */ int arf_ack_encode_apdu( uint8_t * apdu, uint8_t invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data) { int apdu_len = 0; /* total length of the apdu, return value */ uint32_t i = 0; if (apdu) { apdu[0] = PDU_TYPE_COMPLEX_ACK; apdu[1] = invoke_id; apdu[2] = SERVICE_CONFIRMED_ATOMIC_READ_FILE; /* service choice */ apdu_len = 3; /* endOfFile */ apdu_len += encode_application_boolean(&apdu[apdu_len], data->endOfFile); switch (data->access) { case FILE_STREAM_ACCESS: apdu_len += encode_opening_tag(&apdu[apdu_len], 0); apdu_len += encode_application_signed(&apdu[apdu_len], data->type.stream.fileStartPosition); apdu_len += encode_application_octet_string(&apdu[apdu_len], &data->fileData[0]); apdu_len += encode_closing_tag(&apdu[apdu_len], 0); break; case FILE_RECORD_ACCESS: apdu_len += encode_opening_tag(&apdu[apdu_len], 1); apdu_len += encode_application_signed(&apdu[apdu_len], data->type.record.fileStartRecord); apdu_len += encode_application_unsigned(&apdu[apdu_len], data->type.record.RecordCount); for (i = 0; i < data->type.record.RecordCount; i++) { apdu_len += encode_application_octet_string(&apdu[apdu_len], &data->fileData[i]); } apdu_len += encode_closing_tag(&apdu[apdu_len], 1); break; default: break; } } return apdu_len; }
/* encode service */ int pt_encode_apdu( uint8_t * apdu, uint16_t max_apdu, BACNET_PRIVATE_TRANSFER_DATA * private_data) { int len = 0; /* length of each encoding */ int apdu_len = 0; /* total length of the apdu, return value */ /* Unconfirmed/ConfirmedPrivateTransfer-Request ::= SEQUENCE { vendorID [0] Unsigned, serviceNumber [1] Unsigned, serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL } */ if (apdu) { len = encode_context_unsigned(&apdu[apdu_len], 0, private_data->vendorID); apdu_len += len; len = encode_context_unsigned(&apdu[apdu_len], 1, private_data->serviceNumber); apdu_len += len; len = encode_opening_tag(&apdu[apdu_len], 2); apdu_len += len; for (len = 0; len < private_data->serviceParametersLen; len++) { apdu[apdu_len] = private_data->serviceParameters[len]; apdu_len++; } len = encode_closing_tag(&apdu[apdu_len], 2); apdu_len += len; } return apdu_len; }
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; }
/* encode service */ int awf_encode_apdu( uint8_t * apdu, uint8_t invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data) { 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_ATOMIC_WRITE_FILE; /* service choice */ apdu_len = 4; apdu_len += encode_application_object_id(&apdu[apdu_len], data->object_type, data->object_instance); switch (data->access) { case FILE_STREAM_ACCESS: apdu_len += encode_opening_tag(&apdu[apdu_len], 0); apdu_len += encode_application_signed(&apdu[apdu_len], data->type.stream.fileStartPosition); apdu_len += encode_application_octet_string(&apdu[apdu_len], &data->fileData); apdu_len += encode_closing_tag(&apdu[apdu_len], 0); break; case FILE_RECORD_ACCESS: apdu_len += encode_opening_tag(&apdu[apdu_len], 1); apdu_len += encode_application_signed(&apdu[apdu_len], data->type.record.fileStartRecord); apdu_len += encode_application_unsigned(&apdu[apdu_len], data->type.record.returnedRecordCount); apdu_len += encode_application_octet_string(&apdu[apdu_len], &data->fileData); apdu_len += encode_closing_tag(&apdu[apdu_len], 1); break; default: break; } } return apdu_len; }
/** * Encodes into bytes from the lighting-command structure * a context tagged chunk (opening and closing tag) * * @param apdu - buffer to hold the bytes * @param tag_number - tag number to encode this chunk * @param value - lighting command value to encode * * @return number of bytes encoded, or 0 if unable to encode. */ int lighting_command_encode_context( uint8_t * apdu, uint8_t tag_number, BACNET_LIGHTING_COMMAND * value) { int apdu_len = 0; apdu_len += encode_opening_tag(&apdu[apdu_len], tag_number); apdu_len += lighting_command_encode(&apdu[apdu_len], value); apdu_len += encode_closing_tag(&apdu[apdu_len], tag_number); 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 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; }
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; }
int bacapp_encode_context_timestamp( uint8_t * apdu, uint8_t tag_number, BACNET_TIMESTAMP * value) { int len = 0; /* length of each encoding */ int apdu_len = 0; if (value && apdu) { len = encode_opening_tag(&apdu[apdu_len], tag_number); apdu_len += len; len = bacapp_encode_timestamp(&apdu[apdu_len], value); apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], tag_number); apdu_len += len; } return apdu_len; }
int bacapp_encode_context_time_value(uint8_t * apdu, uint8_t tag_number, BACNET_TIME_VALUE * value) { int len; int apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], tag_number); apdu_len += len; len = bacapp_encode_time_value(&apdu[apdu_len], value); apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], tag_number); apdu_len += len; return apdu_len; }
int rpm_ack_encode_apdu_object_property_error( uint8_t * apdu, BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code) { int apdu_len = 0; /* total length of the apdu, return value */ if (apdu) { /* Tag 5: propertyAccessError */ apdu_len += encode_opening_tag(&apdu[apdu_len], 5); apdu_len += encode_application_enumerated(&apdu[apdu_len], error_class); apdu_len += encode_application_enumerated(&apdu[apdu_len], error_code); apdu_len += encode_closing_tag(&apdu[apdu_len], 5); } return apdu_len; }
int bacapp_encode_context_access_rule( uint8_t * apdu, uint8_t tag_number, BACNET_ACCESS_RULE * rule) { int len; int apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], tag_number); apdu_len += len; len = bacapp_encode_access_rule(&apdu[apdu_len], rule); apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], tag_number); apdu_len += len; return apdu_len; }
int bacapp_encode_context_device_obj_property_ref( uint8_t * apdu, uint8_t tag_number, BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value) { int len; int apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], tag_number); apdu_len += len; len = bacapp_encode_device_obj_property_ref(&apdu[apdu_len], value); apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], tag_number); apdu_len += len; return apdu_len; }
int bacapp_encode_context_assigned_access_rights( uint8_t * apdu, uint8_t tag, BACNET_ASSIGNED_ACCESS_RIGHTS * aar) { int len; int apdu_len = 0; len = encode_opening_tag(&apdu[apdu_len], tag); apdu_len += len; len = bacapp_encode_assigned_access_rights(&apdu[apdu_len], aar); apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], tag); apdu_len += len; return apdu_len; }
int ptransfer_ack_encode_apdu( uint8_t * apdu, uint8_t invoke_id, BACNET_PRIVATE_TRANSFER_DATA * private_data) { 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_PRIVATE_TRANSFER; /* service choice */ apdu_len = 3; /* service ack follows */ /* ConfirmedPrivateTransfer-ACK ::= SEQUENCE { vendorID [0] Unsigned, serviceNumber [1] Unsigned, resultBlock [2] ABSTRACT-SYNTAX.&Type OPTIONAL } */ len = encode_context_unsigned(&apdu[apdu_len], 0, private_data->vendorID); apdu_len += len; len = encode_context_unsigned(&apdu[apdu_len], 1, private_data->serviceNumber); apdu_len += len; len = encode_opening_tag(&apdu[apdu_len], 2); apdu_len += len; for (len = 0; len < private_data->serviceParametersLen; len++) { apdu[apdu_len] = private_data->serviceParameters[len]; apdu_len++; } len = encode_closing_tag(&apdu[apdu_len], 2); apdu_len += len; } return apdu_len; }
int bacapp_encode_context_datetime( uint8_t * apdu, uint8_t tag_number, BACNET_DATE_TIME * value) { int len = 0; int apdu_len = 0; if (apdu && value) { len = encode_opening_tag(&apdu[apdu_len], tag_number); apdu_len += len; len = bacapp_encode_datetime(&apdu[apdu_len], value); apdu_len += len; len = encode_closing_tag(&apdu[apdu_len], tag_number); apdu_len += len; } return apdu_len; }
int rpm_ack_encode_apdu_object_property_value( uint8_t * apdu, uint8_t * application_data, unsigned application_data_len) { int apdu_len = 0; /* total length of the apdu, return value */ unsigned len = 0; if (apdu) { /* Tag 4: propertyValue */ apdu_len += encode_opening_tag(&apdu[apdu_len], 4); if (application_data == &apdu[apdu_len]) { /* Is Data already in place? */ apdu_len += application_data_len; /* Yes, step over data */ } else { /* No, copy data in */ for (len = 0; len < application_data_len; len++) { apdu[apdu_len++] = application_data[len]; } } apdu_len += encode_closing_tag(&apdu[apdu_len], 4); } 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; }
/** 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; }
/* return apdu len, or BACNET_STATUS_ERROR on error */ int Analog_Value_Read_Property( BACNET_READ_PROPERTY_DATA * rpdata) { int len = 0; int apdu_len = 0; /* return value */ BACNET_BIT_STRING bit_string; BACNET_CHARACTER_STRING char_string; float real_value = (float) 1.414; unsigned object_index = 0; unsigned i = 0; bool state = false; uint8_t *apdu = NULL; ANALOG_VALUE_DESCR *CurrentAV; if ((rpdata == NULL) || (rpdata->application_data == NULL) || (rpdata->application_data_len == 0)) { return 0; } apdu = rpdata->application_data; object_index = Analog_Value_Instance_To_Index(rpdata->object_instance); if (object_index < MAX_ANALOG_VALUES) CurrentAV = &AV_Descr[object_index]; else return BACNET_STATUS_ERROR; switch (rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE, rpdata->object_instance); break; case PROP_OBJECT_NAME: case PROP_DESCRIPTION: Analog_Value_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_ANALOG_VALUE); break; case PROP_PRESENT_VALUE: real_value = Analog_Value_Present_Value(rpdata->object_instance); apdu_len = encode_application_real(&apdu[0], real_value); break; case PROP_STATUS_FLAGS: bitstring_init(&bit_string); #if defined(INTRINSIC_REPORTING) bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, CurrentAV->Event_State ? true : false); #else bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false); #endif bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false); bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false); bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, CurrentAV->Out_Of_Service); apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_EVENT_STATE: #if defined(INTRINSIC_REPORTING) apdu_len = encode_application_enumerated(&apdu[0], CurrentAV->Event_State); #else apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL); #endif break; case PROP_OUT_OF_SERVICE: state = CurrentAV->Out_Of_Service; apdu_len = encode_application_boolean(&apdu[0], state); break; case PROP_UNITS: apdu_len = encode_application_enumerated(&apdu[0], CurrentAV->Units); break; #if defined(INTRINSIC_REPORTING) case PROP_TIME_DELAY: apdu_len = encode_application_unsigned(&apdu[0], CurrentAV->Time_Delay); break; case PROP_NOTIFICATION_CLASS: apdu_len = encode_application_unsigned(&apdu[0], CurrentAV->Notification_Class); break; case PROP_HIGH_LIMIT: apdu_len = encode_application_real(&apdu[0], CurrentAV->High_Limit); break; case PROP_LOW_LIMIT: apdu_len = encode_application_real(&apdu[0], CurrentAV->Low_Limit); break; case PROP_DEADBAND: apdu_len = encode_application_real(&apdu[0], CurrentAV->Deadband); break; case PROP_LIMIT_ENABLE: bitstring_init(&bit_string); bitstring_set_bit(&bit_string, 0, (CurrentAV-> Limit_Enable & EVENT_LOW_LIMIT_ENABLE) ? true : false); bitstring_set_bit(&bit_string, 1, (CurrentAV-> Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) ? true : false); apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_EVENT_ENABLE: bitstring_init(&bit_string); bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL, (CurrentAV-> Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true : false); bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT, (CurrentAV-> Event_Enable & EVENT_ENABLE_TO_FAULT) ? true : false); bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL, (CurrentAV-> Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true : false); apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_ACKED_TRANSITIONS: bitstring_init(&bit_string); bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL, CurrentAV->Acked_Transitions[TRANSITION_TO_OFFNORMAL]. bIsAcked); bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT, CurrentAV->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked); bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL, CurrentAV->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked); apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_NOTIFY_TYPE: apdu_len = encode_application_enumerated(&apdu[0], CurrentAV->Notify_Type ? NOTIFY_EVENT : NOTIFY_ALARM); break; case PROP_EVENT_TIME_STAMPS: /* Array element zero is the number of elements in the array */ if (rpdata->array_index == 0) apdu_len = encode_application_unsigned(&apdu[0], MAX_BACNET_EVENT_TRANSITION); /* if no index was specified, then try to encode the entire list */ /* into one packet. */ else if (rpdata->array_index == BACNET_ARRAY_ALL) { for (i = 0; i < MAX_BACNET_EVENT_TRANSITION; i++) {; len = encode_opening_tag(&apdu[apdu_len], TIME_STAMP_DATETIME); len += encode_application_date(&apdu[apdu_len + len], &CurrentAV->Event_Time_Stamps[i].date); len += encode_application_time(&apdu[apdu_len + len], &CurrentAV->Event_Time_Stamps[i].time); len += encode_closing_tag(&apdu[apdu_len + len], TIME_STAMP_DATETIME); /* add it if we have room */ if ((apdu_len + len) < MAX_APDU) apdu_len += len; else { rpdata->error_class = ERROR_CLASS_SERVICES; rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; apdu_len = BACNET_STATUS_ERROR; break; } } } else if (rpdata->array_index <= MAX_BACNET_EVENT_TRANSITION) { apdu_len = encode_opening_tag(&apdu[apdu_len], TIME_STAMP_DATETIME); apdu_len += encode_application_date(&apdu[apdu_len], &CurrentAV->Event_Time_Stamps[rpdata->array_index].date); apdu_len += encode_application_time(&apdu[apdu_len], &CurrentAV->Event_Time_Stamps[rpdata->array_index].time); apdu_len += encode_closing_tag(&apdu[apdu_len], TIME_STAMP_DATETIME); } else { rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; apdu_len = BACNET_STATUS_ERROR; } break; #endif default: rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = BACNET_STATUS_ERROR; break; } /* only array properties can have array options */ if ((apdu_len >= 0) && (rpdata->object_property != PROP_PRIORITY_ARRAY) && (rpdata->object_property != PROP_EVENT_TIME_STAMPS) && (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; }
int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata) { int apdu_len = 0; unsigned object_index = 0; SCHEDULE_DESCR *CurrentSC; uint8_t *apdu = NULL; BACNET_BIT_STRING bit_string; BACNET_CHARACTER_STRING char_string; int i; if ((rpdata == NULL) || (rpdata->application_data == NULL) || (rpdata->application_data_len == 0)) { return 0; } object_index = Schedule_Instance_To_Index(rpdata->object_instance); if (object_index < MAX_SCHEDULES) CurrentSC = &Schedule_Descr[object_index]; else return BACNET_STATUS_ERROR; apdu = rpdata->application_data; switch ((int) rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_SCHEDULE, rpdata->object_instance); break; case PROP_OBJECT_NAME: Schedule_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_SCHEDULE); break; case PROP_PRESENT_VALUE: apdu_len = bacapp_encode_data(&apdu[0], CurrentSC->Present_Value); break; case PROP_EFFECTIVE_PERIOD: apdu_len = encode_bacnet_date(&apdu[0], &CurrentSC->Start_Date); apdu_len += encode_bacnet_date(&apdu[apdu_len], &CurrentSC->End_Date); break; case PROP_WEEKLY_SCHEDULE: if (rpdata->array_index == 0) /* count, always 7 */ apdu_len = encode_application_unsigned(&apdu[0], 7); else if (rpdata->array_index == BACNET_ARRAY_ALL) { /* full array */ int day; for (day = 0; day < 7; day++) { apdu_len += encode_opening_tag(&apdu[apdu_len], 0); for (i = 0; i < CurrentSC->Weekly_Schedule[day].TV_Count; i++) { apdu_len += bacapp_encode_time_value(&apdu[apdu_len], &CurrentSC->Weekly_Schedule[day].Time_Values[i]); } apdu_len += encode_closing_tag(&apdu[apdu_len], 0); } } else if (rpdata->array_index <= 7) { /* some array element */ int day = rpdata->array_index - 1; apdu_len += encode_opening_tag(&apdu[apdu_len], 0); for (i = 0; i < CurrentSC->Weekly_Schedule[day].TV_Count; i++) { apdu_len += bacapp_encode_time_value(&apdu[apdu_len], &CurrentSC->Weekly_Schedule[day].Time_Values[i]); } apdu_len += encode_closing_tag(&apdu[apdu_len], 0); } else { /* out of bounds */ rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; apdu_len = BACNET_STATUS_ERROR; } break; case PROP_SCHEDULE_DEFAULT: apdu_len = bacapp_encode_data(&apdu[0], &CurrentSC->Schedule_Default); break; case PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES: for (i = 0; i < CurrentSC->obj_prop_ref_cnt; i++) { apdu_len += bacapp_encode_device_obj_property_ref(&apdu[apdu_len], &CurrentSC->Object_Property_References[i]); } break; case PROP_PRIORITY_FOR_WRITING: apdu_len = encode_application_unsigned(&apdu[0], CurrentSC->Priority_For_Writing); break; case PROP_STATUS_FLAGS: bitstring_init(&bit_string); bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false); bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false); bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false); bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false); apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_RELIABILITY: apdu_len = encode_application_enumerated(&apdu[0], RELIABILITY_NO_FAULT_DETECTED); break; case PROP_OUT_OF_SERVICE: apdu_len = encode_application_boolean(&apdu[0], false); break; default: rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = BACNET_STATUS_ERROR; break; } if ((apdu_len >= 0) && (rpdata->object_property != PROP_WEEKLY_SCHEDULE) && (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; }
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; }
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; }