Added:
-context specific decoders for all of the primitive times to go with the context specific encoders -unconfirmed/confirmed EventNotificationRequest structure/encoder/decoder -BACnetTimestamp structure/encoder/decoder -BACnetPropertyStates structure/encoder/decoder -BACnetDeviceObjectPropertyReference structure/encoder/decoder Changes: -decode_context_object_id::object_type changed to uint16_t -explicit casts have been added to some functions to remove compiler warnings -encode_bacnet_date::year behaviour has been changed slightly
This commit is contained in:
@@ -107,17 +107,27 @@ extern "C" {
|
||||
uint32_t len_value);
|
||||
int encode_context_boolean(
|
||||
uint8_t * apdu,
|
||||
int tag_number,
|
||||
uint8_t tag_number,
|
||||
bool boolean_value);
|
||||
bool decode_context_boolean(
|
||||
uint8_t * apdu);
|
||||
|
||||
int decode_context_boolean2(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
bool *boolean_value);
|
||||
|
||||
/* from clause 20.2.10 Encoding of a Bit String Value */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int decode_bitstring(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
BACNET_BIT_STRING * bit_string);
|
||||
|
||||
int decode_context_bitstring(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_BIT_STRING * bit_string);
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_bitstring(
|
||||
uint8_t * apdu,
|
||||
@@ -146,8 +156,15 @@ extern "C" {
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int decode_object_id(
|
||||
uint8_t * apdu,
|
||||
int *object_type,
|
||||
uint16_t * object_type,
|
||||
uint32_t * instance);
|
||||
|
||||
int decode_context_object_id(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint16_t *object_type,
|
||||
uint32_t * instance);
|
||||
|
||||
int encode_bacnet_object_id(
|
||||
uint8_t * apdu,
|
||||
int object_type,
|
||||
@@ -179,6 +196,10 @@ extern "C" {
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
BACNET_OCTET_STRING * octet_string);
|
||||
int decode_context_octet_string(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_OCTET_STRING * octet_string);
|
||||
|
||||
|
||||
/* from clause 20.2.9 Encoding of a Character String Value */
|
||||
@@ -198,6 +219,11 @@ extern "C" {
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
BACNET_CHARACTER_STRING * char_string);
|
||||
int decode_context_character_string(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_CHARACTER_STRING * char_string);
|
||||
|
||||
|
||||
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
@@ -216,6 +242,10 @@ extern "C" {
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
uint32_t * value);
|
||||
int decode_context_unsigned(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint32_t * value);
|
||||
|
||||
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
@@ -234,6 +264,11 @@ extern "C" {
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
int32_t * value);
|
||||
int decode_context_signed(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
int32_t * value);
|
||||
|
||||
|
||||
/* from clause 20.2.11 Encoding of an Enumerated Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
@@ -242,6 +277,10 @@ extern "C" {
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
int *value);
|
||||
int decode_context_enumerated(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_value,
|
||||
int *value);
|
||||
int encode_bacnet_enumerated(
|
||||
uint8_t * apdu,
|
||||
int value);
|
||||
@@ -269,6 +308,14 @@ extern "C" {
|
||||
uint8_t * apdu,
|
||||
int tag_number,
|
||||
BACNET_TIME * btime);
|
||||
int decode_application_time(
|
||||
uint8_t * apdu,
|
||||
BACNET_TIME * btime);
|
||||
int decode_context_bacnet_time(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME * btime);
|
||||
|
||||
|
||||
/* BACnet Date */
|
||||
/* year = years since 1900 */
|
||||
@@ -292,6 +339,13 @@ extern "C" {
|
||||
int decode_date(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE * bdate);
|
||||
int decode_application_date(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE * bdate);
|
||||
int decode_context_date(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE * bdate);
|
||||
|
||||
/* from clause 20.1.2.4 max-segments-accepted */
|
||||
/* and clause 20.1.2.5 max-APDU-length-accepted */
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2006 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 _BAC_DEV_PROP_REF_H_
|
||||
#define _BAC_DEV_PROP_REF_H_
|
||||
|
||||
|
||||
typedef struct {
|
||||
BACNET_OBJECT_ID objectIdentifier;
|
||||
BACNET_PROPERTY_ID propertyIdentifier;
|
||||
uint32_t arrayIndex;
|
||||
BACNET_OBJECT_ID deviceIndentifier;
|
||||
} BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int bacapp_encode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_encode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_decode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_decode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif //_BAC_DEV_PROP_REF_H_
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2006 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 _BAC_PROP_STATES_H_
|
||||
#define _BAC_PROP_STATES_H_
|
||||
|
||||
#include "bacenum.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacapp.h"
|
||||
#include <time.h>
|
||||
#include "timestamp.h"
|
||||
|
||||
typedef enum {
|
||||
BOOLEAN_VALUE,
|
||||
BINARY_VALUE,
|
||||
EVENT_TYPE,
|
||||
POLARITY,
|
||||
PROGRAM_CHANGE,
|
||||
PROGRAM_STATE,
|
||||
REASON_FOR_HALT,
|
||||
RELIABILITY,
|
||||
STATE,
|
||||
SYSTEM_STATUS,
|
||||
UNITS,
|
||||
UNSIGNED_VALUE,
|
||||
LIFE_SAFETY_MODE,
|
||||
LIFE_SAFETY_STATE,
|
||||
} BACNET_PROPERTY_STATE_TYPE;
|
||||
|
||||
typedef struct {
|
||||
BACNET_PROPERTY_STATE_TYPE tag;
|
||||
union {
|
||||
bool booleanValue;
|
||||
BACNET_BINARY_PV binaryValue;
|
||||
BACNET_EVENT_TYPE eventType;
|
||||
BACNET_POLARITY polarity;
|
||||
BACNET_PROGRAM_REQUEST programChange;
|
||||
BACNET_PROGRAM_STATE programState;
|
||||
BACNET_PROGRAM_ERROR programError;
|
||||
BACNET_RELIABILITY reliability;
|
||||
BACNET_EVENT_STATE state;
|
||||
BACNET_DEVICE_STATUS systemStatus;
|
||||
BACNET_ENGINEERING_UNITS units;
|
||||
uint32_t unsignedValue;
|
||||
BACNET_LIFE_SAFETY_MODE lifeSafetyMode;
|
||||
BACNET_LIFE_SAFETY_STATE lifeSafetyState;
|
||||
} state;
|
||||
} BACNET_PROPERTY_STATE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int bacapp_decode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
int bacapp_decode_context_property_state(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
int bacapp_encode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif // _BAC_PROP_STATES_H_
|
||||
@@ -45,6 +45,11 @@ extern "C" {
|
||||
int decode_real(
|
||||
uint8_t * apdu,
|
||||
float *real_value);
|
||||
|
||||
int decode_context_real(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
float *real_value);
|
||||
int encode_bacnet_real(
|
||||
float value,
|
||||
uint8_t * apdu);
|
||||
|
||||
@@ -79,7 +79,7 @@ extern "C" {
|
||||
uint8_t bitstring_bits_used(
|
||||
BACNET_BIT_STRING * bit_string);
|
||||
/* returns the number of bytes that a bit string is using */
|
||||
int bitstring_bytes_used(
|
||||
uint8_t bitstring_bytes_used(
|
||||
BACNET_BIT_STRING * bit_string);
|
||||
uint8_t bitstring_bits_capacity(
|
||||
BACNET_BIT_STRING * bit_string);
|
||||
|
||||
@@ -138,6 +138,20 @@ extern "C" {
|
||||
void datetime_time_wildcard_set(
|
||||
BACNET_TIME * btime);
|
||||
|
||||
int bacapp_encode_context_datetime(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value);
|
||||
|
||||
int bacapp_decode_datetime(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE_TIME * value);
|
||||
|
||||
int bacapp_decode_context_datetime(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2006 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 BACNET_EVENT_H_
|
||||
#define BACNET_EVENT_H_
|
||||
|
||||
#include "bacenum.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacapp.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacpropstates.h"
|
||||
#include "bacdevobjpropref.h"
|
||||
|
||||
typedef enum {
|
||||
CHANGE_OF_VALUE_BITS,
|
||||
CHANGE_OF_VALUE_REAL
|
||||
} CHANGE_OF_VALUE_TYPE;
|
||||
|
||||
/*
|
||||
** Based on UnconfirmedEventNotification-Request
|
||||
*/
|
||||
|
||||
typedef struct BACnet_Event_Notification_Data {
|
||||
uint32_t processIdentifier;
|
||||
BACNET_OBJECT_ID initiatingObjectIdentifier;
|
||||
BACNET_OBJECT_ID eventObjectIdentifier;
|
||||
BACNET_TIMESTAMP timeStamp;
|
||||
uint32_t notificationClass;
|
||||
uint8_t priority;
|
||||
BACNET_EVENT_TYPE eventType;
|
||||
BACNET_CHARACTER_STRING* messageText; /* OPTIONAL - Set to NULL if not being used */
|
||||
BACNET_NOTIFY_TYPE notifyType;
|
||||
bool ackRequired;
|
||||
BACNET_EVENT_STATE fromState;
|
||||
BACNET_EVENT_STATE toState;
|
||||
/*
|
||||
** Each of these structures in the union maps to a particular eventtype
|
||||
** Based on BACnetNotificationParameters
|
||||
*/
|
||||
|
||||
union {
|
||||
/*
|
||||
** EVENT_CHANGE_OF_BITSTRING
|
||||
*/
|
||||
struct {
|
||||
BACNET_BIT_STRING referencedBitString;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfBitstring;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_STATE
|
||||
*/
|
||||
struct {
|
||||
BACNET_PROPERTY_STATE newState;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfState;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_VALUE
|
||||
*/
|
||||
struct {
|
||||
union {
|
||||
BACNET_BIT_STRING changedBits;
|
||||
float changeValue;
|
||||
} newValue;
|
||||
CHANGE_OF_VALUE_TYPE tag;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfValue;
|
||||
/*
|
||||
** EVENT_COMMAND_FAILURE
|
||||
**
|
||||
** Not Supported!
|
||||
*/
|
||||
/*
|
||||
** EVENT_FLOATING_LIMIT
|
||||
*/
|
||||
struct {
|
||||
float referenceValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
float setPointValue;
|
||||
float errorLimit;
|
||||
} floatingLimit;
|
||||
/*
|
||||
** EVENT_OUT_OF_RANGE
|
||||
*/
|
||||
struct {
|
||||
float exceedingValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
float deadband;
|
||||
float exceededLimit;
|
||||
} outOfRange;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_LIFE_SAFETY
|
||||
*/
|
||||
struct {
|
||||
BACNET_LIFE_SAFETY_STATE newState;
|
||||
BACNET_LIFE_SAFETY_MODE newMode;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
BACNET_LIFE_SAFETY_OPERATION operationExpected;
|
||||
} changeOfLifeSafety;
|
||||
/*
|
||||
** EVENT_EXTENDED
|
||||
**
|
||||
** Not Supported!
|
||||
*/
|
||||
/*
|
||||
** EVENT_BUFFER_READY
|
||||
*/
|
||||
struct {
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE bufferProperty;
|
||||
uint32_t previousNotification;
|
||||
uint32_t currentNotification;
|
||||
} bufferReady;
|
||||
/*
|
||||
** EVENT_UNSIGNED_RANGE
|
||||
*/
|
||||
struct {
|
||||
uint32_t exceedingValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
uint32_t exceededLimit;
|
||||
} unsignedRange;
|
||||
} notificationParams;
|
||||
} BACNET_EVENT_NOTIFICATION_DATA;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Creates a Confirmed Event Notification APDU
|
||||
**
|
||||
****************************************************/
|
||||
int cevent_notify_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
uint8_t invoke_id,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Creates an Unconfirmed Event Notification APDU
|
||||
**
|
||||
****************************************************/
|
||||
int uevent_notify_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Encodes the service data part of Event Notification
|
||||
**
|
||||
****************************************************/
|
||||
int event_notify_encode_service_request(
|
||||
uint8_t * apdu,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Decodes the service data part of Event Notification
|
||||
**
|
||||
****************************************************/
|
||||
int event_notify_decode_service_request(
|
||||
uint8_t * apdu,
|
||||
unsigned apdu_len,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Sends an Unconfirmed Event Notifcation to a dest
|
||||
**
|
||||
****************************************************/
|
||||
int uevent_notify_send(
|
||||
uint8_t * buffer,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data,
|
||||
BACNET_ADDRESS *dest);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* BACNET_EVENT_H_ */
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef _TIMESTAMP_H_
|
||||
#define _TIMESTAMP_H_
|
||||
|
||||
#include "bacdcode.h"
|
||||
|
||||
typedef enum {
|
||||
TIME_STAMP_TIME = 0,
|
||||
TIME_STAMP_SEQUENCE = 1,
|
||||
TIME_STAMP_DATETIME = 2,
|
||||
} BACNET_TIMESTAMP_TAG;
|
||||
|
||||
typedef uint8_t TYPE_BACNET_TIMESTAMP_TYPE;
|
||||
|
||||
typedef struct {
|
||||
TYPE_BACNET_TIMESTAMP_TYPE tag;
|
||||
union {
|
||||
BACNET_TIME time;
|
||||
uint16_t sequenceNum;
|
||||
BACNET_DATE_TIME dateTime;
|
||||
} value;
|
||||
} BACNET_TIMESTAMP;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
|
||||
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,
|
||||
BACNET_TIMESTAMP * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif
|
||||
+711
-25
@@ -71,6 +71,24 @@
|
||||
B'1110' reserved by ASHRAE
|
||||
B'1111' reserved by ASHRAE
|
||||
*/
|
||||
|
||||
/* Encoding of BACNET Length/Value/Type tag
|
||||
From clause 20.2.1.3.1
|
||||
|
||||
B'000' interpreted as Value = FALSE if application class == BOOLEAN
|
||||
B'001' interpreted as Value = TRUE if application class == BOOLEAN
|
||||
|
||||
B'000' interpreted as Length = 0 if application class != BOOLEAN
|
||||
B'001' interpreted as Length = 1
|
||||
B'010' interpreted as Length = 2
|
||||
B'011' interpreted as Length = 3
|
||||
B'100' interpreted as Length = 4
|
||||
B'101' interpreted as Length > 4
|
||||
B'110' interpreted as Type = Opening Tag
|
||||
B'111' interpreted as Type = Closing Tag
|
||||
*/
|
||||
|
||||
|
||||
/* from clause 20.1.2.4 max-segments-accepted */
|
||||
/* and clause 20.1.2.5 max-APDU-length-accepted */
|
||||
/* returns the encoded octet */
|
||||
@@ -285,7 +303,7 @@ int encode_closing_tag(
|
||||
static bool decode_is_extended_tag_number(
|
||||
uint8_t * apdu)
|
||||
{
|
||||
return ((apdu[0] & 0xF0) == 0xF0);
|
||||
return (bool)((apdu[0] & 0xF0) == 0xF0);
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
@@ -293,7 +311,7 @@ static bool decode_is_extended_tag_number(
|
||||
static bool decode_is_extended_value(
|
||||
uint8_t * apdu)
|
||||
{
|
||||
return ((apdu[0] & 0x07) == 5);
|
||||
return (bool)((apdu[0] & 0x07) == 5);
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
@@ -301,7 +319,7 @@ static bool decode_is_extended_value(
|
||||
bool decode_is_context_specific(
|
||||
uint8_t * apdu)
|
||||
{
|
||||
return ((apdu[0] & BIT3) == BIT3);
|
||||
return (bool)((apdu[0] & BIT3) == BIT3);
|
||||
}
|
||||
|
||||
int decode_tag_number(
|
||||
@@ -319,7 +337,7 @@ int decode_tag_number(
|
||||
len++;
|
||||
} else {
|
||||
if (tag_number) {
|
||||
*tag_number = (apdu[0] >> 4);
|
||||
*tag_number = (uint8_t)(apdu[0] >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +347,7 @@ int decode_tag_number(
|
||||
bool decode_is_opening_tag(
|
||||
uint8_t * apdu)
|
||||
{
|
||||
return ((apdu[0] & 0x07) == 6);
|
||||
return (bool)((apdu[0] & 0x07) == 6);
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
@@ -337,7 +355,7 @@ bool decode_is_opening_tag(
|
||||
bool decode_is_closing_tag(
|
||||
uint8_t * apdu)
|
||||
{
|
||||
return ((apdu[0] & 0x07) == 7);
|
||||
return (bool)((apdu[0] & 0x07) == 7);
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
@@ -398,10 +416,26 @@ bool decode_is_context_tag(
|
||||
uint8_t my_tag_number = 0;
|
||||
bool context_specific = false;
|
||||
|
||||
|
||||
context_specific = decode_is_context_specific(apdu);
|
||||
decode_tag_number(apdu, &my_tag_number);
|
||||
|
||||
return (context_specific && (my_tag_number == tag_number));
|
||||
return (bool)(context_specific && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
bool decode_is_context_tag_with_length(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
int * tag_length)
|
||||
{
|
||||
uint8_t my_tag_number = 0;
|
||||
bool context_specific = false;
|
||||
|
||||
|
||||
context_specific = decode_is_context_specific(apdu);
|
||||
*tag_length = decode_tag_number(apdu, &my_tag_number);
|
||||
|
||||
return (bool)(context_specific && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
@@ -413,10 +447,10 @@ bool decode_is_opening_tag_number(
|
||||
uint8_t my_tag_number = 0;
|
||||
bool opening_tag = false;
|
||||
|
||||
opening_tag = ((apdu[0] & 0x07) == 6);
|
||||
opening_tag = (bool)((apdu[0] & 0x07) == 6);
|
||||
decode_tag_number(apdu, &my_tag_number);
|
||||
|
||||
return (opening_tag && (my_tag_number == tag_number));
|
||||
return (bool)(opening_tag && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
@@ -428,10 +462,10 @@ bool decode_is_closing_tag_number(
|
||||
uint8_t my_tag_number = 0;
|
||||
bool closing_tag = false;
|
||||
|
||||
closing_tag = ((apdu[0] & 0x07) == 7);
|
||||
closing_tag = (bool)((apdu[0] & 0x07) == 7);
|
||||
decode_tag_number(apdu, &my_tag_number);
|
||||
|
||||
return (closing_tag && (my_tag_number == tag_number));
|
||||
return (bool)(closing_tag && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/* from clause 20.2.3 Encoding of a Boolean Value */
|
||||
@@ -456,13 +490,13 @@ int encode_application_boolean(
|
||||
/* context tagged is encoded differently */
|
||||
int encode_context_boolean(
|
||||
uint8_t * apdu,
|
||||
int tag_number,
|
||||
uint8_t tag_number,
|
||||
bool boolean_value)
|
||||
{
|
||||
int len = 0; /* return value */
|
||||
|
||||
len = encode_tag(&apdu[0], (uint8_t) tag_number, true, 1);
|
||||
apdu[len] = boolean_value ? 1 : 0;
|
||||
apdu[len] = (bool)(boolean_value ? 1 : 0);
|
||||
len++;
|
||||
|
||||
return len;
|
||||
@@ -480,6 +514,29 @@ bool decode_context_boolean(
|
||||
return boolean_value;
|
||||
}
|
||||
|
||||
int decode_context_boolean2(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
bool *boolean_value)
|
||||
{
|
||||
int len = 0;
|
||||
if (decode_is_context_tag_with_length(&apdu[len], tag_number, &len)) {
|
||||
if (apdu[len]) {
|
||||
*boolean_value = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*boolean_value = false;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.3 Encoding of a Boolean Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
@@ -567,7 +624,7 @@ int decode_bitstring(
|
||||
bitstring_set_octet(bit_string, (uint8_t) i,
|
||||
byte_reverse_bits(apdu[len++]));
|
||||
}
|
||||
unused_bits = apdu[0] & 0x07;
|
||||
unused_bits = (uint8_t)(apdu[0] & 0x07);
|
||||
bitstring_set_bits_used(bit_string, (uint8_t) bytes_used,
|
||||
unused_bits);
|
||||
}
|
||||
@@ -576,6 +633,27 @@ int decode_bitstring(
|
||||
return len;
|
||||
}
|
||||
|
||||
int decode_context_bitstring(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_BIT_STRING * bit_string)
|
||||
{
|
||||
uint32_t len_value;
|
||||
int len = 0;
|
||||
|
||||
if (decode_is_context_tag(&apdu[len], tag_number)) {
|
||||
len += decode_tag_number_and_value(&apdu[len], &tag_number,
|
||||
&len_value);
|
||||
len += decode_bitstring(&apdu[len], len_value, bit_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/* from clause 20.2.10 Encoding of a Bit String Value */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_bitstring(
|
||||
@@ -593,9 +671,9 @@ int encode_bitstring(
|
||||
} else {
|
||||
used_bytes = bitstring_bytes_used(bit_string);
|
||||
remaining_used_bits =
|
||||
bitstring_bits_used(bit_string) - ((used_bytes - 1) * 8);
|
||||
(uint8_t)(bitstring_bits_used(bit_string) - ((used_bytes - 1) * 8));
|
||||
/* number of unused bits in the subsequent final octet */
|
||||
apdu[len++] = 8 - remaining_used_bits;
|
||||
apdu[len++] = (uint8_t)(8 - remaining_used_bits);
|
||||
for (i = 0; i < used_bytes; i++) {
|
||||
apdu[len++] = byte_reverse_bits(bitstring_octet(bit_string, i));
|
||||
}
|
||||
@@ -650,12 +728,30 @@ int decode_object_id(
|
||||
int len = 0;
|
||||
|
||||
len = decode_unsigned32(apdu, &value);
|
||||
*object_type = ((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT);
|
||||
*object_type = (uint16_t)(((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT));
|
||||
*instance = (value & BACNET_MAX_INSTANCE);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int decode_context_object_id(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint16_t * object_type,
|
||||
uint32_t * instance)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (decode_is_context_tag_with_length(&apdu[len], tag_number, &len)) {
|
||||
len += decode_object_id(&apdu[len], object_type, instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.14 Encoding of an Object Identifier Value */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_bacnet_object_id(
|
||||
@@ -807,6 +903,34 @@ int decode_octet_string(
|
||||
return len;
|
||||
}
|
||||
|
||||
int decode_context_octet_string(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_OCTET_STRING * octet_string)
|
||||
{
|
||||
int len = 0; /* return value */
|
||||
bool status = false;
|
||||
uint32_t len_value = 0;
|
||||
|
||||
if (decode_is_context_tag(&apdu[len], tag_number))
|
||||
{
|
||||
len += decode_tag_number_and_value(&apdu[len], &tag_number,
|
||||
&len_value);
|
||||
|
||||
status = octetstring_init(octet_string, &apdu[len], len_value);
|
||||
|
||||
if (status) {
|
||||
len += len_value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.9 Encoding of a Character String Value */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_bacnet_character_string(
|
||||
@@ -889,6 +1013,35 @@ int decode_character_string(
|
||||
return len;
|
||||
}
|
||||
|
||||
int decode_context_character_string(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_CHARACTER_STRING * char_string)
|
||||
{
|
||||
int len = 0; /* return value */
|
||||
bool status = false;
|
||||
uint32_t len_value = 0;
|
||||
|
||||
if (decode_is_context_tag(&apdu[len], tag_number))
|
||||
{
|
||||
len += decode_tag_number_and_value(&apdu[len], &tag_number,
|
||||
&len_value);
|
||||
|
||||
status =
|
||||
characterstring_init(char_string, apdu[len], (char *) &apdu[len+1],
|
||||
len_value - 1);
|
||||
if (status) {
|
||||
len += len_value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
@@ -923,6 +1076,27 @@ int decode_unsigned(
|
||||
return len_value;
|
||||
}
|
||||
|
||||
int decode_context_unsigned(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint32_t * value)
|
||||
{
|
||||
uint32_t len_value;
|
||||
int len = 0;
|
||||
|
||||
if (decode_is_context_tag(&apdu[len], tag_number)) {
|
||||
len += decode_tag_number_and_value(&apdu[len], &tag_number,
|
||||
&len_value);
|
||||
len += decode_unsigned(&apdu[len], len_value, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
@@ -1002,6 +1176,27 @@ int decode_enumerated(
|
||||
return len;
|
||||
}
|
||||
|
||||
int decode_context_enumerated(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_value,
|
||||
int *value)
|
||||
{
|
||||
int len = 0;
|
||||
uint8_t tag_number;
|
||||
uint32_t len_value;
|
||||
|
||||
if (decode_is_context_tag(&apdu[len], tag_value)) {
|
||||
len += decode_tag_number_and_value(&apdu[len], &tag_number,
|
||||
&len_value);
|
||||
len += decode_enumerated(&apdu[len], len_value, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.11 Encoding of an Enumerated Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
@@ -1081,6 +1276,26 @@ int decode_signed(
|
||||
return len_value;
|
||||
}
|
||||
|
||||
int decode_context_signed(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
int32_t * value)
|
||||
{
|
||||
uint32_t len_value;
|
||||
int len = 0;
|
||||
|
||||
if (decode_is_context_tag(&apdu[len], tag_number)) {
|
||||
len += decode_tag_number_and_value(&apdu[len], &tag_number,
|
||||
&len_value);
|
||||
len += decode_signed(&apdu[len], len_value, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
@@ -1281,6 +1496,45 @@ int decode_bacnet_time(
|
||||
return 4;
|
||||
}
|
||||
|
||||
int decode_application_time(
|
||||
uint8_t * apdu,
|
||||
BACNET_TIME * btime)
|
||||
{
|
||||
int len = 0;
|
||||
uint8_t tag_number;
|
||||
decode_tag_number(&apdu[len], &tag_number);
|
||||
|
||||
if ( tag_number == BACNET_APPLICATION_TAG_TIME )
|
||||
{
|
||||
len++;
|
||||
len += decode_bacnet_time(&apdu[len], btime);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int decode_context_bacnet_time(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME * btime)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (decode_is_context_tag_with_length(&apdu[len], tag_number, &len)) {
|
||||
len += decode_bacnet_time(&apdu[len], btime);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/* BACnet Date */
|
||||
/* year = years since 1900 */
|
||||
/* month 1=Jan */
|
||||
@@ -1295,14 +1549,23 @@ int encode_bacnet_date(
|
||||
BACNET_DATE * bdate)
|
||||
{
|
||||
/* allow 2 digit years */
|
||||
if (bdate->year < 1900) {
|
||||
if (bdate->year <= 38) {
|
||||
bdate->year += 2000;
|
||||
} else {
|
||||
bdate->year += 1900;
|
||||
}
|
||||
if (bdate->year >= 1900) {
|
||||
apdu[0] = (uint8_t)(bdate->year - 1900);
|
||||
}
|
||||
apdu[0] = bdate->year - 1900;
|
||||
else if ( bdate->year < 0x100 )
|
||||
{
|
||||
apdu[0] = (uint8_t)bdate->year;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
** Don't try and guess what the user meant here. Just fail
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
apdu[1] = bdate->month;
|
||||
apdu[2] = bdate->day;
|
||||
apdu[3] = bdate->wday;
|
||||
@@ -1310,6 +1573,7 @@ int encode_bacnet_date(
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
/* from clause 20.2.12 Encoding of a Date Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
@@ -1353,7 +1617,7 @@ int decode_date(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE * bdate)
|
||||
{
|
||||
bdate->year = apdu[0] + 1900;
|
||||
bdate->year = (uint16_t)(apdu[0] + 1900);
|
||||
bdate->month = apdu[1];
|
||||
bdate->day = apdu[2];
|
||||
bdate->wday = apdu[3];
|
||||
@@ -1361,6 +1625,45 @@ int decode_date(
|
||||
return 4;
|
||||
}
|
||||
|
||||
int decode_application_date(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE * bdate)
|
||||
{
|
||||
int len = 0;
|
||||
uint8_t tag_number;
|
||||
decode_tag_number(&apdu[len], &tag_number);
|
||||
|
||||
if ( tag_number == BACNET_APPLICATION_TAG_DATE )
|
||||
{
|
||||
len++;
|
||||
len += decode_date(&apdu[len], bdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int decode_context_date(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE * bdate)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (decode_is_context_tag_with_length(&apdu[len], tag_number, &len)) {
|
||||
len += decode_date(&apdu[len], bdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_simple_ack(
|
||||
uint8_t * apdu,
|
||||
@@ -1990,6 +2293,358 @@ void testBACDCodeBitString(
|
||||
}
|
||||
}
|
||||
|
||||
void testUnsignedContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
/* 32 bit number */
|
||||
uint32_t in = 0xdeadbeef;
|
||||
uint32_t out;
|
||||
|
||||
outLen2 = decode_context_unsigned(apdu, 9, &out);
|
||||
|
||||
in = 0xdeadbeef;
|
||||
inLen = encode_context_unsigned(apdu, 10, in);
|
||||
outLen = decode_context_unsigned(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
|
||||
/* 16 bit number */
|
||||
in = 0xdead;
|
||||
inLen = encode_context_unsigned(apdu, 10, in);
|
||||
outLen = decode_context_unsigned(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 8 bit number */
|
||||
in = 0xde;
|
||||
inLen = encode_context_unsigned(apdu, 10, in);
|
||||
outLen = decode_context_unsigned(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 4 bit number */
|
||||
in = 0xd;
|
||||
inLen = encode_context_unsigned(apdu, 10, in);
|
||||
outLen = decode_context_unsigned(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 2 bit number */
|
||||
in = 0x2;
|
||||
inLen = encode_context_unsigned(apdu, 10, in);
|
||||
outLen = decode_context_unsigned(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
}
|
||||
|
||||
void testSignedContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
/* 32 bit number */
|
||||
int32_t in = 0xdeadbeef;
|
||||
int32_t out;
|
||||
|
||||
outLen2 = decode_context_signed(apdu, 9, &out);
|
||||
|
||||
in = 0xdeadbeef;
|
||||
inLen = encode_context_signed(apdu, 10, in);
|
||||
outLen = decode_context_signed(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
|
||||
/* 16 bit number */
|
||||
in = 0xdead;
|
||||
inLen = encode_context_signed(apdu, 10, in);
|
||||
outLen = decode_context_signed(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 8 bit number */
|
||||
in = 0xde;
|
||||
inLen = encode_context_signed(apdu, 10, in);
|
||||
outLen = decode_context_signed(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 4 bit number */
|
||||
in = 0xd;
|
||||
inLen = encode_context_signed(apdu, 10, in);
|
||||
outLen = decode_context_signed(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 2 bit number */
|
||||
in = 0x2;
|
||||
inLen = encode_context_signed(apdu, 10, in);
|
||||
outLen = decode_context_signed(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
}
|
||||
|
||||
void testEnumeratedContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
/* 32 bit number */
|
||||
int32_t in = 0xdeadbeef;
|
||||
int32_t out;
|
||||
|
||||
outLen2 = decode_context_enumerated(apdu, 9, &out);
|
||||
|
||||
in = 0xdeadbeef;
|
||||
inLen = encode_context_enumerated(apdu, 10, in);
|
||||
outLen = decode_context_enumerated(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
|
||||
/* 16 bit number */
|
||||
in = 0xdead;
|
||||
inLen = encode_context_enumerated(apdu, 10, in);
|
||||
outLen = decode_context_enumerated(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 8 bit number */
|
||||
in = 0xde;
|
||||
inLen = encode_context_enumerated(apdu, 10, in);
|
||||
outLen = decode_context_enumerated(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 4 bit number */
|
||||
in = 0xd;
|
||||
inLen = encode_context_enumerated(apdu, 10, in);
|
||||
outLen = decode_context_enumerated(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
|
||||
/* 2 bit number */
|
||||
in = 0x2;
|
||||
inLen = encode_context_enumerated(apdu, 10, in);
|
||||
outLen = decode_context_enumerated(apdu, 10, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
}
|
||||
|
||||
void testFloatContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
/* 32 bit number */
|
||||
float in;
|
||||
float out;
|
||||
|
||||
|
||||
in = 0.1234f;
|
||||
inLen = encode_context_real(apdu, 10, in);
|
||||
outLen = decode_context_real(apdu, 10, &out);
|
||||
outLen2 = decode_context_real(apdu, 9, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
|
||||
in = 0.0f;
|
||||
inLen = encode_context_real(apdu, 10, in);
|
||||
outLen = decode_context_real(apdu, 10, &out);
|
||||
outLen2 = decode_context_real(apdu, 9, &out);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in == out);
|
||||
}
|
||||
|
||||
void testObjectIDContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
/* 32 bit number */
|
||||
uint16_t in_type;
|
||||
uint32_t in_id;
|
||||
|
||||
uint16_t out_type;
|
||||
uint32_t out_id;
|
||||
|
||||
in_type = 0xde;
|
||||
in_id = 0xbeef;
|
||||
|
||||
inLen = encode_context_object_id(apdu, 10, in_type, in_id);
|
||||
outLen = decode_context_object_id(apdu, 10, &out_type, &out_id);
|
||||
outLen2 = decode_context_object_id(apdu, 9, &out_type, &out_id);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in_type == out_type);
|
||||
ct_test(pTest, in_id == out_id);
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
|
||||
}
|
||||
|
||||
void testCharacterStringContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
BACNET_CHARACTER_STRING in;
|
||||
BACNET_CHARACTER_STRING out;
|
||||
|
||||
characterstring_init_ansi(&in, "This is a test");
|
||||
|
||||
inLen = encode_context_character_string(apdu, 10, &in);
|
||||
outLen= decode_context_character_string(apdu, 10, &out);
|
||||
outLen2= decode_context_character_string(apdu, 9, &out);
|
||||
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in.length == out.length);
|
||||
ct_test(pTest, in.encoding == out.encoding);
|
||||
ct_test(pTest, strcmp(in.value, out.value) == 0);
|
||||
}
|
||||
|
||||
void testBitStringContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
BACNET_BIT_STRING in;
|
||||
BACNET_BIT_STRING out;
|
||||
|
||||
bitstring_init(&in);
|
||||
bitstring_set_bit(&in, 1, true);
|
||||
bitstring_set_bit(&in, 3, true);
|
||||
bitstring_set_bit(&in, 6, true);
|
||||
bitstring_set_bit(&in, 10, false);
|
||||
bitstring_set_bit(&in, 11, true);
|
||||
bitstring_set_bit(&in, 12, false);
|
||||
|
||||
inLen = encode_context_bitstring(apdu, 10, &in);
|
||||
outLen= decode_context_bitstring(apdu, 10, &out);
|
||||
outLen2= decode_context_bitstring(apdu, 9, &out);
|
||||
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in.bits_used == out.bits_used);
|
||||
ct_test(pTest, memcmp(in.value, out.value, MAX_BITSTRING_BYTES) == 0);
|
||||
|
||||
}
|
||||
|
||||
void testOctetStringContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
BACNET_OCTET_STRING in;
|
||||
BACNET_OCTET_STRING out;
|
||||
|
||||
uint8_t initData[] = {0xde,0xad,0xbe,0xef};
|
||||
|
||||
octetstring_init(&in, initData, sizeof(initData));
|
||||
|
||||
inLen = encode_context_octet_string(apdu, 10, &in);
|
||||
outLen= decode_context_octet_string(apdu, 10, &out);
|
||||
outLen2= decode_context_octet_string(apdu, 9, &out);
|
||||
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in.length == out.length);
|
||||
ct_test(pTest, memcmp(in.value, out.value, MAX_APDU - 6) == 0);
|
||||
|
||||
}
|
||||
|
||||
void testTimeContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
BACNET_TIME in;
|
||||
BACNET_TIME out;
|
||||
|
||||
in.hour = 10;
|
||||
in.hundredths = 20;
|
||||
in.min = 30;
|
||||
in.sec = 40;
|
||||
|
||||
inLen = encode_context_time(apdu, 10, &in);
|
||||
outLen= decode_context_bacnet_time(apdu, 10, &out);
|
||||
outLen2= decode_context_bacnet_time(apdu, 9, &out);
|
||||
|
||||
ct_test(pTest, outLen2 == -1);
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, in.hour == out.hour);
|
||||
ct_test(pTest, in.hundredths == out.hundredths);
|
||||
ct_test(pTest, in.min == out.min);
|
||||
ct_test(pTest, in.sec == out.sec);
|
||||
}
|
||||
|
||||
void testDateContextDecodes(Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
int outLen2;
|
||||
|
||||
BACNET_DATE in;
|
||||
BACNET_DATE out;
|
||||
|
||||
in.day = 3;
|
||||
in.month = 10;
|
||||
in.wday = 5;
|
||||
in.year = 1945;
|
||||
|
||||
inLen = encode_context_date(apdu, 10, &in);
|
||||
outLen= decode_context_date(apdu, 10, &out);
|
||||
outLen2= decode_context_date(apdu, 9, &out);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_DECODE
|
||||
int main(
|
||||
void)
|
||||
@@ -2023,6 +2678,37 @@ int main(
|
||||
assert(rc);
|
||||
rc = ct_addTestFunction(pTest, testBACDCodeBitString);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testUnsignedContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testSignedContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testEnumeratedContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testCharacterStringContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testFloatContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testObjectIDContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testBitStringContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testTimeContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testDateContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testOctetStringContextDecodes);
|
||||
assert(rc);
|
||||
|
||||
/* configure output */
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
#include <assert.h>
|
||||
#include "bacdcode.h"
|
||||
#include "npdu.h"
|
||||
#include "device.h"
|
||||
#include "datalink.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacdevobjpropref.h"
|
||||
|
||||
int bacapp_encode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_encode_device_obj_property_ref(&apdu[apdu_len], value);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_encode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len = encode_context_object_id(&apdu[apdu_len], 0,
|
||||
value->objectIdentifier.type,
|
||||
value->objectIdentifier.instance);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_context_enumerated(&apdu[apdu_len], 1,
|
||||
value->propertyIdentifier);
|
||||
apdu_len += len;
|
||||
|
||||
if ( value->arrayIndex > 0 )
|
||||
{
|
||||
len = encode_context_unsigned(&apdu[apdu_len], 2,
|
||||
value->arrayIndex);
|
||||
apdu_len += len;
|
||||
}
|
||||
len = encode_context_object_id(&apdu[apdu_len], 3,
|
||||
value->deviceIndentifier.type,
|
||||
value->deviceIndentifier.instance);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
if ( -1 == ( len = decode_context_object_id(&apdu[apdu_len], 0,
|
||||
&value->objectIdentifier.type,
|
||||
&value->objectIdentifier.instance)) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
if ( -1 == ( len = decode_context_enumerated(&apdu[apdu_len], 1,
|
||||
&value->propertyIdentifier)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
if ( decode_is_context_tag(&apdu[apdu_len], 2 ))
|
||||
{
|
||||
if ( -1 == ( len = decode_context_unsigned(&apdu[apdu_len], 2,
|
||||
&value->arrayIndex)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
value->arrayIndex = 0;
|
||||
}
|
||||
|
||||
if ( decode_is_context_tag(&apdu[apdu_len], 3 ))
|
||||
{
|
||||
if ( -1 == ( len = decode_context_object_id(&apdu[apdu_len], 3,
|
||||
&value->deviceIndentifier.type,
|
||||
&value->deviceIndentifier.instance)) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
value->deviceIndentifier.instance = 0;
|
||||
value->deviceIndentifier.type = 0;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_length;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
section_length = bacapp_decode_device_obj_property_ref(
|
||||
&apdu[len], value);
|
||||
|
||||
if ( section_length == -1 )
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += section_length;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void testDevIdPropRef(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE inData;
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE outData;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
|
||||
inData.objectIdentifier.instance = 0x1234;
|
||||
inData.objectIdentifier.type = 15;
|
||||
|
||||
inData.propertyIdentifier = 25;
|
||||
|
||||
inData.arrayIndex = 0x5678;
|
||||
|
||||
inData.deviceIndentifier.instance = 0x4343;
|
||||
inData.deviceIndentifier.type = 28;
|
||||
|
||||
inLen = bacapp_encode_device_obj_property_ref(buffer, &inData);
|
||||
outLen = bacapp_decode_device_obj_property_ref(buffer, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
|
||||
ct_test(pTest, inData.objectIdentifier.instance == outData.objectIdentifier.instance);
|
||||
ct_test(pTest, inData.objectIdentifier.type == outData.objectIdentifier.type);
|
||||
|
||||
ct_test(pTest, inData.propertyIdentifier == outData.propertyIdentifier);
|
||||
|
||||
ct_test(pTest, inData.arrayIndex == outData.arrayIndex);
|
||||
|
||||
ct_test(pTest, inData.deviceIndentifier.instance == outData.deviceIndentifier.instance);
|
||||
ct_test(pTest, inData.deviceIndentifier.type == outData.deviceIndentifier.type);
|
||||
}
|
||||
#ifdef TEST_DEV_ID_PROP_REF
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Prop Ref", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testDevIdPropRef);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_DEV_ID_PROP_REF
|
||||
#endif // TEST
|
||||
@@ -0,0 +1,369 @@
|
||||
#include <assert.h>
|
||||
#include "bacdcode.h"
|
||||
#include "npdu.h"
|
||||
#include "device.h"
|
||||
#include "datalink.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacpropstates.h"
|
||||
|
||||
int bacapp_decode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0;
|
||||
uint32_t len_value_type;
|
||||
int section_length;
|
||||
|
||||
|
||||
section_length =
|
||||
decode_tag_number_and_value(&apdu[len], (uint8_t*)&value->tag,
|
||||
&len_value_type);
|
||||
|
||||
if ( -1 == section_length )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
len += section_length;
|
||||
switch(value->tag)
|
||||
{
|
||||
case BOOLEAN_VALUE:
|
||||
value->state.booleanValue = decode_boolean(len_value_type);
|
||||
break;
|
||||
|
||||
case BINARY_VALUE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.binaryValue)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_TYPE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.eventType)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLARITY:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.polarity)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programChange)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROGRAM_STATE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programState)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case REASON_FOR_HALT:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programError)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case RELIABILITY:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.reliability)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.state)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSTEM_STATUS:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.systemStatus)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNITS:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.units)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNSIGNED_VALUE:
|
||||
if ( -1 == ( section_length = decode_unsigned(&apdu[len], len_value_type, &value->state.unsignedValue)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_MODE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.lifeSafetyMode)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_STATE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.lifeSafetyState)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
len += section_length;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_property_state(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_length;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
section_length = bacapp_decode_property_state(
|
||||
&apdu[len], value);
|
||||
|
||||
if ( section_length == -1 )
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += section_length;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_encode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0; /* length of each encoding */
|
||||
if (value && apdu) {
|
||||
switch(value->tag)
|
||||
{
|
||||
case BOOLEAN_VALUE:
|
||||
len = encode_context_boolean(&apdu[0], 0, value->state.booleanValue);
|
||||
break;
|
||||
|
||||
case BINARY_VALUE:
|
||||
len = encode_context_enumerated(&apdu[0], 1, value->state.binaryValue);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE:
|
||||
len = encode_context_enumerated(&apdu[0], 2, value->state.eventType);
|
||||
break;
|
||||
|
||||
case POLARITY:
|
||||
len = encode_context_enumerated(&apdu[0], 3, value->state.polarity);
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
len = encode_context_enumerated(&apdu[0], 4, value->state.programChange);
|
||||
break;
|
||||
|
||||
case PROGRAM_STATE:
|
||||
len = encode_context_enumerated(&apdu[0], 5, value->state.programState);
|
||||
break;
|
||||
|
||||
case REASON_FOR_HALT:
|
||||
len = encode_context_enumerated(&apdu[0], 6, value->state.programError);
|
||||
break;
|
||||
|
||||
case RELIABILITY:
|
||||
len = encode_context_enumerated(&apdu[0], 7, value->state.reliability);
|
||||
break;
|
||||
|
||||
case STATE:
|
||||
len = encode_context_enumerated(&apdu[0], 8, value->state.state);
|
||||
break;
|
||||
|
||||
case SYSTEM_STATUS:
|
||||
len = encode_context_enumerated(&apdu[0], 9, value->state.systemStatus);
|
||||
break;
|
||||
|
||||
case UNITS:
|
||||
len = encode_context_enumerated(&apdu[0], 10, value->state.units);
|
||||
break;
|
||||
|
||||
case UNSIGNED_VALUE:
|
||||
len = encode_context_unsigned(&apdu[0], 11, value->state.unsignedValue);
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_MODE:
|
||||
len = encode_context_enumerated(&apdu[0], 12, value->state.lifeSafetyMode);
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_STATE:
|
||||
len = encode_context_enumerated(&apdu[0], 13, value->state.lifeSafetyState);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void testPropStates(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_PROPERTY_STATE inData;
|
||||
BACNET_PROPERTY_STATE outData;
|
||||
uint8_t appMsg[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
inData.tag = BOOLEAN_VALUE;
|
||||
inData.state.booleanValue = true;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.booleanValue == outData.state.booleanValue );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = BINARY_VALUE;
|
||||
inData.state.binaryValue = BINARY_ACTIVE;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.binaryValue == outData.state.binaryValue );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = EVENT_TYPE;
|
||||
inData.state.eventType = EVENT_BUFFER_READY;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.eventType == outData.state.eventType );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = POLARITY;
|
||||
inData.state.polarity = POLARITY_REVERSE;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.polarity == outData.state.polarity );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = PROGRAM_CHANGE;
|
||||
inData.state.programChange = PROGRAM_REQUEST_RESTART;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.programChange == outData.state.programChange );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = UNSIGNED_VALUE;
|
||||
inData.state.unsignedValue = 0xdeadbeef;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.unsignedValue == outData.state.unsignedValue );
|
||||
|
||||
}
|
||||
|
||||
#ifdef TEST_PROP_STATES
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Event", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testPropStates);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_PROP_STATES
|
||||
#endif // TEST
|
||||
@@ -76,6 +76,25 @@ int decode_real(
|
||||
return 4;
|
||||
}
|
||||
|
||||
int decode_context_real(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
float *real_value)
|
||||
{
|
||||
uint32_t len_value;
|
||||
int len = 0;
|
||||
|
||||
if (decode_is_context_tag(&apdu[len], tag_number)) {
|
||||
len += decode_tag_number_and_value(&apdu[len], &tag_number,
|
||||
&len_value);
|
||||
len += decode_real(&apdu[len], real_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
/* from clause 20.2.6 Encoding of a Real Number Value */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_bacnet_real(
|
||||
|
||||
@@ -96,10 +96,10 @@ uint8_t bitstring_bits_used(
|
||||
}
|
||||
|
||||
/* returns the number of bytes that a bit string is using */
|
||||
int bitstring_bytes_used(
|
||||
uint8_t bitstring_bytes_used(
|
||||
BACNET_BIT_STRING * bit_string)
|
||||
{
|
||||
int len = 0; /* return value */
|
||||
uint8_t len = 0; /* return value */
|
||||
uint8_t used_bytes = 0;
|
||||
uint8_t last_bit = 0;
|
||||
|
||||
|
||||
+134
-3
@@ -38,6 +38,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "datetime.h"
|
||||
#include "bacdcode.h"
|
||||
|
||||
/* BACnet Date */
|
||||
/* year = years since 1900 */
|
||||
@@ -52,6 +53,7 @@
|
||||
time or date may be interpreted as "any" or "don't care"
|
||||
*/
|
||||
|
||||
|
||||
static bool is_leap_year(
|
||||
uint16_t year)
|
||||
{
|
||||
@@ -73,7 +75,7 @@ static uint8_t month_days(
|
||||
if ((month == 2) && is_leap_year(year))
|
||||
return 29;
|
||||
else if (month >= 1 && month <= 12)
|
||||
return month_days[month];
|
||||
return (uint8_t)month_days[month];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@@ -128,7 +130,7 @@ static void days_since_epoch_into_ymd(
|
||||
month++;
|
||||
}
|
||||
|
||||
day += ((uint8_t) days);
|
||||
day = (uint8_t) (day + days);
|
||||
|
||||
if (pYear)
|
||||
*pYear = year;
|
||||
@@ -148,7 +150,7 @@ static uint8_t day_of_week(
|
||||
uint8_t month,
|
||||
uint8_t day)
|
||||
{
|
||||
return ((uint8_t) (days_since_epoch(year, month, day) % 7) + 1);
|
||||
return (uint8_t) ((days_since_epoch(year, month, day) % 7) + 1);
|
||||
}
|
||||
|
||||
/* if the date1 is the same as date2, return is 0
|
||||
@@ -428,6 +430,93 @@ void datetime_wildcard_set(
|
||||
}
|
||||
}
|
||||
|
||||
int bacapp_encode_context_datetime(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
|
||||
|
||||
if ( apdu && value )
|
||||
{
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_application_date(&apdu[apdu_len], &value->date);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_application_time(&apdu[apdu_len], &value->time);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_datetime(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE_TIME * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_len;
|
||||
|
||||
if ( -1 == ( section_len = decode_application_date(&apdu[len], &value->date) ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
len += section_len;
|
||||
|
||||
if ( -1 == ( section_len = decode_application_time(&apdu[len], &value->time) ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
len += section_len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_datetime(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( -1 == (len = bacapp_decode_datetime(&apdu[apdu_len], value)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
if (decode_is_closing_tag_number(&apdu[apdu_len], tag_number))
|
||||
{
|
||||
apdu_len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
@@ -744,6 +833,43 @@ void testBACnetDayOfWeek(
|
||||
ct_test(pTest, dow == 3);
|
||||
}
|
||||
|
||||
void testDatetimeCodec(
|
||||
Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
BACNET_DATE_TIME datetimeIn;
|
||||
BACNET_DATE_TIME datetimeOut;
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
datetimeIn.date.day = 1;
|
||||
datetimeIn.date.month = 2;
|
||||
datetimeIn.date.wday = 3;
|
||||
datetimeIn.date.year = 1904;
|
||||
|
||||
datetimeIn.time.hour = 5;
|
||||
datetimeIn.time.min = 6;
|
||||
datetimeIn.time.sec = 7;
|
||||
datetimeIn.time.hundredths = 8;
|
||||
|
||||
inLen = bacapp_encode_context_datetime(apdu, 10, &datetimeIn);
|
||||
outLen = bacapp_decode_context_datetime(apdu, 10, &datetimeOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen );
|
||||
|
||||
ct_test(pTest, datetimeIn.date.day == datetimeOut.date.day);
|
||||
ct_test(pTest, datetimeIn.date.month == datetimeOut.date.month);
|
||||
ct_test(pTest, datetimeIn.date.wday == datetimeOut.date.wday);
|
||||
ct_test(pTest, datetimeIn.date.year == datetimeOut.date.year);
|
||||
|
||||
ct_test(pTest, datetimeIn.time.hour == datetimeOut.time.hour);
|
||||
ct_test(pTest, datetimeIn.time.min == datetimeOut.time.min);
|
||||
ct_test(pTest, datetimeIn.time.sec == datetimeOut.time.sec);
|
||||
ct_test(pTest, datetimeIn.time.hundredths == datetimeOut.time.hundredths);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_DATE_TIME
|
||||
int main(
|
||||
void)
|
||||
@@ -769,6 +895,8 @@ int main(
|
||||
assert(rc);
|
||||
rc = ct_addTestFunction(pTest, testBACnetDateTimeWildcard);
|
||||
assert(rc);
|
||||
rc = ct_addTestFunction(pTest, testDatetimeCodec);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
@@ -777,5 +905,8 @@ int main(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* TEST_DATE_TIME */
|
||||
#endif /* TEST */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,249 @@
|
||||
#include "assert.h"
|
||||
#include "timestamp.h"
|
||||
|
||||
int bacapp_encode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value)
|
||||
{
|
||||
int len = 0; /* length of each encoding */
|
||||
int apdu_len = 0;
|
||||
|
||||
if (value && apdu) {
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
switch(value->tag)
|
||||
{
|
||||
case TIME_STAMP_TIME:
|
||||
len = encode_context_time(&apdu[apdu_len], 0, &value->value.time);
|
||||
break;
|
||||
|
||||
case TIME_STAMP_SEQUENCE:
|
||||
len = encode_context_unsigned(&apdu[apdu_len], 1, value->value.sequenceNum);
|
||||
break;
|
||||
|
||||
case TIME_STAMP_DATETIME:
|
||||
len = bacapp_encode_context_datetime(&apdu[apdu_len], 2, &value->value.dateTime);
|
||||
break;
|
||||
|
||||
default:
|
||||
len = 0;
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_len;
|
||||
uint32_t len_value_type;
|
||||
uint32_t sequenceNum;
|
||||
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
|
||||
section_len =
|
||||
decode_tag_number_and_value(&apdu[len], &value->tag,
|
||||
&len_value_type);
|
||||
|
||||
if ( -1 == section_len )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
switch( value->tag )
|
||||
{
|
||||
case TIME_STAMP_TIME:
|
||||
if ( (section_len = decode_context_bacnet_time(&apdu[len], TIME_STAMP_TIME, &value->value.time)) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += section_len;
|
||||
}
|
||||
break;
|
||||
|
||||
case TIME_STAMP_SEQUENCE:
|
||||
if ( (section_len = decode_context_unsigned(&apdu[len], TIME_STAMP_SEQUENCE, &sequenceNum)) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sequenceNum <= 0xffff )
|
||||
{
|
||||
len += section_len;
|
||||
value->value.sequenceNum = (uint16_t)sequenceNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TIME_STAMP_DATETIME:
|
||||
if ( (section_len = bacapp_decode_context_datetime(&apdu[len], TIME_STAMP_DATETIME, &value->value.dateTime)) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += section_len;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
|
||||
void testTimestampSequence(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_SEQUENCE;
|
||||
testTimestampIn.value.sequenceNum = 0x1234;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest, testTimestampIn.value.sequenceNum == testTimestampOut.value.sequenceNum);
|
||||
}
|
||||
|
||||
void testTimestampTime(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_TIME;
|
||||
testTimestampIn.value.time.hour = 1;
|
||||
testTimestampIn.value.time.min = 2;
|
||||
testTimestampIn.value.time.sec = 3;
|
||||
testTimestampIn.value.time.hundredths = 4;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest, testTimestampIn.value.time.hour == testTimestampOut.value.time.hour);
|
||||
ct_test(pTest, testTimestampIn.value.time.min == testTimestampOut.value.time.min);
|
||||
ct_test(pTest, testTimestampIn.value.time.sec == testTimestampOut.value.time.sec);
|
||||
ct_test(pTest, testTimestampIn.value.time.hundredths == testTimestampOut.value.time.hundredths);
|
||||
}
|
||||
|
||||
void testTimestampTimeDate(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_DATETIME;
|
||||
testTimestampIn.value.dateTime.time.hour = 1;
|
||||
testTimestampIn.value.dateTime.time.min = 2;
|
||||
testTimestampIn.value.dateTime.time.sec = 3;
|
||||
testTimestampIn.value.dateTime.time.hundredths = 4;
|
||||
|
||||
testTimestampIn.value.dateTime.date.year = 1901;
|
||||
testTimestampIn.value.dateTime.date.month = 1;
|
||||
testTimestampIn.value.dateTime.date.wday = 2;
|
||||
testTimestampIn.value.dateTime.date.day = 3;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.time.hour == testTimestampOut.value.dateTime.time.hour);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.time.min == testTimestampOut.value.dateTime.time.min);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.time.sec == testTimestampOut.value.dateTime.time.sec);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.time.hundredths == testTimestampOut.value.dateTime.time.hundredths);
|
||||
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.date.year == testTimestampOut.value.dateTime.date.year);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.date.month == testTimestampOut.value.dateTime.date.month);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.date.wday == testTimestampOut.value.dateTime.date.wday);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.date.day == testTimestampOut.value.dateTime.date.day);
|
||||
|
||||
}
|
||||
|
||||
#ifdef TEST_TIME_STAMP
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Time Stamp", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testTimestampSequence);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testTimestampTime);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testTimestampTimeDate);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_TIME_STAMP
|
||||
#endif // TEST
|
||||
|
||||
Reference in New Issue
Block a user