/** returns the invoke ID for confirmed request, or zero on failure */ uint8_t Send_Write_Property_Request_Data( BACNET_ADDRESS * dest, uint16_t max_apdu, BACNET_OBJECT_TYPE object_type, uint32_t object_instance, BACNET_PROPERTY_ID object_property, uint8_t * application_data, int application_data_len, uint8_t priority, uint32_t array_index) { BACNET_ADDRESS my_address; uint8_t invoke_id = 0; int len = 0; int pdu_len = 0; int bytes_sent = 0; BACNET_WRITE_PROPERTY_DATA data; BACNET_NPDU_DATA npdu_data; if (!dcc_communication_enabled()) return 0; /* is there a tsm available? */ invoke_id = tsm_next_free_invokeID(); if (invoke_id) { /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], dest, &my_address, &npdu_data); /* encode the APDU portion of the packet */ data.object_type = object_type; data.object_instance = object_instance; data.object_property = object_property; data.array_index = array_index; data.application_data_len = application_data_len; memcpy(&data.application_data[0], &application_data[0], application_data_len); data.priority = priority; len = wp_encode_apdu(&Handler_Transmit_Buffer[pdu_len], invoke_id, &data); pdu_len += len; /* will it fit in the sender? note: if there is a bottleneck router in between us and the destination, we won't know unless we have a way to check for that and update the max_apdu in the address binding table. */ if (pdu_len < max_apdu) { tsm_set_confirmed_unsegmented_transaction(invoke_id, dest, &npdu_data, &Handler_Transmit_Buffer[0], (uint16_t) pdu_len); bytes_sent = datalink_send_pdu(dest, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "Failed to Send WriteProperty Request (%s)!\n", strerror(errno)); #endif } else { tsm_free_invoke_id(invoke_id); invoke_id = 0; #if PRINT_ENABLED fprintf(stderr, "Failed to Send WriteProperty Request " "(exceeds destination maximum APDU)!\n"); #endif } } else { #if PRINT_ENABLED fprintf(stderr, "Ran out of invoke ids!\n"); #endif } return invoke_id; }
void testWritePropertyTag( Test * pTest, BACNET_APPLICATION_DATA_VALUE * value) { BACNET_WRITE_PROPERTY_DATA wpdata = { 0 }; BACNET_WRITE_PROPERTY_DATA test_data = { 0 }; BACNET_APPLICATION_DATA_VALUE test_value; uint8_t apdu[480] = { 0 }; int len = 0; int apdu_len = 0; uint8_t invoke_id = 128; uint8_t test_invoke_id = 0; wpdata.application_data_len = bacapp_encode_application_data(&wpdata.application_data[0], value); len = wp_encode_apdu(&apdu[0], invoke_id, &wpdata); ct_test(pTest, len != 0); /* decode the data */ apdu_len = len; len = wp_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data); ct_test(pTest, len != -1); ct_test(pTest, test_data.object_type == wpdata.object_type); ct_test(pTest, test_data.object_instance == wpdata.object_instance); ct_test(pTest, test_data.object_property == wpdata.object_property); ct_test(pTest, test_data.array_index == wpdata.array_index); /* decode the application value of the request */ len = bacapp_decode_application_data(test_data.application_data, test_data.application_data_len, &test_value); ct_test(pTest, test_value.tag == value->tag); switch (test_value.tag) { case BACNET_APPLICATION_TAG_NULL: break; case BACNET_APPLICATION_TAG_BOOLEAN: ct_test(pTest, test_value.type.Boolean == value->type.Boolean); break; case BACNET_APPLICATION_TAG_UNSIGNED_INT: ct_test(pTest, test_value.type.Unsigned_Int == value->type.Unsigned_Int); break; case BACNET_APPLICATION_TAG_SIGNED_INT: ct_test(pTest, test_value.type.Signed_Int == value->type.Signed_Int); break; case BACNET_APPLICATION_TAG_REAL: ct_test(pTest, test_value.type.Real == value->type.Real); break; case BACNET_APPLICATION_TAG_ENUMERATED: ct_test(pTest, test_value.type.Enumerated == value->type.Enumerated); break; case BACNET_APPLICATION_TAG_DATE: ct_test(pTest, test_value.type.Date.year == value->type.Date.year); ct_test(pTest, test_value.type.Date.month == value->type.Date.month); ct_test(pTest, test_value.type.Date.day == value->type.Date.day); ct_test(pTest, test_value.type.Date.wday == value->type.Date.wday); break; case BACNET_APPLICATION_TAG_TIME: ct_test(pTest, test_value.type.Time.hour == value->type.Time.hour); ct_test(pTest, test_value.type.Time.min == value->type.Time.min); ct_test(pTest, test_value.type.Time.sec == value->type.Time.sec); ct_test(pTest, test_value.type.Time.hundredths == value->type.Time.hundredths); break; case BACNET_APPLICATION_TAG_OBJECT_ID: ct_test(pTest, test_value.type.Object_Id.type == value->type.Object_Id.type); ct_test(pTest, test_value.type.Object_Id.instance == value->type.Object_Id.instance); break; default: break; } }