From cab93e9db470ae2202f42da78afc3eec5fc71c1c Mon Sep 17 00:00:00 2001 From: skarg Date: Wed, 29 Oct 2014 21:26:35 +0000 Subject: [PATCH] Modified ReadRange demo to be similar to ReadProperty demo. Still needs the print of the data to work correctly, but it mostly works. --- bacnet-stack/demo/Makefile | 4 +- bacnet-stack/demo/readrange/Makefile | 44 ++ bacnet-stack/demo/readrange/main.c | 621 +++++++++-------------- bacnet-stack/demo/readrange/makefile.b32 | 139 ----- bacnet-stack/lib/Makefile | 2 + 5 files changed, 291 insertions(+), 519 deletions(-) create mode 100644 bacnet-stack/demo/readrange/Makefile delete mode 100644 bacnet-stack/demo/readrange/makefile.b32 diff --git a/bacnet-stack/demo/Makefile b/bacnet-stack/demo/Makefile index 0444c8dd..e31cb966 100644 --- a/bacnet-stack/demo/Makefile +++ b/bacnet-stack/demo/Makefile @@ -55,7 +55,7 @@ LFLAGS := -Wl,$(BACNET_LIB),$(SYSTEM_LIB) .EXPORT_ALL_VARIABLES: SUBDIRS = readprop writeprop readfile writefile reinit server dcc \ - whohas whois ucov scov timesync epics readpropm \ + whohas whois ucov scov timesync epics readpropm readrange \ uptransfer ifeq (${BACDL_DEFINE},-DBACDL_BIP=1) @@ -63,7 +63,7 @@ ifeq (${BACDL_DEFINE},-DBACDL_BIP=1) endif ifeq (${BACNET_PORT},linux) -ifneq (${OSTYPE},cygwin) +ifneq (${OSTYPE},cygwin) SUBDIRS += mstpcap mstpcrc #SUBDIRS += router endif diff --git a/bacnet-stack/demo/readrange/Makefile b/bacnet-stack/demo/readrange/Makefile new file mode 100644 index 00000000..67188a8c --- /dev/null +++ b/bacnet-stack/demo/readrange/Makefile @@ -0,0 +1,44 @@ +#Makefile to build BACnet Application using GCC compiler + +# tools - only if you need them. +# Most platforms have this already defined +# CC = gcc +# AR = ar +# MAKE = make +# SIZE = size +# +# Assumes rm and cp are available + +# Executable file name +TARGET = bacrr + +TARGET_BIN = ${TARGET}$(TARGET_EXT) + +SRCS = main.c \ + ../object/device-client.c + +OBJS = ${SRCS:.c=.o} + +all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN} + +${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET} + ${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@ + size $@ + cp $@ ../../bin + +lib: ${BACNET_LIB_TARGET} + +${BACNET_LIB_TARGET}: + ( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) ) + +.c.o: + ${CC} -c ${CFLAGS} $*.c -o $@ + +depend: + rm -f .depend + ${CC} -MM ${CFLAGS} *.c >> .depend + +clean: + rm -rf core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} + +include: .depend diff --git a/bacnet-stack/demo/readrange/main.c b/bacnet-stack/demo/readrange/main.c index 7a457af3..cdca07a9 100644 --- a/bacnet-stack/demo/readrange/main.c +++ b/bacnet-stack/demo/readrange/main.c @@ -31,15 +31,11 @@ #include #include #include /* for time */ -#if defined(WIN32) || defined(__BORLANDC__) -#include -#endif #include "bacdef.h" #include "config.h" #include "bactext.h" #include "bacerror.h" #include "iam.h" -#include "arf.h" #include "tsm.h" #include "address.h" #include "npdu.h" @@ -48,48 +44,32 @@ #include "net.h" #include "datalink.h" #include "whois.h" +#include "version.h" /* some demo stuff needed */ #include "filename.h" #include "handlers.h" #include "client.h" #include "txbuf.h" #include "dlenv.h" -#include "mydata.h" #include "readrange.h" -#include "bactext.h" -/* include the objects */ -#include "device.h" -#include "ai.h" -#include "ao.h" -#include "av.h" -#include "bi.h" -#include "bo.h" -#include "bv.h" -#include "lc.h" -#include "lsp.h" -#include "mso.h" -#include "trendlog.h" -#include "bacfile.h" - -#if !defined(WIN32) && !defined(__BORLANDC__) -#define stricmp strcasecmp -#endif - -#if defined(__BORLANDC__) -#define _kbhit kbhit -#define _stricmp stricmp -#endif /* buffer used for receive */ static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; -/* global variables used in this file */ +/* converted command line arguments */ static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE; - -static int Target_Mode = 0; - +static uint32_t Target_Object_Instance = BACNET_MAX_INSTANCE; +static BACNET_OBJECT_TYPE Target_Object_Type = OBJECT_ANALOG_INPUT; +static BACNET_PROPERTY_ID Target_Object_Property = PROP_ACKED_TRANSITIONS; +static long Target_Object_Range_Type = 0; +static long Target_Object_Index = 0; +static long Target_Object_Count = 0; +/* the invoke id is needed to filter incoming messages */ +static uint8_t Request_Invoke_ID = 0; static BACNET_ADDRESS Target_Address; static bool Error_Detected = false; +/* specific request data */ +static BACNET_READ_RANGE_DATA RR_Request; static void MyErrorHandler( BACNET_ADDRESS * src, @@ -97,13 +77,13 @@ static void MyErrorHandler( BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Error: %s: %s\r\n", - bactext_error_class_name((int) error_class), - bactext_error_code_name((int) error_code)); -/* Error_Detected = true; */ + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Error: %s: %s\r\n", + bactext_error_class_name((int) error_class), + bactext_error_code_name((int) error_code)); + Error_Detected = true; + } } void MyAbortHandler( @@ -112,13 +92,13 @@ void MyAbortHandler( uint8_t abort_reason, bool server) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; (void) server; - printf("BACnet Abort: %s\r\n", - bactext_abort_reason_name((int) abort_reason)); -/* Error_Detected = true; */ + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Abort: %s\n", + bactext_abort_reason_name((int) abort_reason)); + Error_Detected = true; + } } void MyRejectHandler( @@ -126,32 +106,23 @@ void MyRejectHandler( uint8_t invoke_id, uint8_t reject_reason) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Reject: %s\r\n", - bactext_reject_reason_name((int) reject_reason)); -/* Error_Detected = true; */ -} - -static void Init_Objects( - void) -{ - Device_Init(NULL); + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Reject: %s\n", + bactext_reject_reason_name((int) reject_reason)); + Error_Detected = true; + } } static void Init_Service_Handlers( void) { - /* we need to handle who-isx + Device_Init(NULL); + /* we need to handle who-is to support dynamic device binding to us */ apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is); /* handle i-am to support binding to other devices */ -#if 0 apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind); -#else - apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_add); -#endif /* set the handler for all the services we don't implement It is required to send the proper reject message... */ apdu_set_unrecognized_service_handler_handler @@ -159,21 +130,9 @@ static void Init_Service_Handlers( /* we must implement read property - it's required! */ apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property); - apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE, - handler_read_property_multiple); - apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY, - handler_write_property); - apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_RANGE, - handler_read_range); - apdu_set_confirmed_handler(SERVICE_CONFIRMED_PRIVATE_TRANSFER, - handler_conf_private_trans); /* handle the data coming back from confirmed requests */ - apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY, - handler_read_property_ack); apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_RANGE, handler_read_range_ack); - apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_PRIVATE_TRANSFER, - handler_conf_private_trans_ack); /* handle any errors coming back */ apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler); @@ -182,6 +141,56 @@ static void Init_Service_Handlers( apdu_set_reject_handler(MyRejectHandler); } +static void print_usage(char *filename) +{ + printf("Usage: %s device-instance object-type object-instance property\n", + filename); + printf(" range-type > count\n"); + printf(" [--version][--help]\n"); +} + +static void print_help(char *filename) +{ + printf("Read a range of properties from an array or list property\n" + "in an object in a BACnet device and print the values.\n" + "device-instance:\n" + "BACnet Device Object Instance number that you are\n" + "trying to communicate to. This number will be used\n" + "to try and bind with the device using Who-Is and\n" + "I-Am services. For example, if you were reading\n" + "Device Object 123, the device-instance would be 123.\n" + "\nobject-type:\n" + "The object type is the integer value of the enumeration\n" + "BACNET_OBJECT_TYPE in bacenum.h. It is the object\n" + "that you are reading. For example if you were\n" + "reading Trend Log 2, the object-type would be 20.\n" + "\nobject-instance:\n" + "This is the object instance number of the object that\n" + "you are reading. For example, if you were reading\n" + "Trend Log 2, the object-instance would be 2.\n" + "\nproperty:\n" + "The property is an integer value of the enumeration\n" + "BACNET_PROPERTY_ID in bacenum.h. It is the property\n" + "you are reading. For example, if you were reading the\n" + "Log_Buffer property, use 131 as the property.\n" + "\nrange-type:\n" + "1=By Position\n" + "2=By Sequence\n" + "3=By Time\n" + "4=All\n" + "\nindex or date/time:\n" + "This integer parameter is the starting index, or date & time.\n" + "\ncount:\n" + "This integer parameter is the number of elements to read.\n" + "\nExample:\n" + "If you want read the Log_Buffer of Trend Log 2\n" + "in Device 123, from starting position 1 and read 10 entries,\n" + "you could send the following command:\n" + "%s 123 20 2 131 1 1 10\n", filename); + printf("%s 123 20 2 131 2 1 10\n", filename); + printf("%s 123 20 2 131 3 1/1/2014 00:00:01 10\n", filename); +} + int main( int argc, char *argv[]) @@ -196,56 +205,125 @@ int main( time_t last_seconds = 0; time_t current_seconds = 0; time_t timeout_seconds = 0; - uint8_t invoke_id = 0; bool found = false; - BACNET_READ_RANGE_DATA Request; - int iCount = 0; - int iType = 0; - int iKey; - int iSecondsRun = 0; + int argi = 0; + int count = 0; + int hour, min, sec, hundredths; + int year, month, day, wday; + char *filename = NULL; - - if (((argc != 2) && (argc != 3)) || ((argc >= 2) && - (strcmp(argv[1], "--help") == 0))) { - printf("%s\n", argv[0]); - printf("Usage: %s server local-device-instance\r\n or\r\n" - " %s remote-device-instance\r\n" - "--help gives further information\r\n", - filename_remove_path(argv[0]), filename_remove_path(argv[0])); - if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) { - printf("\r\nServer mode:\r\n\r\n" - " determins the device id of the application\r\n" - "when running as the server end of a test set up. The Server simply\r\n" - "returns dummy data for each ReadRange request\r\n\r\n" - "Non server:\r\n\r\n" - " indicates the device id of the server\r\n" - "instance of the application.\r\n" - "The non server application will send a series of ReadRange requests to the\r\n" - "server with examples of different range types.\r\n"); + filename = filename_remove_path(argv[0]); + for (argi = 1; argi < argc; argi++) { + if (strcmp(argv[argi], "--help") == 0) { + print_usage(filename); + print_help(filename); + return 0; } + if (strcmp(argv[argi], "--version") == 0) { + printf("%s %s\n", filename, BACNET_VERSION_TEXT); + printf("Copyright (C) 2014 by Steve Karg and others.\n" + "This is free software; see the source for copying conditions.\n" + "There is NO warranty; not even for MERCHANTABILITY or\n" + "FITNESS FOR A PARTICULAR PURPOSE.\n"); + return 0; + } + } + if (argc < 5) { + print_usage(filename); return 0; } /* decode the command line parameters */ - if (_stricmp(argv[1], "server") == 0) - Target_Mode = 1; - else - Target_Mode = 0; - - Target_Device_Object_Instance = strtol(argv[1 + Target_Mode], NULL, 0); - + Target_Device_Object_Instance = strtol(argv[1], NULL, 0); + Target_Object_Type = strtol(argv[2], NULL, 0); + Target_Object_Instance = strtol(argv[3], NULL, 0); + Target_Object_Property = strtol(argv[4], NULL, 0); + Target_Object_Range_Type = strtol(argv[5], NULL, 0); + /* some bounds checking */ if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) { fprintf(stderr, "device-instance=%u - it must be less than %u\r\n", Target_Device_Object_Instance, BACNET_MAX_INSTANCE); return 1; } - + if (Target_Object_Range_Type == 1) { + if (argc < 7) { + print_usage(filename); + return 0; + } + RR_Request.RequestType = RR_BY_POSITION; + Target_Object_Index = strtol(argv[6], NULL, 0); + Target_Object_Count = strtol(argv[7], NULL, 0); + RR_Request.Range.RefIndex = Target_Object_Index; + RR_Request.Count = Target_Object_Count; + } else if (Target_Object_Range_Type == 2) { + if (argc < 7) { + print_usage(filename); + return 0; + } + RR_Request.RequestType = RR_BY_SEQUENCE; + Target_Object_Index = strtol(argv[6], NULL, 0); + Target_Object_Count = strtol(argv[7], NULL, 0); + RR_Request.Range.RefSeqNum = Target_Object_Index; + RR_Request.Count = Target_Object_Count; + } else if (Target_Object_Range_Type == 3) { + if (argc < 8) { + print_usage(filename); + return 0; + } + RR_Request.RequestType = RR_BY_TIME; + count = + sscanf(argv[6], "%4d/%3d/%3d:%3d", &year, &month, &day, + &wday); + if (count == 3) { + datetime_set_date(&RR_Request.Range.RefTime.date, + (uint16_t) year, + (uint8_t) month, + (uint8_t) day); + } else if (count == 4) { + RR_Request.Range.RefTime.date.year = (uint16_t) year; + RR_Request.Range.RefTime.date.month = (uint8_t) month; + RR_Request.Range.RefTime.date.day = (uint8_t) day; + RR_Request.Range.RefTime.date.wday = (uint8_t) wday; + } else { + fprintf(stderr, "Invalid date format!\r\n"); + return 1; + } + count = + sscanf(argv[7], "%3d:%3d:%3d.%3d", &hour, &min, &sec, + &hundredths); + if (count == 4) { + RR_Request.Range.RefTime.time.hour = (uint8_t) hour; + RR_Request.Range.RefTime.time.min = (uint8_t) min; + RR_Request.Range.RefTime.time.sec = (uint8_t) sec; + RR_Request.Range.RefTime.time.hundredths = (uint8_t) hundredths; + } else if (count == 3) { + RR_Request.Range.RefTime.time.hour = (uint8_t) hour; + RR_Request.Range.RefTime.time.min = (uint8_t) min; + RR_Request.Range.RefTime.time.sec = (uint8_t) sec; + RR_Request.Range.RefTime.time.hundredths = 0; + } else if (count == 2) { + RR_Request.Range.RefTime.time.hour = (uint8_t) hour; + RR_Request.Range.RefTime.time.min = (uint8_t) min; + RR_Request.Range.RefTime.time.sec = 0; + RR_Request.Range.RefTime.time.hundredths = 0; + } else { + fprintf(stderr, "Invalid time format!\r\n"); + return 1; + } + Target_Object_Count = strtol(argv[8], NULL, 0); + RR_Request.Count = Target_Object_Count; + } else if (Target_Object_Range_Type == 4) { + RR_Request.RequestType = RR_READ_ALL; + RR_Request.Count = Target_Object_Count; + } else { + fprintf(stderr, "Invalid Range Type. Use 1, 2, 3, or 4.\r\n"); + return 1; + } + RR_Request.object_type = Target_Object_Type; + RR_Request.object_instance = Target_Object_Instance; + RR_Request.object_property = Target_Object_Property; + RR_Request.array_index = BACNET_ARRAY_ALL; /* setup my info */ - if (Target_Mode) - Device_Set_Object_Instance_Number(Target_Device_Object_Instance); - else - Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); - - Init_Objects(); + Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); address_init(); Init_Service_Handlers(); dlenv_init(); @@ -253,278 +331,65 @@ int main( /* configure the timeout values */ last_seconds = time(NULL); timeout_seconds = (apdu_timeout() / 1000) * apdu_retries(); + /* try to bind with the device */ + found = + address_bind_request(Target_Device_Object_Instance, &max_apdu, + &Target_Address); + if (!found) { + Send_WhoIs(Target_Device_Object_Instance, + Target_Device_Object_Instance); + } + /* loop forever */ + for (;;) { + /* increment timer - exit if timed out */ + current_seconds = time(NULL); - if (Target_Mode) { -#if defined(WIN32) || defined(__BORLANDC__) - printf("Entering server mode. press q to quit program\r\n\r\n"); -#else - printf("Entering server mode.\r\n\r\n"); -#endif - for (;;) { - /* increment timer - exit if timed out */ - current_seconds = time(NULL); - - /* returns 0 bytes on timeout */ - pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); - - /* process */ - if (pdu_len) { - npdu_handler(&src, &Rx_Buf[0], pdu_len); - } - /* at least one second has passed */ - if (current_seconds != last_seconds) { - putchar('.'); /* Just to show that time is passing... */ - tsm_timer_milliseconds(((current_seconds - - last_seconds) * 1000)); - address_cache_timer(current_seconds - last_seconds); - trend_log_timer(current_seconds - last_seconds); - last_seconds = current_seconds; - /* Change the analog input PVs for testing purposes */ - for (iCount = 0; iCount < Analog_Input_Count(); iCount++) { - Analog_Input_Present_Value_Set(iCount, - iSecondsRun * (iCount + 1)); - } - - iSecondsRun++; - } -#if defined(WIN32) || defined(__BORLANDC__) - if (_kbhit()) { - iKey = toupper(_getch()); - if (iKey == 'Q') { - printf("\r\nExiting program now\r\n"); - exit(0); - } - } -#endif - } - } else { - - /* try to bind with the device */ - found = - address_bind_request(Target_Device_Object_Instance, &max_apdu, - &Target_Address); + /* at least one second has passed */ + if (current_seconds != last_seconds) + tsm_timer_milliseconds((uint16_t) ((current_seconds - + last_seconds) * 1000)); + if (Error_Detected) + break; + /* wait until the device is bound, or timeout and quit */ if (!found) { - Send_WhoIs(Target_Device_Object_Instance, - Target_Device_Object_Instance); + found = + address_bind_request(Target_Device_Object_Instance, &max_apdu, + &Target_Address); } - /* loop forever */ - for (;;) { - /* increment timer - exit if timed out */ - current_seconds = time(NULL); - - /* returns 0 bytes on timeout */ - pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); - - /* process */ - if (pdu_len) { - npdu_handler(&src, &Rx_Buf[0], pdu_len); - } - /* at least one second has passed */ - if (current_seconds != last_seconds) { - tsm_timer_milliseconds(((current_seconds - - last_seconds) * 1000)); - address_cache_timer(current_seconds - last_seconds); - trend_log_timer(current_seconds - last_seconds); - last_seconds = current_seconds; - } - if (Error_Detected) + if (found) { + if (Request_Invoke_ID == 0) { + Request_Invoke_ID = Send_ReadRange_Request( + Target_Device_Object_Instance, + &RR_Request); + } else if (tsm_invoke_id_free(Request_Invoke_ID)) + break; + else if (tsm_invoke_id_failed(Request_Invoke_ID)) { + fprintf(stderr, "\rError: TSM Timeout!\n"); + tsm_free_invoke_id(Request_Invoke_ID); + Error_Detected = true; + /* try again or abort? */ + break; + } + } else { + /* increment timer - exit if timed out */ + elapsed_seconds += (current_seconds - last_seconds); + if (elapsed_seconds > timeout_seconds) { + printf("\rError: APDU Timeout!\n"); + Error_Detected = true; break; - /* wait until the device is bound, or timeout and quit */ - if (!found) - found = - address_bind_request(Target_Device_Object_Instance, - &max_apdu, &Target_Address); - if (found) { - if (invoke_id == 0) { /* Safe to send a new request */ - switch (iCount) { - case 0: /* Pass - should read up to 1st 10 */ - Request.RequestType = RR_BY_POSITION; - Request.Range.RefIndex = 1; - Request.Count = 10; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - - case 1: /* Pass - should read entries 2 and 3 */ - Request.RequestType = RR_BY_POSITION; - Request.Range.RefSeqNum = 3; - Request.Count = -2; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - - case 2: /* Fail - By Time not supported */ - Request.RequestType = RR_BY_TIME; - Request.Range.RefTime.date.year = 2009; - Request.Range.RefTime.date.month = 9; - Request.Range.RefTime.date.day = 23; - Request.Range.RefTime.date.wday = 0xFF; - Request.Range.RefTime.time.hour = 22; - Request.Range.RefTime.time.min = 23; - Request.Range.RefTime.time.sec = 24; - Request.Range.RefTime.time.hundredths = 0; - - Request.Count = 10; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - - case 3: /* Fail - array not supported */ - Request.RequestType = RR_BY_POSITION; - Request.Range.RefIndex = 1; - Request.Count = 10; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 1; - break; - - case 4: /* Fail - By Sequence not supported */ - Request.RequestType = RR_BY_SEQUENCE; - Request.Range.RefSeqNum = 1; - Request.Count = 10; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - - case 5: /* Fail Bytime not supported and array not supported */ - Request.RequestType = RR_BY_TIME; - Request.Range.RefTime.date.year = 2009; - Request.Range.RefTime.date.month = 9; - Request.Range.RefTime.date.day = 23; - Request.Range.RefTime.date.wday = 0xFF; /* Day of week unspecified */ - Request.Range.RefTime.time.hour = 22; - Request.Range.RefTime.time.min = 23; - Request.Range.RefTime.time.sec = 24; - Request.Range.RefTime.time.hundredths = 0; - - Request.Count = 10; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 1; - break; - - case 6: /* Pass - should try to return all entries */ - Request.RequestType = RR_READ_ALL; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - - case 7: /* Fail - array not supported */ - Request.RequestType = RR_READ_ALL; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 1; - break; - - case 8: /* Pass - should read 1st 1 */ - Request.RequestType = RR_BY_POSITION; - Request.Range.RefIndex = 1; - Request.Count = 1; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - - case 9: /* Pass - should read 1st 2 */ - Request.RequestType = RR_BY_POSITION; - Request.Range.RefIndex = 1; - Request.Count = 2; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - - case 10: /* Pass - should read 2nd and 3rd */ - Request.RequestType = RR_BY_POSITION; - Request.Range.RefIndex = 2; - Request.Count = 2; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - - case 11: /* Pass - should read 2nd up to 11th */ - Request.RequestType = RR_BY_POSITION; - Request.Range.RefIndex = 2; - Request.Count = 10; - Request.object_type = OBJECT_DEVICE; - Request.object_instance = - Target_Device_Object_Instance; - Request.object_property = - PROP_DEVICE_ADDRESS_BINDING; - Request.array_index = 0; - break; - } - - invoke_id = - Send_ReadRange_Request(Target_Device_Object_Instance, - &Request); - } else if (tsm_invoke_id_free(invoke_id)) { - if (iCount != 11) { - iCount++; - invoke_id = 0; - } else { - break; - } - } else if (tsm_invoke_id_failed(invoke_id)) { - fprintf(stderr, "\rError: TSM Timeout!\r\n"); - tsm_free_invoke_id(invoke_id); - /* Error_Detected = true; */ - /* try again or abort? */ - invoke_id = 0; /* Try next operation */ - /* break; */ - } - } else { - /* increment timer - exit if timed out */ - elapsed_seconds += (current_seconds - last_seconds); - if (elapsed_seconds > timeout_seconds) { - printf("\rError: APDU Timeout!\r\n"); - /* Error_Detected = true; - break; */ - invoke_id = 0; - } } - /* keep track of time for next check */ - last_seconds = current_seconds; } + + /* returns 0 bytes on timeout */ + pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); + + /* process */ + if (pdu_len) { + npdu_handler(&src, &Rx_Buf[0], pdu_len); + } + + /* keep track of time for next check */ + last_seconds = current_seconds; } if (Error_Detected) diff --git a/bacnet-stack/demo/readrange/makefile.b32 b/bacnet-stack/demo/readrange/makefile.b32 deleted file mode 100644 index 145a2d72..00000000 --- a/bacnet-stack/demo/readrange/makefile.b32 +++ /dev/null @@ -1,139 +0,0 @@ -# -# Simple makefile to build an executable for Win32 -# -# This makefile assumes Borland bcc32 development environment -# on Windows NT/9x/2000/XP -# - -!ifndef BORLAND_DIR -BORLAND_DIR_Not_Defined: - @echo . - @echo You must define environment variable BORLAND_DIR to compile. -!endif - -PRODUCT = bacrr -PRODUCT_EXE = $(PRODUCT).exe - -# tools -CC = $(BORLAND_DIR)\bin\bcc32 -MAKE=$(BORLAND_DIR)\bin\make.exe -#LINK = $(BORLAND_DIR)\bin\tlink32 -LINK = $(BORLAND_DIR)\bin\ilink32 - -BACNET_LIB_DIR = ..\..\lib -BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib - -# directories -BACNET_PORT = ..\..\ports\win32 -BACNET_INCLUDE = ..\..\include -BACNET_OBJECT = ..\object -BACNET_HANDLER = ..\handler -INCLUDES = \ - -I$(BACNET_INCLUDE) \ - -I$(BACNET_PORT) \ - -I$(BACNET_OBJECT) \ - -I$(BACNET_HANDLER) \ - -I$(BORLAND_DIR)\include - -# -BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL -#BACDL_DEFINE=-DBACDL_MSTP=1 -BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1 -DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) - -SRCS = main.c \ - $(BACNET_OBJECT)\device-client.c - -OBJS = $(SRCS:.c=.obj) - -# -# Compiler definitions -# -BCC_CFG = bcc32.cfg - -# -# Include directories -# -CFLAGS = $(INCLUDES) $(DEFINES) - -# -# Libraries -# -C_LIB_DIR = $(BORLAND_DIR)\lib - -LIBS = $(BACNET_LIB) \ - $(C_LIB_DIR)\IMPORT32.lib \ - $(C_LIB_DIR)\CW32MT.lib \ - -# -# Main target -# -# This should be the first one in the makefile - -all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE) - del $(BCC_CFG) - -install: $(PRODUCT_EXE) - copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE) - -# Linker specific: the link below is for BCC linker/compiler. If you link -# with a different linker - please change accordingly. -# - -# need a temp response file (@&&| ... |) because command line is too long -# $** lists each dependency -# $< target name -# $* target name without extension -$(PRODUCT_EXE) : $(OBJS) - @echo Running Linker for $(PRODUCT_EXE) - $(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&| - $(BORLAND_DIR)\lib\c0x32.obj $** - $< - $*.map - $(LIBS) -| - -# -# Utilities - -clean : - del $(OBJS) - del $(PRODUCT_EXE) - del $(PRODUCT).map - del $(PRODUCT).ilc - del $(PRODUCT).ild - del $(PRODUCT).ilf - del $(PRODUCT).ils - del $(PRODUCT).tds - del $(BCC_CFG) - -# -# Generic rules -# -.SUFFIXES: .cpp .c .sbr .obj - -# -# cc generic rule -# -.c.obj: - $(CC) +$(BCC_CFG) -o$@ $< - -# Compiler configuration file -$(BCC_CFG): - Copy &&| - $(CFLAGS) - -c - -y #include line numbers in OBJ's - -v #include debug info - -w+ #turn on all warnings - -Od #disable all optimizations - #-a4 #32 bit data alignment - #-M # generate link map - #-ls # linker options - #-WM- #not multithread - -WM #multithread - -w-aus # ignore warning assigned a value that is never used - -w-sig # ignore warning conversion may lose sig digits -| $@ - -# EOF: makefile diff --git a/bacnet-stack/lib/Makefile b/bacnet-stack/lib/Makefile index 606dfc73..d51536ca 100644 --- a/bacnet-stack/lib/Makefile +++ b/bacnet-stack/lib/Makefile @@ -87,6 +87,7 @@ HANDLER_SRC = \ $(BACNET_HANDLER)/h_rpm.c \ $(BACNET_HANDLER)/h_rpm_a.c \ $(BACNET_HANDLER)/h_rr.c \ + $(BACNET_HANDLER)/h_rr_a.c \ $(BACNET_HANDLER)/h_wp.c \ $(BACNET_HANDLER)/h_wpm.c \ $(BACNET_HANDLER)/h_alarm_ack.c \ @@ -119,6 +120,7 @@ HANDLER_SRC = \ $(BACNET_HANDLER)/s_ptransfer.c \ $(BACNET_HANDLER)/s_rd.c \ $(BACNET_HANDLER)/s_rp.c \ + $(BACNET_HANDLER)/s_readrange.c \ $(BACNET_HANDLER)/s_rpm.c \ $(BACNET_HANDLER)/s_ts.c \ $(BACNET_HANDLER)/s_cevent.c \