From e3f91b39161618212c987175616ad457ebcda143 Mon Sep 17 00:00:00 2001 From: skarg Date: Sun, 23 Nov 2008 22:41:57 +0000 Subject: [PATCH] Added ReadPropertyMultiple client demo bacrpm. --- bacnet-stack/demo/readprop/Makefile | 2 +- bacnet-stack/demo/readprop/bacrpm.cbp | 55 +++++++++ bacnet-stack/demo/readprop/main.c | 152 ++++++++++++++++++------ bacnet-stack/demo/readprop/makefile.b32 | 6 +- 4 files changed, 173 insertions(+), 42 deletions(-) create mode 100644 bacnet-stack/demo/readprop/bacrpm.cbp diff --git a/bacnet-stack/demo/readprop/Makefile b/bacnet-stack/demo/readprop/Makefile index e15a87b4..3077c344 100644 --- a/bacnet-stack/demo/readprop/Makefile +++ b/bacnet-stack/demo/readprop/Makefile @@ -2,7 +2,7 @@ # Compiler to use CC = gcc # Executable file name -TARGET = bacrp +TARGET = bacrpm # Configure the BACnet Datalink Layer #BACDL_DEFINE = -DBACDL_ETHERNET=1 diff --git a/bacnet-stack/demo/readprop/bacrpm.cbp b/bacnet-stack/demo/readprop/bacrpm.cbp new file mode 100644 index 00000000..e97178af --- /dev/null +++ b/bacnet-stack/demo/readprop/bacrpm.cbp @@ -0,0 +1,55 @@ + + + + + + diff --git a/bacnet-stack/demo/readprop/main.c b/bacnet-stack/demo/readprop/main.c index ef82b2a4..72017fed 100644 --- a/bacnet-stack/demo/readprop/main.c +++ b/bacnet-stack/demo/readprop/main.c @@ -1,5 +1,5 @@ /************************************************************************* -* Copyright (C) 2006 Steve Karg +* Copyright (C) 2008 Steve Karg * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -47,6 +47,7 @@ #include "datalink.h" #include "whois.h" /* some demo stuff needed */ +#include "rpm.h" #include "filename.h" #include "handlers.h" #include "client.h" @@ -57,10 +58,7 @@ static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; /* global variables used in this file */ static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE; -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 int32_t Target_Object_Index = BACNET_ARRAY_ALL; +static BACNET_READ_ACCESS_DATA *Read_Access_Data; static BACNET_ADDRESS Target_Address; static bool Error_Detected = false; @@ -124,8 +122,8 @@ static void Init_Service_Handlers( apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property); /* 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_PROP_MULTIPLE, + handler_read_property_multiple_ack); /* handle any errors coming back */ apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler); apdu_set_abort_handler(MyAbortHandler); @@ -218,22 +216,49 @@ static void Init_DataLink( #endif } +void cleanup(void) +{ + BACNET_READ_ACCESS_DATA *rpm_object; + BACNET_READ_ACCESS_DATA *old_rpm_object; + BACNET_PROPERTY_REFERENCE *rpm_property; + BACNET_PROPERTY_REFERENCE *old_rpm_property; + + rpm_object = Read_Access_Data; + old_rpm_object = rpm_object; + while (rpm_object) { + rpm_property = rpm_object->listOfProperties; + while (rpm_property) { + old_rpm_property = rpm_property; + rpm_property = rpm_property->next; + free(old_rpm_property); + } + old_rpm_object = rpm_object; + rpm_object = rpm_object->next; + free(old_rpm_object); + } +} + int main(int argc, char *argv[]) { BACNET_ADDRESS src = { 0}; /* address where message came from */ uint16_t pdu_len = 0; unsigned timeout = 100; /* milliseconds */ unsigned max_apdu = 0; + int args_remaining = 0, tag_value_arg = 0, arg_sets = 0; time_t elapsed_seconds = 0; time_t last_seconds = 0; time_t current_seconds = 0; time_t timeout_seconds = 0; uint8_t invoke_id = 0; bool found = false; + uint8_t buffer[MAX_PDU] = {0}; + BACNET_READ_ACCESS_DATA *rpm_object; + BACNET_PROPERTY_REFERENCE *rpm_property; + if (argc < 5) { printf("Usage: %s device-instance object-type object-instance " - "property [index]\r\n", filename_remove_path(argv[0])); + "property index [object-type ...]\r\n", filename_remove_path(argv[0])); if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) { printf("device-instance:\r\n" "BACnet Device Object Instance number that you are\r\n" @@ -261,44 +286,94 @@ int main(int argc, char *argv[]) { "be read. If this parameter is missing and the property\r\n" "is an array, the entire array will be read.\r\n" "\r\nExample:\r\n" - "If you want read the Present-Value of Analog Output 101\r\n" - "in Device 123, you could send the following command:\r\n" - "%s 123 1 101 85\r\n" - "If you want read the Priority-Array of Analog Output 101\r\n" - "in Device 123, you could send the following command:\r\n" - "%s 123 1 101 87\r\n", filename_remove_path(argv[0]), + "If you want read the ALL property in\r\n" + "Device object 123, you would use the following command:\r\n" + "%s 123 8 123 8 -1\r\n" + "If you want read the OPTIONAL property in\r\n" + "Device object 123, you would use the following command:\r\n" + "%s 123 8 123 80 -1\r\n" + "If you want read the REQUIRED property in\r\n" + "Device object 123, you would use the following command:\r\n" + "%s 123 8 123 105 -1\r\n", + filename_remove_path(argv[0]), + filename_remove_path(argv[0]), filename_remove_path(argv[0])); } return 0; } /* decode the command line parameters */ 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); - if (argc > 5) - Target_Object_Index = strtol(argv[5], NULL, 0); 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_Type > MAX_BACNET_OBJECT_TYPE) { - fprintf(stderr, "object-type=%u - it must be less than %u\r\n", - Target_Object_Type, MAX_BACNET_OBJECT_TYPE + 1); - return 1; + atexit(cleanup); + Read_Access_Data = calloc(1, sizeof(BACNET_READ_ACCESS_DATA)); + rpm_object = Read_Access_Data; + args_remaining = (argc - 2); + arg_sets = 0; + while (rpm_object) { + tag_value_arg = 2 + (arg_sets * 4); + rpm_object->object_type = + strtol(argv[tag_value_arg], NULL, 0); + tag_value_arg++; + args_remaining--; + if (args_remaining <= 0) { + fprintf(stderr, "Error: not enough object property quads.\r\n"); + return 1; + } + if (rpm_object->object_type > MAX_BACNET_OBJECT_TYPE) { + fprintf(stderr, "object-type=%u - it must be less than %u\r\n", + rpm_object->object_type, MAX_BACNET_OBJECT_TYPE + 1); + return 1; + } + rpm_object->object_instance = + strtol(argv[tag_value_arg], NULL, 0); + tag_value_arg++; + args_remaining--; + if (args_remaining <= 0) { + fprintf(stderr, "Error: not enough object property quads.\r\n"); + return 1; + } + if (rpm_object->object_instance > BACNET_MAX_INSTANCE) { + fprintf(stderr, "object-instance=%u - it must be less than %u\r\n", + rpm_object->object_instance, BACNET_MAX_INSTANCE + 1); + return 1; + } + rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE)); + rpm_object->listOfProperties = rpm_property; + if (rpm_property) { + rpm_property->propertyIdentifier = + strtol(argv[tag_value_arg], NULL, 0); + /* used up another arg */ + tag_value_arg++; + args_remaining--; + if (args_remaining <= 0) { + fprintf(stderr, "Error: not enough object property quads.\r\n"); + return 1; + } + if (rpm_property->propertyIdentifier > MAX_BACNET_PROPERTY_ID) { + fprintf(stderr, "property=%u - it must be less than %u\r\n", + rpm_property->propertyIdentifier, MAX_BACNET_PROPERTY_ID + 1); + return 1; + } + rpm_property->propertyArrayIndex = + strtol(argv[tag_value_arg], NULL, 0); + /* note: we are only loading one property for now */ + rpm_property->next = NULL; + /* used up another arg */ + tag_value_arg++; + args_remaining--; + } + if (args_remaining) { + arg_sets++; + rpm_object->next = calloc(1, sizeof(BACNET_READ_ACCESS_DATA)); + rpm_object = rpm_object->next; + } else { + break; + } } - if (Target_Object_Instance > BACNET_MAX_INSTANCE) { - fprintf(stderr, "object-instance=%u - it must be less than %u\r\n", - Target_Object_Instance, BACNET_MAX_INSTANCE + 1); - return 1; - } - if (Target_Object_Property > MAX_BACNET_PROPERTY_ID) { - fprintf(stderr, "property=%u - it must be less than %u\r\n", - Target_Object_Property, MAX_BACNET_PROPERTY_ID + 1); - return 1; - } - /* setup my info */ Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); address_init(); @@ -338,10 +413,11 @@ int main(int argc, char *argv[]) { &Target_Address); if (found) { if (invoke_id == 0) { - invoke_id = - Send_Read_Property_Request(Target_Device_Object_Instance, - Target_Object_Type, Target_Object_Instance, - Target_Object_Property, Target_Object_Index); + invoke_id = Send_Read_Property_Multiple_Request( + &buffer[0], + sizeof(buffer), + Target_Device_Object_Instance, + Read_Access_Data); } else if (tsm_invoke_id_free(invoke_id)) break; else if (tsm_invoke_id_failed(invoke_id)) { diff --git a/bacnet-stack/demo/readprop/makefile.b32 b/bacnet-stack/demo/readprop/makefile.b32 index b0893dc4..888309e2 100644 --- a/bacnet-stack/demo/readprop/makefile.b32 +++ b/bacnet-stack/demo/readprop/makefile.b32 @@ -11,7 +11,7 @@ BORLAND_DIR_Not_Defined: @echo You must define environment variable BORLAND_DIR to compile. !endif -PRODUCT = bacrp +PRODUCT = bacrpm PRODUCT_EXE = $(PRODUCT).exe # tools @@ -26,7 +26,7 @@ BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib # directories BACNET_PORT = ..\..\ports\win32 BACNET_INCLUDE = ..\..\include -INCLUDES = \ +INCLUDES = \ -I$(BACNET_INCLUDE) \ -I$(BACNET_PORT) \ -I$(BORLAND_DIR)\include @@ -65,7 +65,7 @@ LIBS = $(BACNET_LIB) \ # # This should be the first one in the makefile -all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE) +all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE) del $(BCC_CFG) install: $(PRODUCT_EXE)