Added GetEventInformation service, handler, unit test.
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacerror.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
#include "event.h"
|
||||
|
||||
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
|
||||
|
||||
static get_event_info_function
|
||||
Get_Event_Info[MAX_BACNET_OBJECT_TYPE];
|
||||
|
||||
void handler_get_event_information_set(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
get_event_info_function pFunction)
|
||||
{
|
||||
if (object_type < MAX_BACNET_OBJECT_TYPE) {
|
||||
Get_Event_Info[object_type] = pFunction;
|
||||
}
|
||||
}
|
||||
|
||||
void handler_get_event_information(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
{
|
||||
int len = 0;
|
||||
int pdu_len = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
bool error = false;
|
||||
int bytes_sent = 0;
|
||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
BACNET_ADDRESS my_address;
|
||||
BACNET_OBJECT_ID object_id;
|
||||
unsigned i = 0; /* counter */
|
||||
BACNET_GET_EVENT_INFORMATION_DATA getevent_data;
|
||||
|
||||
/* encode the NPDU portion of the packet */
|
||||
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], src, &my_address,
|
||||
&npdu_data);
|
||||
if (service_data->segmented_message) {
|
||||
/* we don't support segmentation - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "GetEventInformation: "
|
||||
"Segmented message. Sending Abort!\n");
|
||||
#endif
|
||||
goto GET_EVENT_ABORT;
|
||||
}
|
||||
|
||||
len = getevent_decode_service_request(
|
||||
service_request,
|
||||
service_len,
|
||||
&object_id);
|
||||
if (len < 0) {
|
||||
/* bad decoding - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "GetEventInformation: Bad Encoding. Sending Abort!\n");
|
||||
#endif
|
||||
goto GET_EVENT_ABORT;
|
||||
}
|
||||
|
||||
/* assume that there is an error */
|
||||
error = true;
|
||||
len = getevent_ack_encode_apdu_init(
|
||||
&Handler_Transmit_Buffer[pdu_len],
|
||||
sizeof(Handler_Transmit_Buffer) - pdu_len,
|
||||
service_data->invoke_id);
|
||||
if (len <= 0) {
|
||||
error = true;
|
||||
goto GET_EVENT_ERROR;
|
||||
}
|
||||
pdu_len += len;
|
||||
for (i = 0; i < MAX_BACNET_OBJECT_TYPE; i++) {
|
||||
if (Get_Event_Info[i]) {
|
||||
Get_Event_Info[i](&getevent_data);
|
||||
len = getevent_ack_encode_apdu_data(
|
||||
&Handler_Transmit_Buffer[pdu_len],
|
||||
sizeof(Handler_Transmit_Buffer)-pdu_len,
|
||||
&getevent_data);
|
||||
if (len <= 0) {
|
||||
error = true;
|
||||
goto GET_EVENT_ERROR;
|
||||
}
|
||||
pdu_len += len;
|
||||
}
|
||||
}
|
||||
len = getevent_ack_encode_apdu_end(
|
||||
&Handler_Transmit_Buffer[pdu_len],
|
||||
sizeof(Handler_Transmit_Buffer)-pdu_len,
|
||||
false);
|
||||
if (len <= 0) {
|
||||
error = true;
|
||||
goto GET_EVENT_ERROR;
|
||||
}
|
||||
pdu_len += len;
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "GetEventInformation: Sending Ack!\n");
|
||||
#endif
|
||||
GET_EVENT_ERROR:
|
||||
if (error) {
|
||||
if (len == -2) {
|
||||
/* BACnet APDU too small to fit data, so proper response is Abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "GetEventInformation: "
|
||||
"Reply too big to fit into APDU!\n");
|
||||
#endif
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
error_class, error_code);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "GetEventInformation: Sending Error!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
GET_EVENT_ABORT:
|
||||
pdu_len += len;
|
||||
bytes_sent =
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
||||
pdu_len);
|
||||
#if PRINT_ENABLED
|
||||
if (bytes_sent <= 0)
|
||||
fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno));
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2009 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#ifndef GETEVENT_H
|
||||
#define GETEVENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacdef.h"
|
||||
#include "bacenum.h"
|
||||
#include "timestamp.h"
|
||||
#include "event.h"
|
||||
|
||||
struct BACnet_Get_Event_Information_Data;
|
||||
typedef struct BACnet_Get_Event_Information_Data {
|
||||
BACNET_OBJECT_ID objectIdentifier;
|
||||
BACNET_EVENT_STATE eventState;
|
||||
BACNET_BIT_STRING acknowledgedTransitions;
|
||||
BACNET_TIMESTAMP eventTimeStamps[3];
|
||||
BACNET_NOTIFY_TYPE notifyType;
|
||||
BACNET_BIT_STRING eventEnable;
|
||||
uint32_t eventPriorities[3];
|
||||
struct BACnet_Get_Event_Information_Data *next;
|
||||
} BACNET_GET_EVENT_INFORMATION_DATA;
|
||||
|
||||
typedef int (*get_event_info_function) (
|
||||
BACNET_GET_EVENT_INFORMATION_DATA *getevent_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int getevent_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
uint8_t invoke_id,
|
||||
BACNET_OBJECT_ID * lastReceivedObjectIdentifier);
|
||||
|
||||
int getevent_decode_service_request(
|
||||
uint8_t * apdu,
|
||||
unsigned apdu_len,
|
||||
BACNET_OBJECT_ID * object_id);
|
||||
|
||||
int getevent_ack_encode_apdu_init(
|
||||
uint8_t * apdu,
|
||||
size_t max_apdu,
|
||||
uint8_t invoke_id);
|
||||
|
||||
int getevent_ack_encode_apdu_data(
|
||||
uint8_t * apdu,
|
||||
size_t max_apdu,
|
||||
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data);
|
||||
|
||||
int getevent_ack_encode_apdu_end(
|
||||
uint8_t * apdu,
|
||||
size_t max_apdu,
|
||||
bool moreEvents);
|
||||
|
||||
int getevent_ack_decode_service_request(
|
||||
uint8_t * apdu,
|
||||
int apdu_len, /* total length of the apdu */
|
||||
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data,
|
||||
bool *moreEvents);
|
||||
|
||||
#ifdef TEST
|
||||
#include "ctest.h"
|
||||
int getevent_decode_apdu(
|
||||
uint8_t * apdu,
|
||||
unsigned apdu_len,
|
||||
uint8_t * invoke_id,
|
||||
BACNET_OBJECT_ID * lastReceivedObjectIdentifier);
|
||||
|
||||
int getevent_ack_decode_apdu(
|
||||
uint8_t * apdu,
|
||||
int apdu_len, /* total length of the apdu */
|
||||
uint8_t * invoke_id,
|
||||
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data,
|
||||
bool *moreEvents);
|
||||
|
||||
void testGetEventInformationAck(
|
||||
Test * pTest);
|
||||
|
||||
void testGetEventInformation(
|
||||
Test * pTest);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "rp.h"
|
||||
#include "rpm.h"
|
||||
#include "wp.h"
|
||||
#include "getevent.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -224,6 +225,17 @@ extern "C" {
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
|
||||
|
||||
void handler_get_event_information_set(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
get_event_info_function pFunction);
|
||||
|
||||
void handler_get_event_information(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -66,12 +66,15 @@ extern "C" {
|
||||
int bacapp_encode_timestamp(
|
||||
uint8_t * apdu,
|
||||
BACNET_TIMESTAMP * value);
|
||||
int bacapp_decode_timestamp(
|
||||
uint8_t * apdu,
|
||||
BACNET_TIMESTAMP * value);
|
||||
|
||||
|
||||
int bacapp_encode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value);
|
||||
|
||||
int bacapp_decode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
|
||||
+114
-114
@@ -325,26 +325,26 @@ int decode_tag_number(
|
||||
/* Same as function above, but will safely fail is packet has been truncated */
|
||||
int decode_tag_number_safe(
|
||||
uint8_t * apdu,
|
||||
uint32_t apdu_len_remaining,
|
||||
uint32_t apdu_len_remaining,
|
||||
uint8_t * tag_number)
|
||||
{
|
||||
int len = 0; /* return value */
|
||||
|
||||
/* decode the tag number first */
|
||||
if ( apdu_len_remaining >= 1 ) {
|
||||
if (IS_EXTENDED_TAG_NUMBER(apdu[0]) && apdu_len_remaining >= 2) {
|
||||
/* extended tag */
|
||||
if (tag_number) {
|
||||
*tag_number = apdu[1];
|
||||
}
|
||||
len = 2;
|
||||
} else {
|
||||
if (tag_number) {
|
||||
*tag_number = (uint8_t) (apdu[0] >> 4);
|
||||
}
|
||||
len = 1;
|
||||
}
|
||||
}
|
||||
if ( apdu_len_remaining >= 1 ) {
|
||||
if (IS_EXTENDED_TAG_NUMBER(apdu[0]) && apdu_len_remaining >= 2) {
|
||||
/* extended tag */
|
||||
if (tag_number) {
|
||||
*tag_number = apdu[1];
|
||||
}
|
||||
len = 2;
|
||||
} else {
|
||||
if (tag_number) {
|
||||
*tag_number = (uint8_t) (apdu[0] >> 4);
|
||||
}
|
||||
len = 1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -415,56 +415,56 @@ int decode_tag_number_and_value(
|
||||
/* Same as function above, but will safely fail is packet has been truncated */
|
||||
int decode_tag_number_and_value_safe(
|
||||
uint8_t * apdu,
|
||||
uint32_t apdu_len_remaining,
|
||||
uint32_t apdu_len_remaining,
|
||||
uint8_t * tag_number,
|
||||
uint32_t * value)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
len = decode_tag_number_safe(&apdu[0], apdu_len_remaining, tag_number);
|
||||
len = decode_tag_number_safe(&apdu[0], apdu_len_remaining, tag_number);
|
||||
|
||||
if ( len > 0 ) {
|
||||
apdu_len_remaining -= len;
|
||||
if (IS_EXTENDED_VALUE(apdu[0])) {
|
||||
/* tagged as uint32_t */
|
||||
if (apdu[len] == 255 && apdu_len_remaining >= 5) {
|
||||
uint32_t value32;
|
||||
len++;
|
||||
len += decode_unsigned32(&apdu[len], &value32);
|
||||
if (value) {
|
||||
*value = value32;
|
||||
}
|
||||
}
|
||||
/* tagged as uint16_t */
|
||||
else if (apdu[len] == 254 && apdu_len_remaining >= 3) {
|
||||
uint16_t value16;
|
||||
len++;
|
||||
len += decode_unsigned16(&apdu[len], &value16);
|
||||
if (value) {
|
||||
*value = value16;
|
||||
}
|
||||
}
|
||||
/* no tag - must be uint8_t */
|
||||
else if (apdu[len] < 254 && apdu_len_remaining >= 1) {
|
||||
if (value) {
|
||||
*value = apdu[len];
|
||||
}
|
||||
len++;
|
||||
}
|
||||
else {
|
||||
/* packet is truncated */
|
||||
len = 0;
|
||||
}
|
||||
} else if (decode_is_opening_tag(&apdu[0]) && value) {
|
||||
*value = 0;
|
||||
} else if (decode_is_closing_tag(&apdu[0]) && value) {
|
||||
/* closing tag */
|
||||
*value = 0;
|
||||
} else if (value) {
|
||||
/* small value */
|
||||
*value = apdu[0] & 0x07;
|
||||
}
|
||||
}
|
||||
if ( len > 0 ) {
|
||||
apdu_len_remaining -= len;
|
||||
if (IS_EXTENDED_VALUE(apdu[0])) {
|
||||
/* tagged as uint32_t */
|
||||
if (apdu[len] == 255 && apdu_len_remaining >= 5) {
|
||||
uint32_t value32;
|
||||
len++;
|
||||
len += decode_unsigned32(&apdu[len], &value32);
|
||||
if (value) {
|
||||
*value = value32;
|
||||
}
|
||||
}
|
||||
/* tagged as uint16_t */
|
||||
else if (apdu[len] == 254 && apdu_len_remaining >= 3) {
|
||||
uint16_t value16;
|
||||
len++;
|
||||
len += decode_unsigned16(&apdu[len], &value16);
|
||||
if (value) {
|
||||
*value = value16;
|
||||
}
|
||||
}
|
||||
/* no tag - must be uint8_t */
|
||||
else if (apdu[len] < 254 && apdu_len_remaining >= 1) {
|
||||
if (value) {
|
||||
*value = apdu[len];
|
||||
}
|
||||
len++;
|
||||
}
|
||||
else {
|
||||
/* packet is truncated */
|
||||
len = 0;
|
||||
}
|
||||
} else if (decode_is_opening_tag(&apdu[0]) && value) {
|
||||
*value = 0;
|
||||
} else if (decode_is_closing_tag(&apdu[0]) && value) {
|
||||
/* closing tag */
|
||||
*value = 0;
|
||||
} else if (value) {
|
||||
/* small value */
|
||||
*value = apdu[0] & 0x07;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -784,16 +784,16 @@ int decode_object_id(
|
||||
|
||||
int decode_object_id_safe(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
uint32_t len_value,
|
||||
uint16_t * object_type,
|
||||
uint32_t * instance)
|
||||
{
|
||||
if ( len_value != 4 ) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return decode_object_id(apdu, object_type, instance);
|
||||
}
|
||||
if ( len_value != 4 ) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return decode_object_id(apdu, object_type, instance);
|
||||
}
|
||||
}
|
||||
|
||||
int decode_context_object_id(
|
||||
@@ -1181,7 +1181,7 @@ int encode_context_unsigned(
|
||||
uint32_t value)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
|
||||
/* length of unsigned is variable, as per 20.2.4 */
|
||||
if (value < 0x100) {
|
||||
len = 1;
|
||||
@@ -1193,8 +1193,8 @@ int encode_context_unsigned(
|
||||
len = 4;
|
||||
}
|
||||
|
||||
len = encode_tag(&apdu[0], tag_number, true, len);
|
||||
len += encode_bacnet_unsigned(&apdu[len], value);
|
||||
len = encode_tag(&apdu[0], tag_number, true, len);
|
||||
len += encode_bacnet_unsigned(&apdu[len], value);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -1306,7 +1306,7 @@ int encode_context_enumerated(
|
||||
len = encode_tag(&apdu[0], tag_number, true, (uint32_t) len);
|
||||
len += encode_bacnet_enumerated(&apdu[len], value);
|
||||
|
||||
return len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
||||
@@ -1558,21 +1558,21 @@ int decode_bacnet_time(
|
||||
|
||||
int decode_bacnet_time_safe(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
uint32_t len_value,
|
||||
BACNET_TIME * btime)
|
||||
{
|
||||
if ( len_value != 4 )
|
||||
{
|
||||
btime->hour = 0;
|
||||
btime->hundredths = 0;
|
||||
btime->min = 0;
|
||||
btime->sec = 0;
|
||||
return len_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return decode_bacnet_time(apdu, btime);
|
||||
}
|
||||
if ( len_value != 4 )
|
||||
{
|
||||
btime->hour = 0;
|
||||
btime->hundredths = 0;
|
||||
btime->min = 0;
|
||||
btime->sec = 0;
|
||||
return len_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return decode_bacnet_time(apdu, btime);
|
||||
}
|
||||
}
|
||||
|
||||
int decode_application_time(
|
||||
@@ -1694,19 +1694,19 @@ int decode_date(
|
||||
|
||||
int decode_date_safe(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
uint32_t len_value,
|
||||
BACNET_DATE * bdate)
|
||||
{
|
||||
if ( len_value != 4 ) {
|
||||
bdate->day = 0;
|
||||
bdate->month = 0;
|
||||
bdate->wday = 0;
|
||||
bdate->year = 0;
|
||||
return len_value;
|
||||
}
|
||||
else {
|
||||
return decode_date(apdu, bdate);
|
||||
}
|
||||
if ( len_value != 4 ) {
|
||||
bdate->day = 0;
|
||||
bdate->month = 0;
|
||||
bdate->wday = 0;
|
||||
bdate->year = 0;
|
||||
return len_value;
|
||||
}
|
||||
else {
|
||||
return decode_date(apdu, bdate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2380,7 +2380,7 @@ void testUnsignedContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
/* 32 bit number */
|
||||
uint32_t in = 0xdeadbeef;
|
||||
@@ -2404,7 +2404,7 @@ void testUnsignedContextDecodes(
|
||||
ct_test(pTest, in == out);
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
|
||||
/* 16 bit number */
|
||||
/* 16 bit number */
|
||||
in = 0xdead;
|
||||
inLen = encode_context_unsigned(apdu, 10, in);
|
||||
outLen = decode_context_unsigned(apdu, 10, &out);
|
||||
@@ -2457,7 +2457,7 @@ void testUnsignedContextDecodes(
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
inLen = encode_context_unsigned(apdu, large_context_tag, in);
|
||||
inLen = encode_context_unsigned(apdu, large_context_tag, in);
|
||||
outLen = decode_context_unsigned(apdu, large_context_tag, &out);
|
||||
outLen2 = decode_context_unsigned(apdu, large_context_tag-1, &out);
|
||||
|
||||
@@ -2474,7 +2474,7 @@ void testSignedContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
|
||||
/* 32 bit number */
|
||||
@@ -2555,7 +2555,7 @@ void testSignedContextDecodes(
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
inLen = encode_context_signed(apdu, large_context_tag, in);
|
||||
inLen = encode_context_signed(apdu, large_context_tag, in);
|
||||
outLen = decode_context_signed(apdu, large_context_tag, &out);
|
||||
outLen2 = decode_context_signed(apdu, large_context_tag-1, &out);
|
||||
|
||||
@@ -2572,7 +2572,7 @@ void testEnumeratedContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
/* 32 bit number */
|
||||
uint32_t in = 0xdeadbeef;
|
||||
@@ -2649,7 +2649,7 @@ void testEnumeratedContextDecodes(
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
inLen = encode_context_enumerated(apdu, large_context_tag, in);
|
||||
inLen = encode_context_enumerated(apdu, large_context_tag, in);
|
||||
outLen = decode_context_enumerated(apdu, large_context_tag, &out);
|
||||
outLen2 = decode_context_enumerated(apdu, large_context_tag-1, &out);
|
||||
|
||||
@@ -2665,7 +2665,7 @@ void testFloatContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
/* 32 bit number */
|
||||
float in;
|
||||
@@ -2713,7 +2713,7 @@ void testDoubleContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
/* 64 bit number */
|
||||
double in;
|
||||
@@ -2761,7 +2761,7 @@ static void testObjectIDContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
/* 32 bit number */
|
||||
uint16_t in_type;
|
||||
@@ -2799,7 +2799,7 @@ static void testCharacterStringContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
|
||||
BACNET_CHARACTER_STRING in;
|
||||
@@ -2835,7 +2835,7 @@ void testBitStringContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
BACNET_BIT_STRING in;
|
||||
BACNET_BIT_STRING out;
|
||||
@@ -2874,7 +2874,7 @@ void testOctetStringContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
|
||||
BACNET_OCTET_STRING in;
|
||||
@@ -2911,7 +2911,7 @@ void testTimeContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
BACNET_TIME in;
|
||||
BACNET_TIME out;
|
||||
@@ -2953,7 +2953,7 @@ void testDateContextDecodes(
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
uint8_t large_context_tag = 0xfe;
|
||||
|
||||
|
||||
BACNET_DATE in;
|
||||
@@ -2968,19 +2968,19 @@ void testDateContextDecodes(
|
||||
outLen = decode_context_date(apdu, 10, &out);
|
||||
outLen2 = decode_context_date(apdu, 9, &out);
|
||||
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in.day == out.day);
|
||||
ct_test(pTest, in.month == out.month);
|
||||
ct_test(pTest, in.wday == out.wday);
|
||||
ct_test(pTest, in.year == out.year);
|
||||
|
||||
/* Test large tags */
|
||||
inLen = encode_context_date(apdu, large_context_tag, &in);
|
||||
/* Test large tags */
|
||||
inLen = encode_context_date(apdu, large_context_tag, &in);
|
||||
outLen = decode_context_date(apdu, large_context_tag, &out);
|
||||
outLen2 = decode_context_date(apdu, large_context_tag-1, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in.day == out.day);
|
||||
ct_test(pTest, in.month == out.month);
|
||||
ct_test(pTest, in.wday == out.wday);
|
||||
@@ -2995,7 +2995,7 @@ int main(
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACDCode", NULL);
|
||||
pTest = ct_create("BACDCode", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testBACDCodeTags);
|
||||
assert(rc);
|
||||
|
||||
@@ -0,0 +1,477 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2009 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#include <stdint.h>
|
||||
#include "bacenum.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacdef.h"
|
||||
#include "getevent.h"
|
||||
|
||||
/* encode service */
|
||||
int getevent_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
uint8_t invoke_id,
|
||||
BACNET_OBJECT_ID * lastReceivedObjectIdentifier)
|
||||
{
|
||||
int len = 0; /* length of each encoding */
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
if (apdu) {
|
||||
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
|
||||
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
|
||||
apdu[2] = invoke_id;
|
||||
apdu[3] = SERVICE_CONFIRMED_GET_EVENT_INFORMATION;
|
||||
apdu_len = 4;
|
||||
/* encode optional parameter */
|
||||
if (lastReceivedObjectIdentifier) {
|
||||
len =
|
||||
encode_context_object_id(&apdu[apdu_len], 0,
|
||||
lastReceivedObjectIdentifier->type,
|
||||
lastReceivedObjectIdentifier->instance);
|
||||
apdu_len += len;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* decode the service request only */
|
||||
int getevent_decode_service_request(
|
||||
uint8_t * apdu,
|
||||
unsigned apdu_len,
|
||||
BACNET_OBJECT_ID * lastReceivedObjectIdentifier)
|
||||
{
|
||||
unsigned len = 0;
|
||||
|
||||
/* check for value pointers */
|
||||
if (apdu_len && lastReceivedObjectIdentifier) {
|
||||
/* Tag 0: Object ID - optional */
|
||||
if (!decode_is_context_tag(&apdu[len++], 0))
|
||||
return -1;
|
||||
len += decode_object_id(&apdu[len],
|
||||
&lastReceivedObjectIdentifier->type,
|
||||
&lastReceivedObjectIdentifier->instance);
|
||||
}
|
||||
|
||||
return (int)len;
|
||||
}
|
||||
|
||||
int getevent_ack_encode_apdu_init(
|
||||
uint8_t * apdu,
|
||||
size_t max_apdu,
|
||||
uint8_t invoke_id)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
if (apdu) {
|
||||
apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */
|
||||
apdu[1] = invoke_id; /* original invoke id from request */
|
||||
apdu[2] = SERVICE_CONFIRMED_GET_EVENT_INFORMATION;
|
||||
apdu_len = 3;
|
||||
/* service ack follows */
|
||||
/* Tag 0: listOfEventSummaries */
|
||||
apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int getevent_ack_encode_apdu_data(
|
||||
uint8_t * apdu,
|
||||
size_t max_apdu,
|
||||
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
BACNET_GET_EVENT_INFORMATION_DATA *event_data;
|
||||
unsigned i = 0; /* counter */
|
||||
|
||||
if (apdu) {
|
||||
event_data = get_event_data;
|
||||
while (event_data) {
|
||||
/* Tag 0: objectIdentifier */
|
||||
apdu_len += encode_context_object_id(&apdu[apdu_len], 0,
|
||||
event_data->objectIdentifier.type,
|
||||
event_data->objectIdentifier.instance);
|
||||
/* Tag 1: eventState */
|
||||
apdu_len += encode_context_enumerated(&apdu[apdu_len], 1,
|
||||
event_data->eventState);
|
||||
/* Tag 2: acknowledgedTransitions */
|
||||
apdu_len += encode_context_bitstring(&apdu[apdu_len], 2,
|
||||
&event_data->acknowledgedTransitions);
|
||||
/* Tag 3: eventTimeStamps */
|
||||
apdu_len += encode_opening_tag(&apdu[apdu_len], 3);
|
||||
for (i = 0; i < 3; i++) {
|
||||
apdu_len += bacapp_encode_timestamp(&apdu[apdu_len],
|
||||
&event_data->eventTimeStamps[i]);
|
||||
}
|
||||
apdu_len += encode_closing_tag(&apdu[apdu_len], 3);
|
||||
/* Tag 4: notifyType */
|
||||
apdu_len += encode_context_enumerated(&apdu[apdu_len], 4,
|
||||
event_data->notifyType);
|
||||
/* Tag 5: eventEnable */
|
||||
apdu_len += encode_context_bitstring(&apdu[apdu_len], 5,
|
||||
&event_data->eventEnable);
|
||||
/* Tag 6: eventPriorities */
|
||||
apdu_len += encode_opening_tag(&apdu[apdu_len], 6);
|
||||
for (i = 0; i < 3; i++) {
|
||||
apdu_len += encode_application_unsigned(&apdu[apdu_len],
|
||||
event_data->eventPriorities[i]);
|
||||
}
|
||||
apdu_len += encode_closing_tag(&apdu[apdu_len], 6);
|
||||
event_data = event_data->next;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int getevent_ack_encode_apdu_end(
|
||||
uint8_t * apdu,
|
||||
size_t max_apdu,
|
||||
bool moreEvents)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
if (apdu) {
|
||||
apdu_len += encode_closing_tag(&apdu[apdu_len], 0);
|
||||
apdu_len += encode_context_boolean(&apdu[apdu_len], 1, moreEvents);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int getevent_ack_decode_service_request(
|
||||
uint8_t * apdu,
|
||||
int apdu_len, /* total length of the apdu */
|
||||
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data,
|
||||
bool *moreEvents)
|
||||
{
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value = 0;
|
||||
int len = 0; /* total length of decodes */
|
||||
uint32_t enum_value = 0; /* for decoding */
|
||||
BACNET_GET_EVENT_INFORMATION_DATA * event_data;
|
||||
unsigned i = 0; /* counter */
|
||||
|
||||
/* FIXME: check apdu_len against the len during decode */
|
||||
event_data = get_event_data;
|
||||
if (apdu && apdu_len && event_data && moreEvents) {
|
||||
if (!decode_is_opening_tag_number(&apdu[len], 0)) {
|
||||
return -1;
|
||||
}
|
||||
len++;
|
||||
while (event_data) {
|
||||
/* Tag 0: objectIdentifier */
|
||||
if (decode_is_context_tag(&apdu[len], 0)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
len += decode_object_id(&apdu[len],
|
||||
&event_data->objectIdentifier.type,
|
||||
&event_data->objectIdentifier.instance);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
/* Tag 1: eventState */
|
||||
if (decode_is_context_tag(&apdu[len], 1)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
len += decode_enumerated(&apdu[len], len_value,
|
||||
&enum_value);
|
||||
event_data->eventState = enum_value;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
/* Tag 2: acknowledgedTransitions */
|
||||
if (decode_is_context_tag(&apdu[len], 2)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
len += decode_bitstring(&apdu[len], len_value,
|
||||
&event_data->acknowledgedTransitions);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
/* Tag 3: eventTimeStamps */
|
||||
if (decode_is_opening_tag_number(&apdu[len], 3)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
for (i = 0; i < 3; i++) {
|
||||
len += bacapp_decode_timestamp(&apdu[len],
|
||||
&event_data->eventTimeStamps[i]);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_closing_tag_number(&apdu[len], 3)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
/* Tag 4: notifyType */
|
||||
if (decode_is_context_tag(&apdu[len], 4)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
len += decode_enumerated(&apdu[apdu_len], len_value,
|
||||
&enum_value);
|
||||
event_data->notifyType = enum_value;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
/* Tag 5: eventEnable */
|
||||
if (decode_is_context_tag(&apdu[len], 5)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
len += decode_bitstring(&apdu[len], len_value,
|
||||
&event_data->eventEnable);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
/* Tag 6: eventPriorities */
|
||||
if (decode_is_opening_tag_number(&apdu[len], 6)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
for (i = 0; i < 3; i++) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
len += decode_unsigned(&apdu[len], len_value,
|
||||
&event_data->eventPriorities[i]);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_closing_tag_number(&apdu[len], 6)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_closing_tag_number(&apdu[len], 0)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
event_data->next = NULL;
|
||||
}
|
||||
event_data = event_data->next;
|
||||
}
|
||||
if (decode_is_context_tag(&apdu[len], 1)) {
|
||||
len += decode_tag_number_and_value(&apdu[len],
|
||||
&tag_number, &len_value);
|
||||
*moreEvents = decode_boolean(len_value);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
int getevent_decode_apdu(
|
||||
uint8_t * apdu,
|
||||
unsigned apdu_len,
|
||||
uint8_t * invoke_id,
|
||||
BACNET_OBJECT_ID * lastReceivedObjectIdentifier)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned offset = 0;
|
||||
|
||||
if (!apdu)
|
||||
return -1;
|
||||
/* optional checking - most likely was already done prior to this call */
|
||||
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
|
||||
return -1;
|
||||
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
|
||||
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
|
||||
if (apdu[3] != SERVICE_CONFIRMED_GET_EVENT_INFORMATION)
|
||||
return -1;
|
||||
offset = 4;
|
||||
|
||||
if (apdu_len > offset) {
|
||||
len = getevent_decode_service_request(&apdu[offset],
|
||||
apdu_len - offset, lastReceivedObjectIdentifier);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int getevent_ack_decode_apdu(
|
||||
uint8_t * apdu,
|
||||
int apdu_len, /* total length of the apdu */
|
||||
uint8_t * invoke_id,
|
||||
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data,
|
||||
bool *moreEvents)
|
||||
{
|
||||
int len = 0;
|
||||
int offset = 0;
|
||||
|
||||
if (!apdu)
|
||||
return -1;
|
||||
/* optional checking - most likely was already done prior to this call */
|
||||
if (apdu[0] != PDU_TYPE_COMPLEX_ACK)
|
||||
return -1;
|
||||
*invoke_id = apdu[1];
|
||||
if (apdu[2] != SERVICE_CONFIRMED_GET_EVENT_INFORMATION)
|
||||
return -1;
|
||||
offset = 3;
|
||||
if (apdu_len > offset) {
|
||||
len =
|
||||
getevent_ack_decode_service_request(&apdu[offset], apdu_len - offset,
|
||||
get_event_data, moreEvents);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void testGetEventInformationAck(
|
||||
Test * pTest)
|
||||
{
|
||||
uint8_t apdu[480] = { 0 };
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
uint8_t invoke_id = 1;
|
||||
uint8_t test_invoke_id = 0;
|
||||
BACNET_GET_EVENT_INFORMATION_DATA event_data;
|
||||
BACNET_GET_EVENT_INFORMATION_DATA test_event_data;
|
||||
bool moreEvents = false;
|
||||
bool test_moreEvents = false;
|
||||
unsigned i = 0;
|
||||
|
||||
event_data.objectIdentifier.type = OBJECT_BINARY_INPUT;
|
||||
event_data.objectIdentifier.instance = 1;
|
||||
event_data.eventState = EVENT_STATE_NORMAL;
|
||||
bitstring_init(&event_data.acknowledgedTransitions);
|
||||
bitstring_set_bit(&event_data.acknowledgedTransitions,
|
||||
TRANSITION_TO_OFFNORMAL, false);
|
||||
bitstring_set_bit(&event_data.acknowledgedTransitions,
|
||||
TRANSITION_TO_FAULT, false);
|
||||
bitstring_set_bit(&event_data.acknowledgedTransitions,
|
||||
TRANSITION_TO_NORMAL, false);
|
||||
for (i = 0; i < 3; i++) {
|
||||
event_data.eventTimeStamps[i].tag = TIME_STAMP_SEQUENCE;
|
||||
event_data.eventTimeStamps[i].value.sequenceNum = 0;
|
||||
}
|
||||
event_data.notifyType = NOTIFY_ALARM;
|
||||
bitstring_init(&event_data.eventEnable);
|
||||
bitstring_set_bit(&event_data.eventEnable,
|
||||
TRANSITION_TO_OFFNORMAL, true);
|
||||
bitstring_set_bit(&event_data.eventEnable,
|
||||
TRANSITION_TO_FAULT, true);
|
||||
bitstring_set_bit(&event_data.eventEnable,
|
||||
TRANSITION_TO_NORMAL, true);
|
||||
for (i = 0; i < 3; i++) {
|
||||
event_data.eventPriorities[i] = 1;
|
||||
}
|
||||
event_data.next = NULL;
|
||||
|
||||
len = getevent_ack_encode_apdu(&apdu[0], sizeof(apdu), invoke_id,
|
||||
&event_data, moreEvents);
|
||||
ct_test(pTest, len != 0);
|
||||
ct_test(pTest, len != -1);
|
||||
apdu_len = len;
|
||||
len = getevent_ack_decode_apdu(&apdu[0], apdu_len, /* total length of the apdu */
|
||||
&test_invoke_id, &test_event_data, &test_moreEvents);
|
||||
ct_test(pTest, len != -1);
|
||||
ct_test(pTest, test_invoke_id == invoke_id);
|
||||
|
||||
ct_test(pTest,
|
||||
event_data.objectIdentifier.type ==
|
||||
test_event_data.objectIdentifier.type);
|
||||
ct_test(pTest,
|
||||
event_data.objectIdentifier.instance ==
|
||||
test_event_data.objectIdentifier.instance);
|
||||
|
||||
ct_test(pTest,
|
||||
event_data.eventState ==
|
||||
test_event_data.eventState);
|
||||
}
|
||||
|
||||
void testGetEventInformation(
|
||||
Test * pTest)
|
||||
{
|
||||
uint8_t apdu[480] = { 0 };
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
uint8_t invoke_id = 128;
|
||||
uint8_t test_invoke_id = 0;
|
||||
BACNET_OBJECT_ID lastReceivedObjectIdentifier;
|
||||
BACNET_OBJECT_ID test_lastReceivedObjectIdentifier;
|
||||
|
||||
lastReceivedObjectIdentifier.type = OBJECT_BINARY_INPUT;
|
||||
lastReceivedObjectIdentifier.instance = 12345;
|
||||
len = getevent_encode_apdu(&apdu[0], invoke_id,
|
||||
&lastReceivedObjectIdentifier);
|
||||
ct_test(pTest, len != 0);
|
||||
apdu_len = len;
|
||||
|
||||
len = getevent_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
|
||||
&test_lastReceivedObjectIdentifier);
|
||||
ct_test(pTest, len != -1);
|
||||
ct_test(pTest,
|
||||
test_invoke_id ==
|
||||
invoke_id);
|
||||
ct_test(pTest,
|
||||
test_lastReceivedObjectIdentifier.type ==
|
||||
lastReceivedObjectIdentifier.type);
|
||||
ct_test(pTest,
|
||||
test_lastReceivedObjectIdentifier.instance ==
|
||||
lastReceivedObjectIdentifier.instance);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TEST_GET_EVENT_INFORMATION
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet GetEventInformation", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testGetEventInformation);
|
||||
assert(rc);
|
||||
rc = ct_addTestFunction(pTest, testGetEventInformationAck);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* TEST */
|
||||
@@ -116,9 +116,8 @@ int bacapp_encode_context_timestamp(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_timestamp(
|
||||
int bacapp_decode_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value)
|
||||
{
|
||||
int len = 0;
|
||||
@@ -126,10 +125,7 @@ int bacapp_decode_context_timestamp(
|
||||
uint32_t len_value_type;
|
||||
uint32_t sequenceNum;
|
||||
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
|
||||
if (apdu) {
|
||||
section_len =
|
||||
decode_tag_number_and_value(&apdu[len], &value->tag,
|
||||
&len_value_type);
|
||||
@@ -177,10 +173,30 @@ int bacapp_decode_context_timestamp(
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_len;
|
||||
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
section_len = bacapp_decode_timestamp(&apdu[len], value);
|
||||
if (section_len > 0) {
|
||||
len += section_len;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
LOGFILE = test.log
|
||||
|
||||
all: abort address arf awf bacapp bacdcode bacerror bacint \
|
||||
bacstr cov crc datetime dcc fifo filename iam ihave \
|
||||
bacstr cov crc datetime dcc fifo getevent filename iam ihave \
|
||||
indtext keylist key lso npdu rd reject ringbuf rp \
|
||||
rpm sbuf timesync whohas whois wp event
|
||||
|
||||
@@ -91,6 +91,11 @@ fifo: logfile test/fifo.mak
|
||||
( ./test/fifo >> ${LOGFILE} )
|
||||
make -C test -f fifo.mak clean
|
||||
|
||||
getevent: logfile test/getevent.mak
|
||||
make -C test -f getevent.mak clean all
|
||||
( ./test/getevent >> ${LOGFILE} )
|
||||
make -C test -f getevent.mak clean
|
||||
|
||||
iam: logfile test/iam.mak
|
||||
make -C test -f iam.mak clean all
|
||||
( ./test/iam >> ${LOGFILE} )
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#Makefile to build test case
|
||||
CC = gcc
|
||||
SRC_DIR = ../src
|
||||
INCLUDES = -I../include -I.
|
||||
DEFINES = -DBIG_ENDIAN=0 -DTEST -DTEST_GET_EVENT_INFORMATION
|
||||
|
||||
CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g
|
||||
|
||||
SRCS = $(SRC_DIR)/bacdcode.c \
|
||||
$(SRC_DIR)/bacint.c \
|
||||
$(SRC_DIR)/bacstr.c \
|
||||
$(SRC_DIR)/bacreal.c \
|
||||
$(SRC_DIR)/bacapp.c \
|
||||
$(SRC_DIR)/datetime.c \
|
||||
$(SRC_DIR)/bactext.c \
|
||||
$(SRC_DIR)/indtext.c \
|
||||
$(SRC_DIR)/timestamp.c \
|
||||
$(SRC_DIR)/getevent.c \
|
||||
ctest.c
|
||||
|
||||
TARGET = getevent
|
||||
|
||||
all: ${TARGET}
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
${TARGET}: ${OBJS}
|
||||
${CC} -o $@ ${OBJS}
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $*.c -o $@
|
||||
|
||||
depend:
|
||||
rm -f .depend
|
||||
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||
|
||||
clean:
|
||||
rm -rf core ${TARGET} $(OBJS) *.bak *.1 *.ini
|
||||
|
||||
include: .depend
|
||||
Reference in New Issue
Block a user