diff --git a/bacnet-stack/apdu.c b/bacnet-stack/apdu.c index 42e76431..d339ea46 100644 --- a/bacnet-stack/apdu.c +++ b/bacnet-stack/apdu.c @@ -272,8 +272,8 @@ uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */ return len; } -void apdu_handler(BACNET_ADDRESS * src, /* source address */ - bool data_expecting_reply, uint8_t * apdu, /* APDU data */ +void apdu_handler(BACNET_ADDRESS * src, + uint8_t * apdu, /* APDU data */ uint16_t apdu_len) { BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 }; @@ -289,7 +289,6 @@ void apdu_handler(BACNET_ADDRESS * src, /* source address */ int error_class = 0; uint8_t reason = 0; - (void) data_expecting_reply; if (apdu) { /* PDU Type */ switch (apdu[0] & 0xF0) { diff --git a/bacnet-stack/apdu.h b/bacnet-stack/apdu.h index b0372978..f1a6e07a 100644 --- a/bacnet-stack/apdu.h +++ b/bacnet-stack/apdu.h @@ -149,7 +149,7 @@ extern "C" { uint8_t ** service_request, uint16_t * service_request_len); void apdu_handler(BACNET_ADDRESS * src, /* source address */ - bool data_expecting_reply, uint8_t * apdu, /* APDU data */ + uint8_t * apdu, /* APDU data */ uint16_t pdu_len); /* for confirmed messages */ #ifdef __cplusplus diff --git a/bacnet-stack/bacapp.c b/bacnet-stack/bacapp.c index 6743112d..766b7e6a 100644 --- a/bacnet-stack/bacapp.c +++ b/bacnet-stack/bacapp.c @@ -240,7 +240,7 @@ bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value, return status; } -#if PRINT_ENABLED +#ifdef BACAPP_PRINT_ENABLED bool bacapp_print_value(FILE * stream, BACNET_APPLICATION_DATA_VALUE * value, BACNET_PROPERTY_ID property) { diff --git a/bacnet-stack/bacapp.h b/bacnet-stack/bacapp.h index 0275ab0e..f37f2283 100644 --- a/bacnet-stack/bacapp.h +++ b/bacnet-stack/bacapp.h @@ -73,6 +73,14 @@ extern "C" { BACNET_APPLICATION_DATA_VALUE * src_value); #if PRINT_ENABLED + #define BACAPP_PRINT_ENABLED +#else + #ifdef TEST + #define BACAPP_PRINT_ENABLED + #endif +#endif + +#ifdef BACAPP_PRINT_ENABLED bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number, const char *argv, BACNET_APPLICATION_DATA_VALUE * value); diff --git a/bacnet-stack/bacdef.h b/bacnet-stack/bacdef.h index a8839af2..839a733c 100644 --- a/bacnet-stack/bacdef.h +++ b/bacnet-stack/bacdef.h @@ -39,6 +39,10 @@ #include "bacenum.h" #include "config.h" +/* This stack implements this version of BACnet */ +#define BACNET_PROTOCOL_VERSION 1 +#define BACNET_PROTOCOL_REVISION 5 + /* largest BACnet Instance Number */ /* Also used as a device instance number wildcard address */ #define BACNET_MAX_INSTANCE (0x3FFFFF) diff --git a/bacnet-stack/bactext.h b/bacnet-stack/bactext.h index 72bbe56c..a5a40338 100644 --- a/bacnet-stack/bactext.h +++ b/bacnet-stack/bactext.h @@ -36,6 +36,14 @@ /* tiny implementations have no need to print */ #if PRINT_ENABLED + #define BACTEXT_PRINT_ENABLED +#else + #ifdef TEST + #define BACTEXT_PRINT_ENABLED + #endif +#endif + +#ifdef BACTEXT_PRINT_ENABLED #include #include @@ -70,6 +78,6 @@ extern "C" { } #endif /* __cplusplus */ -#endif +#endif /* BACTEXT_PRINT_ENABLED */ #endif diff --git a/bacnet-stack/bip.c b/bacnet-stack/bip.c index f41cf881..df09931c 100644 --- a/bacnet-stack/bip.c +++ b/bacnet-stack/bip.c @@ -136,67 +136,54 @@ uint16_t bip_get_port(void) return BIP_Port; } -/* function to send a packet out the BACnet/IP socket (Annex J) */ -/* returns number of bytes sent on success, negative number on failure */ -static int bip_send(struct sockaddr_in *bip_dest, uint8_t * pdu, /* any data to be sent - may be null */ - unsigned pdu_len) -{ /* number of bytes of data */ - uint8_t mtu[MAX_MPDU] = { 0 }; - int mtu_len = 0; - int bytes_sent = 0; - - /* assumes that the driver has already been initialized */ - if (BIP_Socket < 0) - return BIP_Socket; - - mtu[0] = BVLL_TYPE_BACNET_IP; - if (bip_dest->sin_addr.s_addr == htonl(BIP_Broadcast_Address.s_addr)) - mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; - else - mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU; - mtu_len = 2; - mtu_len += - encode_unsigned16(&mtu[mtu_len], - (uint16_t) (pdu_len + 4 /*inclusive */ )); - memcpy(&mtu[mtu_len], pdu, pdu_len); - mtu_len += pdu_len; - - /* Send the packet */ - bytes_sent = sendto(BIP_Socket, (char *) mtu, mtu_len, 0, - (struct sockaddr *) bip_dest, sizeof(struct sockaddr)); - - return bytes_sent; -} - /* function to send a packet out the BACnet/IP socket (Annex J) */ /* returns number of bytes sent on success, negative number on failure */ int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ uint8_t * pdu, /* any data to be sent - may be null */ unsigned pdu_len) { /* number of bytes of data */ struct sockaddr_in bip_dest; + uint8_t mtu[MAX_MPDU] = { 0 }; + int mtu_len = 0; + int bytes_sent = 0; + BACNET_ADDRESS src; - /* load destination IP address */ + /* assumes that the driver has already been initialized */ + if (BIP_Socket < 0) + return BIP_Socket; + + mtu[0] = BVLL_TYPE_BACNET_IP; bip_dest.sin_family = AF_INET; if (dest->mac_len == 6) { (void) decode_unsigned32(&dest->mac[0], &(bip_dest.sin_addr.s_addr)); (void) decode_unsigned16(&dest->mac[4], &(bip_dest.sin_port)); memset(&(bip_dest.sin_zero), '\0', 8); + mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU; } /* broadcast */ else if (dest->mac_len == 0) { bip_dest.sin_addr.s_addr = htonl(BIP_Broadcast_Address.s_addr); bip_dest.sin_port = htons(BIP_Port); memset(&(bip_dest.sin_zero), '\0', 8); + mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; } else return -1; - /* function to send a packet out the BACnet/IP socket */ - /* returns 1 on success, 0 on failure */ - return bip_send(&bip_dest, /* destination address */ - pdu, /* any data to be sent - may be null */ - pdu_len); /* number of bytes of data */ + /* len is encoded at mtu[2], but we haven't finished packing yet */ + bip_get_my_address(&src); + mtu_len = npdu_encode_pdu(&mtu[4], dest, &src, npdu_data); + mtu_len += 4; + memcpy(&mtu[mtu_len], pdu, pdu_len); + mtu_len += pdu_len; + encode_unsigned16(&mtu[2],mtu_len); + + /* Send the packet */ + bytes_sent = sendto(BIP_Socket, (char *) mtu, mtu_len, 0, + (struct sockaddr *) &bip_dest, sizeof(struct sockaddr)); + + return bytes_sent; } /* receives a BACnet/IP packet */ diff --git a/bacnet-stack/bip.h b/bacnet-stack/bip.h index 6bb05688..a997e433 100644 --- a/bacnet-stack/bip.h +++ b/bacnet-stack/bip.h @@ -38,6 +38,7 @@ #include #include #include "bacdef.h" +#include "npdu.h" #include "net.h" /* specific defines for BACnet/IP over Ethernet */ @@ -64,6 +65,7 @@ extern "C" { /* function to send a packet out the BACnet/IP socket */ /* returns zero on success, non-zero on failure */ int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ uint8_t * pdu, /* any data to be sent - may be null */ unsigned pdu_len); /* number of bytes of data */ diff --git a/bacnet-stack/config.h b/bacnet-stack/config.h index 0782e172..eae3ffd1 100644 --- a/bacnet-stack/config.h +++ b/bacnet-stack/config.h @@ -11,8 +11,8 @@ /* This is used in constructing messages and to tell others our limits */ /* 50 is the minimum; adjust to your memory and physical layer constraints */ /* Lon=206, MS/TP=480, ARCNET=480, Ethernet=1476 */ -#define MAX_APDU 50 -/* #define MAX_APDU 480 */ +/* #define MAX_APDU 50 */ +#define MAX_APDU 480 /* #define MAX_APDU 1476 */ /* for confirmed messages, this is the number of transactions */ @@ -20,13 +20,13 @@ /* Configure to zero if you don't want any confirmed messages */ /* Configure from 1..255 for number of outstanding confirmed */ /* requests available. */ -#define MAX_TSM_TRANSACTIONS 1 +#define MAX_TSM_TRANSACTIONS 255 /* The address cache is used for binding to BACnet devices */ /* The number of entries corresponds to the number of */ /* devices that might respond to an I-Am on the network. */ /* If your device is a simple server and does not need to bind, */ /* then you don't need to use this. */ -#define MAX_ADDRESS_CACHE 2 +#define MAX_ADDRESS_CACHE 255 #endif diff --git a/bacnet-stack/cov.c b/bacnet-stack/cov.c index dedc538b..77ffbba9 100644 --- a/bacnet-stack/cov.c +++ b/bacnet-stack/cov.c @@ -274,6 +274,31 @@ int cov_notify_decode_service_request(uint8_t * apdu, return len; } +int ucov_notify_send(uint8_t * buffer, BACNET_COV_DATA * data) +{ + int pdu_len = 0; + BACNET_ADDRESS dest; + int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; + + /* unconfirmed is a broadcast */ + datalink_get_broadcast_address(&dest); + /* encode the APDU portion of the packet */ + pdu_len = ucov_notify_encode_apdu(&buffer[0], data); + /* encode the NPDU portion of the packet */ + npdu_encode_unconfirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + /* send the data */ + bytes_sent = datalink_send_pdu(&dest, &npdu_data, &buffer[0], pdu_len); + + return bytes_sent; +} + +#ifdef TEST +#include +#include +#include "ctest.h" +#include "bacapp.h" + int ccov_notify_decode_apdu(uint8_t * apdu, unsigned apdu_len, uint8_t * invoke_id, BACNET_COV_DATA * data) { @@ -325,44 +350,17 @@ int ucov_notify_decode_apdu(uint8_t * apdu, return len; } -int ucov_notify_send(uint8_t * buffer, BACNET_COV_DATA * data) -{ - int pdu_len = 0; - BACNET_ADDRESS dest; - int bytes_sent = 0; - - /* unconfirmed is a broadcast */ - datalink_get_broadcast_address(&dest); - - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&buffer[0], &dest, NULL, - false /* true for confirmed messages */ , - MESSAGE_PRIORITY_NORMAL); - - /* encode the APDU portion of the packet */ - pdu_len += ucov_notify_encode_apdu(&buffer[pdu_len], data); - - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &buffer[0], pdu_len); /* number of bytes of data */ - - return bytes_sent; -} - -#ifdef TEST -#include -#include -#include "ctest.h" -#include "bacapp.h" /* dummy function stubs */ -int npdu_encode_apdu(uint8_t * npdu, BACNET_ADDRESS * dest, BACNET_ADDRESS * src, bool data_expecting_reply, /* true for confirmed messages */ +void npdu_encode_unconfirmed_apdu(BACNET_NPDU_DATA * npdu, BACNET_MESSAGE_PRIORITY priority) { - return 0; + return; } /* dummy function stubs */ int datalink_send_pdu(BACNET_ADDRESS * dest, /* destination address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ uint8_t * pdu, /* any data to be sent - may be null */ unsigned pdu_len) { /* number of bytes of data */ diff --git a/bacnet-stack/datalink.c b/bacnet-stack/datalink.c index 2f9f590c..0e834389 100644 --- a/bacnet-stack/datalink.c +++ b/bacnet-stack/datalink.c @@ -42,20 +42,20 @@ /* returns number of bytes sent on success, negative on failure */ int datalink_send_pdu(BACNET_ADDRESS * dest, /* destination address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ uint8_t * pdu, /* any data to be sent - may be null */ unsigned pdu_len) { /* number of bytes of data */ -#ifdef BACDL_ARCNET - return arcnet_send_pdu(dest, pdu, pdu_len); -#endif -#ifdef BACDL_MSTP - return dlmstp_send_pdu(dest, pdu, pdu_len); -#endif -#ifdef BACDL_ETHERNET - return ethernet_send_pdu(dest, pdu, pdu_len); -#endif -#ifdef BACDL_BIP - return bip_send_pdu(dest, pdu, pdu_len); +#if defined(BACDL_ARCNET) + return arcnet_send_pdu(dest, npdu_data, pdu, pdu_len); +#elif defined(BACDL_MSTP) + return dlmstp_send_pdu(dest, npdu_data, pdu, pdu_len); +#elif defined(BACDL_ETHERNET) + return ethernet_send_pdu(dest, npdu_data, pdu, pdu_len); +#elif defined(BACDL_BIP) + return bip_send_pdu(dest, npdu_data, pdu, pdu_len); +#else + return 0; #endif } @@ -65,64 +65,54 @@ uint16_t datalink_receive(BACNET_ADDRESS * src, /* source address */ uint16_t max_pdu, /* amount of space available in the PDU */ unsigned timeout) { /* number of milliseconds to wait for a packet */ -#ifdef BACDL_ARCNET +#if defined(BACDL_ARCNET) return arcnet_receive(src, pdu, max_pdu, timeout); -#endif -#ifdef BACDL_MSTP +#elif defined(BACDL_MSTP) return dlmstp_receive(src, pdu, max_pdu, timeout); -#endif -#ifdef BACDL_ETHERNET +#elif defined(BACDL_ETHERNET) return ethernet_receive(src, pdu, max_pdu, timeout); -#endif -#ifdef BACDL_BIP +#elif defined(BACDL_BIP) return bip_receive(src, pdu, max_pdu, timeout); +#else + return 0; #endif } void datalink_cleanup(void) { -#ifdef BACDL_ETHERNET - ethernet_cleanup(); -#endif -#ifdef BACDL_BIP - bip_cleanup(); -#endif -#ifdef BACDL_ARCNET +#if defined(BACDL_ARCNET) arcnet_cleanup(); -#endif -#ifdef BACDL_MSTP +#elif defined(BACDL_MSTP) dlmstp_cleanup(); +#elif defined(BACDL_ETHERNET) + ethernet_cleanup(); +#elif defined(BACDL_BIP) + bip_cleanup(); #endif } void datalink_get_broadcast_address(BACNET_ADDRESS * dest) { /* destination address */ -#ifdef BACDL_ARCNET +#if defined(BACDL_ARCNET) arcnet_get_broadcast_address(dest); -#endif -#ifdef BACDL_MSTP +#elif defined(BACDL_MSTP) dlmstp_get_broadcast_address(dest); -#endif -#ifdef BACDL_ETHERNET +#elif defined(BACDL_ETHERNET) ethernet_get_broadcast_address(dest); -#endif -#ifdef BACDL_BIP +#elif defined(BACDL_BIP) bip_get_broadcast_address(dest); #endif } void datalink_get_my_address(BACNET_ADDRESS * my_address) { -#ifdef BACDL_ARCNET +#if defined(BACDL_ARCNET) arcnet_get_my_address(my_address); -#endif -#ifdef BACDL_MSTP +#elif defined(BACDL_MSTP) dlmstp_get_my_address(my_address); -#endif -#ifdef BACDL_ETHERNET +#elif defined(BACDL_ETHERNET) ethernet_get_my_address(my_address); -#endif -#ifdef BACDL_BIP +#elif defined(BACDL_BIP) bip_get_my_address(my_address); #endif } diff --git a/bacnet-stack/datalink.h b/bacnet-stack/datalink.h index 769ffeb1..6451e69a 100644 --- a/bacnet-stack/datalink.h +++ b/bacnet-stack/datalink.h @@ -38,6 +38,7 @@ #include #include #include "bacdef.h" +#include "npdu.h" #ifdef BACDL_ETHERNET #include "ethernet.h" @@ -61,6 +62,7 @@ extern "C" { /* returns number of bytes sent on success, negative on failure */ int datalink_send_pdu(BACNET_ADDRESS * dest, /* destination address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ uint8_t * pdu, /* any data to be sent - may be null */ unsigned pdu_len); /* number of bytes of data */ diff --git a/bacnet-stack/demo/handler/client.h b/bacnet-stack/demo/handler/client.h index b823e7bf..459efee2 100644 --- a/bacnet-stack/demo/handler/client.h +++ b/bacnet-stack/demo/handler/client.h @@ -76,6 +76,13 @@ extern "C" { void Send_TimeSync(BACNET_DATE * bdate, BACNET_TIME * btime); void Send_TimeSyncUTC(BACNET_DATE * bdate, BACNET_TIME * btime); + uint8_t Send_Atomic_Read_File_Stream(uint32_t device_id, + uint32_t file_instance, int fileStartPosition, + unsigned requestedOctetCount); + uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id, + uint32_t file_instance, + int fileStartPosition, BACNET_OCTET_STRING * fileData); + #ifdef __cplusplus } diff --git a/bacnet-stack/demo/handler/h_arf.c b/bacnet-stack/demo/handler/h_arf.c index 96f9c5ca..5d9d4955 100644 --- a/bacnet-stack/demo/handler/h_arf.c +++ b/bacnet-stack/demo/handler/h_arf.c @@ -48,75 +48,65 @@ void handler_atomic_read_file(uint8_t * service_request, BACNET_ATOMIC_READ_FILE_DATA data; int len = 0; int pdu_len = 0; - BACNET_ADDRESS my_address; - bool send = false; bool error = false; int bytes_sent = 0; - BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; - BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; + BACNET_NPDU_DATA npdu_data; + #if PRINT_ENABLED fprintf(stderr, "Received Atomic-Read-File Request!\n"); + #endif len = arf_decode_service_request(service_request, service_len, &data); - if (len < 0) - fprintf(stderr, "Unable to decode Atomic-Read-File Request!\n"); /* prepare a reply */ - datalink_get_my_address(&my_address); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* bad decoding - send an abort */ if (len < 0) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_OTHER); - fprintf(stderr, "Sending Abort!\n"); - send = true; + #if PRINT_ENABLED + fprintf(stderr, "Bad Encoding. Sending Abort!\n"); + #endif } else if (service_data->segmented_message) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); - fprintf(stderr, "Sending Abort!\n"); - send = true; + #if PRINT_ENABLED + fprintf(stderr, "Segmented Message. Sending Abort!\n"); + #endif } else { if (data.access == FILE_STREAM_ACCESS) { if (data.type.stream.requestedOctetCount < octetstring_capacity(&data.fileData)) { if (bacfile_read_data(&data)) { - pdu_len += - arf_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); - send = true; + pdu_len = arf_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); } else { - send = true; error = true; } } else { - pdu_len += - abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); - fprintf(stderr, "Sending Abort!\n"); - send = true; + #if PRINT_ENABLED + fprintf(stderr, "Too Big To Send. Sending Abort!\n"); + #endif } } else { - error_class = ERROR_CLASS_SERVICES; - error_code = ERROR_CODE_INVALID_FILE_ACCESS_METHOD; - send = true; - error = true; + pdu_len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, SERVICE_CONFIRMED_ATOMIC_READ_FILE, + ERROR_CLASS_SERVICES, ERROR_CODE_INVALID_FILE_ACCESS_METHOD); + #if PRINT_ENABLED + fprintf(stderr, "Record Access Requested. Sending Error!\n"); + #endif } } - if (error) { - pdu_len += bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code); - fprintf(stderr, "Sending Error!\n"); - send = true; - } - if (send) { - bytes_sent = datalink_send_pdu(src, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ - if (bytes_sent <= 0) - fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno)); + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + bytes_sent = datalink_send_pdu(src, &npdu_data, + &Handler_Transmit_Buffer[0], pdu_len); + #if PRINT_ENABLED + if (bytes_sent <= 0) { + fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno)); } + #endif return; } diff --git a/bacnet-stack/demo/handler/h_arf_a.c b/bacnet-stack/demo/handler/h_arf_a.c index 47a1d3d0..956bfc6d 100644 --- a/bacnet-stack/demo/handler/h_arf_a.c +++ b/bacnet-stack/demo/handler/h_arf_a.c @@ -62,7 +62,9 @@ void handler_atomic_read_file_ack(uint8_t * service_request, instance = bacfile_instance_from_tsm(service_data->invoke_id); len = arf_ack_decode_service_request(service_request, service_len, &data); + #if PRINT_ENABLED fprintf(stderr, "Received Read-File Ack!\n"); + #endif if ((len > 0) && (instance <= BACNET_MAX_INSTANCE)) { /* write the data received to the file specified */ if (data.access == FILE_STREAM_ACCESS) { @@ -75,8 +77,12 @@ void handler_atomic_read_file_ack(uint8_t * service_request, if (fwrite(octetstring_value(&data.fileData), octetstring_length(&data.fileData), 1, pFile) != 1) + { + #if PRINT_ENABLED fprintf(stderr, "Failed to write to %s (%u)!\n", pFilename, instance); + #endif + } fclose(pFile); } } diff --git a/bacnet-stack/demo/handler/h_dcc.c b/bacnet-stack/demo/handler/h_dcc.c index 420a0af5..3e67b8cb 100644 --- a/bacnet-stack/demo/handler/h_dcc.c +++ b/bacnet-stack/demo/handler/h_dcc.c @@ -38,7 +38,7 @@ #include "reject.h" #include "dcc.h" -static char *My_Password = "AnnaRoseKarg"; +static char *My_Password = "filister"; void handler_device_communication_control(uint8_t * service_request, uint16_t service_len, @@ -49,8 +49,8 @@ void handler_device_communication_control(uint8_t * service_request, BACNET_CHARACTER_STRING password; int len = 0; int pdu_len = 0; - BACNET_ADDRESS my_address; int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; /* decode the service request only */ len = dcc_decode_service_request(service_request, @@ -62,25 +62,17 @@ void handler_device_communication_control(uint8_t * service_request, "timeout=%u state=%u password=%s\n", (unsigned) timeDuration, (unsigned) state, characterstring_value(&password)); - else - fprintf(stderr, "DeviceCommunicationControl: " - "Unable to decode request!\n"); #endif - /* prepare a reply */ - datalink_get_my_address(&my_address); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* bad decoding or something we didn't understand - send an abort */ - if (len == -1) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + if (len < 0) { + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_OTHER); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Abort - could not decode.\n"); #endif } else if (service_data->segmented_message) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); #if PRINT_ENABLED @@ -88,7 +80,7 @@ void handler_device_communication_control(uint8_t * service_request, "Sending Abort - segmented message.\n"); #endif } else if (state >= MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) { - pdu_len += reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = reject_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " @@ -96,7 +88,7 @@ void handler_device_communication_control(uint8_t * service_request, #endif } else { if (characterstring_ansi_same(&password, My_Password)) { - pdu_len += encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL); #if PRINT_ENABLED @@ -105,8 +97,8 @@ void handler_device_communication_control(uint8_t * service_request, #endif dcc_set_status_duration(state, timeDuration); } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE); @@ -117,8 +109,9 @@ void handler_device_communication_control(uint8_t * service_request, #endif } } - bytes_sent = datalink_send_pdu(src, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + bytes_sent = datalink_send_pdu(src, &npdu_data, + &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "DeviceCommunicationControl: " diff --git a/bacnet-stack/demo/handler/h_iam.c b/bacnet-stack/demo/handler/h_iam.c index 6c141075..aee70359 100644 --- a/bacnet-stack/demo/handler/h_iam.c +++ b/bacnet-stack/demo/handler/h_iam.c @@ -44,12 +44,19 @@ void handler_i_am_add(uint8_t * service_request, (void) service_len; len = iam_decode_service_request(service_request, &device_id, &max_apdu, &segmentation, &vendor_id); + #if PRINT_ENABLED fprintf(stderr, "Received I-Am Request"); + #endif if (len != -1) { + #if PRINT_ENABLED fprintf(stderr, " from %u!\n", device_id); + #endif address_add(device_id, max_apdu, src); - } else + } else { + #if PRINT_ENABLED fprintf(stderr, "!\n"); + #endif + } return; } diff --git a/bacnet-stack/demo/handler/h_ihave.c b/bacnet-stack/demo/handler/h_ihave.c index 9a97ecc0..92447c49 100644 --- a/bacnet-stack/demo/handler/h_ihave.c +++ b/bacnet-stack/demo/handler/h_ihave.c @@ -43,13 +43,18 @@ void handler_i_have(uint8_t * service_request, len = ihave_decode_service_request(service_request, service_len, &data); if (len != -1) { + #if PRINT_ENABLED fprintf(stderr, "I-Have: %s %d from %s %u!\r\n", bactext_object_type_name(data.object_id.type), data.object_id.instance, bactext_object_type_name(data.device_id.type), data.device_id.instance); - } else + #endif + } else { + #if PRINT_ENABLED fprintf(stderr, "I-Have: received, but unable to decode!\n"); + #endif + } return; } diff --git a/bacnet-stack/demo/handler/h_rd.c b/bacnet-stack/demo/handler/h_rd.c index 9b13eea5..0913162b 100644 --- a/bacnet-stack/demo/handler/h_rd.c +++ b/bacnet-stack/demo/handler/h_rd.c @@ -49,7 +49,7 @@ void handler_reinitialize_device(uint8_t * service_request, BACNET_CHARACTER_STRING their_password; int len = 0; int pdu_len = 0; - BACNET_ADDRESS my_address; + BACNET_NPDU_DATA npdu_data; int bytes_sent = 0; /* decode the service request only */ @@ -63,21 +63,16 @@ void handler_reinitialize_device(uint8_t * service_request, else fprintf(stderr, "ReinitializeDevice: Unable to decode request!\n"); #endif - /* prepare a reply */ - datalink_get_my_address(&my_address); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* bad decoding or something we didn't understand - send an abort */ - if (len == -1) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + if (len < 0) { + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_OTHER); #if PRINT_ENABLED fprintf(stderr, "ReinitializeDevice: Sending Abort - could not decode.\n"); #endif } else if (service_data->segmented_message) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); #if PRINT_ENABLED @@ -85,7 +80,7 @@ void handler_reinitialize_device(uint8_t * service_request, "ReinitializeDevice: Sending Abort - segmented message.\n"); #endif } else if (state >= MAX_BACNET_REINITIALIZED_STATE) { - pdu_len += reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = reject_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); #if PRINT_ENABLED fprintf(stderr, @@ -94,7 +89,7 @@ void handler_reinitialize_device(uint8_t * service_request, } else { characterstring_init_ansi(&My_Password, Password); if (characterstring_same(&their_password, &My_Password)) { - pdu_len += encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE); #if PRINT_ENABLED @@ -105,8 +100,8 @@ void handler_reinitialize_device(uint8_t * service_request, /* Note: if you don't do something clever like actually restart, you probably should clear any DCC status and timeouts */ } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE, ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE); @@ -116,8 +111,9 @@ void handler_reinitialize_device(uint8_t * service_request, #endif } } - bytes_sent = datalink_send_pdu(src, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + bytes_sent = datalink_send_pdu(src, &npdu_data, + &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "ReinitializeDevice: Failed to send PDU (%s)!\n", diff --git a/bacnet-stack/demo/handler/h_rp.c b/bacnet-stack/demo/handler/h_rp.c index dbe93dfd..db39a3a2 100644 --- a/bacnet-stack/demo/handler/h_rp.c +++ b/bacnet-stack/demo/handler/h_rp.c @@ -58,7 +58,7 @@ void handler_read_property(uint8_t * service_request, BACNET_READ_PROPERTY_DATA data; int len = 0; int pdu_len = 0; - BACNET_ADDRESS my_address; + BACNET_NPDU_DATA npdu_data; bool send = false; bool error = false; int bytes_sent = 0; @@ -70,21 +70,16 @@ void handler_read_property(uint8_t * service_request, if (len <= 0) fprintf(stderr, "Unable to decode Read-Property Request!\n"); #endif - /* prepare a reply */ - datalink_get_my_address(&my_address); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* bad decoding - send an abort */ - if (len == -1) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + if (len < 0) { + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_OTHER); #if PRINT_ENABLED fprintf(stderr, "Sending Abort!\n"); #endif send = true; } else if (service_data->segmented_message) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); #if PRINT_ENABLED @@ -104,9 +99,8 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for Device!\n"); @@ -128,9 +122,9 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for AI!\n"); #endif @@ -151,9 +145,9 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for BI!\n"); #endif @@ -174,9 +168,8 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for BO!\n"); #endif @@ -197,9 +190,9 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for BV!\n"); #endif @@ -220,9 +213,9 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for AO!\n"); #endif @@ -243,9 +236,9 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for AV!\n"); #endif @@ -266,9 +259,9 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for LSP!\n"); @@ -290,9 +283,9 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for MSO!\n"); @@ -315,9 +308,9 @@ void handler_read_property(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); + pdu_len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], + service_data->invoke_id, &data); #if PRINT_ENABLED fprintf(stderr, "Sending Read Property Ack for File!\n"); @@ -335,7 +328,7 @@ void handler_read_property(uint8_t * service_request, } } if (error) { - pdu_len += bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code); #if PRINT_ENABLED @@ -344,7 +337,8 @@ void handler_read_property(uint8_t * service_request, send = true; } if (send) { - bytes_sent = datalink_send_pdu(src, /* destination address */ + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ #if PRINT_ENABLED if (bytes_sent <= 0) diff --git a/bacnet-stack/demo/handler/h_wp.c b/bacnet-stack/demo/handler/h_wp.c index 5aee0185..5e2f69d9 100644 --- a/bacnet-stack/demo/handler/h_wp.c +++ b/bacnet-stack/demo/handler/h_wp.c @@ -56,7 +56,7 @@ void handler_write_property(uint8_t * service_request, BACNET_WRITE_PROPERTY_DATA wp_data; int len = 0; int pdu_len = 0; - BACNET_ADDRESS my_address; + BACNET_NPDU_DATA npdu_data; BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; int bytes_sent = 0; @@ -64,6 +64,7 @@ void handler_write_property(uint8_t * service_request, /* decode the service request only */ len = wp_decode_service_request(service_request, service_len, &wp_data); + #if PRINT_ENABLED fprintf(stderr, "Received Write-Property Request!\n"); if (len > 0) fprintf(stderr, "type=%u instance=%u property=%u index=%d\n", @@ -72,192 +73,231 @@ void handler_write_property(uint8_t * service_request, wp_data.object_property, wp_data.array_index); else fprintf(stderr, "Unable to decode Write-Property Request!\n"); - /* prepare a reply */ - datalink_get_my_address(&my_address); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); + #endif /* bad decoding or something we didn't understand - send an abort */ - if (len == -1) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + if (len <= 0) { + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_OTHER); + #if PRINT_ENABLED fprintf(stderr, "Sending Abort!\n"); + #endif } else if (service_data->segmented_message) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); + #if PRINT_ENABLED fprintf(stderr, "Sending Abort!\n"); + #endif } else { switch (wp_data.object_type) { case OBJECT_DEVICE: if (Device_Write_Property(&wp_data, &error_class, &error_code)) { - pdu_len += - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for Device!\n"); + #endif } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Error for Device!\n"); + #endif } break; case OBJECT_ANALOG_INPUT: case OBJECT_BINARY_INPUT: error_class = ERROR_CLASS_PROPERTY; error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error!\n"); + #endif break; case OBJECT_BINARY_OUTPUT: if (Binary_Output_Write_Property(&wp_data, &error_class, &error_code)) { - pdu_len += - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for BO!\n"); + #endif } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for BO!\n"); + #endif } break; case OBJECT_BINARY_VALUE: if (Binary_Value_Write_Property(&wp_data, &error_class, &error_code)) { - pdu_len += - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for BV!\n"); + #endif } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for BV!\n"); + #endif } break; case OBJECT_ANALOG_OUTPUT: if (Analog_Output_Write_Property(&wp_data, &error_class, &error_code)) { - pdu_len += - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for AO!\n"); + #endif } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for AO!\n"); + #endif } break; case OBJECT_ANALOG_VALUE: if (Analog_Value_Write_Property(&wp_data, &error_class, &error_code)) { - pdu_len += - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for AV!\n"); + #endif } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for AV!\n"); + #endif } break; case OBJECT_LIFE_SAFETY_POINT: if (Life_Safety_Point_Write_Property(&wp_data, &error_class, &error_code)) { - pdu_len += - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for LSP!\n"); + #endif } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for LSP!\n"); + #endif } break; case OBJECT_MULTI_STATE_OUTPUT: if (Multistate_Output_Write_Property(&wp_data, &error_class, &error_code)) { - pdu_len += - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for MSO!\n"); + #endif } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for MSO!\n"); + #endif } break; #if BACFILE case OBJECT_FILE: if (bacfile_write_property(&wp_data, &error_class, &error_code)) { - pdu_len += - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + encode_simple_ack(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for File!\n"); + #endif } else { - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for File!\n"); + #endif } break; #endif default: - pdu_len += - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); + #if PRINT_ENABLED fprintf(stderr, "Sending Unknown Object Error!\n"); + #endif break; } } - bytes_sent = datalink_send_pdu(src, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + bytes_sent = datalink_send_pdu(src, &npdu_data, + &Handler_Transmit_Buffer[0], pdu_len); + #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno)); + #endif return; } diff --git a/bacnet-stack/demo/handler/noserv.c b/bacnet-stack/demo/handler/noserv.c index ada64e6a..86da2742 100644 --- a/bacnet-stack/demo/handler/noserv.c +++ b/bacnet-stack/demo/handler/noserv.c @@ -38,26 +38,25 @@ void handler_unrecognized_service(uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * dest, BACNET_CONFIRMED_SERVICE_DATA * service_data) { - BACNET_ADDRESS src; int pdu_len = 0; int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; (void) service_request; (void) service_len; - datalink_get_my_address(&src); - - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], dest, &src, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* encode the APDU portion of the packet */ - pdu_len += reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = reject_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, REJECT_REASON_UNRECOGNIZED_SERVICE); - - bytes_sent = datalink_send_pdu(dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + /* encode the NPDU portion of the packet */ + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + /* send the data */ + bytes_sent = datalink_send_pdu(dest, &npdu_data, + &Handler_Transmit_Buffer[0], pdu_len); + #if PRINT_ENABLED if (bytes_sent > 0) fprintf(stderr, "Sent Reject!\n"); else fprintf(stderr, "Failed to Send Reject (%s)!\n", strerror(errno)); + #endif } diff --git a/bacnet-stack/demo/handler/s_arfs.c b/bacnet-stack/demo/handler/s_arfs.c new file mode 100644 index 00000000..5a2f81bd --- /dev/null +++ b/bacnet-stack/demo/handler/s_arfs.c @@ -0,0 +1,99 @@ +/************************************************************************** +* +* Copyright (C) 2006 Steve Karg +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +*********************************************************************/ +#include +#include +#include +#include "config.h" +#include "config.h" +#include "txbuf.h" +#include "bacdef.h" +#include "bacdcode.h" +#include "address.h" +#include "tsm.h" +#include "npdu.h" +#include "apdu.h" +#include "device.h" +#include "datalink.h" +#include "arf.h" +/* some demo stuff needed */ +#include "handlers.h" +#include "txbuf.h" + +uint8_t Send_Atomic_Read_File_Stream(uint32_t device_id, + uint32_t file_instance, + int fileStartPosition, unsigned requestedOctetCount) +{ + BACNET_ADDRESS dest; + BACNET_NPDU_DATA npdu_data; + unsigned max_apdu = 0; + uint8_t invoke_id = 0; + bool status = false; + int pdu_len = 0; + int bytes_sent = 0; + BACNET_ATOMIC_READ_FILE_DATA data; + + /* is the device bound? */ + status = address_get_by_device(device_id, &max_apdu, &dest); + /* is there a tsm available? */ + if (status) + invoke_id = tsm_next_free_invokeID(); + if (invoke_id) { + /* load the data for the encoding */ + data.object_type = OBJECT_FILE; + data.object_instance = file_instance; + data.access = FILE_STREAM_ACCESS; + data.type.stream.fileStartPosition = fileStartPosition; + data.type.stream.requestedOctetCount = requestedOctetCount; + pdu_len = arf_encode_apdu(&Handler_Transmit_Buffer[0], + invoke_id, &data); + /* will the APDU fit the target device? + 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 ((unsigned) pdu_len < max_apdu) { + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + tsm_set_confirmed_unsegmented_transaction(invoke_id, + &dest, &npdu_data, &Handler_Transmit_Buffer[0], 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 AtomicReadFile Request (%s)!\n", + strerror(errno)); + #endif + } else { + tsm_free_invoke_id(invoke_id); + invoke_id = 0; + #if PRINT_ENABLED + fprintf(stderr, "Failed to Send AtomicReadFile Request " + "(payload exceeds destination maximum APDU)!\n"); + #endif + } + } + + return invoke_id; +} diff --git a/bacnet-stack/demo/handler/s_awfs.c b/bacnet-stack/demo/handler/s_awfs.c new file mode 100644 index 00000000..8d118922 --- /dev/null +++ b/bacnet-stack/demo/handler/s_awfs.c @@ -0,0 +1,111 @@ +/************************************************************************** +* +* Copyright (C) 2006 Steve Karg +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +*********************************************************************/ +#include +#include +#include +#include "config.h" +#include "config.h" +#include "txbuf.h" +#include "bacdef.h" +#include "bacdcode.h" +#include "address.h" +#include "tsm.h" +#include "npdu.h" +#include "apdu.h" +#include "device.h" +#include "datalink.h" +#include "awf.h" +/* some demo stuff needed */ +#include "handlers.h" +#include "txbuf.h" + +uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id, + uint32_t file_instance, + int fileStartPosition, BACNET_OCTET_STRING * fileData) +{ + BACNET_ADDRESS dest; + BACNET_NPDU_DATA npdu_data; + unsigned max_apdu = 0; + uint8_t invoke_id = 0; + bool status = false; + int pdu_len = 0; + int bytes_sent = 0; + BACNET_ATOMIC_WRITE_FILE_DATA data; + + /* is the device bound? */ + status = address_get_by_device(device_id, &max_apdu, &dest); + /* is there a tsm available? */ + if (status) + invoke_id = tsm_next_free_invokeID(); + if (invoke_id) { + /* load the data for the encoding */ + data.object_type = OBJECT_FILE; + data.object_instance = file_instance; + data.access = FILE_STREAM_ACCESS; + data.type.stream.fileStartPosition = fileStartPosition; + status = octetstring_copy(&data.fileData, fileData); + if (status) { + pdu_len = awf_encode_apdu(&Handler_Transmit_Buffer[0], + invoke_id, &data); + /* will the APDU fit the target device? + 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 ((unsigned) pdu_len <= max_apdu) { + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + tsm_set_confirmed_unsegmented_transaction(invoke_id, + &dest, &npdu_data, &Handler_Transmit_Buffer[0], 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 AtomicWriteFile Request (%s)!\n", + strerror(errno)); + #endif + } else { + tsm_free_invoke_id(invoke_id); + invoke_id = 0; + #if PRINT_ENABLED + fprintf(stderr, "Failed to Send AtomicWriteFile Request " + "(payload [%d] exceeds destination maximum APDU [%u])!\n", + pdu_len, max_apdu); + #endif + } + } else { + tsm_free_invoke_id(invoke_id); + invoke_id = 0; + #if PRINT_ENABLED + fprintf(stderr, "Failed to Send AtomicWriteFile Request " + "(payload [%d] exceeds octet string capacity)!\n", + pdu_len); + #endif + } + } + + return invoke_id; +} + diff --git a/bacnet-stack/demo/handler/s_dcc.c b/bacnet-stack/demo/handler/s_dcc.c index 6e4476be..62063744 100644 --- a/bacnet-stack/demo/handler/s_dcc.c +++ b/bacnet-stack/demo/handler/s_dcc.c @@ -45,13 +45,13 @@ uint8_t Send_Device_Communication_Control_Request(uint32_t device_id, uint16_t t BACNET_COMMUNICATION_ENABLE_DISABLE state, char *password) { /* NULL=optional */ BACNET_ADDRESS dest; - BACNET_ADDRESS my_address; unsigned max_apdu = 0; uint8_t invoke_id = 0; bool status = false; int pdu_len = 0; int bytes_sent = 0; BACNET_CHARACTER_STRING password_string; + BACNET_NPDU_DATA npdu_data; if (!dcc_communication_enabled()) return 0; @@ -60,16 +60,11 @@ uint8_t Send_Device_Communication_Control_Request(uint32_t device_id, uint16_t t status = address_get_by_device(device_id, &max_apdu, &dest); /* is there a tsm available? */ if (status) - status = tsm_transaction_available(); - if (status) { - datalink_get_my_address(&my_address); - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - invoke_id = tsm_next_free_invokeID(); + if (invoke_id) { /* load the data for the encoding */ characterstring_init_ansi(&password_string, password); - pdu_len += dcc_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = dcc_encode_apdu(&Handler_Transmit_Buffer[0], invoke_id, timeDuration, state, password ? &password_string : NULL); /* will it fit in the sender? @@ -78,18 +73,26 @@ uint8_t Send_Device_Communication_Control_Request(uint32_t device_id, uint16_t t we have a way to check for that and update the max_apdu in the address binding table. */ if ((unsigned) pdu_len < max_apdu) { + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); tsm_set_confirmed_unsegmented_transaction(invoke_id, - &dest, &Handler_Transmit_Buffer[0], pdu_len); - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + &dest, &npdu_data, &Handler_Transmit_Buffer[0], 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 DeviceCommunicationControl Request (%s)!\n", strerror(errno)); - } else + #endif + } else { + tsm_free_invoke_id(invoke_id); + invoke_id = 0; + #if PRINT_ENABLED fprintf(stderr, "Failed to Send DeviceCommunicationControl Request " "(exceeds destination maximum APDU)!\n"); + #endif + } } return invoke_id; diff --git a/bacnet-stack/demo/handler/s_ihave.c b/bacnet-stack/demo/handler/s_ihave.c index 0e8bf622..ac036066 100644 --- a/bacnet-stack/demo/handler/s_ihave.c +++ b/bacnet-stack/demo/handler/s_ihave.c @@ -51,26 +51,27 @@ void Send_I_Have(uint32_t device_id, BACNET_ADDRESS dest; int bytes_sent = 0; BACNET_I_HAVE_DATA data; + BACNET_NPDU_DATA npdu_data; /* if we are forbidden to send, don't send! */ if (!dcc_communication_enabled()) return; /* Who-Has is a global broadcast */ datalink_get_broadcast_address(&dest); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* encode the APDU portion of the packet */ data.device_id.type = OBJECT_DEVICE; data.device_id.instance = device_id; data.object_id.type = object_type; data.object_id.instance = object_instance; characterstring_init_ansi(&data.object_name, object_name); - pdu_len += ihave_encode_apdu(&Handler_Transmit_Buffer[pdu_len], &data); + pdu_len = ihave_encode_apdu(&Handler_Transmit_Buffer[0], &data); /* send the data */ - bytes_sent = datalink_send_pdu(&dest, /* destination address */ + npdu_encode_unconfirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + bytes_sent = datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "Failed to Send I-Have Reply (%s)!\n", strerror(errno)); + #endif } diff --git a/bacnet-stack/demo/handler/s_rd.c b/bacnet-stack/demo/handler/s_rd.c index 506642ba..5a5dd0ce 100644 --- a/bacnet-stack/demo/handler/s_rd.c +++ b/bacnet-stack/demo/handler/s_rd.c @@ -46,13 +46,13 @@ uint8_t Send_Reinitialize_Device_Request(uint32_t device_id, BACNET_REINITIALIZED_STATE state, char *password) { BACNET_ADDRESS dest; - BACNET_ADDRESS my_address; unsigned max_apdu = 0; uint8_t invoke_id = 0; bool status = false; int pdu_len = 0; int bytes_sent = 0; BACNET_CHARACTER_STRING password_string; + BACNET_NPDU_DATA npdu_data; if (!dcc_communication_enabled()) return 0; @@ -61,16 +61,11 @@ uint8_t Send_Reinitialize_Device_Request(uint32_t device_id, status = address_get_by_device(device_id, &max_apdu, &dest); /* is there a tsm available? */ if (status) - status = tsm_transaction_available(); - if (status) { - datalink_get_my_address(&my_address); - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - invoke_id = tsm_next_free_invokeID(); + if (invoke_id) { /* load the data for the encoding */ characterstring_init_ansi(&password_string, password); - pdu_len += rd_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = rd_encode_apdu(&Handler_Transmit_Buffer[0], invoke_id, state, password ? &password_string : NULL); /* will it fit in the sender? note: if there is a bottleneck router in between @@ -78,17 +73,25 @@ uint8_t Send_Reinitialize_Device_Request(uint32_t device_id, we have a way to check for that and update the max_apdu in the address binding table. */ if ((unsigned) pdu_len < max_apdu) { + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); tsm_set_confirmed_unsegmented_transaction(invoke_id, - &dest, &Handler_Transmit_Buffer[0], pdu_len); - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + &dest, &npdu_data, &Handler_Transmit_Buffer[0], 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 ReinitializeDevice Request (%s)!\n", strerror(errno)); - } else + #endif + } else { + tsm_free_invoke_id(invoke_id); + invoke_id = 0; + #if PRINT_ENABLED fprintf(stderr, "Failed to Send ReinitializeDevice Request " "(exceeds destination maximum APDU)!\n"); + #endif + } } return invoke_id; diff --git a/bacnet-stack/demo/handler/s_rp.c b/bacnet-stack/demo/handler/s_rp.c index 6d74f50b..7e4651bb 100644 --- a/bacnet-stack/demo/handler/s_rp.c +++ b/bacnet-stack/demo/handler/s_rp.c @@ -49,13 +49,13 @@ uint8_t Send_Read_Property_Request(uint32_t device_id, /* destination device */ BACNET_PROPERTY_ID object_property, int32_t array_index) { BACNET_ADDRESS dest; - BACNET_ADDRESS my_address; unsigned max_apdu = 0; uint8_t invoke_id = 0; bool status = false; int pdu_len = 0; int bytes_sent = 0; BACNET_READ_PROPERTY_DATA data; + BACNET_NPDU_DATA npdu_data; if (!dcc_communication_enabled()) return 0; @@ -64,19 +64,14 @@ uint8_t Send_Read_Property_Request(uint32_t device_id, /* destination device */ status = address_get_by_device(device_id, &max_apdu, &dest); /* is there a tsm available? */ if (status) - status = tsm_transaction_available(); - if (status) { - datalink_get_my_address(&my_address); - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - invoke_id = tsm_next_free_invokeID(); + if (invoke_id) { /* load the data for the encoding */ data.object_type = object_type; data.object_instance = object_instance; data.object_property = object_property; data.array_index = array_index; - pdu_len += rp_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = rp_encode_apdu(&Handler_Transmit_Buffer[0], invoke_id, &data); /* will it fit in the sender? note: if there is a bottleneck router in between @@ -84,17 +79,25 @@ uint8_t Send_Read_Property_Request(uint32_t device_id, /* destination device */ we have a way to check for that and update the max_apdu in the address binding table. */ if ((unsigned) pdu_len < max_apdu) { + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); tsm_set_confirmed_unsegmented_transaction(invoke_id, - &dest, &Handler_Transmit_Buffer[0], pdu_len); - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + &dest, &npdu_data, &Handler_Transmit_Buffer[0], 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 ReadProperty Request (%s)!\n", strerror(errno)); - } else + #endif + } else { + tsm_free_invoke_id(invoke_id); + invoke_id = 0; + #if PRINT_ENABLED fprintf(stderr, "Failed to Send ReadProperty Request " "(exceeds destination maximum APDU)!\n"); + #endif + } } return invoke_id; diff --git a/bacnet-stack/demo/handler/s_ts.c b/bacnet-stack/demo/handler/s_ts.c index 01e85f30..154f032b 100644 --- a/bacnet-stack/demo/handler/s_ts.c +++ b/bacnet-stack/demo/handler/s_ts.c @@ -47,25 +47,26 @@ void Send_TimeSync(BACNET_DATE * bdate, BACNET_TIME * btime) int pdu_len = 0; BACNET_ADDRESS dest; int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; if (!dcc_communication_enabled()) return; /* we could use unicast or broadcast */ datalink_get_broadcast_address(&dest); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* encode the APDU portion of the packet */ - pdu_len += timesync_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = timesync_encode_apdu(&Handler_Transmit_Buffer[0], bdate, btime); + npdu_encode_unconfirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); /* send it out the datalink */ - bytes_sent = datalink_send_pdu(&dest, + 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 Time-Synchronization Request (%s)!\n", strerror(errno)); + #endif } void Send_TimeSyncUTC(BACNET_DATE * bdate, BACNET_TIME * btime) @@ -73,23 +74,23 @@ void Send_TimeSyncUTC(BACNET_DATE * bdate, BACNET_TIME * btime) int pdu_len = 0; BACNET_ADDRESS dest; int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; if (!dcc_communication_enabled()) return; /* we could use unicast or broadcast */ datalink_get_broadcast_address(&dest); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* encode the APDU portion of the packet */ - pdu_len += timesync_utc_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = timesync_utc_encode_apdu(&Handler_Transmit_Buffer[0], bdate, btime); - /* send it out the datalink */ - bytes_sent = datalink_send_pdu(&dest, + npdu_encode_unconfirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + 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 UTC-Time-Synchronization Request (%s)!\n", strerror(errno)); + #endif } diff --git a/bacnet-stack/demo/handler/s_whohas.c b/bacnet-stack/demo/handler/s_whohas.c index 52e76746..531f1b27 100644 --- a/bacnet-stack/demo/handler/s_whohas.c +++ b/bacnet-stack/demo/handler/s_whohas.c @@ -50,28 +50,29 @@ void Send_WhoHas_Name(int32_t low_limit, BACNET_ADDRESS dest; int bytes_sent = 0; BACNET_WHO_HAS_DATA data; + BACNET_NPDU_DATA npdu_data; /* if we are forbidden to send, don't send! */ if (!dcc_communication_enabled()) return; /* Who-Has is a global broadcast */ datalink_get_broadcast_address(&dest); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* encode the APDU portion of the packet */ data.low_limit = low_limit; data.high_limit = high_limit; data.object_name = true; characterstring_init_ansi(&data.object.name, object_name); - pdu_len += whohas_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = whohas_encode_apdu(&Handler_Transmit_Buffer[0], &data); + npdu_encode_unconfirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); /* send the data */ - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + 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 Who-Has Request (%s)!\n", strerror(errno)); + #endif } /* find a specific device, or use -1 for limit if you want unlimited */ @@ -83,27 +84,26 @@ void Send_WhoHas_Object(int32_t low_limit, BACNET_ADDRESS dest; int bytes_sent = 0; BACNET_WHO_HAS_DATA data; + BACNET_NPDU_DATA npdu_data; /* if we are forbidden to send, don't send! */ if (!dcc_communication_enabled()) return; /* Who-Has is a global broadcast */ datalink_get_broadcast_address(&dest); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* encode the APDU portion of the packet */ data.low_limit = low_limit; data.high_limit = high_limit; data.object_name = false; data.object.identifier.type = object_type; data.object.identifier.instance = object_instance; - pdu_len += whohas_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - &data); - /* send the data */ - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + pdu_len = whohas_encode_apdu(&Handler_Transmit_Buffer[0], &data); + npdu_encode_unconfirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + 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 Who-Has Request (%s)!\n", strerror(errno)); + #endif } diff --git a/bacnet-stack/demo/handler/s_whois.c b/bacnet-stack/demo/handler/s_whois.c index e7bda834..395f201e 100644 --- a/bacnet-stack/demo/handler/s_whois.c +++ b/bacnet-stack/demo/handler/s_whois.c @@ -48,24 +48,22 @@ void Send_WhoIs(int32_t low_limit, int32_t high_limit) int pdu_len = 0; BACNET_ADDRESS dest; int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; if (!dcc_communication_enabled()) return; /* Who-Is is a global broadcast */ datalink_get_broadcast_address(&dest); - - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - /* encode the APDU portion of the packet */ - pdu_len += whois_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = whois_encode_apdu(&Handler_Transmit_Buffer[0], low_limit, high_limit); - - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + npdu_encode_unconfirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + 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 Who-Is Request (%s)!\n", strerror(errno)); + #endif } diff --git a/bacnet-stack/demo/handler/s_wp.c b/bacnet-stack/demo/handler/s_wp.c index 660fc71b..52bea99b 100644 --- a/bacnet-stack/demo/handler/s_wp.c +++ b/bacnet-stack/demo/handler/s_wp.c @@ -51,13 +51,13 @@ uint8_t Send_Write_Property_Request(uint32_t device_id, /* destination device */ uint8_t priority, int32_t array_index) { BACNET_ADDRESS dest; - BACNET_ADDRESS my_address; unsigned max_apdu = 0; uint8_t invoke_id = 0; bool status = false; int pdu_len = 0; int bytes_sent = 0; BACNET_WRITE_PROPERTY_DATA data; + BACNET_NPDU_DATA npdu_data; if (!dcc_communication_enabled()) return 0; @@ -66,13 +66,8 @@ uint8_t Send_Write_Property_Request(uint32_t device_id, /* destination device */ status = address_get_by_device(device_id, &max_apdu, &dest); /* is there a tsm available? */ if (status) - status = tsm_transaction_available(); - if (status) { - datalink_get_my_address(&my_address); - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - invoke_id = tsm_next_free_invokeID(); + if (invoke_id) { /* load the data for the encoding */ data.object_type = object_type; data.object_instance = object_instance; @@ -80,7 +75,7 @@ uint8_t Send_Write_Property_Request(uint32_t device_id, /* destination device */ data.array_index = array_index; bacapp_copy(&data.value, object_value); data.priority = priority; - pdu_len += wp_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = wp_encode_apdu(&Handler_Transmit_Buffer[0], invoke_id, &data); /* will it fit in the sender? note: if there is a bottleneck router in between @@ -88,17 +83,25 @@ uint8_t Send_Write_Property_Request(uint32_t device_id, /* destination device */ we have a way to check for that and update the max_apdu in the address binding table. */ if ((unsigned) pdu_len < max_apdu) { + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); tsm_set_confirmed_unsegmented_transaction(invoke_id, - &dest, &Handler_Transmit_Buffer[0], pdu_len); - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ + &dest, &npdu_data, &Handler_Transmit_Buffer[0], 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)); - } else + #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 + } } return invoke_id; diff --git a/bacnet-stack/demo/object/bacfile.c b/bacnet-stack/demo/object/bacfile.c index 648d613a..cef4d769 100644 --- a/bacnet-stack/demo/object/bacfile.c +++ b/bacnet-stack/demo/object/bacfile.c @@ -301,25 +301,21 @@ uint32_t bacfile_instance_from_tsm(uint8_t invokeID) uint8_t *service_request = NULL; uint16_t service_request_len = 0; BACNET_ADDRESS dest; /* where the original packet was destined */ - uint8_t pdu[MAX_PDU] = { 0 }; /* original sent packet */ - uint16_t pdu_len = 0; /* original packet length */ + uint8_t apdu[MAX_PDU] = { 0 }; /* original APDU packet */ + uint16_t apdu_len = 0; /* original APDU packet length */ uint16_t len = 0; /* apdu header length */ BACNET_ATOMIC_READ_FILE_DATA data = { 0 }; uint32_t object_instance = BACNET_MAX_INSTANCE + 1; /* return value */ bool found = false; int apdu_offset = 0; - found = tsm_get_transaction_pdu(invokeID, &dest, &pdu[0], &pdu_len); + found = tsm_get_transaction_pdu(invokeID, &dest, &npdu_data, &apdu[0], + &apdu_len); if (found) { - apdu_offset = npdu_decode(&pdu[0], /* data to decode */ - NULL, /* destination address - get the DNET/DLEN/DADR if in there */ - NULL, /* source address - get the SNET/SLEN/SADR if in there */ - &npdu_data); /* amount of data to decode */ - if (!npdu_data.network_layer_message && - ((pdu[apdu_offset] & 0xF0) == - PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) { - len = apdu_decode_confirmed_service_request(&pdu[apdu_offset], /* APDU data */ - pdu_len - apdu_offset, + if (!npdu_data.network_layer_message && npdu_data.confirmed_message && + (apdu[0] == PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) { + len = apdu_decode_confirmed_service_request(&apdu[0], + apdu_len - apdu_offset, &service_data, &service_choice, &service_request, &service_request_len); if (service_choice == SERVICE_CONFIRMED_ATOMIC_READ_FILE) { diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index 496ff5a6..524fc694 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -269,12 +269,12 @@ bool Device_Set_Location(const char *name, size_t length) uint8_t Device_Protocol_Version(void) { - return 1; + return BACNET_PROTOCOL_VERSION; } uint8_t Device_Protocol_Revision(void) { - return 5; + return BACNET_PROTOCOL_REVISION; } uint16_t Device_Max_APDU_Length_Accepted(void) diff --git a/bacnet-stack/demo/readfile/Makefile b/bacnet-stack/demo/readfile/Makefile index f8bc28d6..c01ae950 100644 --- a/bacnet-stack/demo/readfile/Makefile +++ b/bacnet-stack/demo/readfile/Makefile @@ -26,6 +26,8 @@ SRCS = readfile.c \ $(BACNET_HANDLER)/txbuf.c \ $(BACNET_HANDLER)/noserv.c \ $(BACNET_HANDLER)/h_whois.c \ + $(BACNET_HANDLER)/s_whois.c \ + $(BACNET_HANDLER)/s_arfs.c \ $(BACNET_HANDLER)/h_rp.c \ $(BACNET_ROOT)/rp.c \ $(BACNET_ROOT)/bacdcode.c \ diff --git a/bacnet-stack/demo/readfile/makefile.b32 b/bacnet-stack/demo/readfile/makefile.b32 index b70238a2..449b7ddb 100644 --- a/bacnet-stack/demo/readfile/makefile.b32 +++ b/bacnet-stack/demo/readfile/makefile.b32 @@ -23,6 +23,8 @@ SRCS = readfile.c \ ..\..\demo\handler\txbuf.c \ ..\..\demo\handler\noserv.c \ ..\..\demo\handler\h_whois.c \ + ..\..\demo\handler\s_whois.c \ + ..\..\demo\handler\s_arfs.c \ ..\..\demo\handler\h_rp.c \ ..\..\bacdcode.c \ ..\..\bacapp.c \ diff --git a/bacnet-stack/demo/readfile/readfile.c b/bacnet-stack/demo/readfile/readfile.c index 27f4ebe4..a7041dfa 100644 --- a/bacnet-stack/demo/readfile/readfile.c +++ b/bacnet-stack/demo/readfile/readfile.c @@ -46,6 +46,7 @@ /* some demo stuff needed */ #include "filename.h" #include "handlers.h" +#include "client.h" #include "txbuf.h" /* buffer used for receive */ @@ -97,84 +98,6 @@ void MyRejectHandler(BACNET_ADDRESS * src, Error_Detected = true; } -static uint8_t Send_Atomic_Read_File_Stream(uint32_t device_id, - uint32_t file_instance, - int fileStartPosition, unsigned requestedOctetCount) -{ - BACNET_ADDRESS dest; - BACNET_ADDRESS my_address; - unsigned max_apdu = 0; - uint8_t invoke_id = 0; - bool status = false; - int pdu_len = 0; - int bytes_sent = 0; - BACNET_ATOMIC_READ_FILE_DATA data; - - /* is the device bound? */ - status = address_get_by_device(device_id, &max_apdu, &dest); - /* is there a tsm available? */ - if (status) - status = tsm_transaction_available(); - if (status) { - datalink_get_my_address(&my_address); - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - - invoke_id = tsm_next_free_invokeID(); - /* load the data for the encoding */ - data.object_type = OBJECT_FILE; - data.object_instance = file_instance; - data.access = FILE_STREAM_ACCESS; - data.type.stream.fileStartPosition = fileStartPosition; - data.type.stream.requestedOctetCount = requestedOctetCount; - pdu_len += arf_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - invoke_id, &data); - /* will the APDU fit the target device? - 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 ((unsigned) pdu_len < max_apdu) { - tsm_set_confirmed_unsegmented_transaction(invoke_id, - &dest, &Handler_Transmit_Buffer[0], pdu_len); - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ - if (bytes_sent <= 0) - fprintf(stderr, - "Failed to Send AtomicReadFile Request (%s)!\n", - strerror(errno)); - } else - fprintf(stderr, "Failed to Send AtomicReadFile Request " - "(payload exceeds destination maximum APDU)!\n"); - } - - return invoke_id; -} - -static void Send_WhoIs(uint32_t device_id) -{ - int pdu_len = 0; - BACNET_ADDRESS dest; - int bytes_sent = 0; - - /* Who-Is is a global broadcast */ - datalink_get_broadcast_address(&dest); - - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - - /* encode the APDU portion of the packet */ - pdu_len += whois_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - device_id, device_id); - - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ - if (bytes_sent <= 0) - fprintf(stderr, "Failed to Send Who-Is Request (%s)!\n", - strerror(errno)); -} - static void AtomicReadFileAckHandler(uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data) @@ -316,7 +239,7 @@ int main(int argc, char *argv[]) timeout_seconds = (Device_APDU_Timeout() / 1000) * Device_Number_Of_APDU_Retries(); /* try to bind with the device */ - Send_WhoIs(Target_Device_Object_Instance); + Send_WhoIs(Target_Device_Object_Instance,Target_Device_Object_Instance); /* loop forever */ for (;;) { /* increment timer - exit if timed out */ diff --git a/bacnet-stack/demo/timesync/main.c b/bacnet-stack/demo/timesync/main.c index ce7987c5..cd77551d 100644 --- a/bacnet-stack/demo/timesync/main.c +++ b/bacnet-stack/demo/timesync/main.c @@ -49,8 +49,10 @@ static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; /* global variables used in this file */ +#if 0 static int32_t Target_Object_Instance_Min = 0; static int32_t Target_Object_Instance_Max = BACNET_MAX_INSTANCE; +#endif static bool Error_Detected = false; @@ -133,7 +135,7 @@ int main(int argc, char *argv[]) BACNET_ADDRESS my_address, broadcast_address; #endif - /* FIXME: we could send directed time sync, and how to we send UTC? */ + /* FIXME: we could send directed time sync, and how do we send UTC? */ #if 0 if (argc < 2) { printf("Usage: %s date time [device-instance]\r\n" diff --git a/bacnet-stack/demo/writefile/Makefile b/bacnet-stack/demo/writefile/Makefile index a45bc433..35c7a5ac 100644 --- a/bacnet-stack/demo/writefile/Makefile +++ b/bacnet-stack/demo/writefile/Makefile @@ -27,6 +27,8 @@ SRCS = writefile.c \ $(BACNET_HANDLER)/noserv.c \ $(BACNET_HANDLER)/h_whois.c \ $(BACNET_HANDLER)/h_rp.c \ + $(BACNET_HANDLER)/s_whois.c \ + $(BACNET_HANDLER)/s_awfs.c \ $(BACNET_ROOT)/rp.c \ $(BACNET_ROOT)/bacdcode.c \ $(BACNET_ROOT)/bacapp.c \ diff --git a/bacnet-stack/demo/writefile/makefile.b32 b/bacnet-stack/demo/writefile/makefile.b32 index d6138411..9a157594 100644 --- a/bacnet-stack/demo/writefile/makefile.b32 +++ b/bacnet-stack/demo/writefile/makefile.b32 @@ -24,6 +24,8 @@ SRCS = writefile.c \ ..\..\demo\handler\noserv.c \ ..\..\demo\handler\h_whois.c \ ..\..\demo\handler\h_rp.c \ + ..\..\demo\handler\s_whois.c \ + ..\..\demo\handler\s_awr.c \ ..\..\bacdcode.c \ ..\..\bacapp.c \ ..\..\bacstr.c \ diff --git a/bacnet-stack/demo/writefile/writefile.c b/bacnet-stack/demo/writefile/writefile.c index f76a7f04..afb46ece 100644 --- a/bacnet-stack/demo/writefile/writefile.c +++ b/bacnet-stack/demo/writefile/writefile.c @@ -46,6 +46,7 @@ /* some demo stuff needed */ #include "filename.h" #include "handlers.h" +#include "client.h" #include "txbuf.h" /* buffer used for receive */ @@ -97,90 +98,6 @@ void MyRejectHandler(BACNET_ADDRESS * src, Error_Detected = true; } -static uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id, - uint32_t file_instance, - int fileStartPosition, BACNET_OCTET_STRING * fileData) -{ - BACNET_ADDRESS dest; - BACNET_ADDRESS my_address; - unsigned max_apdu = 0; - uint8_t invoke_id = 0; - bool status = false; - int pdu_len = 0; - int bytes_sent = 0; - BACNET_ATOMIC_WRITE_FILE_DATA data; - - /* is the device bound? */ - status = address_get_by_device(device_id, &max_apdu, &dest); - /* is there a tsm available? */ - if (status) - status = tsm_transaction_available(); - if (status) { - datalink_get_my_address(&my_address); - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - - invoke_id = tsm_next_free_invokeID(); - /* load the data for the encoding */ - data.object_type = OBJECT_FILE; - data.object_instance = file_instance; - data.access = FILE_STREAM_ACCESS; - data.type.stream.fileStartPosition = fileStartPosition; - status = octetstring_copy(&data.fileData, fileData); - if (status) { - pdu_len += awf_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - invoke_id, &data); - /* will the APDU fit the target device? - 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 ((unsigned) pdu_len <= max_apdu) { - tsm_set_confirmed_unsegmented_transaction(invoke_id, - &dest, &Handler_Transmit_Buffer[0], pdu_len); - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ - if (bytes_sent <= 0) - fprintf(stderr, - "Failed to Send AtomicWriteFile Request (%s)!\n", - strerror(errno)); - } else - fprintf(stderr, "Failed to Send AtomicWriteFile Request " - "(payload [%d] exceeds destination maximum APDU [%u])!\n", - pdu_len, max_apdu); - } else - fprintf(stderr, "Failed to Send AtomicWriteFile Request " - "(payload [%d] exceeds octet string capacity)!\n", - pdu_len); - } - - return invoke_id; -} - -static void Send_WhoIs(uint32_t device_id) -{ - int pdu_len = 0; - BACNET_ADDRESS dest; - int bytes_sent = 0; - - /* Who-Is is a global broadcast */ - datalink_get_broadcast_address(&dest); - - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - - /* encode the APDU portion of the packet */ - pdu_len += whois_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - device_id, device_id); - - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ - if (bytes_sent <= 0) - fprintf(stderr, "Failed to Send Who-Is Request (%s)!\n", - strerror(errno)); -} - static void LocalIAmHandler(uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src) { @@ -278,7 +195,7 @@ int main(int argc, char *argv[]) timeout_seconds = (Device_APDU_Timeout() / 1000) * Device_Number_Of_APDU_Retries(); /* try to bind with the device */ - Send_WhoIs(Target_Device_Object_Instance); + Send_WhoIs(Target_Device_Object_Instance,Target_Device_Object_Instance); /* loop forever */ for (;;) { /* increment timer - exit if timed out */ diff --git a/bacnet-stack/iam.c b/bacnet-stack/iam.c index c60b1e77..f8434cdd 100755 --- a/bacnet-stack/iam.c +++ b/bacnet-stack/iam.c @@ -139,21 +139,20 @@ int iam_send(uint8_t * buffer) int pdu_len = 0; BACNET_ADDRESS dest; int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; /* I-Am is a global broadcast */ datalink_get_broadcast_address(&dest); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&buffer[0], &dest, NULL, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); - /* encode the APDU portion of the packet */ - pdu_len += iam_encode_apdu(&buffer[pdu_len], + pdu_len = iam_encode_apdu(&buffer[0], Device_Object_Instance_Number(), MAX_APDU, SEGMENTATION_NONE, Device_Vendor_Identifier()); - - bytes_sent = datalink_send_pdu(&dest, /* destination address */ - &buffer[0], pdu_len); /* number of bytes of data */ + /* encode the NPDU portion of the packet */ + npdu_encode_unconfirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + /* send data */ + bytes_sent = datalink_send_pdu(&dest, &npdu_data, + &buffer[0], pdu_len); return bytes_sent; } @@ -219,6 +218,7 @@ void datalink_get_broadcast_address(BACNET_ADDRESS * dest) } int datalink_send_pdu(BACNET_ADDRESS * dest, /* destination address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ uint8_t * pdu, /* any data to be sent - may be null */ unsigned pdu_len) { /* number of bytes of data */ diff --git a/bacnet-stack/npdu.c b/bacnet-stack/npdu.c index 3df1b9a2..005c3594 100644 --- a/bacnet-stack/npdu.c +++ b/bacnet-stack/npdu.c @@ -40,17 +40,37 @@ #include "npdu.h" #include "apdu.h" -int npdu_encode_raw(uint8_t * npdu, +void npdu_copy_data(BACNET_NPDU_DATA * dest, BACNET_NPDU_DATA * src) +{ + if (dest && src) { + dest->protocol_version = src->protocol_version; + dest->confirmed_message = src->confirmed_message; + dest->network_layer_message = src->network_layer_message; + dest->priority = src->priority; + dest->network_message_type = src->network_message_type; + dest->vendor_id = src->vendor_id; + dest->hop_count = src->hop_count; + } + + return; +} + +int npdu_encode_pdu(uint8_t * npdu, BACNET_ADDRESS * dest, - BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data) + BACNET_ADDRESS * src, + BACNET_NPDU_DATA * npdu_data) { int len = 0; /* return value - number of octets loaded in this function */ int i = 0; /* counter */ + if (npdu && npdu_data) { - /* Protocol Version */ - npdu[0] = 1; - /* control octet */ + /* only include src address for data expecting reply, or replies */ + if (!(npdu_data->confirmed_message)) + src = NULL; + /* protocol version */ + npdu[0] = npdu_data->protocol_version; + /* initialize the control octet */ npdu[1] = 0; /* Bit 7: 1 indicates that the NSDU conveys a network layer message. */ /* Message Type field is present. */ @@ -74,15 +94,15 @@ int npdu_encode_raw(uint8_t * npdu, /* SLEN > 0 specifies length of SADR field */ if (src && src->net) npdu[1] |= BIT3; - /* Bit 2: The value of this bit corresponds to the data_expecting_reply */ - /* parameter in the N-UNITDATA primitives. */ + /* Bit 2: The value of this bit corresponds to the */ + /* data_expecting_reply parameter in the N-UNITDATA primitives. */ /* 1 indicates that a BACnet-Confirmed-Request-PDU, */ /* a segment of a BACnet-ComplexACK-PDU, */ /* or a network layer message expecting a reply is present. */ /* 0 indicates that other than a BACnet-Confirmed-Request-PDU, */ /* a segment of a BACnet-ComplexACK-PDU, */ /* or a network layer message expecting a reply is present. */ - if (npdu_data->data_expecting_reply) + if (npdu_data->confirmed_message) npdu[1] |= BIT2; /* Bits 1,0: Network priority where: */ /* B'11' = Life Safety message */ @@ -133,20 +153,36 @@ int npdu_encode_raw(uint8_t * npdu, return len; } -/* encode the NPDU portion of the packet for an APDU */ +/* Configure the NPDU portion of the packet for an APDU */ /* This function does not handle the network messages, just APDUs. */ -int npdu_encode_apdu(uint8_t * npdu, BACNET_ADDRESS * dest, BACNET_ADDRESS * src, bool data_expecting_reply, /* true for confirmed messages */ +void npdu_encode_confirmed_apdu(BACNET_NPDU_DATA * npdu_data, BACNET_MESSAGE_PRIORITY priority) { - BACNET_NPDU_DATA npdu_data = { 0 }; + if (npdu_data) + { + npdu_data->confirmed_message = true; + npdu_data->protocol_version = BACNET_PROTOCOL_VERSION; + npdu_data->network_layer_message = false; /* false if APDU */ + npdu_data->network_message_type = 0; /* optional */ + npdu_data->vendor_id = 0; /* optional, if net message type is > 0x80 */ + npdu_data->priority = priority; + npdu_data->hop_count = 0; + } +} - npdu_data.data_expecting_reply = data_expecting_reply; - npdu_data.network_layer_message = false; /* false if APDU */ - npdu_data.network_message_type = 0; /* optional */ - npdu_data.vendor_id = 0; /* optional, if net message type is > 0x80 */ - npdu_data.priority = priority; - /* call the real function... */ - return npdu_encode_raw(npdu, dest, src, &npdu_data); +void npdu_encode_unconfirmed_apdu(BACNET_NPDU_DATA * npdu_data, + BACNET_MESSAGE_PRIORITY priority) +{ + if (npdu_data) + { + npdu_data->confirmed_message = false; + npdu_data->protocol_version = BACNET_PROTOCOL_VERSION; + npdu_data->network_layer_message = false; /* false if APDU */ + npdu_data->network_message_type = 0; /* optional */ + npdu_data->vendor_id = 0; /* optional, if net message type is > 0x80 */ + npdu_data->priority = priority; + npdu_data->hop_count = 0; + } } int npdu_decode(uint8_t * npdu, @@ -171,7 +207,7 @@ int npdu_decode(uint8_t * npdu, npdu_data->network_layer_message = (npdu[1] & BIT7) ? true : false; /*Bit 6: Reserved. Shall be zero. */ /* Bit 4: Reserved. Shall be zero. */ - /* Bit 2: The value of this bit corresponds to the data_expecting_reply */ + /* Bit 2: The value of this bit corresponds to data expecting reply */ /* parameter in the N-UNITDATA primitives. */ /* 1 indicates that a BACnet-Confirmed-Request-PDU, */ /* a segment of a BACnet-ComplexACK-PDU, */ @@ -179,7 +215,7 @@ int npdu_decode(uint8_t * npdu, /* 0 indicates that other than a BACnet-Confirmed-Request-PDU, */ /* a segment of a BACnet-ComplexACK-PDU, */ /* or a network layer message expecting a reply is present. */ - npdu_data->data_expecting_reply = (npdu[1] & BIT2) ? true : false; + npdu_data->confirmed_message = (npdu[1] & BIT2) ? true : false; /* Bits 1,0: Network priority where: */ /* B'11' = Life Safety message */ /* B'10' = Critical Equipment message */ @@ -277,16 +313,13 @@ void npdu_handler(BACNET_ADDRESS * src, /* source address */ BACNET_ADDRESS dest = { 0 }; BACNET_NPDU_DATA npdu_data = { 0 }; - apdu_offset = npdu_decode(&pdu[0], /* data to decode */ - &dest, /* destination address - get the DNET/DLEN/DADR if in there */ - src, /* source address - get the SNET/SLEN/SADR if in there */ - &npdu_data); /* amount of data to decode */ + apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data); if (npdu_data.network_layer_message) { /*FIXME: network layer message received! Handle it! */ } else { - apdu_handler(src, - npdu_data.data_expecting_reply, - &pdu[apdu_offset], pdu_len - apdu_offset); + /* only handle the version that we know how to handle */ + if (npdu_data.protocol_version == BACNET_PROTOCOL_VERSION) + apdu_handler(src, &pdu[apdu_offset], pdu_len - apdu_offset); } return; @@ -306,7 +339,7 @@ void testNPDU2(Test * pTest) BACNET_ADDRESS npdu_dest = { 0 }; BACNET_ADDRESS npdu_src = { 0 }; int len = 0; - bool data_expecting_reply = false; /* true for confirmed messages */ + bool confirmed_message = true; /* true for confirmed messages */ BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL; BACNET_NPDU_DATA npdu_data = { 0 }; int i = 0; /* counter */ @@ -336,13 +369,13 @@ void testNPDU2(Test * pTest) for (i = 0; i < src.len; i++) { src.adr[i] = 0x40; } - len = npdu_encode_apdu(&pdu[0], - &dest, &src, data_expecting_reply, priority); + npdu_encode_confirmed_apdu(&npdu_data, priority); + len = npdu_encode_pdu(&pdu[0], &dest, &src, &npdu_data); ct_test(pTest, len != 0); /* can we get the info back? */ npdu_len = npdu_decode(&pdu[0], &npdu_dest, &npdu_src, &npdu_data); ct_test(pTest, npdu_len != 0); - ct_test(pTest, npdu_data.data_expecting_reply == data_expecting_reply); + ct_test(pTest, npdu_data.confirmed_message == confirmed_message); ct_test(pTest, npdu_data.network_layer_message == network_layer_message); ct_test(pTest, npdu_data.network_message_type == network_message_type); @@ -370,7 +403,7 @@ void testNPDU1(Test * pTest) BACNET_ADDRESS npdu_dest = { 0 }; BACNET_ADDRESS npdu_src = { 0 }; int len = 0; - bool data_expecting_reply = false; /* true for confirmed messages */ + bool confirmed_message = false; /* true for confirmed messages */ BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL; BACNET_NPDU_DATA npdu_data = { 0 }; int i = 0; /* counter */ @@ -400,13 +433,13 @@ void testNPDU1(Test * pTest) for (i = 0; i < MAX_MAC_LEN; i++) { src.adr[i] = 0; } - len = npdu_encode_apdu(&pdu[0], - &dest, &src, data_expecting_reply, priority); + npdu_encode_unconfirmed_apdu(&npdu_data, priority); + len = npdu_encode_pdu(&pdu[0], &dest, &src, &npdu_data); ct_test(pTest, len != 0); /* can we get the info back? */ npdu_len = npdu_decode(&pdu[0], &npdu_dest, &npdu_src, &npdu_data); ct_test(pTest, npdu_len != 0); - ct_test(pTest, npdu_data.data_expecting_reply == data_expecting_reply); + ct_test(pTest, npdu_data.confirmed_message == confirmed_message); ct_test(pTest, npdu_data.network_layer_message == network_layer_message); ct_test(pTest, npdu_data.network_message_type == network_message_type); diff --git a/bacnet-stack/npdu.h b/bacnet-stack/npdu.h index 66d304be..ee83b4b7 100644 --- a/bacnet-stack/npdu.h +++ b/bacnet-stack/npdu.h @@ -43,7 +43,7 @@ typedef struct bacnet_npdu_data_t { uint8_t protocol_version; /* parts of the control octet: */ - bool data_expecting_reply; /* true for confirmed messages */ + bool confirmed_message; /* true for confirmed messages */ bool network_layer_message; /* false if APDU */ BACNET_MESSAGE_PRIORITY priority; /* optional network message info */ @@ -57,12 +57,17 @@ extern "C" { #endif /* __cplusplus */ uint8_t npdu_encode_max_seg_max_apdu(int max_segs, int max_apdu); - int npdu_encode_raw(uint8_t * npdu, + + int npdu_encode_pdu(uint8_t * npdu, BACNET_ADDRESS * dest, BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data); -/* encode the NPDU portion of the packet for an APDU */ - int npdu_encode_apdu(uint8_t * npdu, BACNET_ADDRESS * dest, BACNET_ADDRESS * src, bool data_expecting_reply, /* true for confirmed messages */ + + void npdu_encode_confirmed_apdu(BACNET_NPDU_DATA * npdu, BACNET_MESSAGE_PRIORITY priority); + void npdu_encode_unconfirmed_apdu(BACNET_NPDU_DATA * npdu, + BACNET_MESSAGE_PRIORITY priority); + + void npdu_copy_data(BACNET_NPDU_DATA * dest, BACNET_NPDU_DATA * src); int npdu_decode(uint8_t * npdu, BACNET_ADDRESS * dest, diff --git a/bacnet-stack/tsm.c b/bacnet-stack/tsm.c index bd523851..f625d9c1 100644 --- a/bacnet-stack/tsm.c +++ b/bacnet-stack/tsm.c @@ -132,22 +132,26 @@ uint8_t tsm_next_free_invokeID(void) uint8_t invokeID = 0; bool found = false; - while (!found) { - index = tsm_find_invokeID_index(current_invokeID); - /* not found - that is good! */ - if (index == MAX_TSM_TRANSACTIONS) { - found = true; - /* set this id into the table */ - index = tsm_find_first_free_index(); - if (index != MAX_TSM_TRANSACTIONS) { - TSM_List[index].InvokeID = invokeID = current_invokeID; - TSM_List[index].state = TSM_STATE_IDLE; - TSM_List[index].RequestTimer = Device_APDU_Timeout(); - /* update for the next call or check */ - current_invokeID++; - /* skip zero - we treat that internally as invalid or no free */ - if (current_invokeID == 0) - current_invokeID = 1; + /* is there even space available? */ + if (tsm_transaction_available()) + { + while (!found) { + index = tsm_find_invokeID_index(current_invokeID); + /* not found - that is good! */ + if (index == MAX_TSM_TRANSACTIONS) { + found = true; + /* set this id into the table */ + index = tsm_find_first_free_index(); + if (index != MAX_TSM_TRANSACTIONS) { + TSM_List[index].InvokeID = invokeID = current_invokeID; + TSM_List[index].state = TSM_STATE_IDLE; + TSM_List[index].RequestTimer = Device_APDU_Timeout(); + /* update for the next call or check */ + current_invokeID++; + /* skip zero - we treat that internally as invalid or no free */ + if (current_invokeID == 0) + current_invokeID = 1; + } } } } @@ -156,7 +160,8 @@ uint8_t tsm_next_free_invokeID(void) } void tsm_set_confirmed_unsegmented_transaction(uint8_t invokeID, - BACNET_ADDRESS * dest, uint8_t * pdu, uint16_t pdu_len) + BACNET_ADDRESS * dest, BACNET_NPDU_DATA * ndpu_data, + uint8_t * apdu, uint16_t apdu_len) { uint16_t j = 0; uint8_t index; @@ -170,10 +175,11 @@ void tsm_set_confirmed_unsegmented_transaction(uint8_t invokeID, /* start the timer */ TSM_List[index].RequestTimer = Device_APDU_Timeout(); /* copy the data */ - for (j = 0; j < pdu_len; j++) { - TSM_List[index].pdu[j] = pdu[j]; + for (j = 0; j < apdu_len; j++) { + TSM_List[index].apdu[j] = apdu[j]; } - TSM_List[index].pdu_len = pdu_len; + TSM_List[index].apdu_len = apdu_len; + npdu_copy_data(&TSM_List[index].npdu_data, ndpu_data); address_copy(&TSM_List[index].dest, dest); } } @@ -184,7 +190,8 @@ void tsm_set_confirmed_unsegmented_transaction(uint8_t invokeID, /* used to retrieve the transaction payload */ /* if we wanted to find out what we sent (i.e. when we get an ack) */ bool tsm_get_transaction_pdu(uint8_t invokeID, - BACNET_ADDRESS * dest, uint8_t * pdu, uint16_t * pdu_len) + BACNET_ADDRESS * dest, BACNET_NPDU_DATA * ndpu_data, + uint8_t * apdu, uint16_t * apdu_len) { uint16_t j = 0; uint8_t index; @@ -197,10 +204,11 @@ bool tsm_get_transaction_pdu(uint8_t invokeID, /* FIXME: we may want to free the transaction so it doesn't timeout */ /* retrieve the transaction */ /* FIXME: bounds check the pdu_len? */ - *pdu_len = TSM_List[index].pdu_len; - for (j = 0; j < *pdu_len; j++) { - pdu[j] = TSM_List[index].pdu[j]; + *apdu_len = TSM_List[index].apdu_len; + for (j = 0; j < *apdu_len; j++) { + apdu[j] = TSM_List[index].apdu[j]; } + npdu_copy_data(ndpu_data,&TSM_List[index].npdu_data); address_copy(dest, &TSM_List[index].dest); found = true; } @@ -226,8 +234,9 @@ void tsm_timer_milliseconds(uint16_t milliseconds) TSM_List[i].RetryCount--; TSM_List[i].RequestTimer = Device_APDU_Timeout(); if (TSM_List[i].RetryCount) { - bytes_sent = datalink_send_pdu(&TSM_List[i].dest, /* destination address */ - &TSM_List[i].pdu[0], TSM_List[i].pdu_len); /* number of bytes of data */ + bytes_sent = datalink_send_pdu(&TSM_List[i].dest, + &TSM_List[i].npdu_data, + &TSM_List[i].apdu[0], TSM_List[i].apdu_len); } else { TSM_List[i].InvokeID = 0; TSM_List[i].state = TSM_STATE_IDLE; diff --git a/bacnet-stack/tsm.h b/bacnet-stack/tsm.h index 018da8f7..4b7ce5b5 100644 --- a/bacnet-stack/tsm.h +++ b/bacnet-stack/tsm.h @@ -38,6 +38,7 @@ #include #include #include "bacdef.h" +#include "npdu.h" /* note: TSM functionality is optional - only needed if we are doing client requests */ @@ -80,9 +81,11 @@ typedef struct BACnet_TSM_Data { BACNET_TSM_STATE state; /* the address we sent it to */ BACNET_ADDRESS dest; - /* copy of the PDU, should we need to send it again */ - uint8_t pdu[MAX_PDU]; - unsigned pdu_len; + /* the network layer info */ + BACNET_NPDU_DATA npdu_data; + /* copy of the APDU, should we need to send it again */ + uint8_t apdu[MAX_PDU]; + unsigned apdu_len; } BACNET_TSM_DATA; #ifdef __cplusplus @@ -98,10 +101,12 @@ extern "C" { uint8_t tsm_next_free_invokeID(void); /* returns the same invoke ID that was given */ void tsm_set_confirmed_unsegmented_transaction(uint8_t invokeID, - BACNET_ADDRESS * dest, uint8_t * pdu, uint16_t pdu_len); + BACNET_ADDRESS * dest, BACNET_NPDU_DATA * ndpu_data, + uint8_t * apdu, uint16_t apdu_len); /* returns true if transaction is found */ bool tsm_get_transaction_pdu(uint8_t invokeID, - BACNET_ADDRESS * dest, uint8_t * pdu, uint16_t * pdu_len); + BACNET_ADDRESS * dest, BACNET_NPDU_DATA * ndpu_data, + uint8_t * apdu, uint16_t * apdu_len); bool tsm_invoke_id_free(uint8_t invokeID);