Adding SubscribeCOV to demo/server for testing.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
* Copyright (C) 2007-2008 Steve Karg <skarg@users.sourceforge.net>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "npdu.h"
|
#include "npdu.h"
|
||||||
#include "abort.h"
|
#include "abort.h"
|
||||||
#include "cov.h"
|
#include "cov.h"
|
||||||
|
#include "tsm.h"
|
||||||
/* demo objects */
|
/* demo objects */
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
@@ -138,6 +139,88 @@ static bool cov_list_subscribe(
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool cov_send_request(
|
||||||
|
BACNET_COV_SUBSCRIPTION * cov_subscription)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
int pdu_len = 0;
|
||||||
|
BACNET_NPDU_DATA npdu_data;
|
||||||
|
BACNET_ADDRESS my_address;
|
||||||
|
int bytes_sent = 0;
|
||||||
|
uint8_t invoke_id = 0;
|
||||||
|
bool status = false; /* return value */
|
||||||
|
BACNET_COV_DATA cov_data;
|
||||||
|
BACNET_PROPERTY_VALUE value_list[2];
|
||||||
|
|
||||||
|
datalink_get_my_address(&my_address);
|
||||||
|
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||||
|
pdu_len =
|
||||||
|
npdu_encode_pdu(
|
||||||
|
&Handler_Transmit_Buffer[0],
|
||||||
|
&cov_subscription->dest,
|
||||||
|
&my_address,
|
||||||
|
&npdu_data);
|
||||||
|
/* load the COV data structure for outgoing message */
|
||||||
|
cov_data.subscriberProcessIdentifier =
|
||||||
|
cov_subscription->subscriberProcessIdentifier;
|
||||||
|
cov_data.initiatingDeviceIdentifier =
|
||||||
|
Device_Object_Instance_Number();
|
||||||
|
cov_data.monitoredObjectIdentifier.type =
|
||||||
|
cov_subscription->monitoredObjectIdentifier.type;
|
||||||
|
cov_data.monitoredObjectIdentifier.instance =
|
||||||
|
cov_subscription->monitoredObjectIdentifier.instance;
|
||||||
|
cov_data.timeRemaining =
|
||||||
|
cov_subscription->lifetime;
|
||||||
|
/* encode the value list */
|
||||||
|
value_list[0].next = &value_list[1];
|
||||||
|
value_list[1].next = NULL;
|
||||||
|
switch (cov_subscription->monitoredObjectIdentifier.type) {
|
||||||
|
case OBJECT_BINARY_INPUT:
|
||||||
|
Binary_Input_Encode_Value_List(
|
||||||
|
cov_subscription->monitoredObjectIdentifier.instance,
|
||||||
|
&value_list[0]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto COV_FAILED;
|
||||||
|
}
|
||||||
|
if (cov_subscription->issueConfirmedNotifications) {
|
||||||
|
invoke_id = tsm_next_free_invokeID();
|
||||||
|
if (invoke_id) {
|
||||||
|
len = ccov_notify_encode_apdu(
|
||||||
|
&Handler_Transmit_Buffer[pdu_len],
|
||||||
|
invoke_id,
|
||||||
|
&cov_data);
|
||||||
|
} else {
|
||||||
|
goto COV_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
len = ucov_notify_encode_apdu(
|
||||||
|
&Handler_Transmit_Buffer[pdu_len],
|
||||||
|
&cov_data);
|
||||||
|
}
|
||||||
|
pdu_len += len;
|
||||||
|
if (cov_subscription->issueConfirmedNotifications) {
|
||||||
|
tsm_set_confirmed_unsegmented_transaction(
|
||||||
|
invoke_id,
|
||||||
|
&cov_subscription->dest,
|
||||||
|
&npdu_data,
|
||||||
|
&Handler_Transmit_Buffer[0],
|
||||||
|
(uint16_t) pdu_len);
|
||||||
|
}
|
||||||
|
bytes_sent = datalink_send_pdu(
|
||||||
|
&cov_subscription->dest,
|
||||||
|
&npdu_data,
|
||||||
|
&Handler_Transmit_Buffer[0],
|
||||||
|
pdu_len);
|
||||||
|
if (bytes_sent > 0) {
|
||||||
|
status = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
COV_FAILED:
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/* note: worst case tasking: MS/TP with the ability to send only
|
/* note: worst case tasking: MS/TP with the ability to send only
|
||||||
one notification per task cycle */
|
one notification per task cycle */
|
||||||
void handler_cov_task(
|
void handler_cov_task(
|
||||||
@@ -146,6 +229,7 @@ void handler_cov_task(
|
|||||||
int index;
|
int index;
|
||||||
int lifetime_milliseconds;
|
int lifetime_milliseconds;
|
||||||
BACNET_OBJECT_ID object_id;
|
BACNET_OBJECT_ID object_id;
|
||||||
|
bool status = false;
|
||||||
|
|
||||||
|
|
||||||
/* existing? - match Object ID and Process ID */
|
/* existing? - match Object ID and Process ID */
|
||||||
@@ -169,7 +253,11 @@ void handler_cov_task(
|
|||||||
switch (object_id.type) {
|
switch (object_id.type) {
|
||||||
case OBJECT_BINARY_INPUT:
|
case OBJECT_BINARY_INPUT:
|
||||||
if (Binary_Input_Change_Of_Value(object_id.instance)) {
|
if (Binary_Input_Change_Of_Value(object_id.instance)) {
|
||||||
/* FIXME: send confirmed or unconfirmed request */
|
status = cov_send_request(&COV_Subscriptions[index]);
|
||||||
|
if (status) {
|
||||||
|
Binary_Input_Change_Of_Value_Clear(
|
||||||
|
object_id.instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
|
#include "cov.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
|
|
||||||
#define MAX_BINARY_INPUTS 5
|
#define MAX_BINARY_INPUTS 5
|
||||||
@@ -70,12 +71,15 @@ void Binary_Input_Property_Lists(
|
|||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary)
|
const int **pProprietary)
|
||||||
{
|
{
|
||||||
if (pRequired)
|
if (pRequired) {
|
||||||
*pRequired = Binary_Input_Properties_Required;
|
*pRequired = Binary_Input_Properties_Required;
|
||||||
if (pOptional)
|
}
|
||||||
|
if (pOptional) {
|
||||||
*pOptional = Binary_Input_Properties_Optional;
|
*pOptional = Binary_Input_Properties_Optional;
|
||||||
if (pProprietary)
|
}
|
||||||
|
if (pProprietary) {
|
||||||
*pProprietary = Binary_Input_Properties_Proprietary;
|
*pProprietary = Binary_Input_Properties_Proprietary;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -86,8 +90,9 @@ void Binary_Input_Property_Lists(
|
|||||||
bool Binary_Input_Valid_Instance(
|
bool Binary_Input_Valid_Instance(
|
||||||
uint32_t object_instance)
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
if (object_instance < MAX_BINARY_INPUTS)
|
if (object_instance < MAX_BINARY_INPUTS) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -136,8 +141,9 @@ unsigned Binary_Input_Instance_To_Index(
|
|||||||
unsigned index = MAX_BINARY_INPUTS;
|
unsigned index = MAX_BINARY_INPUTS;
|
||||||
|
|
||||||
Binary_Input_Init();
|
Binary_Input_Init();
|
||||||
if (object_instance < MAX_BINARY_INPUTS)
|
if (object_instance < MAX_BINARY_INPUTS) {
|
||||||
index = object_instance;
|
index = object_instance;
|
||||||
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@@ -150,8 +156,9 @@ static BACNET_BINARY_PV Binary_Input_Present_Value(
|
|||||||
|
|
||||||
Binary_Input_Init();
|
Binary_Input_Init();
|
||||||
index = Binary_Input_Instance_To_Index(object_instance);
|
index = Binary_Input_Instance_To_Index(object_instance);
|
||||||
if (index < MAX_BINARY_INPUTS)
|
if (index < MAX_BINARY_INPUTS) {
|
||||||
value = Present_Value[index];
|
value = Present_Value[index];
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -164,8 +171,9 @@ static bool Binary_Input_Out_Of_Service(
|
|||||||
|
|
||||||
Binary_Input_Init();
|
Binary_Input_Init();
|
||||||
index = Binary_Input_Instance_To_Index(object_instance);
|
index = Binary_Input_Instance_To_Index(object_instance);
|
||||||
if (index < MAX_BINARY_INPUTS)
|
if (index < MAX_BINARY_INPUTS) {
|
||||||
value = Out_Of_Service[index];
|
value = Out_Of_Service[index];
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -184,6 +192,58 @@ bool Binary_Input_Change_Of_Value(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Binary_Input_Change_Of_Value_Clear(
|
||||||
|
uint32_t object_instance)
|
||||||
|
{
|
||||||
|
unsigned index;
|
||||||
|
|
||||||
|
index = Binary_Input_Instance_To_Index(object_instance);
|
||||||
|
if (index < MAX_BINARY_INPUTS) {
|
||||||
|
Change_Of_Value[index] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Binary_Input_Encode_Value_List(
|
||||||
|
uint32_t object_instance,
|
||||||
|
BACNET_PROPERTY_VALUE *value_list)
|
||||||
|
{
|
||||||
|
value_list->propertyIdentifier = PROP_PRESENT_VALUE;
|
||||||
|
value_list->propertyArrayIndex = BACNET_ARRAY_ALL;
|
||||||
|
value_list->value.context_specific = false;
|
||||||
|
value_list->value.tag = BACNET_APPLICATION_TAG_ENUMERATED;
|
||||||
|
value_list->value.type.Enumerated =
|
||||||
|
Binary_Input_Present_Value(object_instance);
|
||||||
|
value_list->priority = BACNET_NO_PRIORITY;
|
||||||
|
|
||||||
|
value_list = value_list->next;
|
||||||
|
|
||||||
|
value_list->propertyIdentifier = PROP_STATUS_FLAGS;
|
||||||
|
value_list->propertyArrayIndex = BACNET_ARRAY_ALL;
|
||||||
|
value_list->value.context_specific = false;
|
||||||
|
value_list->value.tag = BACNET_APPLICATION_TAG_BIT_STRING;
|
||||||
|
bitstring_init(&value_list->value.type.Bit_String);
|
||||||
|
bitstring_set_bit(&value_list->value.type.Bit_String,
|
||||||
|
STATUS_FLAG_IN_ALARM, false);
|
||||||
|
bitstring_set_bit(&value_list->value.type.Bit_String,
|
||||||
|
STATUS_FLAG_FAULT, false);
|
||||||
|
bitstring_set_bit(&value_list->value.type.Bit_String,
|
||||||
|
STATUS_FLAG_OVERRIDDEN, false);
|
||||||
|
if (Binary_Input_Out_Of_Service(object_instance)) {
|
||||||
|
bitstring_set_bit(&value_list->value.type.Bit_String,
|
||||||
|
STATUS_FLAG_OUT_OF_SERVICE,
|
||||||
|
true);
|
||||||
|
} else {
|
||||||
|
bitstring_set_bit(&value_list->value.type.Bit_String,
|
||||||
|
STATUS_FLAG_OUT_OF_SERVICE,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
value_list->priority = BACNET_NO_PRIORITY;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void Binary_Input_Present_Value_Set(
|
static void Binary_Input_Present_Value_Set(
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_BINARY_PV value)
|
BACNET_BINARY_PV value)
|
||||||
@@ -210,10 +270,11 @@ static void Binary_Input_Out_Of_Service_Set(
|
|||||||
|
|
||||||
Binary_Input_Init();
|
Binary_Input_Init();
|
||||||
index = Binary_Input_Instance_To_Index(object_instance);
|
index = Binary_Input_Instance_To_Index(object_instance);
|
||||||
if (index < MAX_BINARY_INPUTS)
|
if (index < MAX_BINARY_INPUTS) {
|
||||||
if (Out_Of_Service[index] != value) {
|
if (Out_Of_Service[index] != value) {
|
||||||
Change_Of_Value[index] = true;
|
Change_Of_Value[index] = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Out_Of_Service[index] = value;
|
Out_Of_Service[index] = value;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ static void Init_Service_Handlers(
|
|||||||
handler_timesync_utc);
|
handler_timesync_utc);
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
|
||||||
handler_timesync);
|
handler_timesync);
|
||||||
|
apdu_set_confirmed_handler(SERVICE_CONFIRMED_SUBSCRIBE_COV,
|
||||||
|
handler_cov_subscribe);
|
||||||
/* handle communication so we can shutup when asked */
|
/* handle communication so we can shutup when asked */
|
||||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
||||||
handler_device_communication_control);
|
handler_device_communication_control);
|
||||||
@@ -105,6 +107,7 @@ int main(
|
|||||||
unsigned timeout = 100; /* milliseconds */
|
unsigned timeout = 100; /* milliseconds */
|
||||||
time_t last_seconds = 0;
|
time_t last_seconds = 0;
|
||||||
time_t current_seconds = 0;
|
time_t current_seconds = 0;
|
||||||
|
uint32_t elapsed_milliseconds = 0;
|
||||||
char *pEnv = NULL;
|
char *pEnv = NULL;
|
||||||
|
|
||||||
/* allow the device ID to be set */
|
/* allow the device ID to be set */
|
||||||
@@ -178,6 +181,9 @@ int main(
|
|||||||
if (current_seconds != last_seconds) {
|
if (current_seconds != last_seconds) {
|
||||||
dcc_timer_seconds(current_seconds - last_seconds);
|
dcc_timer_seconds(current_seconds - last_seconds);
|
||||||
Load_Control_State_Machine_Handler();
|
Load_Control_State_Machine_Handler();
|
||||||
|
elapsed_milliseconds = (current_seconds - last_seconds) * 1000;
|
||||||
|
handler_cov_task(elapsed_milliseconds);
|
||||||
|
tsm_timer_milliseconds(elapsed_milliseconds);
|
||||||
}
|
}
|
||||||
/* output */
|
/* output */
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ extern "C" {
|
|||||||
uint32_t object_instance);
|
uint32_t object_instance);
|
||||||
bool Binary_Input_Change_Of_Value(
|
bool Binary_Input_Change_Of_Value(
|
||||||
uint32_t object_instance);
|
uint32_t object_instance);
|
||||||
|
void Binary_Input_Change_Of_Value_Clear(
|
||||||
|
uint32_t object_instance);
|
||||||
int Binary_Input_Encode_Property_APDU(
|
int Binary_Input_Encode_Property_APDU(
|
||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
|
|||||||
@@ -143,7 +143,13 @@ extern "C" {
|
|||||||
BACNET_ERROR_CLASS * error_class,
|
BACNET_ERROR_CLASS * error_class,
|
||||||
BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
|
void handler_cov_subscribe(
|
||||||
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
void handler_cov_task(
|
||||||
|
uint32_t elapsed_milliseconds);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user