apps - allow text strings for object-type and property arguments. (#8)

The existing method of calling various example apps requires the user to
know the enumeration value for the object-type and property values. This
patch enhances to allow the object-type and property arguments to be
specified as strings, using the strings as defined in the spec. It does
not remove the old behaviour.

Current:
  bacrp 1234 3 1 85

New:
  bacrp 1234 binary-input 1 present-value

This change does not currently apply to the property arguments of the
readm and writem applications.
This commit is contained in:
Roger Light
2020-01-15 05:18:30 +00:00
committed by Steve Karg
parent ed3f0982a3
commit 5a7049557b
10 changed files with 193 additions and 66 deletions
+29 -13
View File
@@ -197,19 +197,23 @@ static void print_help(char *filename)
"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 Analog Output 2, the object-type would be 1.\n"
"The object type is object that you are reading. It\n"
"can be defined either as the object-type name string\n"
"as defined in the BACnet specification, or as the\n"
"integer value of the enumeration BACNET_OBJECT_TYPE\n"
"in bacenum.h. For example if you were reading Analog\n"
"Output 2, the object-type would be analog-output or 1.\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"
"Analog Output 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"
"Present Value property, use 85 as the property.\n"
"The property of the object that you are reading. It\n"
"can be defined either as the property name string as\n"
"defined in the BACnet specification, or as an integer\n"
"value of the enumeration BACNET_PROPERTY_ID in\n"
"bacenum.h. For example, if you were reading the Present\n"
"Value property, use present-value or 85 as the property.\n"
"\nindex:\n"
"This integer parameter is the index number of an array.\n"
"If the property is an array, individual elements can\n"
@@ -217,12 +221,16 @@ static void print_help(char *filename)
"is an array, the entire array will be read.\n"
"\nExample:\n"
"If you want read the Present-Value of Analog Output 101\n"
"in Device 123, you could send the following command:\n"
"in Device 123, you could send either of the following\n"
"commands:\n"
"%s 123 analog-output 101 present-value\n"
"%s 123 1 101 85\n"
"If you want read the Priority-Array of Analog Output 101\n"
"in Device 123, you could send the following command:\n"
"in Device 123, you could send either of the following\n"
"commands:\n"
"%s 123 analog-output 101 priority-array\n"
"%s 123 1 101 87\n",
filename, filename);
filename, filename, filename, filename);
}
int main(int argc, char *argv[])
@@ -285,13 +293,21 @@ int main(int argc, char *argv[])
Target_Device_Object_Instance = strtol(argv[argi], NULL, 0);
target_args++;
} else if (target_args == 1) {
Target_Object_Type = strtol(argv[argi], NULL, 0);
if (bactext_object_type_strtol(
argv[argi], &Target_Object_Type) == false) {
fprintf(stderr, "object-type=%s invalid\n", argv[argi]);
return 1;
}
target_args++;
} else if (target_args == 2) {
Target_Object_Instance = strtol(argv[argi], NULL, 0);
target_args++;
} else if (target_args == 3) {
Target_Object_Property = strtol(argv[argi], NULL, 0);
if (bactext_property_strtol(
argv[argi], &Target_Object_Property) == false) {
fprintf(stderr, "property=%s invalid\n", argv[argi]);
return 1;
}
target_args++;
} else if (target_args == 4) {
Target_Object_Index = strtol(argv[argi], NULL, 0);
+24 -11
View File
@@ -242,10 +242,12 @@ static void print_help(char *filename)
"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 Analog Output 2, the object-type would be 1.\n"
"The object type is object that you are reading. It\n"
"can be defined either as the object-type name string\n"
"as defined in the BACnet specification, or as the\n"
"integer value of the enumeration BACNET_OBJECT_TYPE\n"
"in bacenum.h. For example if you were reading Analog\n"
"Output 2, the object-type would be analog-output or 1.\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"
@@ -263,22 +265,28 @@ static void print_help(char *filename)
"\nExample:\n"
"If you want read the PRESENT_VALUE property and various\n"
"array elements of the PRIORITY_ARRAY in Device 123\n"
"Analog Output object 99, use the following command:\n"
"Analog Output object 99, use one of the following commands:\n"
"%s 123 analog-output 99 85,87[0],87\n"
"%s 123 1 99 85,87[0],87\n"
"If you want read the PRESENT_VALUE property in objects\n"
"Analog Input 77 and Analog Input 78 in Device 123\n"
"use the following command:\n"
"use one of the following commands:\n"
"%s 123 analog-input 77 85 analog-input 78 85\n"
"%s 123 0 77 85 0 78 85\n"
"If you want read the ALL property in\n"
"Device object 123, you would use the following command:\n"
"Device object 123, you would use one of the following commands:\n"
"%s 123 device 123 8\n"
"%s 123 8 123 8\n"
"If you want read the OPTIONAL property in\n"
"Device object 123, you would use the following command:\n"
"Device object 123, you would use one of the following commands:\n"
"%s 123 device 123 80\n"
"%s 123 8 123 80\n"
"If you want read the REQUIRED property in\n"
"Device object 123, you would use the following command:\n"
"Device object 123, you would one of use the following commands:\n"
"%s 123 device 123 105\n"
"%s 123 8 123 105\n",
filename, filename, filename, filename, filename);
filename, filename, filename, filename, filename, filename, filename,
filename, filename, filename);
}
int main(int argc, char *argv[])
@@ -338,7 +346,12 @@ int main(int argc, char *argv[])
arg_sets = 0;
while (rpm_object) {
tag_value_arg = 2 + (arg_sets * 3);
rpm_object->object_type = strtol(argv[tag_value_arg], NULL, 0);
if (bactext_object_type_strtol(
argv[tag_value_arg], &rpm_object->object_type) == false) {
fprintf(
stderr, "Error: object-type=%s invalid\n", argv[tag_value_arg]);
return 1;
}
tag_value_arg++;
args_remaining--;
if (args_remaining <= 0) {
+13 -5
View File
@@ -177,9 +177,11 @@ static void print_help(char *filename)
"\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);
"you could send the following commands:\n");
printf("%s 123 trend-log 2 log-buffer 1 1 10\n", filename);
printf("%s 123 trend-log 2 log-buffer 2 1 10\n", filename);
printf("%s 123 trend-log 2 log-buffer 3 1/1/2014 00:00:01 10\n", filename);
printf("%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);
}
@@ -224,9 +226,15 @@ int main(int argc, char *argv[])
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Target_Object_Type = strtol(argv[2], NULL, 0);
if (bactext_object_type_strtol(argv[2], &Target_Object_Type) == false) {
fprintf(stderr, "object-type=%s invalid\n", argv[2]);
return 1;
}
Target_Object_Instance = strtol(argv[3], NULL, 0);
Target_Object_Property = strtol(argv[4], NULL, 0);
if (bactext_property_strtol(argv[4], &Target_Object_Property) == false) {
fprintf(stderr, "property=%s invalid\n", argv[4]);
return 1;
}
Target_Object_Range_Type = strtol(argv[5], NULL, 0);
/* some bounds checking */
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
+12 -5
View File
@@ -193,6 +193,7 @@ int main(int argc, char *argv[])
BACNET_SUBSCRIBE_COV_DATA *cov_data = NULL;
int argi = 0;
int arg_remaining = 0;
unsigned uint;
if (argc < 6) {
print_usage_terse = true;
@@ -216,10 +217,12 @@ int main(int argc, char *argv[])
"The subscriber BACnet Device Object Instance number.\r\n"
"\r\n"
"object-type:\r\n"
"The monitored object type is the integer value of the\r\n"
"enumeration BACNET_OBJECT_TYPE in bacenum.h. For example,\r\n"
"if you were monitoring Analog Output 2, the object-type\r\n"
"would be 1.\r\n"
"The object type is object that you are reading. It\r\n"
"can be defined either as the object-type name string\r\n"
"as defined in the BACnet specification, or as the\r\n"
"integer value of the enumeration BACNET_OBJECT_TYPE\r\n"
"in bacenum.h. For example if you were reading Analog\r\n"
"Output 2, the object-type would be analog-output or 1.\r\n"
"\r\n"
"object-instance:\r\n"
"The monitored object instance number.\r\n"
@@ -264,7 +267,11 @@ int main(int argc, char *argv[])
cov_data = COV_Subscribe_Data;
argi = 2;
while (cov_data) {
cov_data->monitoredObjectIdentifier.type = strtol(argv[argi], NULL, 0);
if (bactext_object_type_strtol(argv[argi], &uint) == false) {
fprintf(stderr, "Error: object-type=%s invalid\n", argv[argi]);
return 1;
}
cov_data->monitoredObjectIdentifier.type = (uint16_t)uint;
if (cov_data->monitoredObjectIdentifier.type >=
MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
+27 -12
View File
@@ -73,6 +73,7 @@ int main(int argc, char *argv[])
BACNET_COV_DATA cov_data;
BACNET_PROPERTY_VALUE value_list;
uint8_t tag;
unsigned int uint;
if (argc < 7) {
/* note: priority 16 and 0 should produce the same end results... */
@@ -87,10 +88,12 @@ int main(int argc, char *argv[])
"The Initiating BACnet Device Object Instance number.\r\n"
"\r\n"
"object-type:\r\n"
"The monitored object type is the integer value of the\r\n"
"enumeration BACNET_OBJECT_TYPE in bacenum.h. For example,\r\n"
"if you were monitoring Analog Output 2, the object-type\r\n"
"would be 1.\r\n"
"The object type is object that you are reading. It\r\n"
"can be defined either as the object-type name string\r\n"
"as defined in the BACnet specification, or as the\r\n"
"integer value of the enumeration BACNET_OBJECT_TYPE\r\n"
"in bacenum.h. For example if you were reading Analog\r\n"
"Output 2, the object-type would be analog-output or 1.\r\n"
"\r\n"
"object-instance:\r\n"
"The monitored object instance number.\r\n"
@@ -99,10 +102,12 @@ int main(int argc, char *argv[])
"The subscription time remaining is conveyed in seconds.\r\n"
"\r\n"
"property:\r\n"
"The property is an integer value of the enumeration \r\n"
"BACNET_PROPERTY_ID in bacenum.h. For example, if you were\r\n"
"monitoring the Present Value property, you would use 85\r\n"
"as the property.\r\n"
"The property of the object that you are reading. It\r\n"
"can be defined either as the property name string as\r\n"
"defined in the BACnet specification, or as an integer\r\n"
"value of the enumeration BACNET_PROPERTY_ID in\\rn"
"bacenum.h. For example, if you were reading the Present\r\n"
"Value property, use present-value or 85 as the property.\r\n"
"\r\n"
"tag:\r\n"
"Tag is the integer value of the enumeration "
@@ -156,22 +161,32 @@ int main(int argc, char *argv[])
"\r\n"
"Example:\r\n"
"If you want generate an unconfirmed COV,\r\n"
"you could send the following command:\r\n"
"you could send one of the following command:\r\n"
"%s 1 2 analog-value 4 5 prevent-value 4 100.0\r\n"
"%s 1 2 3 4 5 85 4 100.0\r\n"
"where 1=pid, 2=device-id, 3=AV, 4=object-id, 5=time,\r\n"
"85=Present-Value, 4=REAL, 100.0=value\r\n",
filename_remove_path(argv[0]), filename_remove_path(argv[0]));
filename_remove_path(argv[0]), filename_remove_path(argv[0]),
filename_remove_path(argv[0]));
return 0;
}
/* decode the command line parameters */
cov_data.subscriberProcessIdentifier = strtol(argv[1], NULL, 0);
cov_data.initiatingDeviceIdentifier = strtol(argv[2], NULL, 0);
cov_data.monitoredObjectIdentifier.type = strtol(argv[3], NULL, 0);
if (bactext_object_type_strtol(argv[3], &uint) == false) {
fprintf(stderr, "error: object-type=%s invalid\n", argv[3]);
return 1;
}
cov_data.monitoredObjectIdentifier.type = (uint16_t)uint;
cov_data.monitoredObjectIdentifier.instance = strtol(argv[4], NULL, 0);
cov_data.timeRemaining = strtol(argv[5], NULL, 0);
cov_data.listOfValues = &value_list;
value_list.next = NULL;
value_list.propertyIdentifier = strtol(argv[6], NULL, 0);
if (bactext_property_strtol(argv[6], &value_list.propertyIdentifier) ==
false) {
fprintf(stderr, "property=%s invalid\n", argv[6]);
return 1;
}
tag = strtol(argv[7], NULL, 0);
value_string = argv[8];
/* optional priority */
+9 -3
View File
@@ -117,7 +117,7 @@ static void print_help(char *filename)
"The device-instance-min or max can be 0 to %d.\r\n"
"\r\n"
"Use either:\r\n"
"The object-type can be 0 to %d.\r\n"
"The object-type can be 0 to %d, or a string e.g. analog-output.\r\n"
"The object-instance can be 0 to %d.\r\n"
"or:\r\n"
"The object-name can be any string of characters.\r\n",
@@ -157,7 +157,10 @@ int main(int argc, char *argv[])
} else if (argc < 4) {
/* bacwh 8 1234 */
Target_Object_Instance_Min = Target_Object_Instance_Max = -1;
Target_Object_Type = strtol(argv[1], NULL, 0);
if (bactext_object_type_strtol(argv[1], &Target_Object_Type) == false) {
fprintf(stderr, "object-type=%s invalid\n", argv[1]);
return 1;
}
Target_Object_Instance = strtol(argv[2], NULL, 0);
} else if (argc < 5) {
/* bacwh 0 4194303 "name" */
@@ -169,7 +172,10 @@ int main(int argc, char *argv[])
/* bacwh 0 4194303 8 1234 */
Target_Object_Instance_Min = strtol(argv[1], NULL, 0);
Target_Object_Instance_Max = strtol(argv[2], NULL, 0);
Target_Object_Type = strtol(argv[3], NULL, 0);
if (bactext_object_type_strtol(argv[3], &Target_Object_Type) == false) {
fprintf(stderr, "object-type=%s invalid\n", argv[3]);
return 1;
}
Target_Object_Instance = strtol(argv[4], NULL, 0);
} else {
print_usage(filename_remove_path(argv[0]));
+24 -12
View File
@@ -165,10 +165,12 @@ static void print_help(char *filename)
"writing to Device Object 123, the device-instance would be 123.\n"
"\n"
"object-type:\n"
"The object type is the integer value of the enumeration\n"
"BACNET_OBJECT_TYPE in bacenum.h. It is the object that you are\n"
"writing to. For example if you were writing to Analog Output 2, \n"
"the object-type would be 1.\n"
"The object type is object that you are reading. It\n"
"can be defined either as the object-type name string\n"
"as defined in the BACnet specification, or as the\n"
"integer value of the enumeration BACNET_OBJECT_TYPE\n"
"in bacenum.h. For example if you were reading Analog\n"
"Output 2, the object-type would be analog-output or 1.\n"
"\n"
"object-instance:\n"
"This is the object instance number of the object that you are \n"
@@ -176,10 +178,12 @@ static void print_help(char *filename)
"the object-instance would be 2.\n"
"\n"
"property:\n"
"The property is an integer value of the enumeration \n"
"BACNET_PROPERTY_ID in bacenum.h. It is the property you are \n"
"writing to. For example, if you were writing to the Present Value\n"
"property, you would use 85 as the property.\n"
"The property of the object that you are reading. It\n"
"can be defined either as the property name string as\n"
"defined in the BACnet specification, or as an integer\n"
"value of the enumeration BACNET_PROPERTY_ID in\n"
"bacenum.h. For example, if you were reading the Present\n"
"Value property, use present-value or 85 as the property.\n"
"\n"
"priority:\n"
"This parameter is used for setting the priority of the\n"
@@ -221,11 +225,13 @@ static void print_help(char *filename)
"\nExample:\n"
"If you want send a value of 100 to the Present-Value in\n"
"Analog Output 0 of Device 123 at priority 16,\n"
"send the following command:\n"
"send the one of following commands:\n"
"%s 123 analog-output 0 present-value 16 -1 4 100\n"
"%s 123 1 0 85 16 -1 4 100\n"
"To send a relinquish command to the same object:\n"
"%s 123 analog-output 0 present-value 16 -1 0 0\n"
"%s 123 1 0 85 16 -1 0 0\n",
filename, filename);
filename, filename, filename, filename);
}
int main(int argc, char *argv[])
@@ -270,9 +276,15 @@ int main(int argc, char *argv[])
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Target_Object_Type = strtol(argv[2], NULL, 0);
if (bactext_object_type_strtol(argv[2], &Target_Object_Type) == false) {
fprintf(stderr, "object-type=%s invalid\n", argv[2]);
return 1;
}
Target_Object_Instance = strtol(argv[3], NULL, 0);
Target_Object_Property = strtol(argv[4], NULL, 0);
if (bactext_property_strtol(argv[4], &Target_Object_Property) == false) {
fprintf(stderr, "property=%s invalid\n", argv[4]);
return 1;
}
Target_Object_Property_Priority = (uint8_t)strtol(argv[5], NULL, 0);
Target_Object_Property_Index = strtol(argv[6], NULL, 0);
if (Target_Object_Property_Index == -1)
+12 -5
View File
@@ -184,10 +184,12 @@ static void print_help(char *filename)
"I-Am services. For example, if you were writing\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 writing. For example if you were\n"
"writing Analog Output 2, the object-type would be 1.\n"
"The object type is object that you are reading. It\n"
"can be defined either as the object-type name string\n"
"as defined in the BACnet specification, or as the\n"
"integer value of the enumeration BACNET_OBJECT_TYPE\n"
"in bacenum.h. For example if you were reading Analog\n"
"Output 2, the object-type would be analog-output or 1.\n"
"\nobject-instance:\n"
"This is the object instance number of the object that\n"
"you are writing. For example, if you were writing\n"
@@ -302,7 +304,12 @@ int main(int argc, char *argv[])
arg_sets = 0;
while (wpm_object) {
tag_value_arg = 2 + (arg_sets * 6);
wpm_object->object_type = strtol(argv[tag_value_arg], NULL, 0);
if (bactext_object_type_strtol(
argv[tag_value_arg], &wpm_object->object_type) == false) {
fprintf(
stderr, "Error: object-type=%s invalid\n", argv[tag_value_arg]);
return 1;
}
tag_value_arg++;
args_remaining--;
if (Verbose) {
+37
View File
@@ -33,6 +33,7 @@
####COPYRIGHTEND####*/
#include <stdio.h>
#include <stdlib.h>
#include "bacnet/indtext.h"
#include "bacnet/bacenum.h"
#include "bacnet/bactext.h"
@@ -42,6 +43,30 @@
static const char *ASHRAE_Reserved_String = "Reserved for Use by ASHRAE";
static const char *Vendor_Proprietary_String = "Vendor Proprietary Value";
/* Search for a text value first based on the corresponding text list, then by
* attempting to convert to an integer value. */
static bool bactext_strtol_index(INDTEXT_DATA *istring, const char *search_name, unsigned *found_index)
{
char *endptr;
long value;
if (indtext_by_istring(istring, search_name, found_index) == true) {
return true;
} else {
value = strtol(search_name, &endptr, 0);
if (endptr == search_name) {
/* No digits found */
return false;
} else if (*endptr != '\0') {
/* Extra text found */
return false;
} else {
*found_index = (unsigned)value;
return true;
}
}
}
INDTEXT_DATA bacnet_confirmed_service_names[] = {
{ SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM, "Acknowledge-Alarm" },
{ SERVICE_CONFIRMED_COV_NOTIFICATION, "COV-Notification" },
@@ -206,6 +231,12 @@ bool bactext_object_type_index(const char *search_name, unsigned *found_index)
bacnet_object_type_names, search_name, found_index);
}
bool bactext_object_type_strtol(const char *search_name, unsigned *found_index)
{
return bactext_strtol_index(
bacnet_object_type_names, search_name, found_index);
}
INDTEXT_DATA bacnet_property_names[] = {
/* FIXME: use the enumerations from bacenum.h */
{ PROP_ACKED_TRANSITIONS, "acked-transitions" },
@@ -660,6 +691,12 @@ bool bactext_property_index(const char *search_name, unsigned *found_index)
return indtext_by_istring(bacnet_property_names, search_name, found_index);
}
bool bactext_property_strtol(const char *search_name, unsigned *found_index)
{
return bactext_strtol_index(
bacnet_property_names, search_name, found_index);
}
INDTEXT_DATA bacnet_engineering_unit_names[] = {
{ UNITS_SQUARE_METERS, "square-meters" },
{ UNITS_SQUARE_FEET, "square-feet" },
+6
View File
@@ -55,6 +55,9 @@ extern "C" {
bool bactext_object_type_index(
const char *search_name,
unsigned *found_index);
bool bactext_object_type_strtol(
const char *search_name,
unsigned *found_index);
const char *bactext_notify_type_name(
unsigned index);
const char *bactext_event_type_name(
@@ -67,6 +70,9 @@ extern "C" {
bool bactext_property_index(
const char *search_name,
unsigned *found_index);
bool bactext_property_strtol(
const char *search_name,
unsigned *found_index);
const char *bactext_engineering_unit_name(
unsigned index);
bool bactext_engineering_unit_index(