diff --git a/bacnet-stack/demo/handler/h_cov.c b/bacnet-stack/demo/handler/h_cov.c index 61db1836..d279643c 100644 --- a/bacnet-stack/demo/handler/h_cov.c +++ b/bacnet-stack/demo/handler/h_cov.c @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (C) 2007 Steve Karg +* Copyright (C) 2007-2008 Steve Karg * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -36,6 +36,7 @@ #include "npdu.h" #include "abort.h" #include "cov.h" +#include "tsm.h" /* demo objects */ #include "device.h" #include "ai.h" @@ -138,6 +139,88 @@ static bool cov_list_subscribe( 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 one notification per task cycle */ void handler_cov_task( @@ -146,6 +229,7 @@ void handler_cov_task( int index; int lifetime_milliseconds; BACNET_OBJECT_ID object_id; + bool status = false; /* existing? - match Object ID and Process ID */ @@ -169,7 +253,11 @@ void handler_cov_task( switch (object_id.type) { case OBJECT_BINARY_INPUT: 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; default: diff --git a/bacnet-stack/demo/object/bi.c b/bacnet-stack/demo/object/bi.c index 066faaca..def97e8c 100644 --- a/bacnet-stack/demo/object/bi.c +++ b/bacnet-stack/demo/object/bi.c @@ -32,6 +32,7 @@ #include "bacdcode.h" #include "bacenum.h" #include "wp.h" +#include "cov.h" #include "config.h" /* the custom stuff */ #define MAX_BINARY_INPUTS 5 @@ -70,12 +71,15 @@ void Binary_Input_Property_Lists( const int **pOptional, const int **pProprietary) { - if (pRequired) + if (pRequired) { *pRequired = Binary_Input_Properties_Required; - if (pOptional) + } + if (pOptional) { *pOptional = Binary_Input_Properties_Optional; - if (pProprietary) + } + if (pProprietary) { *pProprietary = Binary_Input_Properties_Proprietary; + } return; } @@ -86,8 +90,9 @@ void Binary_Input_Property_Lists( bool Binary_Input_Valid_Instance( uint32_t object_instance) { - if (object_instance < MAX_BINARY_INPUTS) + if (object_instance < MAX_BINARY_INPUTS) { return true; + } return false; } @@ -136,8 +141,9 @@ unsigned Binary_Input_Instance_To_Index( unsigned index = MAX_BINARY_INPUTS; Binary_Input_Init(); - if (object_instance < MAX_BINARY_INPUTS) + if (object_instance < MAX_BINARY_INPUTS) { index = object_instance; + } return index; } @@ -150,8 +156,9 @@ static BACNET_BINARY_PV Binary_Input_Present_Value( Binary_Input_Init(); index = Binary_Input_Instance_To_Index(object_instance); - if (index < MAX_BINARY_INPUTS) + if (index < MAX_BINARY_INPUTS) { value = Present_Value[index]; + } return value; } @@ -164,8 +171,9 @@ static bool Binary_Input_Out_Of_Service( Binary_Input_Init(); index = Binary_Input_Instance_To_Index(object_instance); - if (index < MAX_BINARY_INPUTS) + if (index < MAX_BINARY_INPUTS) { value = Out_Of_Service[index]; + } return value; } @@ -184,6 +192,58 @@ bool Binary_Input_Change_Of_Value( 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( uint32_t object_instance, BACNET_BINARY_PV value) @@ -210,10 +270,11 @@ static void Binary_Input_Out_Of_Service_Set( Binary_Input_Init(); index = Binary_Input_Instance_To_Index(object_instance); - if (index < MAX_BINARY_INPUTS) + if (index < MAX_BINARY_INPUTS) { if (Out_Of_Service[index] != value) { Change_Of_Value[index] = true; } + } Out_Of_Service[index] = value; return; diff --git a/bacnet-stack/demo/server/main.c b/bacnet-stack/demo/server/main.c index 57475234..188efee8 100644 --- a/bacnet-stack/demo/server/main.c +++ b/bacnet-stack/demo/server/main.c @@ -85,6 +85,8 @@ static void Init_Service_Handlers( handler_timesync_utc); apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, handler_timesync); + apdu_set_confirmed_handler(SERVICE_CONFIRMED_SUBSCRIBE_COV, + handler_cov_subscribe); /* handle communication so we can shutup when asked */ apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, handler_device_communication_control); @@ -105,6 +107,7 @@ int main( unsigned timeout = 100; /* milliseconds */ time_t last_seconds = 0; time_t current_seconds = 0; + uint32_t elapsed_milliseconds = 0; char *pEnv = NULL; /* allow the device ID to be set */ @@ -178,6 +181,9 @@ int main( if (current_seconds != last_seconds) { dcc_timer_seconds(current_seconds - last_seconds); Load_Control_State_Machine_Handler(); + elapsed_milliseconds = (current_seconds - last_seconds) * 1000; + handler_cov_task(elapsed_milliseconds); + tsm_timer_milliseconds(elapsed_milliseconds); } /* output */ diff --git a/bacnet-stack/include/bi.h b/bacnet-stack/include/bi.h index 4f6a7ac0..9249ad89 100644 --- a/bacnet-stack/include/bi.h +++ b/bacnet-stack/include/bi.h @@ -47,6 +47,8 @@ extern "C" { uint32_t object_instance); bool Binary_Input_Change_Of_Value( uint32_t object_instance); + void Binary_Input_Change_Of_Value_Clear( + uint32_t object_instance); int Binary_Input_Encode_Property_APDU( uint8_t * apdu, uint32_t object_instance, diff --git a/bacnet-stack/include/handlers.h b/bacnet-stack/include/handlers.h index 0938d76c..389f5bd6 100644 --- a/bacnet-stack/include/handlers.h +++ b/bacnet-stack/include/handlers.h @@ -143,7 +143,13 @@ extern "C" { BACNET_ERROR_CLASS * error_class, 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 }