From cef68dc0792e9c48bb9db9b2530a9b1da04432da Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Tue, 2 Dec 2025 11:27:19 -0600 Subject: [PATCH] Feature/refactor-apps-string-parsing (#1152) * Added bacnet_str functions for parsing various numeric strings. * Renamed BACnet string API to be clearer when no stdlib function exists. * Fixed incompatible types - from 'BACNET_UNSIGNED_INTEGER *' to 'unsigned long *' warning * Changed bacnet-str-to functions to use ERANGE for error detection. * Refactored some apps to use common string parsing for BACnet data types. * Refactor bacapp_parse_application_data to use bacnet_string_to_unsigned for better clarity * Added strtol for BACnetEventType. --- CHANGELOG.md | 1 + apps/abort/main.c | 69 ++++---- apps/ack-alarm/main.c | 102 +++++++----- apps/add-list-element/main.c | 79 ++++++--- apps/apdu/main.c | 11 +- apps/blinkt/main.c | 10 +- apps/create-object/main.c | 26 ++- apps/dcc/main.c | 143 ++++++++++++---- apps/delete-object/main.c | 26 ++- apps/error/main.c | 56 +++---- apps/event/main.c | 282 +++----------------------------- apps/iam/main.c | 5 +- apps/readprop/main.c | 5 +- apps/readpropm/main.c | 5 +- apps/remove-list-element/main.c | 61 ++++--- apps/server-mini/main.c | 2 +- apps/timesync/main.c | 5 +- apps/uevent/main.c | 210 ++---------------------- apps/who-am-i/main.c | 5 +- apps/whois/main.c | 5 +- apps/writeprop/main.c | 5 +- apps/you-are/main.c | 5 +- src/bacnet/bactext.c | 173 ++++++++++++++++++++ src/bacnet/bactext.h | 9 + src/bacnet/event.c | 262 +++++++++++++++++++++++++++++ src/bacnet/event.h | 4 + 26 files changed, 904 insertions(+), 662 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 074df890..f8c32d32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ The git repositories are hosted at the following sites: ### Changed +* Changed apps to use common BACnet value string parsing functions. (#1152) * Changed basic object API for units properties to use BACNET_ENGINEERING_UNITS datatype. (#1104) * Changed all the property list values into int32_t to support the larger diff --git a/apps/abort/main.c b/apps/abort/main.c index be22b01d..462a753c 100644 --- a/apps/abort/main.c +++ b/apps/abort/main.c @@ -121,6 +121,8 @@ int main(int argc, char *argv[]) BACNET_MAC_ADDRESS mac = { 0 }; BACNET_MAC_ADDRESS adr = { 0 }; BACNET_ADDRESS dest = { 0 }; + unsigned long long_value = 0; + bool server = false; bool specific_address = false; int argi = 0; unsigned int target_args = 0; @@ -150,7 +152,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } @@ -163,13 +168,37 @@ int main(int argc, char *argv[]) } } else { if (target_args == 0) { - Target_Abort_Reason = strtol(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &long_value)) { + fprintf(stderr, "abort-reason=%s invalid\n", argv[argi]); + return 1; + } + if (long_value > UINT16_MAX) { + fprintf( + stderr, "abort-reason=%lu exceeds %u\n", long_value, + UINT16_MAX); + return 1; + } + Target_Abort_Reason = (uint16_t)long_value; target_args++; } else if (target_args == 1) { - Target_Invoke_ID = strtol(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &long_value)) { + fprintf(stderr, "invoke-id=%s invalid\n", argv[argi]); + return 1; + } + if (long_value > UINT8_MAX) { + fprintf( + stderr, "invoke-id=%lu exceeds %u\n", long_value, + UINT8_MAX); + return 1; + } + Target_Invoke_ID = (uint8_t)long_value; target_args++; } else if (target_args == 2) { - Target_Server = strtol(argv[argi], NULL, 0); + if (!bacnet_string_to_bool(argv[argi], &server)) { + fprintf(stderr, "server=%s invalid\n", argv[argi]); + return 1; + } + Target_Server = server; target_args++; } else { print_usage(filename); @@ -177,41 +206,13 @@ int main(int argc, char *argv[]) } } } - address_init(); + /* setup my info */ if (specific_address) { - if (adr.len && mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - memcpy(&dest.adr[0], &adr.adr[0], adr.len); - dest.len = adr.len; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - } else if (mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - dest.len = 0; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = 0; - } - } else { - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - dest.mac_len = 0; - dest.len = 0; - } + bacnet_address_init(&dest, &mac, dnet, &adr); } /* setup my info */ Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); Init_Service_Handlers(); - address_init(); dlenv_init(); atexit(datalink_cleanup); /* send the request */ diff --git a/apps/ack-alarm/main.c b/apps/ack-alarm/main.c index dd693fd8..0f5516f4 100644 --- a/apps/ack-alarm/main.c +++ b/apps/ack-alarm/main.c @@ -220,7 +220,8 @@ int main(int argc, char *argv[]) time_t timeout_seconds = 0; bool found = false; long dnet = -1; - unsigned object_type = 0; + unsigned long long_value = 0; + uint32_t object_type = 0; BACNET_MAC_ADDRESS mac = { 0 }; BACNET_MAC_ADDRESS adr = { 0 }; BACNET_ADDRESS dest = { 0 }; @@ -253,7 +254,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } @@ -267,26 +271,56 @@ int main(int argc, char *argv[]) } else { if (target_args == 0) { /* device-id */ - Target_Device_Object_Instance = strtol(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &long_value)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } + if (long_value > BACNET_MAX_INSTANCE) { + fprintf( + stderr, "device-instance=%lu - exceeds %d\n", + long_value, BACNET_MAX_INSTANCE); + return 1; + } + Target_Device_Object_Instance = (uint32_t)long_value; target_args++; } else if (target_args == 1) { /* process-id */ - data.ackProcessIdentifier = strtol(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &long_value)) { + fprintf(stderr, "process-id=%s invalid\n", argv[argi]); + return 1; + } + if (long_value > UINT32_MAX) { + fprintf( + stderr, "process-id=%lu - exceeds %u\n", long_value, + UINT32_MAX); + return 1; + } + data.ackProcessIdentifier = (uint32_t)long_value; target_args++; } else if (target_args == 2) { /* event-object-type */ - if (bactext_object_type_strtol(argv[argi], &object_type)) { - data.eventObjectIdentifier.type = object_type; - target_args++; - } else { + if (!bactext_object_type_strtol(argv[argi], &object_type)) { fprintf( stderr, "event-object-type=%s invalid\n", argv[argi]); return 1; } + data.eventObjectIdentifier.type = object_type; + target_args++; } else if (target_args == 3) { /* event-object-instance */ - data.eventObjectIdentifier.instance = - strtol(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &long_value)) { + fprintf( + stderr, "event-object-instance=%s invalid\n", + argv[argi]); + return 1; + } + if (long_value > BACNET_MAX_INSTANCE) { + fprintf( + stderr, "event-object-instance=%lu - exceeds %u\n", + long_value, BACNET_MAX_INSTANCE); + return 1; + } + data.eventObjectIdentifier.instance = (uint32_t)long_value; target_args++; } else if (target_args == 4) { /* event-state-acked */ @@ -299,15 +333,27 @@ int main(int argc, char *argv[]) } } else if (target_args == 5) { /* event-time-stamp */ - bacapp_timestamp_init_ascii(&data.eventTimeStamp, argv[argi]); + if (!bacapp_timestamp_init_ascii( + &data.eventTimeStamp, argv[argi])) { + fprintf( + stderr, "event-time-stamp=%s invalid\n", argv[argi]); + return 1; + } target_args++; } else if (target_args == 6) { /* ack-source */ - characterstring_init_ansi(&data.ackSource, argv[argi]); + if (!characterstring_init_ansi(&data.ackSource, argv[argi])) { + fprintf(stderr, "ack-source=%s invalid\n", argv[argi]); + return 1; + } target_args++; } else if (target_args == 7) { /* ack-time-stamp */ - bacapp_timestamp_init_ascii(&data.ackTimeStamp, argv[argi]); + if (!bacapp_timestamp_init_ascii( + &data.ackTimeStamp, argv[argi])) { + fprintf(stderr, "ack-time-stamp=%s invalid\n", argv[argi]); + return 1; + } target_args++; } else { print_usage(filename); @@ -319,36 +365,10 @@ int main(int argc, char *argv[]) print_usage(filename); return 0; } + /* setup my info */ address_init(); if (specific_address) { - if (adr.len && mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - memcpy(&dest.adr[0], &adr.adr[0], adr.len); - dest.len = adr.len; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - } else if (mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - dest.len = 0; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = 0; - } - } else { - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - dest.mac_len = 0; - dest.len = 0; - } + bacnet_address_init(&dest, &mac, dnet, &adr); address_add(Target_Device_Object_Instance, MAX_APDU, &dest); printf( "Added Device %u to address cache\n", diff --git a/apps/add-list-element/main.c b/apps/add-list-element/main.c index d54dd0b9..4b106054 100644 --- a/apps/add-list-element/main.c +++ b/apps/add-list-element/main.c @@ -154,6 +154,24 @@ static void print_help(const char *filename) printf("Add a BACnetLIST element to a property of an object\n" "in a BACnet device.\n"); printf("\n"); + printf("--mac A\n" + "Optional BACnet mac address.\n" + "Valid ranges are from 00 to FF (hex) for MS/TP or ARCNET,\n" + "or an IP string with optional port number like 10.1.2.3:47808\n" + "or an Ethernet MAC in hex like 00:21:70:7e:32:bb\n"); + printf("\n"); + printf("--dnet N\n" + "Optional BACnet network number N for directed requests.\n" + "Valid range is from 0 to 65535 where 0 is the local connection\n" + "and 65535 is network broadcast.\n"); + printf("\n"); + printf("--dadr A\n" + "Optional BACnet mac address on the destination BACnet network " + "number.\n" + "Valid ranges are from 00 to FF (hex) for MS/TP or ARCNET,\n" + "or an IP string with optional port number like 10.1.2.3:47808\n" + "or an Ethernet MAC in hex like 00:21:70:7e:32:bb\n"); + printf("\n"); printf("device-instance:\n" "BACnet Device Object Instance number that you are\n" "trying to communicate to. This number will be used\n" @@ -234,12 +252,12 @@ int main(int argc, char *argv[]) bool found = false; char *value_string = NULL; bool status = false; - unsigned context_tag = 0; + unsigned long context_tag = 0; BACNET_APPLICATION_DATA_VALUE *application_value = NULL; - unsigned object_type = 0; - unsigned object_instance = 0; - unsigned property_id = 0; - unsigned property_array_index = 0; + uint32_t object_type = 0; + unsigned long object_instance = 0; + uint32_t property_id = 0; + long property_array_index = 0; long property_tag = 0; long dnet = -1; BACNET_MAC_ADDRESS mac = { 0 }; @@ -274,7 +292,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= UINT16_MAX)) { specific_address = true; } @@ -289,39 +310,43 @@ int main(int argc, char *argv[]) Verbose = true; } else { if (target_args == 0) { - object_instance = strtoul(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &object_instance)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } if (object_instance > BACNET_MAX_INSTANCE) { fprintf( - stderr, "device-instance=%u - not greater than %u\n", + stderr, "device-instance=%lu - not greater than %u\n", object_instance, BACNET_MAX_INSTANCE); return 1; } Target_Device_Object_Instance = object_instance; target_args++; } else if (target_args == 1) { - if (bactext_object_type_strtol(argv[argi], &object_type) == - false) { + if (!bactext_object_type_strtol(argv[argi], &object_type)) { fprintf(stderr, "object-type=%s invalid\n", argv[argi]); return 1; } Target_Object_Type = object_type; target_args++; } else if (target_args == 2) { - object_instance = strtoul(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &object_instance)) { + fprintf(stderr, "object-instance=%s invalid\n", argv[argi]); + return 1; + } if (object_instance > BACNET_MAX_INSTANCE) { fprintf( - stderr, "device-instance=%u - not greater than %u\n", + stderr, "object-instance=%u - not greater than %u\n", Target_Device_Object_Instance, BACNET_MAX_INSTANCE); return 1; } Target_Object_Instance = object_instance; if (Verbose) { - printf("Instance=%u=%s\n", object_instance, argv[argi]); + printf("Instance=%lu=%s\n", object_instance, argv[argi]); } target_args++; } else if (target_args == 3) { - if (bactext_property_strtol(argv[argi], &property_id) == - false) { + if (!bactext_property_strtol(argv[argi], &property_id)) { fprintf(stderr, "property=%s invalid\n", argv[argi]); return 1; } @@ -331,11 +356,18 @@ int main(int argc, char *argv[]) } target_args++; } else if (target_args == 4) { - property_array_index = strtol(argv[argi], NULL, 0); - Target_Object_Array_Index = property_array_index; + if (!bacnet_strtol(argv[argi], &property_array_index)) { + fprintf(stderr, "array-index=%s invalid\n", argv[argi]); + return 1; + } + if (property_array_index < 0) { + Target_Object_Array_Index = BACNET_ARRAY_ALL; + } else { + Target_Object_Array_Index = property_array_index; + } if (Verbose) { printf( - "Array_Index=%i=%s\n", property_array_index, + "Array_Index=%li=%s\n", property_array_index, argv[argi]); } target_args++; @@ -346,7 +378,11 @@ int main(int argc, char *argv[]) if (tag_value_arg == 0) { /* special case for context tagged values */ if (toupper(argv[argi][0]) == 'C') { - context_tag = strtoul(&argv[target_args][1], NULL, 0); + if (!bacnet_strtoul( + &argv[target_args][1], &context_tag)) { + fprintf(stderr, "tag=%s invalid\n", argv[argi]); + return 1; + } application_value->context_tag = context_tag; application_value->context_specific = true; argi++; @@ -354,7 +390,10 @@ int main(int argc, char *argv[]) application_value->context_specific = false; } /* application tag */ - property_tag = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &property_tag)) { + fprintf(stderr, "tag=%s invalid\n", argv[argi]); + return 1; + } if (Verbose) { printf("tag=%ld\n", property_tag); } diff --git a/apps/apdu/main.c b/apps/apdu/main.c index 9c34dd27..1ac0e7f9 100644 --- a/apps/apdu/main.c +++ b/apps/apdu/main.c @@ -329,7 +329,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } @@ -359,7 +362,11 @@ int main(int argc, char *argv[]) } } else { if (target_args == 0) { - Target_Device_Object_Instance = strtol(argv[argi], NULL, 0); + if (!bacnet_string_to_uint32( + argv[argi], &Target_Device_Object_Instance)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } target_args++; } else if (target_args == 1) { APDU_Hex_ASCII = argv[argi]; diff --git a/apps/blinkt/main.c b/apps/blinkt/main.c index ddd36206..78635050 100644 --- a/apps/blinkt/main.c +++ b/apps/blinkt/main.c @@ -381,13 +381,19 @@ int main(int argc, char *argv[]) } if (strcmp(argv[argi], "--device") == 0) { if (++argi < argc) { - device_id = strtol(argv[argi], NULL, 0); + if (!bacnet_string_to_uint32(argv[argi], &device_id)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } } } else if (strcmp(argv[argi], "--test") == 0) { blinkt_test = true; } else { if (target_args == 0) { - device_id = strtol(argv[argi], NULL, 0); + if (!bacnet_string_to_uint32(argv[argi], &device_id)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } target_args++; } } diff --git a/apps/create-object/main.c b/apps/create-object/main.c index 907c3246..4a9499e1 100644 --- a/apps/create-object/main.c +++ b/apps/create-object/main.c @@ -229,8 +229,8 @@ int main(int argc, char *argv[]) struct mstimer apdu_timer; struct mstimer maintenance_timer; bool found = false; - unsigned object_type = 0; - unsigned object_instance = 0; + unsigned long object_type = 0; + unsigned long object_instance = 0; long dnet = -1; BACNET_MAC_ADDRESS mac = { 0 }; BACNET_MAC_ADDRESS adr = { 0 }; @@ -264,7 +264,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= UINT16_MAX)) { specific_address = true; } @@ -279,25 +282,30 @@ int main(int argc, char *argv[]) Verbose = true; } else { if (target_args == 0) { - object_instance = strtoul(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &object_instance)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } if (object_instance > BACNET_MAX_INSTANCE) { fprintf( - stderr, "device-instance=%u - not greater than %u\n", + stderr, "device-instance=%lu - not greater than %u\n", object_instance, BACNET_MAX_INSTANCE); return 1; } Target_Device_Object_Instance = object_instance; target_args++; } else if (target_args == 1) { - if (bactext_object_type_strtol(argv[argi], &object_type) == - false) { + if (!bacnet_strtoul(argv[argi], &object_type)) { fprintf(stderr, "object-type=%s invalid\n", argv[argi]); return 1; } Target_Object_Type = object_type; target_args++; } else if (target_args == 2) { - object_instance = strtoul(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &object_instance)) { + fprintf(stderr, "object-instance=%s invalid\n", argv[argi]); + return 1; + } if (object_instance > BACNET_MAX_INSTANCE) { fprintf( stderr, "object-instance=%u - not greater than %u\n", @@ -306,7 +314,7 @@ int main(int argc, char *argv[]) } Target_Object_Instance = object_instance; if (Verbose) { - printf("Instance=%u=%s\n", object_instance, argv[argi]); + printf("Instance=%lu=%s\n", object_instance, argv[argi]); } target_args++; } diff --git a/apps/dcc/main.c b/apps/dcc/main.c index 6bbbaf76..ea5a3d1d 100644 --- a/apps/dcc/main.c +++ b/apps/dcc/main.c @@ -121,27 +121,59 @@ static void Init_Service_Handlers(void) static void print_usage(const char *filename) { printf("Usage: %s device-instance state [timeout [password]]\n", filename); + printf(" [--dnet][--dadr][--mac]\n"); printf(" [--version][--help]\n"); } static void print_help(const char *filename) { + printf("Send BACnet DeviceCommunicationControl service to device.\n"); + printf("\n"); + printf("--mac A\n" + "Optional BACnet mac address. " + "Valid ranges are from 00 to FF (hex) for MS/TP or ARCNET,\n" + "or an IP string with optional port number like 10.1.2.3:47808\n" + "or an Ethernet MAC in hex like 00:21:70:7e:32:bb\n"); + printf("\n"); + printf("--dnet N\n" + "Optional BACnet network number N for directed requests.\n" + "Valid range is from 0 to 65535 where 0 is the local connection\n" + "and 65535 is network broadcast.\n"); + printf("\n"); + printf("--dadr A\n" + "Optional BACnet mac address on the destination BACnet network " + "number.\n" + "Valid ranges are from 00 to FF (hex) for MS/TP or ARCNET,\n" + "or an IP string with optional port number like 10.1.2.3:47808\n" + "or an Ethernet MAC in hex like 00:21:70:7e:32:bb\n"); + printf("\n"); + printf("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 writing\n" + "Device Object 123, the device-instance would be 123.\n"); + printf("\n"); + printf("state:\n" + "Possible state values:\n" + " 0=enable\n" + " 1=disable\n" + " 2=disable-initiation\n"); + printf("\n"); + printf("timeout:\n" + "The timeout can be 0 for infinite, or a value in minutes for " + "disable.\n"); + printf("\n"); printf( - "Send BACnet DeviceCommunicationControl service to device.\n" - "\n" - "The device-instance can be 0 to %lu.\n" - "Possible state values:\n" - " 0=enable\n" - " 1=disable\n" - " 2=disable-initiation\n" - "The timeout can be 0 for infinite, or a value in minutes for " - "disable.\n" - "The optional password is a character string of 1 to 20 characters.\n" - "\nExample:\n" + "password:\n" + "The optional password is a character string of 1 to 20 characters.\n"); + printf("\n"); + printf( + "Example:\n" "If you want disable Device Communications in Device 123\n" "for 60 minutes with password 'filister', use the following command:\n" "%s 123 1 60 filister\n", - (unsigned long)BACNET_MAX_INSTANCE, filename); + filename); } int main(int argc, char *argv[]) @@ -156,6 +188,13 @@ int main(int argc, char *argv[]) time_t timeout_seconds = 0; uint8_t invoke_id = 0; bool found = false; + long dnet = -1; + BACNET_MAC_ADDRESS mac = { 0 }; + BACNET_MAC_ADDRESS adr = { 0 }; + BACNET_ADDRESS dest = { 0 }; + bool specific_address = false; + unsigned int target_args = 0; + uint32_t target_value = 0; int argi = 0; const char *filename = NULL; @@ -175,31 +214,75 @@ int main(int argc, char *argv[]) "FITNESS FOR A PARTICULAR PURPOSE.\n"); return 0; } + if (strcmp(argv[argi], "--mac") == 0) { + if (++argi < argc) { + if (bacnet_address_mac_from_ascii(&mac, argv[argi])) { + specific_address = true; + } + } + } else if (strcmp(argv[argi], "--dnet") == 0) { + if (++argi < argc) { + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } + if ((dnet >= 0) && (dnet <= UINT16_MAX)) { + specific_address = true; + } + } + } else if (strcmp(argv[argi], "--dadr") == 0) { + if (++argi < argc) { + if (bacnet_address_mac_from_ascii(&adr, argv[argi])) { + specific_address = true; + } + } + } else { + /* unnamed arguments */ + if (target_args == 0) { + if (!bacnet_string_to_uint32( + argv[argi], &Target_Device_Object_Instance)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } + if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) { + fprintf( + stderr, "device-instance=%u - not greater than %u\n", + Target_Device_Object_Instance, BACNET_MAX_INSTANCE); + return 1; + } + target_args++; + } else if (target_args == 1) { + if (!bacnet_string_to_uint32(argv[argi], &target_value)) { + fprintf(stderr, "state=%s invalid\n", argv[argi]); + return 1; + } + Communication_State = + (BACNET_COMMUNICATION_ENABLE_DISABLE)target_value; + target_args++; + } else if (target_args == 2) { + if (!bacnet_string_to_uint16( + argv[argi], &Communication_Timeout_Minutes)) { + fprintf(stderr, "timeout=%s invalid\n", argv[argi]); + return 1; + } + target_args++; + } else if (target_args == 3) { + Communication_Password = argv[argi]; + target_args++; + } + } } if (argc < 3) { print_usage(filename); return 0; } - /* decode the command line parameters */ - Target_Device_Object_Instance = strtol(argv[1], NULL, 0); - Communication_State = (uint16_t)strtol(argv[2], NULL, 0); - /* optional timeout, required if password is included */ - if (argc > 3) { - Communication_Timeout_Minutes = (uint16_t)strtol(argv[3], NULL, 0); - } - /* optional password */ - if (argc > 4) { - Communication_Password = argv[4]; - } - if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) { - fprintf( - stderr, "device-instance=%u - not greater than %u\n", - Target_Device_Object_Instance, BACNET_MAX_INSTANCE); - return 1; - } /* setup my info */ - Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); address_init(); + if (specific_address) { + bacnet_address_init(&dest, &mac, dnet, &adr); + address_add(Target_Device_Object_Instance, MAX_APDU, &dest); + } + Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); Init_Service_Handlers(); dlenv_init(); atexit(datalink_cleanup); diff --git a/apps/delete-object/main.c b/apps/delete-object/main.c index 65c54cf3..d9cb0a15 100644 --- a/apps/delete-object/main.c +++ b/apps/delete-object/main.c @@ -183,8 +183,8 @@ int main(int argc, char *argv[]) struct mstimer apdu_timer; struct mstimer maintenance_timer; bool found = false; - unsigned object_type = 0; - unsigned object_instance = 0; + unsigned long object_type = 0; + unsigned long object_instance = 0; long dnet = -1; BACNET_MAC_ADDRESS mac = { 0 }; BACNET_MAC_ADDRESS adr = { 0 }; @@ -218,7 +218,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= UINT16_MAX)) { specific_address = true; } @@ -233,25 +236,30 @@ int main(int argc, char *argv[]) Verbose = true; } else { if (target_args == 0) { - object_instance = strtoul(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &object_instance)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } if (object_instance > BACNET_MAX_INSTANCE) { fprintf( - stderr, "device-instance=%u - not greater than %u\n", + stderr, "device-instance=%lu - not greater than %u\n", object_instance, BACNET_MAX_INSTANCE); return 1; } Target_Device_Object_Instance = object_instance; target_args++; } else if (target_args == 1) { - if (bactext_object_type_strtol(argv[argi], &object_type) == - false) { + if (!bacnet_strtoul(argv[argi], &object_type)) { fprintf(stderr, "object-type=%s invalid\n", argv[argi]); return 1; } Target_Object_Type = object_type; target_args++; } else if (target_args == 2) { - object_instance = strtoul(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &object_instance)) { + fprintf(stderr, "object-instance=%s invalid\n", argv[argi]); + return 1; + } if (object_instance > BACNET_MAX_INSTANCE) { fprintf( stderr, "object-instance=%u - not greater than %u\n", @@ -260,7 +268,7 @@ int main(int argc, char *argv[]) } Target_Object_Instance = object_instance; if (Verbose) { - printf("Instance=%u=%s\n", object_instance, argv[argi]); + printf("Instance=%lu=%s\n", object_instance, argv[argi]); } target_args++; } diff --git a/apps/error/main.c b/apps/error/main.c index 0997eb15..b79f2fd7 100644 --- a/apps/error/main.c +++ b/apps/error/main.c @@ -153,7 +153,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } @@ -166,16 +169,28 @@ int main(int argc, char *argv[]) } } else { if (target_args == 0) { - Target_Error_Class = strtol(argv[argi], NULL, 0); + if (!bacnet_string_to_uint16(argv[argi], &Target_Error_Class)) { + fprintf(stderr, "error-class=%s invalid\n", argv[argi]); + return 1; + } target_args++; } else if (target_args == 1) { - Target_Error_Code = strtol(argv[argi], NULL, 0); + if (!bacnet_string_to_uint16(argv[argi], &Target_Error_Code)) { + fprintf(stderr, "error-code=%s invalid\n", argv[argi]); + return 1; + } target_args++; } else if (target_args == 2) { - Target_Service = strtol(argv[argi], NULL, 0); + if (!bacnet_string_to_uint16(argv[argi], &Target_Service)) { + fprintf(stderr, "service=%s invalid\n", argv[argi]); + return 1; + } target_args++; - } else if (target_args == 2) { - Target_Invoke_ID = strtol(argv[argi], NULL, 0); + } else if (target_args == 3) { + if (!bacnet_string_to_uint8(argv[argi], &Target_Invoke_ID)) { + fprintf(stderr, "invoke-id=%s invalid\n", argv[argi]); + return 1; + } target_args++; } else { print_usage(filename); @@ -185,34 +200,7 @@ int main(int argc, char *argv[]) } address_init(); if (specific_address) { - if (adr.len && mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - memcpy(&dest.adr[0], &adr.adr[0], adr.len); - dest.len = adr.len; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - } else if (mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - dest.len = 0; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = 0; - } - } else { - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - dest.mac_len = 0; - dest.len = 0; - } + bacnet_address_init(&dest, &mac, dnet, &adr); } /* setup my info */ Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); diff --git a/apps/event/main.c b/apps/event/main.c index 4e8da690..db106f39 100644 --- a/apps/event/main.c +++ b/apps/event/main.c @@ -232,9 +232,7 @@ static void print_help(const char *filename) int main(int argc, char *argv[]) { BACNET_EVENT_NOTIFICATION_DATA event_data = { 0 }; - BACNET_BIT_STRING *pBitString; - BACNET_CHARACTER_STRING bcstring; - BACNET_PROPERTY_STATES tag = PROP_STATE_BOOLEAN_VALUE; + unsigned long long_value = 0; BACNET_ADDRESS src = { 0 }; /* address where message came from */ unsigned timeout = 100; /* milliseconds */ uint16_t pdu_len = 0; @@ -252,7 +250,6 @@ int main(int argc, char *argv[]) int argi = 0; unsigned int target_args = 0; const char *filename = NULL; - unsigned found_index = 0; filename = filename_remove_path(argv[0]); for (argi = 1; argi < argc; argi++) { @@ -278,7 +275,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } @@ -292,226 +292,28 @@ int main(int argc, char *argv[]) } else { if (target_args == 0) { /* device-id */ - Target_Device_Object_Instance = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 1) { - /* process-id */ - event_data.processIdentifier = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 2) { - /* initiating-device-id */ - event_data.initiatingObjectIdentifier.type = OBJECT_DEVICE; - event_data.initiatingObjectIdentifier.instance = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 3) { - /* event-object-type */ - event_data.eventObjectIdentifier.type = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 4) { - /* event-object-instance */ - event_data.eventObjectIdentifier.instance = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 5) { - /* sequence-number */ - event_data.timeStamp.tag = TIME_STAMP_SEQUENCE; - event_data.timeStamp.value.sequenceNum = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 6) { - /* notification-class */ - event_data.notificationClass = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 7) { - /* priority */ - event_data.priority = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 8) { - /* message-text */ - characterstring_init_ansi(&bcstring, argv[argi]); - event_data.messageText = &bcstring; - target_args++; - } else if (target_args == 9) { - /* notify-type */ - if (bactext_notify_type_index(argv[argi], &found_index)) { - event_data.notifyType = found_index; - } else { - event_data.notifyType = strtol(argv[argi], NULL, 0); - } - target_args++; - } else if (target_args == 10) { - /* ack-required */ - event_data.ackRequired = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 11) { - /* from-state */ - if (bactext_event_state_index(argv[argi], &found_index)) { - event_data.fromState = found_index; - } else { - event_data.fromState = strtol(argv[argi], NULL, 0); - } - target_args++; - } else if (target_args == 12) { - /* to-state */ - if (bactext_event_state_index(argv[argi], &found_index)) { - event_data.toState = found_index; - } else { - event_data.toState = strtol(argv[argi], NULL, 0); - } - target_args++; - } else if (target_args == 13) { - /* event-type - see BACNET_EVENT_TYPE */ - if (bactext_event_type_index(argv[argi], &found_index)) { - event_data.eventType = found_index; - } else { - event_data.eventType = strtol(argv[argi], NULL, 0); - } - target_args++; - } else { - if (event_data.eventType == EVENT_CHANGE_OF_BITSTRING) { - if (target_args == 14) { - pBitString = - &event_data.notificationParams.changeOfBitstring - .referencedBitString; - bitstring_init_ascii(pBitString, argv[argi]); - target_args++; - } else if (target_args == 15) { - pBitString = &event_data.notificationParams - .changeOfBitstring.statusFlags; - bitstring_init_ascii(pBitString, argv[argi]); - target_args++; - } else { - print_usage(filename); - return 1; - } - } else if (event_data.eventType == EVENT_CHANGE_OF_STATE) { - if (target_args == 14) { - tag = strtol(argv[argi], NULL, 0); - event_data.notificationParams.changeOfState.newState - .tag = tag; - target_args++; - } else if (target_args == 15) { - if (tag == PROP_STATE_BOOLEAN_VALUE) { - event_data.notificationParams.changeOfState.newState - .state.booleanValue = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_BINARY_VALUE) { - event_data.notificationParams.changeOfState.newState - .state.binaryValue = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_EVENT_TYPE) { - event_data.notificationParams.changeOfState.newState - .state.eventType = strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_POLARITY) { - event_data.notificationParams.changeOfState.newState - .state.polarity = strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_PROGRAM_CHANGE) { - event_data.notificationParams.changeOfState.newState - .state.programChange = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_PROGRAM_STATE) { - event_data.notificationParams.changeOfState.newState - .state.programState = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_REASON_FOR_HALT) { - event_data.notificationParams.changeOfState.newState - .state.programError = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_RELIABILITY) { - event_data.notificationParams.changeOfState.newState - .state.reliability = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_EVENT_STATE) { - event_data.notificationParams.changeOfState.newState - .state.state = strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_SYSTEM_STATUS) { - event_data.notificationParams.changeOfState.newState - .state.systemStatus = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_UNITS) { - event_data.notificationParams.changeOfState.newState - .state.units = strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_UNSIGNED_VALUE) { - event_data.notificationParams.changeOfState.newState - .state.unsignedValue = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_LIFE_SAFETY_MODE) { - event_data.notificationParams.changeOfState.newState - .state.lifeSafetyMode = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_LIFE_SAFETY_STATE) { - event_data.notificationParams.changeOfState.newState - .state.lifeSafetyState = - strtol(argv[argi], NULL, 0); - } else { - printf("Invalid Change-Of-State Tag\n"); - return 1; - } - target_args++; - } else if (target_args == 16) { - pBitString = &event_data.notificationParams - .changeOfBitstring.statusFlags; - bitstring_init_ascii(pBitString, argv[argi]); - target_args++; - } else { - print_usage(filename); - return 1; - } - } else if (event_data.eventType == EVENT_CHANGE_OF_VALUE) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_COMMAND_FAILURE) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_FLOATING_LIMIT) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_OUT_OF_RANGE) { - /* FIXME: add event type parameters */ - } else if ( - event_data.eventType == EVENT_CHANGE_OF_LIFE_SAFETY) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_EXTENDED) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_BUFFER_READY) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_UNSIGNED_RANGE) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_ACCESS_EVENT) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_DOUBLE_OUT_OF_RANGE) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_SIGNED_OUT_OF_RANGE) { - /* FIXME: add event type parameters */ - } else if ( - event_data.eventType == EVENT_UNSIGNED_OUT_OF_RANGE) { - /* FIXME: add event type parameters */ - } else if ( - event_data.eventType == EVENT_CHANGE_OF_CHARACTERSTRING) { - /* FIXME: add event type parameters */ - } else if ( - event_data.eventType == EVENT_CHANGE_OF_STATUS_FLAGS) { - /* FIXME: add event type parameters */ - } else if ( - event_data.eventType == EVENT_CHANGE_OF_RELIABILITY) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_NONE) { - /* FIXME: add event type parameters */ - } else if ( - event_data.eventType == EVENT_CHANGE_OF_DISCRETE_VALUE) { - /* FIXME: add event type parameters */ - } else if (event_data.eventType == EVENT_CHANGE_OF_TIMER) { - /* FIXME: add event type parameters */ - } else if ( - (event_data.eventType >= EVENT_PROPRIETARY_MIN) && - (event_data.eventType <= EVENT_PROPRIETARY_MAX)) { - /* Enumerated values 64-65535 may - be used by others subject to - the procedures and constraints - described in Clause 23. */ - } else { - print_usage(filename); + if (!bacnet_strtoul(argv[argi], &long_value)) { + fprintf(stderr, "device-id=%s invalid\n", argv[argi]); return 1; } + if (long_value > BACNET_MAX_INSTANCE) { + fprintf( + stderr, "device-id=%lu - exceeds %u\n", long_value, + BACNET_MAX_INSTANCE); + return 1; + } + Target_Device_Object_Instance = (uint32_t)long_value; + target_args++; + } else if (target_args == 1) { + if (!event_notify_parse( + &event_data, argc - argi, &argv[argi])) { + fprintf(stderr, "event=%s invalid\n", argv[argi]); + } else { + target_args++; + } + } else { + print_usage(filename); + return 1; } } } @@ -519,42 +321,12 @@ int main(int argc, char *argv[]) print_usage(filename); return 0; } + /* setup my info */ address_init(); if (specific_address) { - if (adr.len && mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - memcpy(&dest.adr[0], &adr.adr[0], adr.len); - dest.len = adr.len; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - } else if (mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - dest.len = 0; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = 0; - } - } else { - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - dest.mac_len = 0; - dest.len = 0; - } + bacnet_address_init(&dest, &mac, dnet, &adr); address_add(Target_Device_Object_Instance, MAX_APDU, &dest); - printf( - "Added Device %u to address cache\n", - Target_Device_Object_Instance); } - /* setup my info */ Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); Init_Service_Handlers(); dlenv_init(); diff --git a/apps/iam/main.c b/apps/iam/main.c index c7354902..9e98249f 100644 --- a/apps/iam/main.c +++ b/apps/iam/main.c @@ -178,7 +178,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } diff --git a/apps/readprop/main.c b/apps/readprop/main.c index 062327d8..1fb21986 100644 --- a/apps/readprop/main.c +++ b/apps/readprop/main.c @@ -279,7 +279,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } diff --git a/apps/readpropm/main.c b/apps/readpropm/main.c index ddac918b..ec1c4046 100644 --- a/apps/readpropm/main.c +++ b/apps/readpropm/main.c @@ -390,7 +390,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= UINT16_MAX)) { specific_address = true; } diff --git a/apps/remove-list-element/main.c b/apps/remove-list-element/main.c index 23a94754..6cc103d4 100644 --- a/apps/remove-list-element/main.c +++ b/apps/remove-list-element/main.c @@ -235,12 +235,12 @@ int main(int argc, char *argv[]) bool found = false; char *value_string = NULL; bool status = false; - unsigned context_tag = 0; + unsigned long context_tag = 0; BACNET_APPLICATION_DATA_VALUE *application_value = NULL; - unsigned object_type = 0; - unsigned object_instance = 0; - unsigned property_id = 0; - unsigned property_array_index = 0; + unsigned long object_type = 0; + unsigned long object_instance = 0; + uint32_t property_id = 0; + long property_array_index = 0; long property_tag = 0; long dnet = -1; BACNET_MAC_ADDRESS mac = { 0 }; @@ -275,7 +275,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= UINT16_MAX)) { specific_address = true; } @@ -290,34 +293,39 @@ int main(int argc, char *argv[]) Verbose = true; } else { if (target_args == 0) { - object_instance = strtoul(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &object_instance)) { + fprintf(stderr, "device-instance=%s invalid\n", argv[argi]); + return 1; + } if (object_instance > BACNET_MAX_INSTANCE) { fprintf( - stderr, "device-instance=%u - not greater than %u\n", + stderr, "device-instance=%lu - not greater than %u\n", object_instance, BACNET_MAX_INSTANCE); return 1; } Target_Device_Object_Instance = object_instance; target_args++; } else if (target_args == 1) { - if (bactext_object_type_strtol(argv[argi], &object_type) == - false) { + if (!bacnet_strtoul(argv[argi], &object_type)) { fprintf(stderr, "object-type=%s invalid\n", argv[argi]); return 1; } Target_Object_Type = object_type; target_args++; } else if (target_args == 2) { - object_instance = strtoul(argv[argi], NULL, 0); + if (!bacnet_strtoul(argv[argi], &object_instance)) { + fprintf(stderr, "object-instance=%s invalid\n", argv[argi]); + return 1; + } if (object_instance > BACNET_MAX_INSTANCE) { fprintf( - stderr, "device-instance=%u - not greater than %u\n", + stderr, "object-instance=%u - not greater than %u\n", Target_Device_Object_Instance, BACNET_MAX_INSTANCE); return 1; } Target_Object_Instance = object_instance; if (Verbose) { - printf("Instance=%u=%s\n", object_instance, argv[argi]); + printf("Instance=%lu=%s\n", object_instance, argv[argi]); } target_args++; } else if (target_args == 3) { @@ -332,11 +340,19 @@ int main(int argc, char *argv[]) } target_args++; } else if (target_args == 4) { - property_array_index = strtol(argv[argi], NULL, 0); - Target_Object_Array_Index = property_array_index; + if (!bacnet_strtol(argv[argi], &property_array_index)) { + fprintf(stderr, "array-index=%s invalid\n", argv[argi]); + return 1; + } + if (property_array_index < 0) { + Target_Object_Array_Index = BACNET_ARRAY_ALL; + } else { + Target_Object_Array_Index = + (BACNET_ARRAY_INDEX)property_array_index; + } if (Verbose) { printf( - "Array_Index=%i=%s\n", property_array_index, + "Array_Index=%li=%s\n", property_array_index, argv[argi]); } target_args++; @@ -347,15 +363,22 @@ int main(int argc, char *argv[]) if (tag_value_arg == 0) { /* special case for context tagged values */ if (toupper(argv[argi][0]) == 'C') { - context_tag = strtoul(&argv[target_args][1], NULL, 0); + if (!bacnet_strtoul( + &argv[target_args][1], &context_tag)) { + fprintf(stderr, "tag=%s invalid\n", argv[argi]); + return 1; + } application_value->context_tag = context_tag; application_value->context_specific = true; argi++; } else { application_value->context_specific = false; } - /* application tag */ - property_tag = strtol(argv[argi], NULL, 0); + /* property application tag */ + if (!bacnet_strtol(argv[argi], &property_tag)) { + fprintf(stderr, "tag=%s invalid\n", argv[argi]); + return 1; + } if (Verbose) { printf("tag=%ld\n", property_tag); } diff --git a/apps/server-mini/main.c b/apps/server-mini/main.c index 31406b95..fa6e81f5 100644 --- a/apps/server-mini/main.c +++ b/apps/server-mini/main.c @@ -297,7 +297,7 @@ int main(int argc, char *argv[]) /* Handle command-line arguments */ if (argc > 1) { - device_instance = strtoul(argv[1], NULL, 10); + bacnet_string_to_uint32(argv[1], &device_instance); } Device_Set_Object_Instance_Number(device_instance); printf("BACnet Device ID: %u\n", device_instance); diff --git a/apps/timesync/main.c b/apps/timesync/main.c index 42e7e43e..4efc49d7 100644 --- a/apps/timesync/main.c +++ b/apps/timesync/main.c @@ -186,7 +186,10 @@ int main(int argc, char *argv[]) } if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { global_broadcast = false; } diff --git a/apps/uevent/main.c b/apps/uevent/main.c index c72aabd7..92dd8469 100644 --- a/apps/uevent/main.c +++ b/apps/uevent/main.c @@ -89,9 +89,6 @@ static void print_help(const char *filename) int main(int argc, char *argv[]) { BACNET_EVENT_NOTIFICATION_DATA event_data = { 0 }; - BACNET_BIT_STRING *pBitString; - BACNET_CHARACTER_STRING bcstring; - BACNET_PROPERTY_STATES tag = PROP_STATE_BOOLEAN_VALUE; long dnet = -1; BACNET_MAC_ADDRESS mac = { 0 }; BACNET_MAC_ADDRESS adr = { 0 }; @@ -125,7 +122,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } @@ -138,206 +138,20 @@ int main(int argc, char *argv[]) } } else { if (target_args == 0) { - event_data.processIdentifier = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 1) { - event_data.initiatingObjectIdentifier.type = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 2) { - event_data.initiatingObjectIdentifier.instance = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 3) { - event_data.eventObjectIdentifier.type = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 4) { - event_data.eventObjectIdentifier.instance = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 5) { - event_data.timeStamp.tag = TIME_STAMP_SEQUENCE; - event_data.timeStamp.value.sequenceNum = - strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 6) { - event_data.notificationClass = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 7) { - event_data.priority = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 8) { - event_data.eventType = strtol(argv[argi], NULL, 0); - target_args++; - } else { - if (event_data.eventType == EVENT_CHANGE_OF_BITSTRING) { - if (target_args == 9) { - pBitString = - &event_data.notificationParams.changeOfBitstring - .referencedBitString; - bitstring_init_ascii(pBitString, argv[argi]); - target_args++; - } else if (target_args == 10) { - pBitString = &event_data.notificationParams - .changeOfBitstring.statusFlags; - bitstring_init_ascii(pBitString, argv[argi]); - target_args++; - } else if (target_args == 11) { - characterstring_init_ansi(&bcstring, argv[argi]); - event_data.messageText = &bcstring; - target_args++; - } else if (target_args == 12) { - event_data.notifyType = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 13) { - event_data.ackRequired = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 14) { - event_data.fromState = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 15) { - event_data.toState = strtol(argv[argi], NULL, 0); - target_args++; - } else { - print_usage(filename); - return 1; - } - } else if (event_data.eventType == EVENT_CHANGE_OF_STATE) { - if (target_args == 9) { - tag = strtol(argv[argi], NULL, 0); - event_data.notificationParams.changeOfState.newState - .tag = tag; - target_args++; - } else if (target_args == 10) { - if (tag == PROP_STATE_BOOLEAN_VALUE) { - event_data.notificationParams.changeOfState.newState - .state.booleanValue = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_BINARY_VALUE) { - event_data.notificationParams.changeOfState.newState - .state.binaryValue = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_EVENT_TYPE) { - event_data.notificationParams.changeOfState.newState - .state.eventType = strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_POLARITY) { - event_data.notificationParams.changeOfState.newState - .state.polarity = strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_PROGRAM_CHANGE) { - event_data.notificationParams.changeOfState.newState - .state.programChange = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_PROGRAM_STATE) { - event_data.notificationParams.changeOfState.newState - .state.programState = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_REASON_FOR_HALT) { - event_data.notificationParams.changeOfState.newState - .state.programError = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_RELIABILITY) { - event_data.notificationParams.changeOfState.newState - .state.reliability = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_EVENT_STATE) { - event_data.notificationParams.changeOfState.newState - .state.state = strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_SYSTEM_STATUS) { - event_data.notificationParams.changeOfState.newState - .state.systemStatus = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_UNITS) { - event_data.notificationParams.changeOfState.newState - .state.units = strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_UNSIGNED_VALUE) { - event_data.notificationParams.changeOfState.newState - .state.unsignedValue = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_LIFE_SAFETY_MODE) { - event_data.notificationParams.changeOfState.newState - .state.lifeSafetyMode = - strtol(argv[argi], NULL, 0); - } else if (tag == PROP_STATE_LIFE_SAFETY_STATE) { - event_data.notificationParams.changeOfState.newState - .state.lifeSafetyState = - strtol(argv[argi], NULL, 0); - } else { - printf("Invalid Change-Of-State Tag\n"); - return 1; - } - target_args++; - } else if (target_args == 11) { - pBitString = &event_data.notificationParams - .changeOfBitstring.statusFlags; - bitstring_init_ascii(pBitString, argv[argi]); - target_args++; - } else if (target_args == 12) { - characterstring_init_ansi(&bcstring, argv[argi]); - event_data.messageText = &bcstring; - target_args++; - } else if (target_args == 13) { - event_data.notifyType = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 14) { - event_data.ackRequired = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 15) { - event_data.fromState = strtol(argv[argi], NULL, 0); - target_args++; - } else if (target_args == 16) { - event_data.toState = strtol(argv[argi], NULL, 0); - target_args++; - } else { - print_usage(filename); - return 1; - } - } else if (event_data.eventType == EVENT_CHANGE_OF_VALUE) { - } else if (event_data.eventType == EVENT_COMMAND_FAILURE) { - } else if (event_data.eventType == EVENT_FLOATING_LIMIT) { - } else if (event_data.eventType == EVENT_OUT_OF_RANGE) { - } else if ( - event_data.eventType == EVENT_CHANGE_OF_LIFE_SAFETY) { - } else if (event_data.eventType == EVENT_EXTENDED) { - } else if (event_data.eventType == EVENT_BUFFER_READY) { - } else if (event_data.eventType == EVENT_UNSIGNED_RANGE) { + if (!event_notify_parse( + &event_data, argc - argi, &argv[argi])) { + fprintf(stderr, "event=%s invalid\n", argv[argi]); } else { - print_usage(filename); - return 1; + target_args++; } + } else { + print_usage(filename); + return 1; } } } - address_init(); if (specific_address) { - if (adr.len && mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - memcpy(&dest.adr[0], &adr.adr[0], adr.len); - dest.len = adr.len; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - } else if (mac.len) { - memcpy(&dest.mac[0], &mac.adr[0], mac.len); - dest.mac_len = mac.len; - dest.len = 0; - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = 0; - } - } else { - if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { - dest.net = dnet; - } else { - dest.net = BACNET_BROADCAST_NETWORK; - } - dest.mac_len = 0; - dest.len = 0; - } + bacnet_address_init(&dest, &mac, dnet, &adr); } /* setup my info */ Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); diff --git a/apps/who-am-i/main.c b/apps/who-am-i/main.c index 7426cc04..130ce7ed 100644 --- a/apps/who-am-i/main.c +++ b/apps/who-am-i/main.c @@ -224,7 +224,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { global_broadcast = false; } diff --git a/apps/whois/main.c b/apps/whois/main.c index 5cb28129..20279a9a 100644 --- a/apps/whois/main.c +++ b/apps/whois/main.c @@ -383,7 +383,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { global_broadcast = false; } diff --git a/apps/writeprop/main.c b/apps/writeprop/main.c index 16544ff3..9e981dcb 100644 --- a/apps/writeprop/main.c +++ b/apps/writeprop/main.c @@ -279,7 +279,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } diff --git a/apps/you-are/main.c b/apps/you-are/main.c index 8c195675..c8195f24 100644 --- a/apps/you-are/main.c +++ b/apps/you-are/main.c @@ -236,7 +236,10 @@ int main(int argc, char *argv[]) } } else if (strcmp(argv[argi], "--dnet") == 0) { if (++argi < argc) { - dnet = strtol(argv[argi], NULL, 0); + if (!bacnet_strtol(argv[argi], &dnet)) { + fprintf(stderr, "dnet=%s invalid\n", argv[argi]); + return 1; + } if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) { specific_address = true; } diff --git a/src/bacnet/bactext.c b/src/bacnet/bactext.c index 96daaa7c..1f2b410b 100644 --- a/src/bacnet/bactext.c +++ b/src/bacnet/bactext.c @@ -2827,6 +2827,179 @@ const char *bactext_timer_transition_name(uint32_t index) bactext_timer_transition_names, index, ASHRAE_Reserved_String); } +INDTEXT_DATA bactext_boolean_value_names[] = { { false, "false" }, + { true, "true" }, + { 0, NULL } }; + +const char *bactext_boolean_value_name(uint32_t index) +{ + return indtext_by_index_default( + bactext_boolean_value_names, index, ASHRAE_Reserved_String); +} + +bool bactext_property_states_strtoul( + BACNET_PROPERTY_STATES property_state, + const char *search_name, + uint32_t *found_index) +{ + bool status = false; + + switch (property_state) { + case PROP_STATE_BOOLEAN_VALUE: + status = bactext_string_to_uint32_index( + bactext_boolean_value_names, search_name, found_index); + break; + case PROP_STATE_BINARY_VALUE: + status = bactext_string_to_uint32_index( + bacnet_binary_present_value_names, search_name, found_index); + break; + case PROP_STATE_EVENT_TYPE: + status = bactext_string_to_uint32_index( + bacnet_event_type_names, search_name, found_index); + break; + case PROP_STATE_POLARITY: + status = bactext_string_to_uint32_index( + bacnet_binary_polarity_names, search_name, found_index); + break; + case PROP_STATE_PROGRAM_CHANGE: + status = bactext_string_to_uint32_index( + bactext_program_request_names, search_name, found_index); + break; + case PROP_STATE_PROGRAM_STATE: + status = bactext_string_to_uint32_index( + bactext_program_state_names, search_name, found_index); + break; + case PROP_STATE_REASON_FOR_HALT: + status = bactext_string_to_uint32_index( + bactext_program_error_names, search_name, found_index); + break; + case PROP_STATE_RELIABILITY: + status = bactext_string_to_uint32_index( + bacnet_reliability_names, search_name, found_index); + break; + case PROP_STATE_EVENT_STATE: + status = bactext_string_to_uint32_index( + bacnet_event_state_names, search_name, found_index); + break; + case PROP_STATE_SYSTEM_STATUS: + status = bactext_string_to_uint32_index( + bacnet_device_status_names, search_name, found_index); + break; + case PROP_STATE_UNITS: + status = bactext_string_to_uint32_index( + bacnet_engineering_unit_names, search_name, found_index); + break; + case PROP_STATE_LIFE_SAFETY_MODE: + status = bactext_string_to_uint32_index( + bactext_life_safety_mode_names, search_name, found_index); + break; + case PROP_STATE_LIFE_SAFETY_STATE: + status = bactext_string_to_uint32_index( + bactext_life_safety_state_names, search_name, found_index); + break; + case PROP_STATE_RESTART_REASON: + status = bactext_string_to_uint32_index( + bactext_restart_reason_names, search_name, found_index); + break; + case PROP_STATE_LIFE_SAFETY_OPERATION: + status = bactext_string_to_uint32_index( + bactext_life_safety_operation_names, search_name, found_index); + break; + case PROP_STATE_NODE_TYPE: + status = bactext_string_to_uint32_index( + bacnet_node_type_names, search_name, found_index); + break; + case PROP_STATE_NOTIFY_TYPE: + status = bactext_string_to_uint32_index( + bacnet_notify_type_names, search_name, found_index); + break; + case PROP_STATE_SHED_STATE: + status = bactext_string_to_uint32_index( + bacnet_shed_state_names, search_name, found_index); + break; + case PROP_STATE_SILENCED_STATE: + status = bactext_string_to_uint32_index( + bactext_silenced_state_names, search_name, found_index); + break; + case PROP_STATE_LIGHTING_IN_PROGRESS: + status = bactext_string_to_uint32_index( + bacnet_lighting_in_progress_names, search_name, found_index); + break; + case PROP_STATE_LIGHTING_OPERATION: + status = bactext_string_to_uint32_index( + bacnet_lighting_operation_names, search_name, found_index); + break; + case PROP_STATE_LIGHTING_TRANSITION: + status = bactext_string_to_uint32_index( + bacnet_lighting_transition_names, search_name, found_index); + break; + case PROP_STATE_BINARY_LIGHTING_VALUE: + status = bactext_string_to_uint32_index( + bacnet_binary_lighting_pv_names, search_name, found_index); + break; + case PROP_STATE_TIMER_STATE: + status = bactext_string_to_uint32_index( + bactext_timer_state_names, search_name, found_index); + break; + case PROP_STATE_TIMER_TRANSITION: + status = bactext_string_to_uint32_index( + bactext_timer_transition_names, search_name, found_index); + break; + case PROP_STATE_NETWORK_PORT_COMMAND: + status = bactext_string_to_uint32_index( + bactext_network_port_command_names, search_name, found_index); + break; + case PROP_STATE_NETWORK_TYPE: + status = bactext_string_to_uint32_index( + bactext_network_port_type_names, search_name, found_index); + break; + case PROP_STATE_NETWORK_NUMBER_QUALITY: + status = bactext_string_to_uint32_index( + bactext_network_number_quality_names, search_name, found_index); + break; + case PROP_STATE_PROTOCOL_LEVEL: + status = bactext_string_to_uint32_index( + bactext_protocol_level_names, search_name, found_index); + break; + case PROP_STATE_ACTION: + case PROP_STATE_DOOR_SECURED_STATUS: + case PROP_STATE_DOOR_STATUS: + case PROP_STATE_DOOR_VALUE: + case PROP_STATE_FILE_ACCESS_METHOD: + case PROP_STATE_LOCK_STATUS: + case PROP_STATE_MAINTENANCE: + case PROP_STATE_SECURITY_LEVEL: + case PROP_STATE_ACCESS_EVENT: + case PROP_STATE_ZONE_OCCUPANCY_STATE: + case PROP_STATE_ACCESS_CRED_DISABLE_REASON: + case PROP_STATE_ACCESS_CRED_DISABLE: + case PROP_STATE_AUTHENTICATION_STATUS: + case PROP_STATE_BACKUP_STATE: + case PROP_STATE_WRITE_STATUS: + case PROP_STATE_INTEGER_VALUE: + case PROP_STATE_BACNET_IP_MODE: + case PROP_STATE_ESCALATOR_OPERATION_DIRECTION: + case PROP_STATE_ESCALATOR_FAULT: + case PROP_STATE_ESCALATOR_MODE: + case PROP_STATE_LIFT_CAR_DIRECTION: + case PROP_STATE_LIFT_CAR_DOOR_COMMAND: + case PROP_STATE_LIFT_CAR_DRIVE_STATUS: + case PROP_STATE_LIFT_CAR_MODE: + case PROP_STATE_LIFT_GROUP_MODE: + case PROP_STATE_LIFT_FAULT: + case PROP_STATE_AUDIT_LEVEL: + case PROP_STATE_AUDIT_OPERATION: + case PROP_STATE_EXTENDED_VALUE: + case PROP_STATE_DOOR_ALARM_STATE: + case PROP_STATE_UNSIGNED_VALUE: + default: + status = bacnet_string_to_uint32(search_name, found_index); + break; + } + + return status; +} + /** * @brief For a given enumerated object property string, * find the enumeration value diff --git a/src/bacnet/bactext.h b/src/bacnet/bactext.h index ff622b53..2f5851bf 100644 --- a/src/bacnet/bactext.h +++ b/src/bacnet/bactext.h @@ -242,6 +242,15 @@ const char *bactext_timer_transition_name(uint32_t index); BACNET_STACK_EXPORT const char *bactext_timer_state_name(uint32_t index); +BACNET_STACK_EXPORT +const char *bactext_boolean_value_name(uint32_t index); + +BACNET_STACK_EXPORT +bool bactext_property_states_strtoul( + BACNET_PROPERTY_STATES object_property, + const char *search_name, + uint32_t *found_index); + BACNET_STACK_EXPORT bool bactext_object_property_strtoul( BACNET_OBJECT_TYPE object_type, diff --git a/src/bacnet/event.c b/src/bacnet/event.c index 76a90044..25d18cd6 100644 --- a/src/bacnet/event.c +++ b/src/bacnet/event.c @@ -13,6 +13,7 @@ #include "bacnet/timestamp.h" #include "bacnet/authentication_factor.h" #include "bacnet/bacapp.h" +#include "bacnet/bactext.h" /** @file event.c Encode/Decode Event Notifications */ @@ -3114,3 +3115,264 @@ int event_notify_decode_service_request( return apdu_len; } + +/** + * @brief parse a list of strings for the event notification: + * @details event-notification string: + * process-id initiating-device-id event-object-type event-object-instance + * sequence-number notification-class priority message-text notify-type + * ack-required from-state to-state event-type + * [change-of-bitstring reference-bit-string status-flags] + * [change-of-state new-state-tag new-state-value status-flags] + * @param data [out] BACnetEventNotification data to store parsed data + * @param argc [in] number of arguments in argv + * @param argv [in] array of strings to parse + * @return true if successful, false if error + */ +bool event_notify_parse( + BACNET_EVENT_NOTIFICATION_DATA *data, int argc, char *argv[]) +{ + int argi = 0; + unsigned int target_args = 1; + uint32_t found_index = 0; + unsigned long long_value = 0; + BACNET_PROPERTY_STATES tag = PROP_STATE_BOOLEAN_VALUE; + BACNET_BIT_STRING *pBitString = NULL; + + for (argi = 1; argi < argc; argi++) { + if (target_args == 1) { + /* process-id */ + if (!bacnet_string_to_uint32( + argv[argi], &data->processIdentifier)) { + return false; + } + target_args++; + } else if (target_args == 2) { + /* initiating-device-id */ + data->initiatingObjectIdentifier.type = OBJECT_DEVICE; + if (!bacnet_strtoul(argv[argi], &long_value)) { + return false; + } + if (long_value > BACNET_MAX_INSTANCE) { + return false; + } + data->initiatingObjectIdentifier.instance = (uint32_t)long_value; + target_args++; + } else if (target_args == 3) { + /* event-object-type */ + if (!bactext_object_type_strtol(argv[argi], &found_index)) { + return false; + } + data->eventObjectIdentifier.type = (BACNET_OBJECT_TYPE)found_index; + target_args++; + } else if (target_args == 4) { + /* event-object-instance */ + if (!bacnet_strtoul(argv[argi], &long_value)) { + return false; + } + if (long_value > BACNET_MAX_INSTANCE) { + return false; + } + data->eventObjectIdentifier.instance = (uint32_t)long_value; + target_args++; + } else if (target_args == 5) { + /* sequence-number */ + if (!bacnet_string_to_uint16( + argv[argi], &data->timeStamp.value.sequenceNum)) { + return false; + } + data->timeStamp.tag = TIME_STAMP_SEQUENCE; + target_args++; + } else if (target_args == 6) { + /* notification-class */ + if (!bacnet_string_to_uint32( + argv[argi], &data->notificationClass)) { + return false; + } + target_args++; + } else if (target_args == 7) { + /* priority */ + if (!bacnet_string_to_uint8(argv[argi], &data->priority)) { + return false; + } + target_args++; + } else if (target_args == 8) { + /* message-text */ + if (!characterstring_init_ansi(data->messageText, argv[argi])) { + return false; + } + target_args++; + } else if (target_args == 9) { + /* notify-type */ + if (!bactext_notify_type_strtol(argv[argi], &found_index)) { + return false; + } + data->notifyType = (BACNET_NOTIFY_TYPE)found_index; + target_args++; + } else if (target_args == 10) { + /* ack-required */ + if (!bacnet_string_to_bool(argv[argi], &data->ackRequired)) { + return false; + } + target_args++; + } else if (target_args == 11) { + /* from-state */ + if (!bactext_event_state_strtol(argv[argi], &found_index)) { + return false; + } + data->fromState = (BACNET_EVENT_STATE)found_index; + target_args++; + } else if (target_args == 12) { + /* to-state */ + if (!bactext_event_state_strtol(argv[argi], &found_index)) { + return false; + } + data->toState = (BACNET_EVENT_STATE)found_index; + target_args++; + } else if (target_args == 13) { + /* event-type */ + if (!bactext_event_type_strtol(argv[argi], &found_index)) { + return false; + } + data->eventType = (BACNET_EVENT_TYPE)found_index; + target_args++; + } else { + if (data->eventType == EVENT_CHANGE_OF_BITSTRING) { + if (target_args == 14) { + pBitString = &data->notificationParams.changeOfBitstring + .referencedBitString; + bitstring_init_ascii(pBitString, argv[argi]); + target_args++; + } else if (target_args == 15) { + pBitString = + &data->notificationParams.changeOfBitstring.statusFlags; + bitstring_init_ascii(pBitString, argv[argi]); + target_args++; + } else { + return false; + } + } else if (data->eventType == EVENT_CHANGE_OF_STATE) { + if (target_args == 14) { + if (!bacnet_strtoul(argv[argi], &long_value)) { + return false; + } + tag = (BACNET_PROPERTY_STATES)long_value; + data->notificationParams.changeOfState.newState.tag = tag; + target_args++; + } else if (target_args == 15) { + if (!bactext_property_states_strtoul( + tag, argv[argi], &found_index)) { + return false; + } + if (tag == PROP_STATE_BOOLEAN_VALUE) { + if (found_index) { + data->notificationParams.changeOfState.newState + .state.booleanValue = true; + } else { + data->notificationParams.changeOfState.newState + .state.booleanValue = false; + } + } else if (tag == PROP_STATE_BINARY_VALUE) { + data->notificationParams.changeOfState.newState.state + .binaryValue = (BACNET_BINARY_PV)found_index; + } else if (tag == PROP_STATE_EVENT_TYPE) { + data->notificationParams.changeOfState.newState.state + .eventType = (BACNET_EVENT_TYPE)found_index; + } else if (tag == PROP_STATE_POLARITY) { + data->notificationParams.changeOfState.newState.state + .polarity = (BACNET_POLARITY)found_index; + } else if (tag == PROP_STATE_PROGRAM_CHANGE) { + data->notificationParams.changeOfState.newState.state + .programChange = + (BACNET_PROGRAM_REQUEST)found_index; + } else if (tag == PROP_STATE_PROGRAM_STATE) { + data->notificationParams.changeOfState.newState.state + .programState = (BACNET_PROGRAM_STATE)found_index; + } else if (tag == PROP_STATE_REASON_FOR_HALT) { + data->notificationParams.changeOfState.newState.state + .programError = (BACNET_PROGRAM_ERROR)found_index; + } else if (tag == PROP_STATE_RELIABILITY) { + data->notificationParams.changeOfState.newState.state + .reliability = (BACNET_RELIABILITY)found_index; + } else if (tag == PROP_STATE_EVENT_STATE) { + data->notificationParams.changeOfState.newState.state + .state = (BACNET_EVENT_STATE)found_index; + } else if (tag == PROP_STATE_SYSTEM_STATUS) { + data->notificationParams.changeOfState.newState.state + .systemStatus = (BACNET_DEVICE_STATUS)found_index; + } else if (tag == PROP_STATE_UNITS) { + data->notificationParams.changeOfState.newState.state + .units = (BACNET_ENGINEERING_UNITS)found_index; + } else if (tag == PROP_STATE_UNSIGNED_VALUE) { + data->notificationParams.changeOfState.newState.state + .unsignedValue = + (BACNET_UNSIGNED_INTEGER)found_index; + } else if (tag == PROP_STATE_LIFE_SAFETY_MODE) { + data->notificationParams.changeOfState.newState.state + .lifeSafetyMode = + (BACNET_LIFE_SAFETY_MODE)found_index; + } else if (tag == PROP_STATE_LIFE_SAFETY_STATE) { + data->notificationParams.changeOfState.newState.state + .lifeSafetyState = + (BACNET_LIFE_SAFETY_STATE)found_index; + } else { + return false; + } + target_args++; + } else if (target_args == 16) { + pBitString = + &data->notificationParams.changeOfState.statusFlags; + bitstring_init_ascii(pBitString, argv[argi]); + target_args++; + } else { + return false; + } + } else if (data->eventType == EVENT_CHANGE_OF_VALUE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_COMMAND_FAILURE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_FLOATING_LIMIT) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_OUT_OF_RANGE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_CHANGE_OF_LIFE_SAFETY) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_EXTENDED) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_BUFFER_READY) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_UNSIGNED_RANGE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_ACCESS_EVENT) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_DOUBLE_OUT_OF_RANGE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_SIGNED_OUT_OF_RANGE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_UNSIGNED_OUT_OF_RANGE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_CHANGE_OF_CHARACTERSTRING) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_CHANGE_OF_STATUS_FLAGS) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_CHANGE_OF_RELIABILITY) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_NONE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_CHANGE_OF_DISCRETE_VALUE) { + /* FIXME: add event type parameters */ + } else if (data->eventType == EVENT_CHANGE_OF_TIMER) { + /* FIXME: add event type parameters */ + } else if ( + (data->eventType >= EVENT_PROPRIETARY_MIN) && + (data->eventType <= EVENT_PROPRIETARY_MAX)) { + /* Enumerated values 64-65535 may + be used by others subject to + the procedures and constraints + described in Clause 23. */ + } + } + } + + return true; +} diff --git a/src/bacnet/event.h b/src/bacnet/event.h index 6e7718fc..6a6e1df4 100644 --- a/src/bacnet/event.h +++ b/src/bacnet/event.h @@ -471,6 +471,10 @@ int uevent_notify_send( BACNET_EVENT_NOTIFICATION_DATA *data, BACNET_ADDRESS *dest); +BACNET_STACK_EXPORT +bool event_notify_parse( + BACNET_EVENT_NOTIFICATION_DATA *data, int argc, char *argv[]); + #ifdef __cplusplus } #endif /* __cplusplus */