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:
+180
-90
@@ -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__
|
||||||
|
|||||||
Reference in New Issue
Block a user