Feature/apdu null length returned (#285)
* Add APDU as NULL to get BACnet type lengths. * Fix bacapp copy test to succeed * fix BACnet REAL and DOUBLE decode * Add unit test for NULL APDU encoding for length * Add unit tests for bacapp context * refactor host-n-port to hostnport.c module * fix BVLC decoder * additional unit testing for bacapp * include bacdevobjpropref module in builds * simplify bacapp snprintf to be able to return length * adjust compiler for variable-length arrays * fix bug found by scan-build Authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
+498
-887
File diff suppressed because it is too large
Load Diff
+32
-36
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*********************************************************************/
|
||||
#ifndef BACAPP_H
|
||||
#define BACAPP_H
|
||||
|
||||
@@ -32,15 +32,9 @@
|
||||
#include "bacnet/bacint.h"
|
||||
#include "bacnet/bacstr.h"
|
||||
#include "bacnet/datetime.h"
|
||||
#if defined (BACAPP_LIGHTING_COMMAND)
|
||||
#include "bacnet/lighting.h"
|
||||
#endif
|
||||
#if defined (BACAPP_DEVICE_OBJECT_PROP_REF)
|
||||
#include "bacnet/bacdevobjpropref.h"
|
||||
#endif
|
||||
#if defined(BACAPP_HOST_N_PORT)
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
#endif
|
||||
#include "bacnet/hostnport.h"
|
||||
|
||||
struct BACnet_Application_Data_Value;
|
||||
typedef struct BACnet_Application_Data_Value {
|
||||
@@ -85,13 +79,9 @@ typedef struct BACnet_Application_Data_Value {
|
||||
#if defined (BACAPP_OBJECT_ID)
|
||||
BACNET_OBJECT_ID Object_Id;
|
||||
#endif
|
||||
#if defined (BACAPP_LIGHTING_COMMAND)
|
||||
#if defined (BACAPP_TYPES_EXTRA)
|
||||
BACNET_LIGHTING_COMMAND Lighting_Command;
|
||||
#endif
|
||||
#if defined(BACAPP_HOST_N_PORT)
|
||||
BACNET_IP_ADDRESS IP_Address;
|
||||
#endif
|
||||
#if defined (BACAPP_DEVICE_OBJECT_PROP_REF)
|
||||
BACNET_HOST_N_PORT Host_Address;
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE
|
||||
Device_Object_Property_Reference;
|
||||
#endif
|
||||
@@ -204,6 +194,13 @@ extern "C" {
|
||||
BACNET_PROPERTY_ID property,
|
||||
uint8_t tag_number);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacapp_decode_generic_property(
|
||||
uint8_t * apdu,
|
||||
int max_apdu_len,
|
||||
BACNET_APPLICATION_DATA_VALUE * value,
|
||||
BACNET_PROPERTY_ID prop);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool bacapp_copy(
|
||||
BACNET_APPLICATION_DATA_VALUE * dest_value,
|
||||
@@ -238,7 +235,6 @@ extern "C" {
|
||||
#define BACAPP_PRINT_ENABLED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacapp_snprintf_value(
|
||||
char *str,
|
||||
|
||||
+624
-297
File diff suppressed because it is too large
Load Diff
+28
-22
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*********************************************************************/
|
||||
#ifndef BACDCODE_H
|
||||
#define BACDCODE_H
|
||||
|
||||
@@ -215,10 +215,16 @@ extern "C" {
|
||||
uint8_t * apdu,
|
||||
BACNET_OBJECT_TYPE * object_type,
|
||||
uint32_t * object_instance);
|
||||
int decode_object_id_safe(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
BACNET_OBJECT_TYPE * object_type,
|
||||
uint32_t * object_instance);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_object_id_decode(
|
||||
uint8_t * apdu,
|
||||
uint16_t apdu_len_max,
|
||||
uint32_t len_value,
|
||||
BACNET_OBJECT_TYPE * object_type,
|
||||
uint32_t * instance);
|
||||
|
||||
+100
-55
@@ -43,15 +43,17 @@
|
||||
|
||||
int encode_unsigned16(uint8_t *apdu, uint16_t value)
|
||||
{
|
||||
apdu[0] = (uint8_t)((value & 0xff00) >> 8);
|
||||
apdu[1] = (uint8_t)(value & 0x00ff);
|
||||
if (apdu) {
|
||||
apdu[0] = (uint8_t)((value & 0xff00) >> 8);
|
||||
apdu[1] = (uint8_t)(value & 0x00ff);
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int decode_unsigned16(uint8_t *apdu, uint16_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (apdu && value) {
|
||||
*value = (uint16_t)((((uint16_t)apdu[0]) << 8) & 0xff00);
|
||||
*value |= ((uint16_t)(((uint16_t)apdu[1]) & 0x00ff));
|
||||
}
|
||||
@@ -61,16 +63,18 @@ int decode_unsigned16(uint8_t *apdu, uint16_t *value)
|
||||
|
||||
int encode_unsigned24(uint8_t *apdu, uint32_t value)
|
||||
{
|
||||
apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
|
||||
apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
|
||||
apdu[2] = (uint8_t)(value & 0x0000ff);
|
||||
if (apdu) {
|
||||
apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
|
||||
apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
|
||||
apdu[2] = (uint8_t)(value & 0x0000ff);
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int decode_unsigned24(uint8_t *apdu, uint32_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (apdu && value) {
|
||||
*value = ((uint32_t)((((uint32_t)apdu[0]) << 16) & 0x00ff0000));
|
||||
*value |= (uint32_t)((((uint32_t)apdu[1]) << 8) & 0x0000ff00);
|
||||
*value |= ((uint32_t)(((uint32_t)apdu[2]) & 0x000000ff));
|
||||
@@ -81,17 +85,19 @@ int decode_unsigned24(uint8_t *apdu, uint32_t *value)
|
||||
|
||||
int encode_unsigned32(uint8_t *apdu, uint32_t value)
|
||||
{
|
||||
apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
|
||||
apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
|
||||
apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
|
||||
apdu[3] = (uint8_t)(value & 0x000000ff);
|
||||
if (apdu) {
|
||||
apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
|
||||
apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
|
||||
apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
|
||||
apdu[3] = (uint8_t)(value & 0x000000ff);
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int decode_unsigned32(uint8_t *apdu, uint32_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (apdu && value) {
|
||||
*value = ((uint32_t)((((uint32_t)apdu[0]) << 24) & 0xff000000));
|
||||
*value |= ((uint32_t)((((uint32_t)apdu[1]) << 16) & 0x00ff0000));
|
||||
*value |= ((uint32_t)((((uint32_t)apdu[2]) << 8) & 0x0000ff00));
|
||||
@@ -110,11 +116,13 @@ int decode_unsigned32(uint8_t *apdu, uint32_t *value)
|
||||
*/
|
||||
int encode_unsigned40(uint8_t *buffer, uint64_t value)
|
||||
{
|
||||
buffer[0] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
|
||||
buffer[1] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
|
||||
buffer[2] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
|
||||
buffer[3] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
|
||||
buffer[4] = (uint8_t)(value & 0x00000000000000ffULL);
|
||||
if (buffer) {
|
||||
buffer[0] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
|
||||
buffer[1] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
|
||||
buffer[2] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
|
||||
buffer[3] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
|
||||
buffer[4] = (uint8_t)(value & 0x00000000000000ffULL);
|
||||
}
|
||||
|
||||
return 5;
|
||||
}
|
||||
@@ -127,7 +135,7 @@ int encode_unsigned40(uint8_t *buffer, uint64_t value)
|
||||
*/
|
||||
int decode_unsigned40(uint8_t *buffer, uint64_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (buffer && value) {
|
||||
*value =
|
||||
((uint64_t)((((uint64_t)buffer[0]) << 32) & 0x000000ff00000000ULL));
|
||||
*value |=
|
||||
@@ -150,12 +158,14 @@ int decode_unsigned40(uint8_t *buffer, uint64_t *value)
|
||||
*/
|
||||
int encode_unsigned48(uint8_t *buffer, uint64_t value)
|
||||
{
|
||||
buffer[0] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
|
||||
buffer[1] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
|
||||
buffer[2] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
|
||||
buffer[3] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
|
||||
buffer[4] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
|
||||
buffer[5] = (uint8_t)(value & 0x00000000000000ffULL);
|
||||
if (buffer) {
|
||||
buffer[0] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
|
||||
buffer[1] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
|
||||
buffer[2] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
|
||||
buffer[3] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
|
||||
buffer[4] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
|
||||
buffer[5] = (uint8_t)(value & 0x00000000000000ffULL);
|
||||
}
|
||||
|
||||
return 6;
|
||||
}
|
||||
@@ -168,7 +178,7 @@ int encode_unsigned48(uint8_t *buffer, uint64_t value)
|
||||
*/
|
||||
int decode_unsigned48(uint8_t *buffer, uint64_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (buffer && value) {
|
||||
*value =
|
||||
((uint64_t)((((uint64_t)buffer[0]) << 40) & 0x0000ff0000000000ULL));
|
||||
*value |=
|
||||
@@ -193,13 +203,15 @@ int decode_unsigned48(uint8_t *buffer, uint64_t *value)
|
||||
*/
|
||||
int encode_unsigned56(uint8_t *buffer, uint64_t value)
|
||||
{
|
||||
buffer[0] = (uint8_t)((value & 0x00ff000000000000ULL) >> 48);
|
||||
buffer[1] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
|
||||
buffer[2] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
|
||||
buffer[3] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
|
||||
buffer[4] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
|
||||
buffer[5] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
|
||||
buffer[6] = (uint8_t)(value & 0x00000000000000ffULL);
|
||||
if (buffer) {
|
||||
buffer[0] = (uint8_t)((value & 0x00ff000000000000ULL) >> 48);
|
||||
buffer[1] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
|
||||
buffer[2] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
|
||||
buffer[3] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
|
||||
buffer[4] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
|
||||
buffer[5] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
|
||||
buffer[6] = (uint8_t)(value & 0x00000000000000ffULL);
|
||||
}
|
||||
|
||||
return 7;
|
||||
}
|
||||
@@ -212,7 +224,7 @@ int encode_unsigned56(uint8_t *buffer, uint64_t value)
|
||||
*/
|
||||
int decode_unsigned56(uint8_t *buffer, uint64_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (buffer && value) {
|
||||
*value =
|
||||
((uint64_t)((((uint64_t)buffer[0]) << 48) & 0x00ff000000000000ULL));
|
||||
*value |=
|
||||
@@ -239,14 +251,16 @@ int decode_unsigned56(uint8_t *buffer, uint64_t *value)
|
||||
*/
|
||||
int encode_unsigned64(uint8_t *buffer, uint64_t value)
|
||||
{
|
||||
buffer[0] = (uint8_t)((value & 0xff00000000000000ULL) >> 56);
|
||||
buffer[1] = (uint8_t)((value & 0x00ff000000000000ULL) >> 48);
|
||||
buffer[2] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
|
||||
buffer[3] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
|
||||
buffer[4] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
|
||||
buffer[5] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
|
||||
buffer[6] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
|
||||
buffer[7] = (uint8_t)(value & 0x00000000000000ffULL);
|
||||
if (buffer) {
|
||||
buffer[0] = (uint8_t)((value & 0xff00000000000000ULL) >> 56);
|
||||
buffer[1] = (uint8_t)((value & 0x00ff000000000000ULL) >> 48);
|
||||
buffer[2] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
|
||||
buffer[3] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
|
||||
buffer[4] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
|
||||
buffer[5] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
|
||||
buffer[6] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
|
||||
buffer[7] = (uint8_t)(value & 0x00000000000000ffULL);
|
||||
}
|
||||
|
||||
return 8;
|
||||
}
|
||||
@@ -259,7 +273,7 @@ int encode_unsigned64(uint8_t *buffer, uint64_t value)
|
||||
*/
|
||||
int decode_unsigned64(uint8_t *buffer, uint64_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (buffer && value) {
|
||||
*value =
|
||||
((uint64_t)((((uint64_t)buffer[0]) << 56) & 0xff00000000000000ULL));
|
||||
*value |=
|
||||
@@ -320,14 +334,16 @@ int bacnet_unsigned_length(BACNET_UNSIGNED_INTEGER value)
|
||||
#if BACNET_USE_SIGNED
|
||||
int encode_signed8(uint8_t *apdu, int8_t value)
|
||||
{
|
||||
apdu[0] = (uint8_t)value;
|
||||
if (apdu) {
|
||||
apdu[0] = (uint8_t)value;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int decode_signed8(uint8_t *apdu, int32_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (apdu && value) {
|
||||
/* negative - bit 7 is set */
|
||||
if (apdu[0] & 0x80) {
|
||||
*value = 0xFFFFFF00;
|
||||
@@ -342,15 +358,17 @@ int decode_signed8(uint8_t *apdu, int32_t *value)
|
||||
|
||||
int encode_signed16(uint8_t *apdu, int16_t value)
|
||||
{
|
||||
apdu[0] = (uint8_t)((value & 0xff00) >> 8);
|
||||
apdu[1] = (uint8_t)(value & 0x00ff);
|
||||
if (apdu) {
|
||||
apdu[0] = (uint8_t)((value & 0xff00) >> 8);
|
||||
apdu[1] = (uint8_t)(value & 0x00ff);
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int decode_signed16(uint8_t *apdu, int32_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (apdu && value) {
|
||||
/* negative - bit 7 is set */
|
||||
if (apdu[0] & 0x80) {
|
||||
*value = 0xFFFF0000;
|
||||
@@ -366,16 +384,18 @@ int decode_signed16(uint8_t *apdu, int32_t *value)
|
||||
|
||||
int encode_signed24(uint8_t *apdu, int32_t value)
|
||||
{
|
||||
apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
|
||||
apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
|
||||
apdu[2] = (uint8_t)(value & 0x0000ff);
|
||||
if (apdu) {
|
||||
apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
|
||||
apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
|
||||
apdu[2] = (uint8_t)(value & 0x0000ff);
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int decode_signed24(uint8_t *apdu, int32_t *value)
|
||||
{
|
||||
if (value) {
|
||||
if (apdu && value) {
|
||||
/* negative - bit 7 is set */
|
||||
if (apdu[0] & 0x80) {
|
||||
*value = 0xFF000000;
|
||||
@@ -392,10 +412,12 @@ int decode_signed24(uint8_t *apdu, int32_t *value)
|
||||
|
||||
int encode_signed32(uint8_t *apdu, int32_t value)
|
||||
{
|
||||
apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
|
||||
apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
|
||||
apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
|
||||
apdu[3] = (uint8_t)(value & 0x000000ff);
|
||||
if (apdu) {
|
||||
apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
|
||||
apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
|
||||
apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
|
||||
apdu[3] = (uint8_t)(value & 0x000000ff);
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
@@ -411,4 +433,27 @@ int decode_signed32(uint8_t *apdu, int32_t *value)
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines the number of bytes used by a BACnet Signed Integer
|
||||
* from clause 20.2.5 Encoding of an Signed Integer Value
|
||||
* @param value - signed value
|
||||
* @return number of bytes used by a BACnet Signed Integer
|
||||
*/
|
||||
int bacnet_signed_length(int32_t value)
|
||||
{
|
||||
int len;
|
||||
|
||||
if ((value >= -128) && (value < 128)) {
|
||||
len = 1;
|
||||
} else if ((value >= -32768) && (value < 32768)) {
|
||||
len = 2;
|
||||
} else if ((value > -8388608) && (value < 8388608)) {
|
||||
len = 3;
|
||||
} else {
|
||||
len = 4;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -100,9 +100,14 @@ extern "C" {
|
||||
uint8_t * buffer,
|
||||
uint64_t * value);
|
||||
#endif
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_unsigned_length(
|
||||
BACNET_UNSIGNED_INTEGER value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_signed_length(
|
||||
int32_t value);
|
||||
|
||||
/* signed value encoding and decoding */
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_signed8(
|
||||
|
||||
+78
-62
@@ -56,20 +56,24 @@ int decode_real(uint8_t *apdu, float *real_value)
|
||||
float real_value;
|
||||
} my_data;
|
||||
|
||||
/* NOTE: assumes the compiler stores float as IEEE-754 float */
|
||||
if (big_endian()) {
|
||||
my_data.byte[0] = apdu[0];
|
||||
my_data.byte[1] = apdu[1];
|
||||
my_data.byte[2] = apdu[2];
|
||||
my_data.byte[3] = apdu[3];
|
||||
} else {
|
||||
my_data.byte[0] = apdu[3];
|
||||
my_data.byte[1] = apdu[2];
|
||||
my_data.byte[2] = apdu[1];
|
||||
my_data.byte[3] = apdu[0];
|
||||
if (apdu) {
|
||||
/* NOTE: assumes the compiler stores float as IEEE-754 float */
|
||||
if (big_endian()) {
|
||||
my_data.byte[0] = apdu[0];
|
||||
my_data.byte[1] = apdu[1];
|
||||
my_data.byte[2] = apdu[2];
|
||||
my_data.byte[3] = apdu[3];
|
||||
} else {
|
||||
my_data.byte[0] = apdu[3];
|
||||
my_data.byte[1] = apdu[2];
|
||||
my_data.byte[2] = apdu[1];
|
||||
my_data.byte[3] = apdu[0];
|
||||
}
|
||||
if (real_value) {
|
||||
*real_value = my_data.real_value;
|
||||
}
|
||||
}
|
||||
|
||||
*real_value = my_data.real_value;
|
||||
|
||||
return 4;
|
||||
}
|
||||
@@ -77,7 +81,9 @@ int decode_real(uint8_t *apdu, float *real_value)
|
||||
int decode_real_safe(uint8_t *apdu, uint32_t len_value, float *real_value)
|
||||
{
|
||||
if (len_value != 4) {
|
||||
*real_value = 0.0f;
|
||||
if (real_value) {
|
||||
*real_value = 0.0f;
|
||||
}
|
||||
return (int)len_value;
|
||||
} else {
|
||||
return decode_real(apdu, real_value);
|
||||
@@ -95,16 +101,18 @@ int encode_bacnet_real(float value, uint8_t *apdu)
|
||||
|
||||
/* NOTE: assumes the compiler stores float as IEEE-754 float */
|
||||
my_data.real_value = value;
|
||||
if (big_endian()) {
|
||||
apdu[0] = my_data.byte[0];
|
||||
apdu[1] = my_data.byte[1];
|
||||
apdu[2] = my_data.byte[2];
|
||||
apdu[3] = my_data.byte[3];
|
||||
} else {
|
||||
apdu[0] = my_data.byte[3];
|
||||
apdu[1] = my_data.byte[2];
|
||||
apdu[2] = my_data.byte[1];
|
||||
apdu[3] = my_data.byte[0];
|
||||
if (apdu) {
|
||||
if (big_endian()) {
|
||||
apdu[0] = my_data.byte[0];
|
||||
apdu[1] = my_data.byte[1];
|
||||
apdu[2] = my_data.byte[2];
|
||||
apdu[3] = my_data.byte[3];
|
||||
} else {
|
||||
apdu[0] = my_data.byte[3];
|
||||
apdu[1] = my_data.byte[2];
|
||||
apdu[2] = my_data.byte[1];
|
||||
apdu[3] = my_data.byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
return 4;
|
||||
@@ -121,27 +129,31 @@ int decode_double(uint8_t *apdu, double *double_value)
|
||||
double double_value;
|
||||
} my_data;
|
||||
|
||||
/* NOTE: assumes the compiler stores float as IEEE-754 float */
|
||||
if (big_endian()) {
|
||||
my_data.byte[0] = apdu[0];
|
||||
my_data.byte[1] = apdu[1];
|
||||
my_data.byte[2] = apdu[2];
|
||||
my_data.byte[3] = apdu[3];
|
||||
my_data.byte[4] = apdu[4];
|
||||
my_data.byte[5] = apdu[5];
|
||||
my_data.byte[6] = apdu[6];
|
||||
my_data.byte[7] = apdu[7];
|
||||
} else {
|
||||
my_data.byte[0] = apdu[7];
|
||||
my_data.byte[1] = apdu[6];
|
||||
my_data.byte[2] = apdu[5];
|
||||
my_data.byte[3] = apdu[4];
|
||||
my_data.byte[4] = apdu[3];
|
||||
my_data.byte[5] = apdu[2];
|
||||
my_data.byte[6] = apdu[1];
|
||||
my_data.byte[7] = apdu[0];
|
||||
if (apdu) {
|
||||
/* NOTE: assumes the compiler stores float as IEEE-754 float */
|
||||
if (big_endian()) {
|
||||
my_data.byte[0] = apdu[0];
|
||||
my_data.byte[1] = apdu[1];
|
||||
my_data.byte[2] = apdu[2];
|
||||
my_data.byte[3] = apdu[3];
|
||||
my_data.byte[4] = apdu[4];
|
||||
my_data.byte[5] = apdu[5];
|
||||
my_data.byte[6] = apdu[6];
|
||||
my_data.byte[7] = apdu[7];
|
||||
} else {
|
||||
my_data.byte[0] = apdu[7];
|
||||
my_data.byte[1] = apdu[6];
|
||||
my_data.byte[2] = apdu[5];
|
||||
my_data.byte[3] = apdu[4];
|
||||
my_data.byte[4] = apdu[3];
|
||||
my_data.byte[5] = apdu[2];
|
||||
my_data.byte[6] = apdu[1];
|
||||
my_data.byte[7] = apdu[0];
|
||||
}
|
||||
if (double_value) {
|
||||
*double_value = my_data.double_value;
|
||||
}
|
||||
}
|
||||
*double_value = my_data.double_value;
|
||||
|
||||
return 8;
|
||||
}
|
||||
@@ -149,7 +161,9 @@ int decode_double(uint8_t *apdu, double *double_value)
|
||||
int decode_double_safe(uint8_t *apdu, uint32_t len_value, double *double_value)
|
||||
{
|
||||
if (len_value != 8) {
|
||||
*double_value = 0.0;
|
||||
if (double_value) {
|
||||
*double_value = 0.0;
|
||||
}
|
||||
return (int)len_value;
|
||||
} else {
|
||||
return decode_double(apdu, double_value);
|
||||
@@ -167,24 +181,26 @@ int encode_bacnet_double(double value, uint8_t *apdu)
|
||||
|
||||
/* NOTE: assumes the compiler stores float as IEEE-754 float */
|
||||
my_data.double_value = value;
|
||||
if (big_endian()) {
|
||||
apdu[0] = my_data.byte[0];
|
||||
apdu[1] = my_data.byte[1];
|
||||
apdu[2] = my_data.byte[2];
|
||||
apdu[3] = my_data.byte[3];
|
||||
apdu[4] = my_data.byte[4];
|
||||
apdu[5] = my_data.byte[5];
|
||||
apdu[6] = my_data.byte[6];
|
||||
apdu[7] = my_data.byte[7];
|
||||
} else {
|
||||
apdu[0] = my_data.byte[7];
|
||||
apdu[1] = my_data.byte[6];
|
||||
apdu[2] = my_data.byte[5];
|
||||
apdu[3] = my_data.byte[4];
|
||||
apdu[4] = my_data.byte[3];
|
||||
apdu[5] = my_data.byte[2];
|
||||
apdu[6] = my_data.byte[1];
|
||||
apdu[7] = my_data.byte[0];
|
||||
if (apdu) {
|
||||
if (big_endian()) {
|
||||
apdu[0] = my_data.byte[0];
|
||||
apdu[1] = my_data.byte[1];
|
||||
apdu[2] = my_data.byte[2];
|
||||
apdu[3] = my_data.byte[3];
|
||||
apdu[4] = my_data.byte[4];
|
||||
apdu[5] = my_data.byte[5];
|
||||
apdu[6] = my_data.byte[6];
|
||||
apdu[7] = my_data.byte[7];
|
||||
} else {
|
||||
apdu[0] = my_data.byte[7];
|
||||
apdu[1] = my_data.byte[6];
|
||||
apdu[2] = my_data.byte[5];
|
||||
apdu[3] = my_data.byte[4];
|
||||
apdu[4] = my_data.byte[3];
|
||||
apdu[5] = my_data.byte[2];
|
||||
apdu[6] = my_data.byte[1];
|
||||
apdu[7] = my_data.byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
return 8;
|
||||
|
||||
+25
-3
@@ -129,8 +129,8 @@ const char *bactext_unconfirmed_service_name(unsigned index)
|
||||
bacnet_unconfirmed_service_names, index, ASHRAE_Reserved_String);
|
||||
}
|
||||
|
||||
INDTEXT_DATA bacnet_application_tag_names[] = { { BACNET_APPLICATION_TAG_NULL,
|
||||
"Null" },
|
||||
INDTEXT_DATA bacnet_application_tag_names[] = {
|
||||
{ BACNET_APPLICATION_TAG_NULL, "Null" },
|
||||
{ BACNET_APPLICATION_TAG_BOOLEAN, "Boolean" },
|
||||
{ BACNET_APPLICATION_TAG_UNSIGNED_INT, "Unsigned Int" },
|
||||
{ BACNET_APPLICATION_TAG_SIGNED_INT, "Signed Int" },
|
||||
@@ -145,7 +145,29 @@ INDTEXT_DATA bacnet_application_tag_names[] = { { BACNET_APPLICATION_TAG_NULL,
|
||||
{ BACNET_APPLICATION_TAG_OBJECT_ID, "Object ID" },
|
||||
{ BACNET_APPLICATION_TAG_RESERVE1, "Reserved 1" },
|
||||
{ BACNET_APPLICATION_TAG_RESERVE2, "Reserved 2" },
|
||||
{ BACNET_APPLICATION_TAG_RESERVE3, "Reserved 3" }, { 0, NULL } };
|
||||
{ BACNET_APPLICATION_TAG_RESERVE3, "Reserved 3" },
|
||||
/* complex data types */
|
||||
{ BACNET_APPLICATION_TAG_EMPTYLIST, "Empty List" },
|
||||
{ BACNET_APPLICATION_TAG_WEEKNDAY, "BACnetWeeknday" },
|
||||
{ BACNET_APPLICATION_TAG_DATERANGE, "BACnetDateRange" },
|
||||
{ BACNET_APPLICATION_TAG_DATETIME, "BACnetDateTime" },
|
||||
{ BACNET_APPLICATION_TAG_TIMESTAMP, "BACnetTimeStamp" },
|
||||
{ BACNET_APPLICATION_TAG_ERROR, "Error" },
|
||||
{ BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE,
|
||||
"BACnetDeviceObjectPropertyReference" },
|
||||
{ BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE,
|
||||
"BACnetDeviceObjectReference" },
|
||||
{ BACNET_APPLICATION_TAG_DESTINATION, "BACnetDestination" },
|
||||
{ BACNET_APPLICATION_TAG_RECIPIENT, "BACnetRecipient" },
|
||||
{ BACNET_APPLICATION_TAG_COV_SUBSCRIPTION, "BACnetCOVSubscription" },
|
||||
{ BACNET_APPLICATION_TAG_CALENDAR_ENTRY, "BACnetCalendarEntry" },
|
||||
{ BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE, "BACnetWeeklySchedule" },
|
||||
{ BACNET_APPLICATION_TAG_SPECIAL_EVENT, "BACnetSpecialEvent" },
|
||||
{ BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION,
|
||||
"BACnetReadAccessSpecification" },
|
||||
{ BACNET_APPLICATION_TAG_LIGHTING_COMMAND, "BACnetLightingCommand" },
|
||||
{ BACNET_APPLICATION_TAG_HOST_N_PORT, "BACnetHostNPort" },
|
||||
{ 0, NULL } };
|
||||
|
||||
const char *bactext_application_tag_name(unsigned index)
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include "bacnet/proplist.h"
|
||||
#include "bacnet/lighting.h"
|
||||
#include "bacnet/basic/object/device.h"
|
||||
#if defined(CHANNEL_LIGHTING_COMMAND) || defined(BACAPP_LIGHTING_COMMAND)
|
||||
#if defined(CHANNEL_LIGHTING_COMMAND)
|
||||
#include "bacnet/basic/object/lo.h"
|
||||
#endif
|
||||
/* me! */
|
||||
@@ -628,7 +628,7 @@ bool Channel_Value_Copy(
|
||||
status = true;
|
||||
break;
|
||||
#endif
|
||||
#if defined(BACAPP_LIGHTING_COMMAND) && defined(CHANNEL_LIGHTING_COMMAND)
|
||||
#if defined(BACAPP_TYPES_EXTRA) && defined(CHANNEL_LIGHTING_COMMAND)
|
||||
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
|
||||
cvalue->tag = value->tag;
|
||||
lighting_command_copy(
|
||||
@@ -1045,7 +1045,7 @@ int Channel_Coerce_Data_Encode(uint8_t *apdu,
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined(BACAPP_LIGHTING_COMMAND)
|
||||
#if defined(BACAPP_TYPES_EXTRA)
|
||||
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
|
||||
if (tag == BACNET_APPLICATION_TAG_LIGHTING_COMMAND) {
|
||||
apdu_len = lighting_command_encode(
|
||||
|
||||
@@ -279,7 +279,7 @@ int cl_decode_apdu(uint8_t *apdu,
|
||||
&bcl->Value.type.Object_Id.type,
|
||||
&bcl->Value.type.Object_Id.instance);
|
||||
break;
|
||||
#if defined(BACAPP_LIGHTING_COMMAND)
|
||||
#if defined(BACAPP_TYPES_EXTRA)
|
||||
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
|
||||
len = lighting_command_decode(&apdu[dec_len], apdu_len - dec_len,
|
||||
&bcl->Value.type.Lighting_Command);
|
||||
|
||||
@@ -210,7 +210,7 @@ static object_functions_t My_Object_Table[] = {
|
||||
Trend_Log_Write_Property, Trend_Log_Property_Lists, TrendLogGetRRInfo,
|
||||
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
|
||||
NULL /* COV Clear */, NULL /* Intrinsic Reporting */ },
|
||||
#if (BACNET_PROTOCOL_REVISION >= 14) && defined(BACAPP_LIGHTING_COMMAND)
|
||||
#if (BACNET_PROTOCOL_REVISION >= 14)
|
||||
{ OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count,
|
||||
Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance,
|
||||
Lighting_Output_Object_Name, Lighting_Output_Read_Property,
|
||||
|
||||
+3
-5
@@ -143,9 +143,8 @@
|
||||
defined(BACAPP_ENUMERATED) || \
|
||||
defined(BACAPP_DATE) || \
|
||||
defined(BACAPP_TIME) || \
|
||||
defined(BACAPP_LIGHTING_COMMAND) || \
|
||||
defined(BACAPP_DEVICE_OBJECT_PROP_REF) || \
|
||||
defined(BACAPP_OBJECT_ID))
|
||||
defined(BACAPP_OBJECT_ID) || \
|
||||
defined(BACAPP_TYPES_EXTRA))
|
||||
#define BACAPP_ALL
|
||||
#endif
|
||||
|
||||
@@ -163,8 +162,7 @@
|
||||
#define BACAPP_DATE
|
||||
#define BACAPP_TIME
|
||||
#define BACAPP_OBJECT_ID
|
||||
#define BACAPP_DEVICE_OBJECT_PROP_REF
|
||||
#define BACAPP_LIGHTING_COMMAND
|
||||
#define BACAPP_TYPES_EXTRA
|
||||
#elif defined (BACAPP_MINIMAL)
|
||||
#define BACAPP_NULL
|
||||
#define BACAPP_BOOLEAN
|
||||
|
||||
+25
-105
@@ -39,6 +39,7 @@
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacint.h"
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/hostnport.h"
|
||||
#include "bacnet/datalink/bvlc.h"
|
||||
|
||||
/**
|
||||
@@ -2623,15 +2624,6 @@ const char *bvlc_result_code_name(uint16_t result_code)
|
||||
|
||||
/**
|
||||
* @brief Encode a BBMD Address for Network Port object
|
||||
*
|
||||
* BACnetHostNPort ::= SEQUENCE {
|
||||
* host [0] BACnetHostAddress,
|
||||
* BACnetHostAddress ::= CHOICE {
|
||||
* ip-address [1] OCTET STRING, -- 4 octets for B/IP
|
||||
* }
|
||||
* port [1] Unsigned16
|
||||
* }
|
||||
*
|
||||
* @param apdu - the APDU buffer
|
||||
* @param apdu_size - the APDU buffer size
|
||||
* @param ip_address - IP address and port number
|
||||
@@ -2641,27 +2633,17 @@ int bvlc_foreign_device_bbmd_host_address_encode(uint8_t *apdu,
|
||||
uint16_t apdu_size,
|
||||
BACNET_IP_ADDRESS *ip_address)
|
||||
{
|
||||
int len = 0;
|
||||
BACNET_HOST_N_PORT address = { 0 };
|
||||
int apdu_len = 0;
|
||||
BACNET_OCTET_STRING octet_string;
|
||||
|
||||
if (apdu && (apdu_size >= 9) && ip_address) {
|
||||
/* host [0] BACnetHostAddress - opening */
|
||||
len = encode_opening_tag(&apdu[apdu_len], 0);
|
||||
apdu_len += len;
|
||||
/* CHOICE - ip-address [1] OCTET STRING */
|
||||
octetstring_init(&octet_string,
|
||||
&ip_address->address[0], IP_ADDRESS_MAX);
|
||||
len = encode_context_octet_string(&apdu[apdu_len], 1,
|
||||
&octet_string);
|
||||
apdu_len += len;
|
||||
/* host [0] BACnetHostAddress - closing */
|
||||
len = encode_closing_tag(&apdu[apdu_len], 0);
|
||||
apdu_len += len;
|
||||
/* port [1] Unsigned16 */
|
||||
len = encode_context_unsigned(
|
||||
&apdu[apdu_len], 1, ip_address->port);
|
||||
apdu_len += len;
|
||||
address.host_ip_address = true;
|
||||
address.host_name = false;
|
||||
octetstring_init(&address.host.ip_address, &ip_address->address[0],
|
||||
IP_ADDRESS_MAX);
|
||||
address.port = ip_address->port;
|
||||
apdu_len = host_n_port_encode(NULL, &address);
|
||||
if (apdu_len <= apdu_size) {
|
||||
apdu_len = host_n_port_encode(apdu, &address);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
@@ -2669,15 +2651,6 @@ int bvlc_foreign_device_bbmd_host_address_encode(uint8_t *apdu,
|
||||
|
||||
/**
|
||||
* @brief Decode the Broadcast-Distribution-Table for Network Port object
|
||||
*
|
||||
* BACnetHostNPort ::= SEQUENCE {
|
||||
* host [0] BACnetHostAddress,
|
||||
* BACnetHostAddress ::= CHOICE {
|
||||
* ip-address [1] OCTET STRING, -- 4 octets for B/IP
|
||||
* }
|
||||
* port [1] Unsigned16
|
||||
* }
|
||||
*
|
||||
* @param apdu - the APDU buffer
|
||||
* @param apdu_len - the APDU buffer length
|
||||
* @param ip_address - IP address and port number
|
||||
@@ -2688,77 +2661,24 @@ int bvlc_foreign_device_bbmd_host_address_decode(uint8_t *apdu,
|
||||
BACNET_ERROR_CODE *error_code,
|
||||
BACNET_IP_ADDRESS *ip_address)
|
||||
{
|
||||
BACNET_HOST_N_PORT address = { 0 };
|
||||
int len = 0;
|
||||
BACNET_OCTET_STRING octet_string = { 0 };
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value_type = 0;
|
||||
BACNET_UNSIGNED_INTEGER unsigned_value = 0;
|
||||
|
||||
/* default reject code */
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
|
||||
}
|
||||
/* check for value pointers */
|
||||
if ((apdu_len == 0) || (!apdu)) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
/* host [0] BACnetHostAddress - opening */
|
||||
if (!decode_is_opening_tag_number(&apdu[len++], 0)) {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
|
||||
len = host_n_port_decode(apdu, apdu_len, error_code, &address);
|
||||
if (len > 0) {
|
||||
if (address.host_ip_address) {
|
||||
ip_address->port = address.port;
|
||||
(void)octetstring_copy_value(
|
||||
&ip_address->address[0],
|
||||
IP_ADDRESS_MAX,
|
||||
&address.host.ip_address);
|
||||
} else {
|
||||
len = BACNET_STATUS_REJECT;
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
/* CHOICE - ip-address [1] OCTET STRING */
|
||||
len += decode_tag_number_and_value(
|
||||
&apdu[len], &tag_number, &len_value_type);
|
||||
if (tag_number != 1) {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
len += decode_octet_string(&apdu[len], len_value_type,
|
||||
&octet_string);
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
(void)octetstring_copy_value(&ip_address->address[0],
|
||||
IP_ADDRESS_MAX, &octet_string);
|
||||
/* host [0] BACnetHostAddress - closing */
|
||||
if (!decode_is_closing_tag_number(&apdu[len++], 0)) {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
/* port [1] Unsigned16 */
|
||||
len += decode_tag_number_and_value(
|
||||
&apdu[len], &tag_number, &len_value_type);
|
||||
if (tag_number != 1) {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
if (unsigned_value <= UINT16_MAX) {
|
||||
ip_address->port = unsigned_value;
|
||||
} else {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ typedef struct dlmstp_statistics {
|
||||
} DLMSTP_STATISTICS;
|
||||
|
||||
/* callback to signify the receipt of a preamble */
|
||||
typedef void (*dlmstp_hook_frame_rx_start_cb)();
|
||||
typedef void (*dlmstp_hook_frame_rx_start_cb)(void);
|
||||
|
||||
/* callback on for receiving every valid frame */
|
||||
typedef void (*dlmstp_hook_frame_rx_complete_cb)(
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief BACnetHostNPort complex data type encode and decode
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date May 2022
|
||||
* @section LICENSE
|
||||
*
|
||||
* Copyright (C) 2022 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include "bacnet/hostnport.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
|
||||
/**
|
||||
* @brief Encode a BACnetHostNPort complex data type
|
||||
*
|
||||
* BACnetHostNPort ::= SEQUENCE {
|
||||
* host [0] BACnetHostAddress,
|
||||
* BACnetHostAddress ::= CHOICE {
|
||||
* none [0] NULL,
|
||||
* ip-address [1] OCTET STRING,
|
||||
* -- 4 octets for B/IP or 16 octets for B/IPv6
|
||||
* name [2] CharacterString
|
||||
* -- Internet host name (see RFC 1123)
|
||||
* }
|
||||
* port [1] Unsigned16
|
||||
* }
|
||||
*
|
||||
* @param apdu - the APDU buffer, or NULL for length
|
||||
* @param address - IP address and port number
|
||||
* @return length of the encoded APDU buffer
|
||||
*/
|
||||
int host_n_port_encode(uint8_t *apdu,
|
||||
BACNET_HOST_N_PORT *address)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
if (address) {
|
||||
/* host [0] BACnetHostAddress - opening */
|
||||
len = encode_opening_tag(apdu, 0);
|
||||
apdu_len += len;
|
||||
if (address->host_ip_address) {
|
||||
/* CHOICE - ip-address [1] OCTET STRING */
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_context_octet_string(apdu_offset, 1, &address->host.ip_address);
|
||||
apdu_len += len;
|
||||
} else if (address->host_name) {
|
||||
/* CHOICE - name [2] CharacterString */
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_context_character_string(apdu_offset, 1,
|
||||
&address->host.name);
|
||||
apdu_len += len;
|
||||
} else {
|
||||
/* none */
|
||||
}
|
||||
/* host [0] BACnetHostAddress - closing */
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_closing_tag(apdu_offset, 0);
|
||||
apdu_len += len;
|
||||
/* port [1] Unsigned16 */
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_context_unsigned(
|
||||
apdu_offset, 1, address->port);
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a BACnetHostNPort complex data type
|
||||
* @param apdu - the APDU buffer
|
||||
* @param tag_number - the APDU buffer size
|
||||
* @param address - IP address and port number
|
||||
* @return length of the APDU buffer, or 0 if not able to encode
|
||||
*/
|
||||
int host_n_port_context_encode(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_HOST_N_PORT *address)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
if (address) {
|
||||
apdu_offset = apdu;
|
||||
len = encode_opening_tag(apdu_offset, tag_number);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = host_n_port_encode(apdu_offset, address);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_closing_tag(apdu_offset, tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode the BACnetHostNPort complex data
|
||||
*
|
||||
* BACnetHostNPort ::= SEQUENCE {
|
||||
* host [0] BACnetHostAddress,
|
||||
* BACnetHostAddress ::= CHOICE {
|
||||
* BACnetHostAddress ::= CHOICE {
|
||||
* none [0] NULL,
|
||||
* ip-address [1] OCTET STRING,
|
||||
* -- 4 octets for B/IP or 16 octets for B/IPv6
|
||||
* name [2] CharacterString
|
||||
* -- Internet host name (see RFC 1123)
|
||||
* }
|
||||
* port [1] Unsigned16
|
||||
* }
|
||||
*
|
||||
* @param apdu - the APDU buffer
|
||||
* @param apdu_len - the APDU buffer length
|
||||
* @param ip_address - IP address and port number
|
||||
* @return length of the APDU buffer decoded, or ERROR, REJECT, or ABORT
|
||||
*/
|
||||
int host_n_port_decode(uint8_t *apdu,
|
||||
uint16_t apdu_len,
|
||||
BACNET_ERROR_CODE *error_code,
|
||||
BACNET_HOST_N_PORT *address)
|
||||
{
|
||||
int len = 0;
|
||||
BACNET_OCTET_STRING octet_string = { 0 };
|
||||
BACNET_CHARACTER_STRING char_string = { 0 };
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value_type = 0;
|
||||
BACNET_UNSIGNED_INTEGER unsigned_value = 0;
|
||||
|
||||
/* default reject code */
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
|
||||
}
|
||||
/* check for value pointers */
|
||||
if ((apdu_len == 0) || (!apdu)) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
/* host [0] BACnetHostAddress - opening */
|
||||
if (!decode_is_opening_tag_number(&apdu[len++], 0)) {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
len += decode_tag_number_and_value(
|
||||
&apdu[len], &tag_number, &len_value_type);
|
||||
if (tag_number == 0) {
|
||||
/* CHOICE - none [0] NULL */
|
||||
address->host_ip_address = false;
|
||||
address->host_name = false;
|
||||
} else if (tag_number == 1) {
|
||||
/* CHOICE - ip-address [1] OCTET STRING */
|
||||
address->host_ip_address = true;
|
||||
address->host_name = false;
|
||||
len += decode_octet_string(&apdu[len], len_value_type,
|
||||
&octet_string);
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
(void)octetstring_copy(&address->host.ip_address,
|
||||
&octet_string);
|
||||
} else if (tag_number == 2) {
|
||||
address->host_ip_address = false;
|
||||
address->host_name = true;
|
||||
len += decode_character_string(&apdu[len], len_value_type,
|
||||
&char_string);
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
(void)characterstring_copy(&address->host.name,
|
||||
&char_string);
|
||||
} else {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
/* host [0] BACnetHostAddress - closing */
|
||||
if (!decode_is_closing_tag_number(&apdu[len++], 0)) {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
/* port [1] Unsigned16 */
|
||||
len += decode_tag_number_and_value(
|
||||
&apdu[len], &tag_number, &len_value_type);
|
||||
if (tag_number != 1) {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
|
||||
if (len > apdu_len) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
if (unsigned_value <= UINT16_MAX) {
|
||||
address->port = unsigned_value;
|
||||
} else {
|
||||
if (error_code) {
|
||||
*error_code = ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy the BACnetHostNPort complex data from src to dst
|
||||
* @param dst - destination structure
|
||||
* @param src - source structure
|
||||
* @return true if successfully copied
|
||||
*/
|
||||
bool host_n_port_copy(
|
||||
BACNET_HOST_N_PORT * dst,
|
||||
BACNET_HOST_N_PORT * src)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (dst && src) {
|
||||
dst->host_ip_address = src->host_ip_address;
|
||||
dst->host_name = src->host_name;
|
||||
if (src->host_ip_address) {
|
||||
status = octetstring_copy(
|
||||
&dst->host.ip_address,
|
||||
&src->host.ip_address);
|
||||
} else if (src->host_name) {
|
||||
status = characterstring_copy(
|
||||
&dst->host.name,
|
||||
&src->host.name);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
dst->port = src->port;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare the BACnetHostNPort complex data of src and dst
|
||||
* @param host1 - host 1 structure
|
||||
* @param host2 - host 2 structure
|
||||
* @return true if successfully copied
|
||||
*/
|
||||
bool host_n_port_same(
|
||||
BACNET_HOST_N_PORT * host1,
|
||||
BACNET_HOST_N_PORT * host2)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (host1 && host2) {
|
||||
if ((host1->host_ip_address == host2->host_ip_address) &&
|
||||
(host1->host_name == host2->host_name)) {
|
||||
if (host1->host_ip_address) {
|
||||
status = octetstring_value_same(
|
||||
&host1->host.ip_address,
|
||||
&host2->host.ip_address);
|
||||
} else if (host1->host_name) {
|
||||
status = characterstring_same(
|
||||
&host1->host.name,
|
||||
&host2->host.name);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
if (status) {
|
||||
if (host1->port != host2->port) {
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief API for BACnetHostNPort complex data type encode and decode
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date May 2022
|
||||
* @section LICENSE
|
||||
*
|
||||
* Copyright (C) 2022 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#ifndef BACNET_HOST_N_PORT_H
|
||||
#define BACNET_HOST_N_PORT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacnet/bacnet_stack_exports.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacstr.h"
|
||||
#include "bacnet/datalink/bvlc.h"
|
||||
|
||||
/**
|
||||
* BACnetHostNPort ::= SEQUENCE {
|
||||
* host [0] BACnetHostAddress,
|
||||
* BACnetHostAddress ::= CHOICE {
|
||||
* none [0] NULL,
|
||||
* ip-address [1] OCTET STRING,
|
||||
* name [2] CharacterString
|
||||
* }
|
||||
* port [1] Unsigned16
|
||||
* }
|
||||
*/
|
||||
typedef struct BACnetHostNPort {
|
||||
bool host_ip_address:1;
|
||||
bool host_name:1;
|
||||
union BACnetHostAddress {
|
||||
/* none = host_ip_address AND host_name are FALSE */
|
||||
BACNET_OCTET_STRING ip_address;
|
||||
BACNET_CHARACTER_STRING name;
|
||||
} host;
|
||||
uint16_t port;
|
||||
} BACNET_HOST_N_PORT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int host_n_port_encode(
|
||||
uint8_t * apdu,
|
||||
BACNET_HOST_N_PORT *address);
|
||||
BACNET_STACK_EXPORT
|
||||
int host_n_port_context_encode(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_HOST_N_PORT *address);
|
||||
BACNET_STACK_EXPORT
|
||||
int host_n_port_decode(uint8_t *apdu,
|
||||
uint16_t apdu_len,
|
||||
BACNET_ERROR_CODE *error_code,
|
||||
BACNET_HOST_N_PORT *address);
|
||||
BACNET_STACK_EXPORT
|
||||
bool host_n_port_copy(
|
||||
BACNET_HOST_N_PORT * dst,
|
||||
BACNET_HOST_N_PORT * src);
|
||||
BACNET_STACK_EXPORT
|
||||
bool host_n_port_same(
|
||||
BACNET_HOST_N_PORT * dst,
|
||||
BACNET_HOST_N_PORT * src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
+49
-100
@@ -50,44 +50,58 @@
|
||||
/**
|
||||
* Encodes into bytes from the lighting-command structure
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu - buffer to hold the bytes, or null for length
|
||||
* @param value - lighting command value to encode
|
||||
*
|
||||
* @return number of bytes encoded, or 0 if unable to encode.
|
||||
* @return number of bytes encoded
|
||||
*/
|
||||
int lighting_command_encode(uint8_t *apdu, BACNET_LIGHTING_COMMAND *data)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
int len = 0; /* total length of the apdu, return value */
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
if (apdu) {
|
||||
len = encode_context_enumerated(&apdu[apdu_len], 0, data->operation);
|
||||
len = encode_context_enumerated(apdu, 0, data->operation);
|
||||
apdu_len += len;
|
||||
/* optional target-level */
|
||||
if (data->use_target_level) {
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_context_real(apdu_offset, 1, data->target_level);
|
||||
apdu_len += len;
|
||||
/* optional target-level */
|
||||
if (data->use_target_level) {
|
||||
len = encode_context_real(&apdu[apdu_len], 1, data->target_level);
|
||||
apdu_len += len;
|
||||
}
|
||||
/* optional ramp-rate */
|
||||
if (data->use_ramp_rate) {
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
/* optional ramp-rate */
|
||||
if (data->use_ramp_rate) {
|
||||
len = encode_context_real(&apdu[apdu_len], 2, data->ramp_rate);
|
||||
apdu_len += len;
|
||||
len = encode_context_real(apdu_offset, 2, data->ramp_rate);
|
||||
apdu_len += len;
|
||||
}
|
||||
/* optional step increment */
|
||||
if (data->use_step_increment) {
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
/* optional step increment */
|
||||
if (data->use_step_increment) {
|
||||
len = encode_context_real(&apdu[apdu_len], 3, data->step_increment);
|
||||
apdu_len += len;
|
||||
len = encode_context_real(apdu_offset, 3, data->step_increment);
|
||||
apdu_len += len;
|
||||
}
|
||||
/* optional fade time */
|
||||
if (data->use_fade_time) {
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
/* optional fade time */
|
||||
if (data->use_fade_time) {
|
||||
len = encode_context_unsigned(&apdu[apdu_len], 4, data->fade_time);
|
||||
apdu_len += len;
|
||||
}
|
||||
/* optional priority */
|
||||
if (data->use_priority) {
|
||||
len = encode_context_unsigned(&apdu[apdu_len], 5, data->priority);
|
||||
apdu_len += len;
|
||||
len = encode_context_unsigned(apdu_offset, 4, data->fade_time);
|
||||
apdu_len += len;
|
||||
}
|
||||
/* optional priority */
|
||||
if (data->use_priority) {
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_context_unsigned(apdu_offset, 5, data->priority);
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
@@ -107,10 +121,17 @@ int lighting_command_encode_context(
|
||||
uint8_t *apdu, uint8_t tag_number, BACNET_LIGHTING_COMMAND *value)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
apdu_len += encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += lighting_command_encode(&apdu[apdu_len], value);
|
||||
apdu_len += encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += encode_opening_tag(apdu, tag_number);
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
apdu_len += lighting_command_encode(apdu_offset, value);
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
apdu_len += encode_closing_tag(apdu_offset, tag_number);
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
@@ -292,75 +313,3 @@ bool lighting_command_same(
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef TEST_LIGHTING_COMMAND
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
static void testBACnetLightingCommand(Test *pTest, BACNET_LIGHTING_COMMAND *data)
|
||||
{
|
||||
bool status = false;
|
||||
BACNET_LIGHTING_COMMAND test_data;
|
||||
int len, apdu_len;
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
|
||||
status = lighting_command_copy(&test_data, NULL);
|
||||
ct_test(pTest, status == false);
|
||||
status = lighting_command_copy(NULL, data);
|
||||
ct_test(pTest, status == false);
|
||||
status = lighting_command_copy(&test_data, data);
|
||||
ct_test(pTest, status == true);
|
||||
status = lighting_command_same(&test_data, data);
|
||||
ct_test(pTest, status == true);
|
||||
len = lighting_command_encode(apdu, data);
|
||||
apdu_len = lighting_command_decode(apdu, sizeof(apdu), &test_data);
|
||||
ct_test(pTest, len > 0);
|
||||
ct_test(pTest, apdu_len > 0);
|
||||
status = lighting_command_same(&test_data, data);
|
||||
}
|
||||
|
||||
static void testBACnetLightingCommandAll(Test *pTest)
|
||||
{
|
||||
BACNET_LIGHTING_COMMAND data;
|
||||
|
||||
data.operation = BACNET_LIGHTS_NONE;
|
||||
data.use_target_level = false;
|
||||
data.use_ramp_rate = false;
|
||||
data.use_step_increment = false;
|
||||
data.use_fade_time = false;
|
||||
data.use_priority = false;
|
||||
data.target_level = 0.0;
|
||||
data.ramp_rate = 100.0;
|
||||
data.step_increment = 1.0;
|
||||
data.fade_time = 100;
|
||||
data.priority = 1;
|
||||
testBACnetLightingCommand(pTest, &data);
|
||||
data.operation = BACNET_LIGHTS_STOP;
|
||||
data.use_target_level = true;
|
||||
data.use_ramp_rate = true;
|
||||
data.use_step_increment = true;
|
||||
data.use_fade_time = true;
|
||||
data.use_priority = true;
|
||||
testBACnetLightingCommand(pTest, &data);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Lighting Command", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testBACnetLightingCommandAll);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void)ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user