diff --git a/bacnet-stack/apdu.h b/bacnet-stack/apdu.h index cce3e565..f5d994a1 100644 --- a/bacnet-stack/apdu.h +++ b/bacnet-stack/apdu.h @@ -62,19 +62,39 @@ typedef struct _confirmed_service_ack_data } BACNET_CONFIRMED_SERVICE_ACK_DATA; // generic unconfirmed function handler +// Suitable to handle the following services: +// I_Am, Who_Is, Unconfirmed_COV_Notification, I_Have, +// Unconfirmed_Event_Notification, Unconfirmed_Private_Transfer, +// Unconfirmed_Text_Message, Time_Synchronization, Who_Has, +// UTC_Time_Synchronization typedef void (*unconfirmed_function)( uint8_t *service_request, uint16_t len, BACNET_ADDRESS *src); // generic confirmed function handler +// Suitable to handle the following services: +// Acknowledge_Alarm, Confirmed_COV_Notification, +// Confirmed_Event_Notification, Get_Alarm_Summary, +// Get_Enrollment_Summary_Handler, Get_Event_Information, +// Subscribe_COV_Handler, Subscribe_COV_Property, +// Life_Safety_Operation, Atomic_Read_File, +// Confirmed_Atomic_Write_File, Add_List_Element, +// Remove_List_Element, Create_Object_Handler, +// Delete_Object_Handler, Read_Property, +// Read_Property_Conditional, Read_Property_Multiple, Read_Range, +// Write_Property, Write_Property_Multiple, +// Device_Communication_Control, Confirmed_Private_Transfer, +// Confirmed_Text_Message, Reinitialize_Device, +// VT_Open, VT_Close, VT_Data_Handler, +// Authenticate, Request_Key typedef void (*confirmed_function)( uint8_t *service_request, uint16_t service_len, BACNET_ADDRESS *src, BACNET_CONFIRMED_SERVICE_DATA *service_data); -// generic confirmed function handler +// generic confirmed simple ack function handler typedef void (*confirmed_simple_ack_function)( BACNET_ADDRESS *src, uint8_t invoke_id); diff --git a/bacnet-stack/bacdef.h b/bacnet-stack/bacdef.h index 8e2158a1..22916939 100644 --- a/bacnet-stack/bacdef.h +++ b/bacnet-stack/bacdef.h @@ -56,17 +56,6 @@ typedef struct BACnet_Object_Data BACNET_OBJECT_TYPE Object_Type; } BACNET_OBJECT_DATA; -typedef struct BACnet_Read_Property_Data -{ - BACNET_OBJECT_TYPE object_type; - uint32_t object_instance; - BACNET_PROPERTY_ID object_property; - int32_t array_index; - uint8_t *application_data; - int application_data_len; -} BACNET_READ_PROPERTY_DATA; - - #define BACNET_BROADCAST_NETWORK 0xFFFF #define MAX_MAC_LEN 8 struct BACnet_Device_Address { diff --git a/bacnet-stack/device.c b/bacnet-stack/device.c index 22d17079..be43882b 100644 --- a/bacnet-stack/device.c +++ b/bacnet-stack/device.c @@ -231,7 +231,7 @@ void Device_Set_Database_Revision(uint8_t revision) int Device_Encode_Property_APDU( uint8_t *apdu, BACNET_PROPERTY_ID property, - int array_index) + int32_t array_index) { int apdu_len = 0; // return value diff --git a/bacnet-stack/device.h b/bacnet-stack/device.h index 87fac700..fbead96f 100644 --- a/bacnet-stack/device.h +++ b/bacnet-stack/device.h @@ -82,7 +82,7 @@ void Device_Set_Database_Revision(uint8_t revision); int Device_Encode_Property_APDU( uint8_t *apdu, BACNET_PROPERTY_ID property, - int array_index); + int32_t array_index); #endif diff --git a/bacnet-stack/ports/linux/main.c b/bacnet-stack/ports/linux/main.c index 290b21c1..e1406663 100644 --- a/bacnet-stack/ports/linux/main.c +++ b/bacnet-stack/ports/linux/main.c @@ -19,6 +19,7 @@ // buffers used for transmit and receive static uint8_t Tx_Buf[MAX_MPDU] = {0}; static uint8_t Rx_Buf[MAX_MPDU] = {0}; +static uint8_t Temp_Buf[MAX_MPDU] = {0}; // flag to send an I-Am bool I_Am_Request = true; @@ -116,6 +117,117 @@ void WhoIsHandler( return; } +void ReadPropertyHandler( + uint8_t *service_request, + uint16_t service_len, + BACNET_ADDRESS *src, + BACNET_CONFIRMED_SERVICE_DATA *service_data) +{ + BACNET_CONFIRMED_SERVICE_DATA service_data; + BACNET_READ_PROPERTY_DATA rp_data; + int len = 0; + int pdu_len = 0; + BACNET_OBJECT_TYPE object_type; + uint32_t object_instance; + BACNET_PROPERTY_ID object_property; + int32_t array_index; + + fprintf(stderr,"Received Read-Property Request!\n"); + len = rp_decode_service_request( + service_request, + service_len, + &object_type, + &object_instance, + &object_property, + &array_index); + // bad encoding - send an abort + if (len == -1) + { + pdu_len = abort_encode_apdu( + &Tx_Buf[0], + service_data->invoke_id, + ABORT_REASON_OTHER); + (void)ethernet_send_pdu( + &src, // destination address + &Tx_Buf[0], + pdu_len); // number of bytes of data + fprintf(stderr,"Sent Abort!\n"); + } + else if (service_data->segmented_message) + { + pdu_len = abort_encode_apdu( + &Tx_Buf[0], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); + (void)ethernet_send_pdu( + &src, // destination address + &Tx_Buf[0], + pdu_len); // number of bytes of data + } + else + { + switch (object_type) + { + case OBJECT_DEVICE: + // FIXME: probably need a length limitation sent with encode + // FIXME: might need to return error codes + len = Device_Encode_Property_APDU( + &Temp_Buf[0], + object_property, + array_index); + if (len > 0) + { + rp_data.object_type = object_type; + rp_data.object_instance = object_instance; + rp_data.object_property = object_property; + rp_data.array_index = array_index; + rp_data.application_data = &Temp_Buf[0]; + rp_data.application_data_len = len; + // FIXME: probably need a length limitation sent with encode + pdu_len = rp_ack_encode_apdu( + &Tx_Buf[0], + service_data->invoke_id, + &rp_data); + (void)ethernet_send_pdu( + &src, // destination address + &Tx_Buf[0], + pdu_len); // number of bytes of data + fprintf(stderr,"Sent Read Property Ack!\n"); + } + else + { + pdu_len = bacerror_encode_apdu( + &Tx_Buf[0], + service_data->invoke_id, + SERVICE_CONFIRMED_READ_PROPERTY, + ERROR_CLASS_PROPERTY, + ERROR_CODE_UNKNOWN_PROPERTY); + (void)ethernet_send_pdu( + &src, // destination address + &Tx_Buf[0], + pdu_len); // number of bytes of data + fprintf(stderr,"Sent Unknown Property Error!\n"); + } + break; + default: + pdu_len = bacerror_encode_apdu( + &Tx_Buf[0], + service_data->invoke_id, + SERVICE_CONFIRMED_READ_PROPERTY, + ERROR_CLASS_OBJECT, + ERROR_CODE_UNKNOWN_OBJECT); + (void)ethernet_send_pdu( + &src, // destination address + &Tx_Buf[0], + pdu_len); // number of bytes of data + fprintf(stderr,"Sent Unknown Object Error!\n"); + break; + } + } + + return; +} + static void Init_Device_Parameters(void) { // configure my initial values @@ -185,7 +297,7 @@ static void Init_Service_Handlers(void) // FIXME: we must implement read property - it's required! apdu_set_confirmed_handler( SERVICE_CONFIRMED_READ_PROPERTY, - UnrecognizedServiceHandler); + ReadPropertyHandler); apdu_set_confirmed_handler( SERVICE_CONFIRMED_READ_PROPERTY_CONDITIONAL, UnrecognizedServiceHandler); diff --git a/bacnet-stack/rp.h b/bacnet-stack/rp.h index b87b43fc..a22359d6 100644 --- a/bacnet-stack/rp.h +++ b/bacnet-stack/rp.h @@ -37,6 +37,16 @@ #include #include +typedef struct BACnet_Read_Property_Data +{ + BACNET_OBJECT_TYPE object_type; + uint32_t object_instance; + BACNET_PROPERTY_ID object_property; + int32_t array_index; + uint8_t *application_data; + int application_data_len; +} BACNET_READ_PROPERTY_DATA; + // encode service - use -1 for limit if you want unlimited int rp_encode_apdu( uint8_t *apdu, diff --git a/bacnet-stack/test.sh b/bacnet-stack/test.sh index aa2df00e..e25747f2 100755 --- a/bacnet-stack/test.sh +++ b/bacnet-stack/test.sh @@ -44,6 +44,11 @@ make -f reject.mak ./reject >> test.log make -f reject.mak clean +make -f abort.mak clean +make -f abort.mak +./abort >> test.log +make -f abort.mak clean + make -f bacerror.mak clean make -f bacerror.mak ./bacerror >> test.log