Feature/bacrpm dnet mac adr destinations (#295)

* add dnet,mac,adr for bacrpm explicit destinations

* add usage help to readpropm for dnet,mac,dadr

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2022-06-12 15:02:20 -05:00
committed by GitHub
parent 20ffb968ef
commit ff6fcf456c
+180 -90
View File
@@ -143,7 +143,7 @@ static void My_Read_Property_Multiple_Ack_Handler(uint8_t *service_request,
while (rpm_data) { while (rpm_data) {
rpm_ack_print_data(rpm_data); rpm_ack_print_data(rpm_data);
rpm_data = rpm_data_free(rpm_data); rpm_data = rpm_data_free(rpm_data);
} }
} else { } else {
fprintf(stderr, "RPM Ack Malformed! Freeing memory...\n"); fprintf(stderr, "RPM Ack Malformed! Freeing memory...\n");
@@ -213,19 +213,78 @@ static void cleanup(void)
} }
} }
static void target_address_add(
long dnet,
BACNET_MAC_ADDRESS *mac,
BACNET_MAC_ADDRESS *adr)
{
BACNET_ADDRESS dest = { 0 };
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 <= UINT16_MAX)) {
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 <= UINT16_MAX)) {
dest.net = dnet;
} else {
dest.net = 0;
}
} else {
if ((dnet >= 0) && (dnet <= UINT16_MAX)) {
dest.net = dnet;
} else {
dest.net = BACNET_BROADCAST_NETWORK;
}
dest.mac_len = 0;
dest.len = 0;
}
address_add(Target_Device_Object_Instance, MAX_APDU, &dest);
}
static void print_usage(char *filename) static void print_usage(char *filename)
{ {
printf("Usage: %s device-instance object-type object-instance " printf("Usage: %s device-instance object-type object-instance "
"property[index][,property[index]] [object-type ...]\n", "property[index][,property[index]] [object-type ...]\n",
filename); filename);
printf(" [--dnet][--dadr][--mac]\n");
printf(" [--version][--help]\n"); printf(" [--version][--help]\n");
} }
static void print_help(char *filename) static void print_help(char *filename)
{ {
printf("Read one or more properties from one or more objects\n" printf("Read one or more properties from one or more objects\n"
"in a BACnet device and print the value(s).\n" "in a BACnet device and print the value(s).\n");
"device-instance:\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"
"\n"
"--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"
"\n"
"--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"
"\n");
printf("device-instance:\n"
"BACnet Device Object Instance number that you are\n" "BACnet Device Object Instance number that you are\n"
"trying to communicate to. This number will be used\n" "trying to communicate to. This number will be used\n"
"to try and bind with the device using Who-Is and\n" "to try and bind with the device using Who-Is and\n"
@@ -285,20 +344,26 @@ int main(int argc, char *argv[])
uint16_t pdu_len = 0; uint16_t pdu_len = 0;
unsigned timeout = 100; /* milliseconds */ unsigned timeout = 100; /* milliseconds */
unsigned max_apdu = 0; unsigned max_apdu = 0;
int args_remaining = 0, tag_value_arg = 0, arg_sets = 0; int tag_value_arg = 0;
time_t elapsed_seconds = 0; time_t elapsed_seconds = 0;
time_t last_seconds = 0; time_t last_seconds = 0;
time_t current_seconds = 0; time_t current_seconds = 0;
time_t timeout_seconds = 0; time_t timeout_seconds = 0;
bool found = false; bool found = false;
uint8_t buffer[MAX_PDU] = { 0 }; uint8_t buffer[MAX_PDU] = { 0 };
BACNET_READ_ACCESS_DATA *rpm_object; BACNET_READ_ACCESS_DATA *rpm_object = NULL;
BACNET_PROPERTY_REFERENCE *rpm_property; BACNET_PROPERTY_REFERENCE *rpm_property = NULL;
char *property_token = NULL; char *property_token = NULL;
unsigned property_id = 0; unsigned property_id = 0;
unsigned property_array_index = 0; unsigned property_array_index = 0;
int scan_count = 0; int scan_count = 0;
int argi = 0; int argi = 0;
long dnet = -1;
BACNET_MAC_ADDRESS mac = { 0 };
BACNET_MAC_ADDRESS adr = { 0 };
bool specific_address = false;
unsigned int target_args = 0;
bool status = false;
char *filename = NULL; char *filename = NULL;
filename = filename_remove_path(argv[0]); filename = filename_remove_path(argv[0]);
@@ -317,100 +382,125 @@ int main(int argc, char *argv[])
"FITNESS FOR A PARTICULAR PURPOSE.\n"); "FITNESS FOR A PARTICULAR PURPOSE.\n");
return 0; return 0;
} }
} if (strcmp(argv[argi], "--mac") == 0) {
if (argc < 5) { if (++argi < argc) {
print_usage(filename); if (address_mac_from_ascii(&mac, argv[argi])) {
return 0; specific_address = true;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
atexit(cleanup);
Read_Access_Data = calloc(1, sizeof(BACNET_READ_ACCESS_DATA));
rpm_object = Read_Access_Data;
args_remaining = (argc - 2);
arg_sets = 0;
while (rpm_object) {
tag_value_arg = 2 + (arg_sets * 3);
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) {
fprintf(stderr, "Error: not enough object property triples.\n");
return 1;
}
if (rpm_object->object_type >= MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\n",
rpm_object->object_type, MAX_BACNET_OBJECT_TYPE);
return 1;
}
rpm_object->object_instance = strtol(argv[tag_value_arg], NULL, 0);
tag_value_arg++;
args_remaining--;
if (args_remaining <= 0) {
fprintf(stderr, "Error: not enough object property triples.\n");
return 1;
}
if (rpm_object->object_instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "object-instance=%u - it must be less than %u\n",
rpm_object->object_instance, BACNET_MAX_INSTANCE + 1);
return 1;
}
rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE));
rpm_object->listOfProperties = rpm_property;
property_token = strtok(argv[tag_value_arg], ",");
/* add all the properties and optional index to our list */
while (rpm_property) {
scan_count = sscanf(
property_token, "%u[%u]", &property_id, &property_array_index);
if (scan_count > 0) {
rpm_property->propertyIdentifier = property_id;
if (rpm_property->propertyIdentifier > MAX_BACNET_PROPERTY_ID) {
fprintf(stderr, "property=%u - it must be less than %u\n",
rpm_property->propertyIdentifier,
MAX_BACNET_PROPERTY_ID + 1);
return 1;
} }
} }
if (scan_count > 1) { } else if (strcmp(argv[argi], "--dnet") == 0) {
rpm_property->propertyArrayIndex = property_array_index; if (++argi < argc) {
} else { dnet = strtol(argv[argi], NULL, 0);
rpm_property->propertyArrayIndex = BACNET_ARRAY_ALL; if ((dnet >= 0) && (dnet <= UINT16_MAX)) {
specific_address = true;
}
} }
/* is there another property? */ } else if (strcmp(argv[argi], "--dadr") == 0) {
property_token = strtok(NULL, ","); if (++argi < argc) {
if (property_token) { if (address_mac_from_ascii(&adr, argv[argi])) {
rpm_property->next = specific_address = true;
calloc(1, sizeof(BACNET_PROPERTY_REFERENCE)); }
rpm_property = rpm_property->next;
} else {
rpm_property->next = NULL;
break;
} }
}
/* used up another arg */
tag_value_arg++;
args_remaining--;
if (args_remaining) {
arg_sets++;
rpm_object->next = calloc(1, sizeof(BACNET_READ_ACCESS_DATA));
rpm_object = rpm_object->next;
} else { } else {
break; if (target_args == 0) {
Target_Device_Object_Instance = strtol(argv[argi], NULL, 0);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr,
"device-instance=%u - it must be less than %u\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
tag_value_arg = 0;
target_args++;
} else if (target_args >= 1) {
if (tag_value_arg == 0) {
if (rpm_object) {
rpm_object->next = calloc(1,
sizeof(BACNET_READ_ACCESS_DATA));
rpm_object = rpm_object->next;
} else {
Read_Access_Data = calloc(1,
sizeof(BACNET_READ_ACCESS_DATA));
rpm_object = Read_Access_Data;
atexit(cleanup);
}
status = bactext_object_type_strtol(
argv[argi], &rpm_object->object_type);
if (status == false) {
fprintf(stderr, "Error: object-type=%s invalid\n",
argv[argi]);
return 1;
}
if (rpm_object->object_type >= MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr,
"object-type=%u - it must be less than %u\n",
rpm_object->object_type, MAX_BACNET_OBJECT_TYPE);
return 1;
}
tag_value_arg++;
} else if (tag_value_arg == 1) {
rpm_object->object_instance = strtol(argv[argi], NULL, 0);
if (rpm_object->object_instance > BACNET_MAX_INSTANCE) {
fprintf(stderr,
"object-instance=%u - it must be less than %u\n",
rpm_object->object_instance, BACNET_MAX_INSTANCE + 1);
return 1;
}
tag_value_arg++;
} else if (tag_value_arg == 2) {
rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE));
rpm_object->listOfProperties = rpm_property;
property_token = strtok(argv[argi], ",");
/* add all the properties and optional index to our list */
while (rpm_property) {
scan_count = sscanf(
property_token, "%u[%u]", &property_id,
&property_array_index);
if (scan_count > 0) {
rpm_property->propertyIdentifier = property_id;
if (rpm_property->propertyIdentifier >
MAX_BACNET_PROPERTY_ID) {
fprintf(stderr,
"property=%u - it must be less than %u\n",
rpm_property->propertyIdentifier,
MAX_BACNET_PROPERTY_ID + 1);
return 1;
}
}
if (scan_count > 1) {
rpm_property->propertyArrayIndex =
property_array_index;
} else {
rpm_property->propertyArrayIndex = BACNET_ARRAY_ALL;
}
/* is there another property? */
property_token = strtok(NULL, ",");
if (property_token) {
rpm_property->next =
calloc(1, sizeof(BACNET_PROPERTY_REFERENCE));
rpm_property = rpm_property->next;
} else {
rpm_property->next = NULL;
break;
}
}
/* start over with the next arg set */
tag_value_arg = 0;
}
}
} }
} }
if (tag_value_arg != 0) {
fprintf(stderr, "Error: not enough object property triples.\n");
return 1;
}
/* setup my info */ /* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init(); address_init();
if (specific_address) {
target_address_add(dnet, &mac, &adr);
}
Init_Service_Handlers(); Init_Service_Handlers();
dlenv_init(); dlenv_init();
#ifdef __STDC_ISO_10646__ #ifdef __STDC_ISO_10646__