Added DeviceCommunicationControl in the demos and into the stack.
This commit is contained in:
+12
-2
@@ -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 )
|
||||
|
||||
|
||||
+26
-21
@@ -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:
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
+18
-1
@@ -36,14 +36,31 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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? */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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? */
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user