Refactored address decoding from demo command line function into address library.
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include "address.h"
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
@@ -103,88 +104,42 @@ static void Init_Service_Handlers(
|
|||||||
apdu_set_reject_handler(MyRejectHandler);
|
apdu_set_reject_handler(MyRejectHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parse a string for a bacnet-address
|
|
||||||
*
|
|
||||||
* @param mac [out] BACNET Address MAC at least 6 octets
|
|
||||||
* @param arg [in] nul terminated string to parse
|
|
||||||
* @return length of address parsed in bytes
|
|
||||||
*/
|
|
||||||
int address_from_ascii(
|
|
||||||
uint8_t *mac,
|
|
||||||
char *arg)
|
|
||||||
{
|
|
||||||
unsigned a[6] = {0}, p = 0;
|
|
||||||
uint16_t port = 0;
|
|
||||||
int c, len = 0;
|
|
||||||
|
|
||||||
c = sscanf(arg, "%3u.%3u.%3u.%3u:%5u", &a[0],&a[1],&a[2],&a[3],&p);
|
|
||||||
if ((c == 4) || (c == 5)) {
|
|
||||||
mac[0] = a[0];
|
|
||||||
mac[1] = a[1];
|
|
||||||
mac[2] = a[2];
|
|
||||||
mac[3] = a[3];
|
|
||||||
if (c == 4) {
|
|
||||||
port = htons((uint16_t) 0xBAC0);
|
|
||||||
} else {
|
|
||||||
port = htons((uint16_t) p);
|
|
||||||
}
|
|
||||||
memcpy(&mac[4], &port, 2);
|
|
||||||
len = 6;
|
|
||||||
} else {
|
|
||||||
c = sscanf(arg, "%2x:%2x:%2x:%2x:%2x:%2x",
|
|
||||||
&a[0],&a[1],&a[2],&a[3],&a[4],&a[5]);
|
|
||||||
if (c == 6) {
|
|
||||||
mac[0] = a[0];
|
|
||||||
mac[1] = a[1];
|
|
||||||
mac[2] = a[2];
|
|
||||||
mac[3] = a[3];
|
|
||||||
mac[4] = a[4];
|
|
||||||
mac[5] = a[5];
|
|
||||||
len = 6;
|
|
||||||
} else if (c == 1) {
|
|
||||||
a[0] = (unsigned)strtol(arg, NULL, 0);
|
|
||||||
if (a[0] <= 255) {
|
|
||||||
mac[0] = a[0];
|
|
||||||
len = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_usage(char *filename)
|
static void print_usage(char *filename)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [--dnet][--dadr][--mac][--version][--help]\n", filename);
|
printf("Usage: %s [--dnet][--dadr][--mac]\n", filename);
|
||||||
|
printf(" [--version][--help]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_help(char *filename)
|
static void print_help(char *filename)
|
||||||
{
|
{
|
||||||
printf("Send BACnet TimeSynchronization request.\n"
|
printf("Send BACnet TimeSynchronization request.\n"
|
||||||
|
"\n"
|
||||||
|
"--mac A\n"
|
||||||
|
"BACnet mac address."
|
||||||
|
"Valid ranges are from 0 to 255\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"
|
"\n"
|
||||||
"--dnet N\n"
|
"--dnet N\n"
|
||||||
" BACnet network number N for directed requests."
|
"BACnet network number N for directed requests.\n"
|
||||||
" Valid range is from 0 to 65535\n"
|
"Valid range is from 0 to 65535 where 0 is the local connection\n"
|
||||||
" where 0 is the local connection\n"
|
"and 65535 is network broadcast.\n"
|
||||||
" and 65535 is network broadcast.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"--dadr A\n"
|
"--dadr A\n"
|
||||||
" BACnet mac address."
|
"BACnet mac address on the destination BACnet network number.\n"
|
||||||
" Valid ranges are from 0 to 255\n"
|
"Valid ranges are from 0 to 255\n"
|
||||||
" or an IP string with optional port number like 10.1.2.3:47808\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"
|
"or an Ethernet MAC in hex like 00:21:70:7e:32:bb\n"
|
||||||
"\n"
|
"\n");
|
||||||
"Examples:\n"
|
printf("Examples:\n"
|
||||||
"Send a TimeSynchronization request to DNET 123:\n"
|
"Send a TimeSynchronization request to DNET 123:\n"
|
||||||
"%s --dnet 123\n"
|
"%s --dnet 123\n", filename);
|
||||||
"Send a TimeSynchronization request to MAC 10.0.0.1 DNET 123 DADR 5:\n"
|
printf("Send a TimeSynchronization request to MAC 10.0.0.1 DNET 123 DADR 5:\n"
|
||||||
"%s --mac 10.0.0.1 --dnet 123 --dadr 5\n"
|
"%s --mac 10.0.0.1 --dnet 123 --dadr 5\n", filename);
|
||||||
"Send a TimeSynchronization request to MAC 10.1.2.3:47808:\n"
|
printf("Send a TimeSynchronization request to MAC 10.1.2.3:47808:\n"
|
||||||
"%s --mac 10.1.2.3:47808\n",
|
"%s --mac 10.1.2.3:47808\n", filename);
|
||||||
filename,
|
|
||||||
filename,
|
|
||||||
filename);
|
|
||||||
#if 0
|
#if 0
|
||||||
|
/* FIXME: it would be nice to be able to send arbitrary time values */
|
||||||
"date format: year/month/day:dayofweek (e.g. 2006/4/1:6)\n"
|
"date format: year/month/day:dayofweek (e.g. 2006/4/1:6)\n"
|
||||||
"year: AD, such as 2006\n" "month: 1=January, 12=December\n"
|
"year: AD, such as 2006\n" "month: 1=January, 12=December\n"
|
||||||
"day: 1-31\n" "dayofweek: 1=Monday, 7=Sunday\n" "\n"
|
"day: 1-31\n" "dayofweek: 1=Monday, 7=Sunday\n" "\n"
|
||||||
@@ -213,26 +168,25 @@ int main(
|
|||||||
struct tm *my_time;
|
struct tm *my_time;
|
||||||
BACNET_DATE bdate;
|
BACNET_DATE bdate;
|
||||||
BACNET_TIME btime;
|
BACNET_TIME btime;
|
||||||
BACNET_ADDRESS dest;
|
|
||||||
long dnet = -1;
|
long dnet = -1;
|
||||||
uint8_t mac[MAX_MAC_LEN];
|
BACNET_MAC_ADDRESS mac = { 0 };
|
||||||
uint8_t adr[MAX_MAC_LEN];
|
BACNET_MAC_ADDRESS adr = { 0 };
|
||||||
int argi = 0;
|
BACNET_ADDRESS dest = { 0 };
|
||||||
int len = 0, mac_len = 0;
|
|
||||||
bool global_broadcast = true;
|
bool global_broadcast = true;
|
||||||
|
int argi = 0;
|
||||||
|
char *filename = NULL;
|
||||||
|
|
||||||
/* decode any command line parameters */
|
/* decode any command line parameters */
|
||||||
|
filename = filename_remove_path(argv[0]);
|
||||||
for (argi = 1; argi < argc; argi++) {
|
for (argi = 1; argi < argc; argi++) {
|
||||||
if (strcmp(argv[argi], "--help") == 0) {
|
if (strcmp(argv[argi], "--help") == 0) {
|
||||||
print_usage(filename_remove_path(argv[0]));
|
print_usage(filename);
|
||||||
print_help(filename_remove_path(argv[0]));
|
print_help(filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (strcmp(argv[argi], "--version") == 0) {
|
if (strcmp(argv[argi], "--version") == 0) {
|
||||||
printf("%s %s\n",
|
printf("%s %s\n", filename, BACNET_VERSION_TEXT);
|
||||||
filename_remove_path(argv[0]),
|
printf("Copyright (C) 2014 by Steve Karg and others.\n"
|
||||||
BACNET_VERSION_TEXT);
|
|
||||||
printf("Copyright (C) 2014 by Steve Karg\n"
|
|
||||||
"This is free software; see the source for copying conditions.\n"
|
"This is free software; see the source for copying conditions.\n"
|
||||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||||
"FITNESS FOR A PARTICULAR PURPOSE.\n");
|
"FITNESS FOR A PARTICULAR PURPOSE.\n");
|
||||||
@@ -240,8 +194,7 @@ int main(
|
|||||||
}
|
}
|
||||||
if (strcmp(argv[argi], "--mac") == 0) {
|
if (strcmp(argv[argi], "--mac") == 0) {
|
||||||
if (++argi < argc) {
|
if (++argi < argc) {
|
||||||
mac_len = address_from_ascii(&mac[0], argv[argi]);
|
if (address_mac_from_ascii(&mac, argv[argi])) {
|
||||||
if (mac_len) {
|
|
||||||
global_broadcast = false;
|
global_broadcast = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,8 +209,7 @@ int main(
|
|||||||
}
|
}
|
||||||
if (strcmp(argv[argi], "--dadr") == 0) {
|
if (strcmp(argv[argi], "--dadr") == 0) {
|
||||||
if (++argi < argc) {
|
if (++argi < argc) {
|
||||||
len = address_from_ascii(&adr[0], argv[argi]);
|
if (address_mac_from_ascii(&adr, argv[argi])) {
|
||||||
if (len) {
|
|
||||||
global_broadcast = false;
|
global_broadcast = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,19 +218,19 @@ int main(
|
|||||||
if (global_broadcast) {
|
if (global_broadcast) {
|
||||||
datalink_get_broadcast_address(&dest);
|
datalink_get_broadcast_address(&dest);
|
||||||
} else {
|
} else {
|
||||||
if (len && mac_len) {
|
if (adr.len && mac.len) {
|
||||||
memcpy(&dest.mac[0], &mac[0], mac_len);
|
memcpy(&dest.mac[0], &mac.adr[0], mac.len);
|
||||||
dest.mac_len = mac_len;
|
dest.mac_len = mac.len;
|
||||||
memcpy(&dest.adr[0], &adr[0], len);
|
memcpy(&dest.adr[0], &adr.adr[0], adr.len);
|
||||||
dest.len = len;
|
dest.len = adr.len;
|
||||||
if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) {
|
if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) {
|
||||||
dest.net = dnet;
|
dest.net = dnet;
|
||||||
} else {
|
} else {
|
||||||
dest.net = BACNET_BROADCAST_NETWORK;
|
dest.net = BACNET_BROADCAST_NETWORK;
|
||||||
}
|
}
|
||||||
} else if (mac_len) {
|
} else if (mac.len) {
|
||||||
memcpy(&dest.mac[0], &mac[0], mac_len);
|
memcpy(&dest.mac[0], &mac.adr[0], mac.len);
|
||||||
dest.mac_len = mac_len;
|
dest.mac_len = mac.len;
|
||||||
dest.len = 0;
|
dest.len = 0;
|
||||||
if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) {
|
if ((dnet >= 0) && (dnet <= BACNET_BROADCAST_NETWORK)) {
|
||||||
dest.net = dnet;
|
dest.net = dnet;
|
||||||
|
|||||||
@@ -96,6 +96,15 @@ extern "C" {
|
|||||||
void address_cache_timer(
|
void address_cache_timer(
|
||||||
uint16_t uSeconds);
|
uint16_t uSeconds);
|
||||||
|
|
||||||
|
void address_mac_init(
|
||||||
|
BACNET_MAC_ADDRESS *mac,
|
||||||
|
uint8_t *adr,
|
||||||
|
uint8_t len);
|
||||||
|
|
||||||
|
bool address_mac_from_ascii(
|
||||||
|
BACNET_MAC_ADDRESS *mac,
|
||||||
|
char *arg);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -134,6 +134,12 @@ struct BACnet_Device_Address {
|
|||||||
uint8_t adr[MAX_MAC_LEN]; /* hwaddr (MAC) address */
|
uint8_t adr[MAX_MAC_LEN]; /* hwaddr (MAC) address */
|
||||||
};
|
};
|
||||||
typedef struct BACnet_Device_Address BACNET_ADDRESS;
|
typedef struct BACnet_Device_Address BACNET_ADDRESS;
|
||||||
|
/* define a MAC address for manipulation */
|
||||||
|
struct BACnet_MAC_Address {
|
||||||
|
uint8_t len; /* length of MAC address */
|
||||||
|
uint8_t adr[MAX_MAC_LEN];
|
||||||
|
};
|
||||||
|
typedef struct BACnet_MAC_Address BACNET_MAC_ADDRESS;
|
||||||
|
|
||||||
/* note: with microprocessors having lots more code space than memory,
|
/* note: with microprocessors having lots more code space than memory,
|
||||||
it might be better to have a packed encoding with a library to
|
it might be better to have a packed encoding with a library to
|
||||||
|
|||||||
+91
-15
@@ -189,6 +189,86 @@ static struct Address_Cache_Entry *address_remove_oldest(
|
|||||||
return (pCandidate);
|
return (pCandidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Initialize a BACNET_MAC_ADDRESS
|
||||||
|
*
|
||||||
|
* @param mac [out] BACNET_MAC_ADDRESS structure
|
||||||
|
* @param adr [in] address to initialize, null if empty
|
||||||
|
* @param len [in] length of address in bytes
|
||||||
|
*/
|
||||||
|
void address_mac_init(
|
||||||
|
BACNET_MAC_ADDRESS *mac,
|
||||||
|
uint8_t *adr,
|
||||||
|
uint8_t len)
|
||||||
|
{
|
||||||
|
uint8_t i = 0;
|
||||||
|
|
||||||
|
if (mac && adr && (len <= sizeof(mac->adr))) {
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
mac->adr[i] = adr[i];
|
||||||
|
}
|
||||||
|
mac->len = len;
|
||||||
|
} else {
|
||||||
|
mac->len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Parse an ASCII string for a bacnet-address
|
||||||
|
*
|
||||||
|
* @param mac [out] BACNET_MAC_ADDRESS structure to store the results
|
||||||
|
* @param arg [in] nul terminated ASCII string to parse
|
||||||
|
*
|
||||||
|
* @return true if the address was parsed
|
||||||
|
*/
|
||||||
|
bool address_mac_from_ascii(
|
||||||
|
BACNET_MAC_ADDRESS *mac,
|
||||||
|
char *arg)
|
||||||
|
{
|
||||||
|
unsigned a[6] = {0}, p = 0;
|
||||||
|
uint16_t port = 0;
|
||||||
|
int c;
|
||||||
|
bool status = false;
|
||||||
|
|
||||||
|
if (!(mac && arg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
c = sscanf(arg, "%3u.%3u.%3u.%3u:%5u", &a[0],&a[1],&a[2],&a[3],&p);
|
||||||
|
if ((c == 4) || (c == 5)) {
|
||||||
|
mac->adr[0] = a[0];
|
||||||
|
mac->adr[1] = a[1];
|
||||||
|
mac->adr[2] = a[2];
|
||||||
|
mac->adr[3] = a[3];
|
||||||
|
if (c == 4) {
|
||||||
|
port = 0xBAC0;
|
||||||
|
} else {
|
||||||
|
port = (uint16_t)p;
|
||||||
|
}
|
||||||
|
encode_unsigned16(&mac->adr[4], port);
|
||||||
|
mac->len = 6;
|
||||||
|
status = true;
|
||||||
|
} else {
|
||||||
|
c = sscanf(arg, "%2x:%2x:%2x:%2x:%2x:%2x",
|
||||||
|
&a[0],&a[1],&a[2],&a[3],&a[4],&a[5]);
|
||||||
|
if (c == 6) {
|
||||||
|
mac->adr[0] = a[0];
|
||||||
|
mac->adr[1] = a[1];
|
||||||
|
mac->adr[2] = a[2];
|
||||||
|
mac->adr[3] = a[3];
|
||||||
|
mac->adr[4] = a[4];
|
||||||
|
mac->adr[5] = a[5];
|
||||||
|
mac->len = 6;
|
||||||
|
status = true;
|
||||||
|
} else if (c == 1) {
|
||||||
|
a[0] = (unsigned)strtol(arg, NULL, 0);
|
||||||
|
if (a[0] <= 255) {
|
||||||
|
mac->adr[0] = a[0];
|
||||||
|
mac->len = 1;
|
||||||
|
status = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/* File format:
|
/* File format:
|
||||||
DeviceID MAC SNET SADR MAX-APDU
|
DeviceID MAC SNET SADR MAX-APDU
|
||||||
@@ -206,11 +286,10 @@ static void address_file_init(
|
|||||||
long device_id = 0;
|
long device_id = 0;
|
||||||
unsigned snet = 0;
|
unsigned snet = 0;
|
||||||
unsigned max_apdu = 0;
|
unsigned max_apdu = 0;
|
||||||
unsigned mac[MAX_MAC_LEN] = { 0 };
|
|
||||||
int count = 0;
|
|
||||||
char mac_string[80] = { "" }, sadr_string[80] = {
|
char mac_string[80] = { "" }, sadr_string[80] = {
|
||||||
""};
|
""};
|
||||||
BACNET_ADDRESS src = { 0 };
|
BACNET_ADDRESS src = { 0 };
|
||||||
|
BACNET_MAC_ADDRESS mac = { 0 };
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
pFile = fopen(pFilename, "r");
|
pFile = fopen(pFilename, "r");
|
||||||
@@ -221,22 +300,19 @@ static void address_file_init(
|
|||||||
if (sscanf(line, "%7ld %79s %5u %79s %4u", &device_id,
|
if (sscanf(line, "%7ld %79s %5u %79s %4u", &device_id,
|
||||||
&mac_string[0], &snet, &sadr_string[0],
|
&mac_string[0], &snet, &sadr_string[0],
|
||||||
&max_apdu) == 5) {
|
&max_apdu) == 5) {
|
||||||
count =
|
if (address_mac_from_ascii(&mac, mac_string)) {
|
||||||
sscanf(mac_string, "%2x:%2x:%2x:%2x:%2x:%2x", &mac[0],
|
src.mac_len = mac.len;
|
||||||
&mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
|
for (index = 0; index < MAX_MAC_LEN; index++) {
|
||||||
src.mac_len = (uint8_t) count;
|
src.mac[index] = mac.adr[index];
|
||||||
for (index = 0; index < MAX_MAC_LEN; index++) {
|
}
|
||||||
src.mac[index] = (uint8_t) mac[index];
|
|
||||||
}
|
}
|
||||||
src.net = (uint16_t) snet;
|
src.net = (uint16_t) snet;
|
||||||
if (snet) {
|
if (snet) {
|
||||||
count =
|
if (address_mac_from_ascii(&mac, sadr_string)) {
|
||||||
sscanf(sadr_string, "%2x:%2x:%2x:%2x:%2x:%2x",
|
src.len = mac.len;
|
||||||
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4],
|
for (index = 0; index < MAX_MAC_LEN; index++) {
|
||||||
&mac[5]);
|
src.adr[index] = mac.adr[index];
|
||||||
src.len = (uint8_t) count;
|
}
|
||||||
for (index = 0; index < MAX_MAC_LEN; index++) {
|
|
||||||
src.adr[index] = (uint8_t) mac[index];
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
src.len = 0;
|
src.len = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user