From 566749508c90cb28294a3cb2baa83307e87be157 Mon Sep 17 00:00:00 2001 From: skarg Date: Fri, 10 Feb 2006 22:44:34 +0000 Subject: [PATCH] Added DeviceCommunicationControl in the demos and into the stack. --- bacnet-stack/Makefile | 14 +++- bacnet-stack/apdu.c | 47 ++++++++------ bacnet-stack/bacenum.h | 3 +- bacnet-stack/bacstr.c | 38 +++++++++++ bacnet-stack/bacstr.h | 3 + bacnet-stack/dcc.c | 82 ++++++++++++++++++++++++ bacnet-stack/dcc.h | 19 +++++- bacnet-stack/demo/handler/client.h | 30 ++++++--- bacnet-stack/demo/handler/h_rd.c | 2 + bacnet-stack/demo/handler/handlers.h | 6 ++ bacnet-stack/demo/handler/s_rp.c | 4 ++ bacnet-stack/demo/handler/s_whois.c | 4 ++ bacnet-stack/demo/handler/s_wp.c | 4 ++ bacnet-stack/demo/readfile/Makefile | 2 + bacnet-stack/demo/readfile/makefile.b32 | 1 + bacnet-stack/demo/readfile/readfile.c | 4 +- bacnet-stack/demo/readprop/Makefile | 1 + bacnet-stack/demo/readprop/makefile.b32 | 1 + bacnet-stack/demo/reinit/Makefile | 2 + bacnet-stack/demo/reinit/main.c | 66 ------------------- bacnet-stack/demo/reinit/makefile.b32 | 1 + bacnet-stack/demo/server/Makefile | 2 + bacnet-stack/demo/server/makefile.b32 | 2 + bacnet-stack/demo/server/server.c | 16 ++++- bacnet-stack/demo/writefile/Makefile | 1 + bacnet-stack/demo/writeprop/Makefile | 1 + bacnet-stack/demo/writeprop/makefile.b32 | 1 + bacnet-stack/demo/writeprop/writeprop.c | 71 +++++++++++++++++++- 28 files changed, 324 insertions(+), 104 deletions(-) diff --git a/bacnet-stack/Makefile b/bacnet-stack/Makefile index 39b57c0f..a95c3c01 100644 --- a/bacnet-stack/Makefile +++ b/bacnet-stack/Makefile @@ -1,13 +1,20 @@ -all: readprop writeprop readfile writefile reinit server +all: readprop writeprop readfile writefile reinit server dcc @echo "utilities are in demo/xx directories" -clean: demo/readprop/Makefile demo/writeprop/Makefile demo/readfile/Makefile demo/writefile/Makefile demo/server/Makefile +clean: \ + demo/readprop/Makefile \ + demo/writeprop/Makefile \ + demo/readfile/Makefile \ + demo/writefile/Makefile \ + demo/server/Makefile \ + demo/dcc/Makefile ( cd demo/readprop ; make clean ) ( cd demo/writeprop ; make clean ) ( cd demo/readfile ; make clean ) ( cd demo/writefile ; make clean ) ( cd demo/reinit ; make clean ) ( cd demo/server ; make clean ) + ( cd demo/dcc ; make clean ) readprop: demo/readprop/Makefile ( cd demo/readprop ; make clean ; make ) @@ -27,3 +34,6 @@ reinit: demo/reinit/Makefile server: demo/server/Makefile ( cd demo/server ; make clean ; make ) +dcc: demo/dcc/Makefile + ( cd demo/dcc ; make clean ; make ) + diff --git a/bacnet-stack/apdu.c b/bacnet-stack/apdu.c index f8b35e61..ba1e86d6 100644 --- a/bacnet-stack/apdu.c +++ b/bacnet-stack/apdu.c @@ -40,6 +40,7 @@ #include "bacdcode.h" #include "bacenum.h" #include "tsm.h" +#include "dcc.h" #include "iam.h" /* a simple table for crossing the services supported */ @@ -347,26 +348,30 @@ void apdu_handler( &service_choice, &service_request, &service_request_len); - if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) - { - if (Confirmed_Function[service_choice]) - Confirmed_Function[service_choice]( - service_request, - service_request_len, - src, - &service_data); - else - { - if (Unrecognized_Service_Handler) - Unrecognized_Service_Handler( - service_request, - service_request_len, - src, - &service_data); - } - } + /* When network communications are completely disabled, + only DeviceCommunicationControl and ReinitializeDevice APDUs + shall be processed and no messages shall be initiated.*/ + if (dcc_communication_disabled() && + ((service_choice != SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL) && + (service_choice != SERVICE_CONFIRMED_REINITIALIZE_DEVICE))) + break; + if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) && + (Confirmed_Function[service_choice])) + Confirmed_Function[service_choice]( + service_request, + service_request_len, + src, + &service_data); + else if (Unrecognized_Service_Handler) + Unrecognized_Service_Handler( + service_request, + service_request_len, + src, + &service_data); break; case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: + if (dcc_communication_disabled()) + break; service_choice = apdu[1]; service_request = &apdu[2]; service_request_len = apdu_len - 2; @@ -374,9 +379,9 @@ void apdu_handler( { if (Unconfirmed_Function[service_choice]) Unconfirmed_Function[service_choice]( - service_request, - service_request_len, - src); + service_request, + service_request_len, + src); } break; case PDU_TYPE_SIMPLE_ACK: diff --git a/bacnet-stack/bacenum.h b/bacnet-stack/bacenum.h index 6c9a6930..d9134c99 100644 --- a/bacnet-stack/bacenum.h +++ b/bacnet-stack/bacenum.h @@ -932,7 +932,8 @@ typedef enum { typedef enum { COMMUNICATION_ENABLE = 0, COMMUNICATION_DISABLE = 1, - COMMUNICATION_DISABLE_INITIATION = 2 + COMMUNICATION_DISABLE_INITIATION = 2, + MAX_BACNET_COMMUNICATION_ENABLE_DISABLE = 3 } BACNET_COMMUNICATION_ENABLE_DISABLE; typedef enum { diff --git a/bacnet-stack/bacstr.c b/bacnet-stack/bacstr.c index 106b6dfe..d69170d8 100644 --- a/bacnet-stack/bacstr.c +++ b/bacnet-stack/bacstr.c @@ -271,6 +271,44 @@ bool characterstring_same( return same_status; } +bool characterstring_ansi_same( + BACNET_CHARACTER_STRING *dest, + const char *src) +{ + size_t i; /* counter */ + bool same_status = false; + + if (src && dest) + { + if ((dest->length == strlen(src)) && + (dest->encoding == CHARACTER_ANSI_X34)) + { + same_status = true; + for (i = 0; i < dest->length; i++) + { + if (src[i] != dest->value[i]) + { + same_status = false; + break; + } + } + } + } + /* NULL matches an empty string in our world */ + else if (src) + { + if (strlen(src) == 0) + same_status = true; + } + else if (dest) + { + if (dest->length == 0) + same_status = true; + } + + return same_status; +} + /* returns false if the string exceeds capacity */ bool characterstring_append( BACNET_CHARACTER_STRING *char_string, diff --git a/bacnet-stack/bacstr.h b/bacnet-stack/bacstr.h index 11fd129f..2a664295 100644 --- a/bacnet-stack/bacstr.h +++ b/bacnet-stack/bacstr.h @@ -106,6 +106,9 @@ bool characterstring_copy( bool characterstring_same( BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING *src); +bool characterstring_ansi_same( + BACNET_CHARACTER_STRING *dest, + const char *src); /* returns false if the string exceeds capacity */ bool characterstring_append( BACNET_CHARACTER_STRING *char_string, diff --git a/bacnet-stack/dcc.c b/bacnet-stack/dcc.c index 4212f252..4df97828 100644 --- a/bacnet-stack/dcc.c +++ b/bacnet-stack/dcc.c @@ -37,6 +37,88 @@ #include "bacdef.h" #include "dcc.h" +/* note: the disable and time are not expected to survive + over a power cycle or reinitialization. */ +/* note: time duration is given in Minutes, but in order to be accurate, + we need to count down in seconds. */ +static uint32_t DCC_Time_Duration_Seconds = 0; +static BACNET_COMMUNICATION_ENABLE_DISABLE DCC_Enable_Disable = + COMMUNICATION_ENABLE; +/* password is optionally supported */ + +BACNET_COMMUNICATION_ENABLE_DISABLE dcc_enable_status(void) +{ + return DCC_Enable_Disable; +} + +bool dcc_communication_enabled(void) +{ + return (DCC_Enable_Disable == COMMUNICATION_ENABLE); +} + +/* When network communications are completely disabled, + only DeviceCommunicationControl and ReinitializeDevice APDUs + shall be processed and no messages shall be initiated.*/ +bool dcc_communication_disabled(void) +{ + return (DCC_Enable_Disable == COMMUNICATION_DISABLE); +} + +/* When the initiation of communications is disabled, + all APDUs shall be processed and responses returned as + required and no messages shall be initiated with the + exception of I-Am requests, which shall be initiated only in + response to Who-Is messages. In this state, a device that + supports I-Am request initiation shall send one I-Am request + for any Who-Is request that is received if and only if + the Who-Is request does not contain an address range or + the device is included in the address range. */ +bool dcc_communication_initiation_disabled(void) +{ + return (DCC_Enable_Disable == COMMUNICATION_DISABLE_INITIATION); +} + +uint32_t dcc_duration_seconds(void) +{ + return DCC_Time_Duration_Seconds; +} + +/* called every second or so. If more than one second, + then seconds should be the number of seconds to tick away */ +void dcc_timer_seconds(uint32_t seconds) +{ + if (DCC_Time_Duration_Seconds) + { + if (DCC_Time_Duration_Seconds > seconds) + DCC_Time_Duration_Seconds -= seconds; + else + DCC_Time_Duration_Seconds = 0; + /* just expired - do something */ + if (DCC_Time_Duration_Seconds == 0) + DCC_Enable_Disable = COMMUNICATION_ENABLE; + } +} + +bool dcc_set_status_duration( + BACNET_COMMUNICATION_ENABLE_DISABLE status, + uint16_t minutes) +{ + bool valid = false; + + /* valid? */ + if (status < MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) + { + DCC_Enable_Disable = status; + if (status == COMMUNICATION_ENABLE) + DCC_Time_Duration_Seconds = 0; + else + DCC_Time_Duration_Seconds = minutes * 60; + valid = true; + } + + return valid; +} + /* encode service */ int dcc_encode_apdu( uint8_t *apdu, diff --git a/bacnet-stack/dcc.h b/bacnet-stack/dcc.h index dc9468ce..f2bc4a01 100644 --- a/bacnet-stack/dcc.h +++ b/bacnet-stack/dcc.h @@ -36,14 +36,31 @@ #include #include +#include "bacenum.h" +#include "bacstr.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +/* return the status */ +BACNET_COMMUNICATION_ENABLE_DISABLE dcc_enable_status(void); +bool dcc_communication_enabled(void); +bool dcc_communication_disabled(void); +bool dcc_communication_initiation_disabled(void); +/* return the time */ +uint32_t dcc_duration_seconds(void); +/* called every second or so. If more than one second, + then seconds should be the number of seconds to tick away */ +void dcc_timer_seconds(uint32_t seconds); +/* setup the communication values */ +bool dcc_set_status_duration( + BACNET_COMMUNICATION_ENABLE_DISABLE status, + uint16_t minutes); + // encode service int dcc_encode_apdu( - uint8_t *apdu, + uint8_t *apdu, uint8_t invoke_id, uint16_t timeDuration, /* 0=optional */ BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable, diff --git a/bacnet-stack/demo/handler/client.h b/bacnet-stack/demo/handler/client.h index 8eb1bdd8..60713e95 100644 --- a/bacnet-stack/demo/handler/client.h +++ b/bacnet-stack/demo/handler/client.h @@ -31,25 +31,26 @@ #include "bacdef.h" #include "apdu.h" #include "bacapp.h" +#include "bacenum.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -/* FIXME: probably should return the invoke ID for confirmed request */ -bool Send_Read_Property_Request( +void Send_WhoIs( + int32_t low_limit, + int32_t high_limit); + +/* returns the invoke ID for confirmed request, or 0 if failed */ +uint8_t Send_Read_Property_Request( uint32_t device_id, /* destination device */ BACNET_OBJECT_TYPE object_type, uint32_t object_instance, BACNET_PROPERTY_ID object_property, int32_t array_index); -void Send_WhoIs( - int32_t low_limit, - int32_t high_limit); - -/* FIXME: probably should return the invoke ID for confirmed request */ -bool Send_Write_Property_Request( +/* returns the invoke ID for confirmed request, or 0 if failed */ +uint8_t Send_Write_Property_Request( uint32_t device_id, // destination device BACNET_OBJECT_TYPE object_type, uint32_t object_instance, @@ -58,6 +59,19 @@ bool Send_Write_Property_Request( uint8_t priority, int32_t array_index); +/* returns the invoke ID for confirmed request, or 0 if failed */ +uint8_t Send_Reinitialize_Device_Request( + uint32_t device_id, + BACNET_REINITIALIZED_STATE state, + char *password); + +/* returns the invoke ID for confirmed request, or 0 if failed */ +uint8_t Send_Device_Communication_Control_Request( + uint32_t device_id, + uint16_t timeDuration, /* 0=optional */ + BACNET_COMMUNICATION_ENABLE_DISABLE state, + char *password); /* NULL=optional */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bacnet-stack/demo/handler/h_rd.c b/bacnet-stack/demo/handler/h_rd.c index d2d14f72..24866e4e 100644 --- a/bacnet-stack/demo/handler/h_rd.c +++ b/bacnet-stack/demo/handler/h_rd.c @@ -112,6 +112,8 @@ void handler_reinitialize_device( fprintf(stderr,"ReinitializeDevice: Sending Simple Ack!\n"); /* FIXME: now you can reboot, restart, quit, or something clever */ /* Note: you can use a mix of state and password to do specific stuff */ + /* Note: if you don't do something clever like actually restart, + you probably should clear any DCC status and timeouts */ } else { diff --git a/bacnet-stack/demo/handler/handlers.h b/bacnet-stack/demo/handler/handlers.h index b4a89cc5..65d4a220 100644 --- a/bacnet-stack/demo/handler/handlers.h +++ b/bacnet-stack/demo/handler/handlers.h @@ -96,6 +96,12 @@ void handler_reinitialize_device( BACNET_ADDRESS *src, BACNET_CONFIRMED_SERVICE_DATA *service_data); +void handler_device_communication_control( + uint8_t *service_request, + uint16_t service_len, + BACNET_ADDRESS *src, + BACNET_CONFIRMED_SERVICE_DATA *service_data); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bacnet-stack/demo/handler/s_rp.c b/bacnet-stack/demo/handler/s_rp.c index 43f3c01b..8ed48f3c 100644 --- a/bacnet-stack/demo/handler/s_rp.c +++ b/bacnet-stack/demo/handler/s_rp.c @@ -36,6 +36,7 @@ #include "apdu.h" #include "device.h" #include "datalink.h" +#include "dcc.h" #include "rp.h" /* some demo stuff needed */ #include "handlers.h" @@ -58,6 +59,9 @@ uint8_t Send_Read_Property_Request( int bytes_sent = 0; BACNET_READ_PROPERTY_DATA data; + if (!dcc_communication_enabled()) + return 0; + /* is the device bound? */ status = address_get_by_device(device_id, &max_apdu, &dest); /* is there a tsm available? */ diff --git a/bacnet-stack/demo/handler/s_whois.c b/bacnet-stack/demo/handler/s_whois.c index 9ab7a2e0..680a659f 100644 --- a/bacnet-stack/demo/handler/s_whois.c +++ b/bacnet-stack/demo/handler/s_whois.c @@ -36,6 +36,7 @@ #include "apdu.h" #include "device.h" #include "datalink.h" +#include "dcc.h" #include "whois.h" /* some demo stuff needed */ #include "handlers.h" @@ -50,6 +51,9 @@ void Send_WhoIs( BACNET_ADDRESS dest; int bytes_sent = 0; + if (!dcc_communication_enabled()) + return; + // Who-Is is a global broadcast datalink_get_broadcast_address(&dest); diff --git a/bacnet-stack/demo/handler/s_wp.c b/bacnet-stack/demo/handler/s_wp.c index 4e19e836..05d333c7 100644 --- a/bacnet-stack/demo/handler/s_wp.c +++ b/bacnet-stack/demo/handler/s_wp.c @@ -36,6 +36,7 @@ #include "apdu.h" #include "device.h" #include "datalink.h" +#include "dcc.h" #include "whois.h" /* some demo stuff needed */ #include "handlers.h" @@ -60,6 +61,9 @@ uint8_t Send_Write_Property_Request( int bytes_sent = 0; BACNET_WRITE_PROPERTY_DATA data; + if (!dcc_communication_enabled()) + return 0; + /* is the device bound? */ status = address_get_by_device(device_id, &max_apdu, &dest); /* is there a tsm available? */ diff --git a/bacnet-stack/demo/readfile/Makefile b/bacnet-stack/demo/readfile/Makefile index 671c3191..ba10a0d7 100644 --- a/bacnet-stack/demo/readfile/Makefile +++ b/bacnet-stack/demo/readfile/Makefile @@ -40,11 +40,13 @@ SRCS = readfile.c \ $(BACNET_ROOT)/tsm.c \ $(BACNET_ROOT)/datalink.c \ $(BACNET_ROOT)/address.c \ + $(BACNET_ROOT)/filename.c \ $(BACNET_OBJECT)/device.c \ $(BACNET_OBJECT)/ai.c \ $(BACNET_OBJECT)/ao.c \ $(BACNET_OBJECT)/bacfile.c \ $(BACNET_ROOT)/arf.c \ + $(BACNET_ROOT)/dcc.c \ $(BACNET_ROOT)/abort.c \ $(BACNET_ROOT)/reject.c \ $(BACNET_ROOT)/bacerror.c \ diff --git a/bacnet-stack/demo/readfile/makefile.b32 b/bacnet-stack/demo/readfile/makefile.b32 index d457fbbf..01b5e43a 100644 --- a/bacnet-stack/demo/readfile/makefile.b32 +++ b/bacnet-stack/demo/readfile/makefile.b32 @@ -36,6 +36,7 @@ SRCS = readfile.c \ ..\..\wp.c \ ..\..\arf.c \ ..\..\awf.c \ + ..\..\dcc.c \ ..\..\demo\object\bacfile.c \ ..\..\demo\object\device.c \ ..\..\demo\object\ai.c \ diff --git a/bacnet-stack/demo/readfile/readfile.c b/bacnet-stack/demo/readfile/readfile.c index 7143fb4f..bf07310b 100644 --- a/bacnet-stack/demo/readfile/readfile.c +++ b/bacnet-stack/demo/readfile/readfile.c @@ -44,6 +44,7 @@ #include "datalink.h" #include "whois.h" /* some demo stuff needed */ +#include "filename.h" #include "handlers.h" #include "txbuf.h" @@ -339,7 +340,8 @@ int main(int argc, char *argv[]) if (argc < 4) { /* FIXME: what about access method - record or stream? */ - printf("%s device-instance file-instance local-name\r\n",argv[0]); + printf("%s device-instance file-instance local-name\r\n", + filename_remove_path(argv[0])); return 0; } /* decode the command line parameters */ diff --git a/bacnet-stack/demo/readprop/Makefile b/bacnet-stack/demo/readprop/Makefile index 7851b266..cd064e72 100644 --- a/bacnet-stack/demo/readprop/Makefile +++ b/bacnet-stack/demo/readprop/Makefile @@ -50,6 +50,7 @@ SRCS = readprop.c \ $(BACNET_ROOT)/datalink.c \ $(BACNET_ROOT)/address.c \ $(BACNET_ROOT)/arf.c \ + $(BACNET_ROOT)/dcc.c \ $(BACNET_ROOT)/abort.c \ $(BACNET_ROOT)/reject.c \ $(BACNET_ROOT)/bacerror.c \ diff --git a/bacnet-stack/demo/readprop/makefile.b32 b/bacnet-stack/demo/readprop/makefile.b32 index 60f006b4..601371b2 100644 --- a/bacnet-stack/demo/readprop/makefile.b32 +++ b/bacnet-stack/demo/readprop/makefile.b32 @@ -41,6 +41,7 @@ SRCS = readprop.c \ ..\..\wp.c \ ..\..\arf.c \ ..\..\awf.c \ + ..\..\dcc.c \ ..\..\demo\object\bacfile.c \ ..\..\demo\object\device.c \ ..\..\demo\object\ai.c \ diff --git a/bacnet-stack/demo/reinit/Makefile b/bacnet-stack/demo/reinit/Makefile index d78db137..35ad42cf 100644 --- a/bacnet-stack/demo/reinit/Makefile +++ b/bacnet-stack/demo/reinit/Makefile @@ -30,6 +30,7 @@ SRCS = main.c \ $(BACNET_HANDLER)/h_rp.c \ $(BACNET_HANDLER)/h_iam.c \ $(BACNET_HANDLER)/s_whois.c \ + $(BACNET_HANDLER)/s_rd.c \ $(BACNET_OBJECT)/device.c \ $(BACNET_OBJECT)/ai.c \ $(BACNET_OBJECT)/ao.c \ @@ -50,6 +51,7 @@ SRCS = main.c \ $(BACNET_ROOT)/datalink.c \ $(BACNET_ROOT)/address.c \ $(BACNET_ROOT)/arf.c \ + $(BACNET_ROOT)/dcc.c \ $(BACNET_ROOT)/abort.c \ $(BACNET_ROOT)/reject.c \ $(BACNET_ROOT)/bacerror.c \ diff --git a/bacnet-stack/demo/reinit/main.c b/bacnet-stack/demo/reinit/main.c index 4f08efe4..0bcca5da 100644 --- a/bacnet-stack/demo/reinit/main.c +++ b/bacnet-stack/demo/reinit/main.c @@ -61,72 +61,6 @@ static char *Reinitialize_Password = NULL; static bool Error_Detected = false; -static uint8_t Send_Reinitialize_Device_Request( - uint32_t device_id, - BACNET_REINITIALIZED_STATE state, - char *password) -{ - BACNET_ADDRESS dest; - BACNET_ADDRESS my_address; - unsigned max_apdu = 0; - uint8_t invoke_id = 0; - bool status = false; - int pdu_len = 0; - int bytes_sent = 0; - BACNET_CHARACTER_STRING password_string; - - /* is the device bound? */ - status = address_get_by_device(device_id, &max_apdu, &dest); - /* is there a tsm available? */ - if (status) - status = tsm_transaction_available(); - if (status) - { - datalink_get_my_address(&my_address); - pdu_len = npdu_encode_apdu( - &Handler_Transmit_Buffer[0], - &dest, - &my_address, - true, // true for confirmed messages - MESSAGE_PRIORITY_NORMAL); - - invoke_id = tsm_next_free_invokeID(); - // load the data for the encoding - characterstring_init_ansi(&password_string,password); - pdu_len += rd_encode_apdu( - &Handler_Transmit_Buffer[pdu_len], - invoke_id, - state, - password?&password_string:NULL); - /* will it fit in the sender? - note: if there is a bottleneck router in between - us and the destination, we won't know unless - we have a way to check for that and update the - max_apdu in the address binding table. */ - if ((unsigned)pdu_len < max_apdu) - { - tsm_set_confirmed_unsegmented_transaction( - invoke_id, - &dest, - &Handler_Transmit_Buffer[0], - pdu_len); - bytes_sent = datalink_send_pdu( - &dest, // destination address - &Handler_Transmit_Buffer[0], - pdu_len); // number of bytes of data - if (bytes_sent <= 0) - fprintf(stderr,"Failed to Send ReinitializeDevice Request (%s)!\n", - strerror(errno)); - } - else - fprintf(stderr,"Failed to Send ReinitializeDevice Request " - "(exceeds destination maximum APDU)!\n"); - } - - return invoke_id; -} - - static void MyErrorHandler( BACNET_ADDRESS *src, uint8_t invoke_id, diff --git a/bacnet-stack/demo/reinit/makefile.b32 b/bacnet-stack/demo/reinit/makefile.b32 index ab3385c2..06adbf89 100644 --- a/bacnet-stack/demo/reinit/makefile.b32 +++ b/bacnet-stack/demo/reinit/makefile.b32 @@ -40,6 +40,7 @@ SRCS = main.c \ ..\..\wp.c \ ..\..\arf.c \ ..\..\awf.c \ + ..\..\dcc.c \ ..\..\demo\object\bacfile.c \ ..\..\demo\object\device.c \ ..\..\demo\object\ai.c \ diff --git a/bacnet-stack/demo/server/Makefile b/bacnet-stack/demo/server/Makefile index e99e6770..6cded1c7 100644 --- a/bacnet-stack/demo/server/Makefile +++ b/bacnet-stack/demo/server/Makefile @@ -30,6 +30,7 @@ SRCS = server.c \ $(BACNET_HANDLER)/h_wp.c \ $(BACNET_HANDLER)/h_arf.c \ $(BACNET_HANDLER)/h_rd.c \ + $(BACNET_HANDLER)/h_dcc.c \ $(BACNET_OBJECT)/device.c \ $(BACNET_OBJECT)/ai.c \ $(BACNET_OBJECT)/ao.c \ @@ -49,6 +50,7 @@ SRCS = server.c \ $(BACNET_ROOT)/wp.c \ $(BACNET_ROOT)/arf.c \ $(BACNET_ROOT)/rd.c \ + $(BACNET_ROOT)/dcc.c \ $(BACNET_ROOT)/abort.c \ $(BACNET_ROOT)/reject.c \ $(BACNET_ROOT)/bacerror.c \ diff --git a/bacnet-stack/demo/server/makefile.b32 b/bacnet-stack/demo/server/makefile.b32 index afa0c1bc..268789e0 100644 --- a/bacnet-stack/demo/server/makefile.b32 +++ b/bacnet-stack/demo/server/makefile.b32 @@ -29,6 +29,7 @@ SRCS = server.c \ ..\..\demo\handler\h_wp.c \ ..\..\demo\handler\h_arf.c \ ..\..\demo\handler\h_rd.c \ + ..\..\demo\handler\h_dcc.c \ ..\..\bacdcode.c \ ..\..\bacapp.c \ ..\..\bacstr.c \ @@ -42,6 +43,7 @@ SRCS = server.c \ ..\..\arf.c \ ..\..\awf.c \ ..\..\rd.c \ + ..\..\dcc.c \ ..\..\demo\object\bacfile.c \ ..\..\demo\object\device.c \ ..\..\demo\object\ai.c \ diff --git a/bacnet-stack/demo/server/server.c b/bacnet-stack/demo/server/server.c index 20acb5e1..13ebfe7c 100644 --- a/bacnet-stack/demo/server/server.c +++ b/bacnet-stack/demo/server/server.c @@ -41,6 +41,7 @@ #include "device.h" #include "bacfile.h" #include "datalink.h" +#include "dcc.h" #include "net.h" #include "txbuf.h" @@ -55,7 +56,6 @@ static void Init_Service_Handlers(void) apdu_set_unconfirmed_handler( SERVICE_UNCONFIRMED_WHO_IS, handler_who_is); - /* set the handler for all the services we don't implement */ /* It is required to send the proper reject message... */ apdu_set_unrecognized_service_handler_handler( @@ -74,6 +74,10 @@ static void Init_Service_Handlers(void) apdu_set_confirmed_handler( SERVICE_CONFIRMED_REINITIALIZE_DEVICE, handler_reinitialize_device); + /* handle communication so we can shutup when asked */ + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, + handler_device_communication_control); } static void cleanup(void) @@ -104,6 +108,8 @@ int main(int argc, char *argv[]) uint16_t pdu_len = 0; unsigned timeout = 100; // milliseconds BACNET_ADDRESS my_address, broadcast_address; + time_t last_seconds = 0; + time_t current_seconds = 0; /* allow the device ID to be set */ if (argc > 1) @@ -133,13 +139,15 @@ int main(int argc, char *argv[]) datalink_get_my_address(&my_address); print_address("Address",&my_address); atexit(cleanup); - + /* configure the timeout values */ + last_seconds = time(NULL); /* broadcast an I-Am on startup */ I_Am_Request = true; // loop forever for (;;) { // input + current_seconds = time(NULL); // returns 0 bytes on timeout pdu_len = datalink_receive( @@ -156,6 +164,10 @@ int main(int argc, char *argv[]) &Rx_Buf[0], pdu_len); } + /* at least one second has passed */ + if (current_seconds != last_seconds) + dcc_timer_seconds(current_seconds - last_seconds); + /* send out the I-Am if requested */ if (I_Am_Request) { I_Am_Request = false; diff --git a/bacnet-stack/demo/writefile/Makefile b/bacnet-stack/demo/writefile/Makefile index 5fb2f7cf..e0c3616c 100644 --- a/bacnet-stack/demo/writefile/Makefile +++ b/bacnet-stack/demo/writefile/Makefile @@ -46,6 +46,7 @@ SRCS = writefile.c \ $(BACNET_OBJECT)/bacfile.c \ $(BACNET_ROOT)/arf.c \ $(BACNET_ROOT)/awf.c \ + $(BACNET_ROOT)/dcc.c \ $(BACNET_ROOT)/abort.c \ $(BACNET_ROOT)/reject.c \ $(BACNET_ROOT)/bacerror.c \ diff --git a/bacnet-stack/demo/writeprop/Makefile b/bacnet-stack/demo/writeprop/Makefile index 6fde2599..62be5e7a 100644 --- a/bacnet-stack/demo/writeprop/Makefile +++ b/bacnet-stack/demo/writeprop/Makefile @@ -50,6 +50,7 @@ SRCS = writeprop.c \ $(BACNET_ROOT)/datalink.c \ $(BACNET_ROOT)/address.c \ $(BACNET_ROOT)/arf.c \ + $(BACNET_ROOT)/dcc.c \ $(BACNET_ROOT)/abort.c \ $(BACNET_ROOT)/reject.c \ $(BACNET_ROOT)/bacerror.c \ diff --git a/bacnet-stack/demo/writeprop/makefile.b32 b/bacnet-stack/demo/writeprop/makefile.b32 index 3bc492cd..d722636d 100644 --- a/bacnet-stack/demo/writeprop/makefile.b32 +++ b/bacnet-stack/demo/writeprop/makefile.b32 @@ -40,6 +40,7 @@ SRCS = writeprop.c \ ..\..\wp.c \ ..\..\arf.c \ ..\..\awf.c \ + ..\..\dcc.c \ ..\..\demo\object\bacfile.c \ ..\..\demo\object\device.c \ ..\..\demo\object\ai.c \ diff --git a/bacnet-stack/demo/writeprop/writeprop.c b/bacnet-stack/demo/writeprop/writeprop.c index b14b44d8..8ca2a5da 100644 --- a/bacnet-stack/demo/writeprop/writeprop.c +++ b/bacnet-stack/demo/writeprop/writeprop.c @@ -172,8 +172,75 @@ int main(int argc, char *argv[]) if (argc < 7) { /* note: priority 16 and 0 should produce the same end results... */ - printf("%s device-instance object-type object-instance " - "property tag value [priority] [index]\r\n", + printf("Usage: %s device-instance object-type object-instance " + "property tag value [priority] [index]\r\n" + "\r\n" + "device-instance:\r\n" + "BACnet Device Object Instance number that you are trying to\r\n" + "communicate to. This number will be used to try and bind with\r\n" + "the device using Who-Is and I-Am services. For example, if you were\r\n" + "writing to Device Object 123, the device-instance would be 123.\r\n" + "\r\n" + "object-type:\r\n" + "The object type is the integer value of the enumeration\r\n" + "BACNET_OBJECT_TYPE in bacenum.h. It is the object that you are\r\n" + "writing to. For example if you were writing to Analog Output 2, \r\n" + "the object-type would be 1.\r\n" + "\r\n" + "object-instance:\r\n" + "This is the object instance number of the object that you are \r\n" + "writing to. For example, if you were writing to Analog Output 2, \r\n" + "the object-instance would be 2.\r\n" + "\r\n" + "property:\r\n" + "The property is an integer value of the enumeration \r\n" + "BACNET_PROPERTY_ID in bacenum.h. It is the property you are \r\n" + "writing to. For example, if you were writing to the Present Value\r\n" + "property, you would use 85 as the property.\r\n" + "\r\n" + "tag:\r\n" + "Tag is the integer value of the enumeration BACNET_APPLICATION_TAG \r\n" + "in bacenum.h. It is the data type of the value that you are\r\n" + "writing. For example, if you were writing a REAL value, you would \r\n" + "use a tag of 4." + "\r\n" + "value:\r\n" + "The value is an ASCII representation of some type of data that you\r\n" + "are writing. It is encoded using the tag information provided. For\r\n" + "example, if you were writing a REAL value of 100.0, you would use \r\n" + "100.0 as the value.\r\n" + "\r\n" + "[priority]:\r\n" + "This optional parameter is used for setting the priority of the\r\n" + "write. If no priority is given, none is sent, and the BACnet \r\n" + "standard requires that the value is written at the lowest \r\n" + "priority (16) if the object property supports priorities.\r\n" + "\r\n" + "[index]\r\n" + "This optional integer parameter is the index number of an array.\r\n" + "If the property is an array, individual elements can be written\r\n" + "to if supported.\r\n" + "\r\n" + "Here is a brief overview of BACnet property and tags:\r\n" + "Certain properties are expected to be written with certain \r\n" + "application tags, so you probably need to know which ones to use\r\n" + "with each property of each object. It is almost safe to say that\r\n" + "given a property and an object and a table, the tag could be looked\r\n" + "up automatically. There may be a few exceptions to this, such as\r\n" + "the Any property type in the schedule object and the Present Value\r\n" + "accepting REAL, BOOLEAN, NULL, etc. Perhaps it would be simpler for\r\n" + "the demo to use this kind of table - but I also wanted to be able\r\n" + "to do negative testing by passing the wrong tag and have the server\r\n" + "return a reject message.\r\n" + "\r\n" + "Example:\r\n" + "If you want send a 100 to the Present-Value in the Analog Output\r\n" + "at priority 16, you could send the following command:\r\n" + "%s 123 1 0 85 4 100\r\n" + "You could also send a relinquish command:\r\n" + "%s 123 1 0 85 0 0\r\n", + filename_remove_path(argv[0]), + filename_remove_path(argv[0]), filename_remove_path(argv[0])); return 0; }