Added IAm APDU encoding and decoding along with unit tests.

This commit is contained in:
skarg
2005-03-09 22:42:29 +00:00
parent 5b4c6bbf74
commit 4748432666
6 changed files with 292 additions and 9 deletions
+5 -5
View File
@@ -471,7 +471,7 @@ int encode_tagged_real(uint8_t * apdu, float value)
// from clause 20.2.14 Encoding of an Object Identifier Value
// returns the number of apdu bytes consumed
int decode_object_id(uint8_t * apdu, int *object_type, int *instance)
int decode_object_id(uint8_t * apdu, int *object_type, uint32_t *instance)
{
union {
uint8_t byte[4];
@@ -498,7 +498,7 @@ int decode_object_id(uint8_t * apdu, int *object_type, int *instance)
// from clause 20.2.14 Encoding of an Object Identifier Value
// returns the number of apdu bytes consumed
int encode_bacnet_object_id(uint8_t * apdu, int object_type, int instance)
int encode_bacnet_object_id(uint8_t * apdu, int object_type, uint32_t instance)
{
union {
uint8_t byte[4];
@@ -526,7 +526,7 @@ int encode_bacnet_object_id(uint8_t * apdu, int object_type, int instance)
// and 20.2.1 General Rules for Encoding BACnet Tags
// returns the number of apdu bytes consumed
int encode_context_object_id(uint8_t * apdu, int tag_number,
int object_type, int instance)
int object_type, uint32_t instance)
{
int len = 0;
@@ -540,7 +540,7 @@ int encode_context_object_id(uint8_t * apdu, int tag_number,
// from clause 20.2.14 Encoding of an Object Identifier Value
// and 20.2.1 General Rules for Encoding BACnet Tags
// returns the number of apdu bytes consumed
int encode_tagged_object_id(uint8_t * apdu, int object_type, int instance)
int encode_tagged_object_id(uint8_t * apdu, int object_type, uint32_t instance)
{
int len = 0;
@@ -1231,7 +1231,7 @@ void testBACDCodeObject(Test * pTest)
BACNET_OBJECT_TYPE type = OBJECT_BINARY_INPUT;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
int instance = 123;
int decoded_instance = 0;
uint32_t decoded_instance = 0;
encode_bacnet_object_id(&encoded_array[0], type, instance);
decode_object_id(&encoded_array[0],
+4 -4
View File
@@ -67,11 +67,11 @@ int encode_tagged_real(uint8_t * apdu, float value);
// from clause 20.2.14 Encoding of an Object Identifier Value
// and 20.2.1 General Rules for Encoding BACnet Tags
// returns the number of apdu bytes consumed
int decode_object_id(uint8_t * apdu, int *object_type, int *instance);
int encode_bacnet_object_id(uint8_t * apdu, int object_type, int instance);
int decode_object_id(uint8_t * apdu, int *object_type, uint32_t *instance);
int encode_bacnet_object_id(uint8_t * apdu, int object_type, uint32_t instance);
int encode_context_object_id(uint8_t * apdu, int tag_number,
int object_type, int instance);
int encode_tagged_object_id(uint8_t * apdu, int object_type, int instance);
int object_type, uint32_t instance);
int encode_tagged_object_id(uint8_t * apdu, int object_type, uint32_t instance);
// from clause 20.2.9 Encoding of a Character String Value
// and 20.2.1 General Rules for Encoding BACnet Tags
+1
View File
@@ -579,6 +579,7 @@ typedef enum
SEGMENTATION_TRANSMIT = 1,
SEGMENTATION_RECEIVE = 2,
SEGMENTATION_NONE = 3,
MAX_BACNET_SEGMENTATION = 4,
} BACNET_SEGMENTATION;
typedef enum
+191
View File
@@ -0,0 +1,191 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdint.h>
#include "bacenum.h"
#include "bacdcode.h"
// encode I-Am service
int iam_encode_apdu(
uint8_t *apdu,
uint32_t device_id,
unsigned max_apdu,
int segmentation,
uint16_t vendor_id)
{
int len = 0; // length of each encoding
int apdu_len = 0; // total length of the apdu, return value
if (apdu) {
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
apdu[1] = SERVICE_UNCONFIRMED_I_AM; // service choice
apdu_len = 2;
len = encode_tagged_object_id(
&apdu[apdu_len],
OBJECT_DEVICE,
device_id);
apdu_len += len;
len = encode_tagged_unsigned(
&apdu[apdu_len],
max_apdu);
apdu_len += len;
len = encode_tagged_enumerated(
&apdu[apdu_len],
segmentation);
apdu_len += len;
len = encode_tagged_unsigned(
&apdu[apdu_len],
vendor_id);
apdu_len += len;
}
return apdu_len;
}
int iam_decode_apdu(
uint8_t *apdu,
uint32_t *pDevice_id,
unsigned *pMax_apdu,
int *pSegmentation,
uint16_t *pVendor_id)
{
int len = 0;
int object_type = 0; // should be a Device Object
uint32_t object_instance = 0;
uint8_t tag_number = 0;
uint32_t len_value = 0;
unsigned int decoded_value = 0;
// optional checking - most likely was already done prior to this call
if (apdu[0] != PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST)
return -1;
if (apdu[1] != SERVICE_UNCONFIRMED_I_AM)
return -1;
// OBJECT ID - object id
len = 2;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID)
return -1;
len += decode_object_id(&apdu[len], &object_type, &object_instance);
if (object_type != OBJECT_DEVICE)
return -1;
*pDevice_id = object_instance;
// MAX APDU - unsigned
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1;
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
*pMax_apdu = decoded_value;
// Segmentation - enumerated
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED)
return -1;
len += decode_enumerated(&apdu[len],len_value, &decoded_value);
if (decoded_value >= MAX_BACNET_SEGMENTATION)
return -1;
*pSegmentation = decoded_value;
// Vendor ID - unsigned16
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1;
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
if (decoded_value > 0xFFFF)
return -1;
*pVendor_id = decoded_value;
return len;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testIAm(Test * pTest)
{
uint8_t apdu[480] = {0};
int len = 0;
uint32_t device_id = 42;
unsigned max_apdu = 480;
int segmentation = SEGMENTATION_NONE;
uint16_t vendor_id = 42;
uint32_t test_device_id = 0;
unsigned test_max_apdu = 0;
int test_segmentation = 0;
uint16_t test_vendor_id = 0;
len = iam_encode_apdu(
&apdu[0],
device_id,
max_apdu,
segmentation,
vendor_id);
ct_test(pTest, len != 0);
len = iam_decode_apdu(
&apdu[0],
&test_device_id,
&test_max_apdu,
&test_segmentation,
&test_vendor_id);
ct_test(pTest, len != -1);
ct_test(pTest, test_device_id == device_id);
ct_test(pTest, test_vendor_id == vendor_id);
ct_test(pTest, test_max_apdu == max_apdu);
ct_test(pTest, test_segmentation == segmentation);
// check the error conditions
}
#ifdef TEST_IAM
int main(void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet I-Am", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testIAm);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif /* TEST_DECODE */
#endif /* TEST */
+58
View File
@@ -0,0 +1,58 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2004 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 IAM_H
#define IAM_H
#include <stdint.h>
#include <stdbool.h>
int iam_encode_apdu(
uint8_t *apdu,
uint32_t device_id,
unsigned max_apdu,
int segmentation,
uint16_t vendor_id);
int iam_decode_apdu(
uint8_t *apdu,
uint32_t *pDevice_id,
unsigned *pMax_apdu,
int *pSegmentation,
uint16_t *pVendor_id);
#ifdef TEST
void testIAm(Test * pTest);
#endif
#endif
+33
View File
@@ -0,0 +1,33 @@
#Makefile to build test case
CC = gcc
BASEDIR = .
#CFLAGS = -Wall -I.
# -g for debugging with gdb
#CFLAGS = -Wall -I. -g
CFLAGS = -Wall -I. -Itest -DTEST -DTEST_IAM -g
SRCS = bacdcode.c \
bigend.c \
iam.c \
test/ctest.c
OBJS = ${SRCS:.c=.o}
TARGET = iam
all: ${TARGET}
${TARGET}: ${OBJS}
${CC} -o $@ ${OBJS}
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET} $(OBJS) *.bak *.1 *.ini
include: .depend