diff --git a/bacnet-stack/bacint.c b/bacnet-stack/bacint.c
index d9fd23c0..38e15c7e 100644
--- a/bacnet-stack/bacint.c
+++ b/bacnet-stack/bacint.c
@@ -1,580 +1,580 @@
-/*####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####*/
-
-/* BACnet Integer encoding and decoding */
-
-#include
-#include
-
-int encode_unsigned16(uint8_t * apdu, uint16_t value)
-{
-#if BIG_ENDIAN
- apdu[0] = (uint8_t)(value & 0x00ff);
- apdu[1] = (uint8_t)((value & 0xff00) >> 8);
-#else
- apdu[0] = (uint8_t)((value & 0xff00) >> 8);
- apdu[1] = (uint8_t)(value & 0x00ff);
-#endif
-
- return 2;
-}
-
-int decode_unsigned16(uint8_t * apdu, uint16_t * value)
-{
- if (value) {
-#if BIG_ENDIAN
- *value = (uint16_t)(apdu[0] & 0x00ff);
- *value |= ((uint16_t)((apdu[1] << 8) & 0xff00));
-#else
- *value = (uint16_t)((apdu[0] << 8) & 0xff00);
- *value |= ((uint16_t)(apdu[1] & 0x00ff));
-#endif
- }
-
- return 2;
-}
-
-int encode_unsigned24(uint8_t * apdu, uint32_t value)
-{
-#if BIG_ENDIAN
- apdu[0] = (uint8_t)(value & 0x0000ff);
- apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
- apdu[2] = (uint8_t)((value & 0xff0000) >> 16);
-#else
- apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
- apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
- apdu[2] = (uint8_t)(value & 0x0000ff);
-#endif
-
- return 3;
-}
-
-int decode_unsigned24(uint8_t * apdu, uint32_t * value)
-{
- if (value) {
-#if BIG_ENDIAN
- *value = (uint32_t)(apdu[0] & 0x000000ff);
- *value |= ((uint32_t)((apdu[1] << 8) & 0x0000ff00));
- *value |= ((uint32_t)((apdu[2] << 16) & 0x00ff0000));
-#else
- *value = ((uint32_t)((apdu[0] << 16) & 0x00ff0000));
- *value |= (uint32_t)((apdu[1] << 8) & 0x0000ff00);
- *value |= ((uint32_t)(apdu[2] & 0x000000ff));
-#endif
- }
-
- return 3;
-}
-
-int encode_unsigned32(uint8_t * apdu, uint32_t value)
-{
-#if BIG_ENDIAN
- apdu[0] = (uint8_t)(value & 0x000000ff);
- apdu[1] = (uint8_t)((value & 0x0000ff00) >> 8);
- apdu[2] = (uint8_t)((value & 0x00ff0000) >> 16);
- apdu[3] = (uint8_t)((value & 0xff000000) >> 24);
-#else
- 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);
-#endif
-
- return 4;
-}
-
-int decode_unsigned32(uint8_t * apdu, uint32_t * value)
-{
- if (value) {
-#if BIG_ENDIAN
- *value = (uint32_t)(apdu[0] & 0x000000ff);
- *value |= ((uint32_t)((apdu[1] << 8) & 0x0000ff00));
- *value |= ((uint32_t)((apdu[2] << 16) & 0x00ff0000));
- *value |= ((uint32_t)((apdu[3] << 24) & 0xff000000));
-#else
- *value = ((uint32_t)((apdu[0] << 24) & 0xff000000));
- *value |= ((uint32_t)((apdu[1] << 16) & 0x00ff0000));
- *value |= ((uint32_t)((apdu[2] << 8) & 0x0000ff00));
- *value |= ((uint32_t)(apdu[3] & 0x000000ff));
-#endif
- }
-
- return 4;
-}
-
-int encode_signed8(uint8_t * apdu, int8_t value)
-{
- apdu[0] = (uint8_t)value;
-
- return 1;
-}
-
-int decode_signed8(uint8_t * apdu, int32_t * value)
-{
- if (value) {
-#if BIG_ENDIAN
- /* negative - bit 7 is set */
- if (apdu[0] & 0x80)
- *value = 0x00FFFFFF;
- else
- *value = 0;
- *value |= ((int32_t)((apdu[0] << 24) & 0xff000000));
-#else
- /* negative - bit 7 is set */
- if (apdu[0] & 0x80)
- *value = 0xFFFFFF00;
- else
- *value = 0;
- *value |= ((int32_t)(apdu[0] & 0x000000ff));
-#endif
- }
-
- return 1;
-}
-
-int encode_signed16(uint8_t * apdu, int16_t value)
-{
-#if BIG_ENDIAN
- apdu[0] = (uint8_t)(value & 0x00ff);
- apdu[1] = (uint8_t)((value & 0xff00) >> 8);
-#else
- apdu[0] = (uint8_t)((value & 0xff00) >> 8);
- apdu[1] = (uint8_t)(value & 0x00ff);
-#endif
-
- return 2;
-}
-
-int decode_signed16(uint8_t * apdu, int32_t * value)
-{
- if (value) {
-#if BIG_ENDIAN
- /* negative - bit 7 is set */
- if (apdu[0] & 0x80)
- *value = 0x0000FFFF;
- else
- *value = 0;
- *value |= ((int32_t)((apdu[0] << 24) & 0xff000000));
- *value |= ((int32_t)((apdu[1] << 16) & 0x00ff0000));
-#else
- /* negative - bit 7 is set */
- if (apdu[0] & 0x80)
- *value = 0xFFFF0000;
- else
- *value = 0;
- *value |= ((int32_t)((apdu[0] << 8) & 0x0000ff00));
- *value |= ((int32_t)(apdu[1] & 0x000000ff));
-#endif
- }
-
- return 2;
-}
-
-int encode_signed24(uint8_t * apdu, int32_t value)
-{
-#if BIG_ENDIAN
- apdu[0] = (uint8_t)(value & 0x0000ff);
- apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
- apdu[2] = (uint8_t)((value & 0xff0000) >> 16);
-#else
- apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
- apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
- apdu[2] = (uint8_t)(value & 0x0000ff);
-#endif
-
- return 3;
-}
-
-int decode_signed24(uint8_t * apdu, int32_t * value)
-{
- if (value) {
-#if BIG_ENDIAN
- /* negative - bit 7 is set */
- if (apdu[0] & 0x80)
- *value = 0x000000FF;
- else
- *value = 0;
- *value |= ((uint32_t)((apdu[0] << 8) & 0x0000ff00));
- *value |= ((uint32_t)((apdu[1] << 16) & 0x00ff0000));
- *value |= ((uint32_t)((apdu[2] << 24) & 0xff000000));
-#else
- /* negative - bit 7 is set */
- if (apdu[0] & 0x80)
- *value = 0xFF000000;
- else
- *value = 0;
- *value |= ((uint32_t)((apdu[0] << 16) & 0x00ff0000));
- *value |= ((uint32_t)((apdu[1] << 8) & 0x0000ff00));
- *value |= ((uint32_t)(apdu[2] & 0x000000ff));
-#endif
- }
-
- return 3;
-}
-
-int encode_signed32(uint8_t * apdu, int32_t value)
-{
-#if BIG_ENDIAN
- apdu[0] = (uint8_t)(value & 0x000000ff);
- apdu[1] = (uint8_t)((value & 0x0000ff00) >> 8);
- apdu[2] = (uint8_t)((value & 0x00ff0000) >> 16);
- apdu[3] = (uint8_t)((value & 0xff000000) >> 24);
-#else
- 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);
-#endif
-
- return 4;
-}
-
-int decode_signed32(uint8_t * apdu, int32_t * value)
-{
- if (value) {
-#if BIG_ENDIAN
- *value = (int32_t)(apdu[0] & 0x000000ff);
- *value |= ((int32_t)((apdu[1] << 8) & 0x0000ff00));
- *value |= ((int32_t)((apdu[2] << 16) & 0x00ff0000));
- *value |= ((int32_t)((apdu[3] << 24) & 0xff000000));
-#else
- *value = ((int32_t)((apdu[0] << 24) & 0xff000000));
- *value |= ((int32_t)((apdu[1] << 16) & 0x00ff0000));
- *value |= ((int32_t)((apdu[2] << 8) & 0x0000ff00));
- *value |= ((int32_t)(apdu[3] & 0x000000ff));
-#endif
- }
-
- return 4;
-}
-
-/* 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 */
-int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t * value)
-{
- if (value) {
- switch (len_value) {
- case 1:
- decode_signed8(&apdu[0], value);
- break;
- case 2:
- decode_signed16(&apdu[0], value);
- break;
- case 3:
- decode_signed24(&apdu[0], value);
- break;
- case 4:
- decode_signed32(&apdu[0], value);
- break;
- default:
- *value = 0;
- break;
- }
- }
-
- return len_value;
-}
-
-/* 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 */
-int encode_bacnet_signed(uint8_t * apdu, int32_t value)
-{
- int len = 0; /* return value */
-
- /* don't encode the leading X'FF' or X'00' of the two's compliment.
- That is, the first octet of any multi-octet encoded value shall
- not be X'00' if the most significant bit (bit 7) of the second
- octet is 0, and the first octet shall not be X'FF' if the most
- significant bit of the second octet is 1. */
- if ((value >= -128) && (value < 128)) {
- len = encode_signed8(&apdu[0], (int8_t) value);
- } else if ((value >= -32768) && (value < 32768)) {
- len = encode_signed16(&apdu[0], (int16_t) value);
- } else if ((value > -8388608) && (value < 8388608)) {
- len = encode_signed24(&apdu[0], value);
- } else {
- len = encode_signed32(&apdu[0], value);
- }
-
- 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 */
-int encode_bacnet_unsigned(uint8_t * apdu, uint32_t value)
-{
- int len = 0; /* return value */
-
- if (value < 0x100) {
- apdu[0] = (uint8_t) value;
- len = 1;
- } else if (value < 0x10000) {
- len = encode_unsigned16(&apdu[0], (uint16_t) value);
- } else if (value < 0x1000000) {
- len = encode_unsigned24(&apdu[0], value);
- } else {
- len = encode_unsigned32(&apdu[0], value);
- }
-
- 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 */
-int decode_unsigned(uint8_t * apdu, uint32_t len_value, uint32_t * value)
-{
- uint16_t unsigned16_value = 0;
-
- if (value) {
- switch (len_value) {
- case 1:
- *value = apdu[0];
- break;
- case 2:
- decode_unsigned16(&apdu[0], &unsigned16_value);
- *value = unsigned16_value;
- break;
- case 3:
- decode_unsigned24(&apdu[0], value);
- break;
- case 4:
- decode_unsigned32(&apdu[0], value);
- break;
- default:
- *value = 0;
- break;
- }
- }
-
- return len_value;
-}
-
-/* end of decoding_encoding.c */
-#ifdef TEST
-#include
-#include
-#include
-#include "ctest.h"
-
-void testBACnetUnsigned16(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- uint16_t value = 0, test_value = 0;
- int len = 0;
-
- for (value = 0; ; value++) {
- len = encode_unsigned16(&apdu[0], value);
- ct_test(pTest, len == 2);
- len = decode_unsigned16(&apdu[0], &test_value);
- ct_test(pTest, value == test_value);
- if (value == 0xFFFF)
- break;
- }
-}
-
-void testBACnetUnsigned24(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- uint32_t value = 0, test_value = 0;
- int len = 0;
-
- for (value = 0; ; value+=0xf) {
- len = encode_unsigned24(&apdu[0], value);
- ct_test(pTest, len == 3);
- len = decode_unsigned24(&apdu[0], &test_value);
- ct_test(pTest, value == test_value);
- if (value == 0xffffff)
- break;
- }
-}
-
-void testBACnetUnsigned32(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- uint32_t value = 0, test_value = 0;
- int len = 0;
-
- for (value = 0; ; value+=0xff) {
- len = encode_unsigned32(&apdu[0], value);
- ct_test(pTest, len == 4);
- len = decode_unsigned32(&apdu[0], &test_value);
- ct_test(pTest, value == test_value);
- if (value == 0xffffffff)
- break;
- }
-}
-
-void testBACnetSigned8(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- int32_t value = 0, test_value = 0;
- int len = 0;
-
- for (value = -127; ; value++) {
- len = encode_signed8(&apdu[0], value);
- ct_test(pTest, len == 1);
- len = decode_signed8(&apdu[0], &test_value);
- ct_test(pTest, value == test_value);
- if (value == 127)
- break;
- }
-}
-
-void testBACnetSigned16(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- int32_t value = 0, test_value = 0;
- int len = 0;
-
- for (value = -32767; ; value++) {
- len = encode_signed16(&apdu[0], value);
- ct_test(pTest, len == 2);
- len = decode_signed16(&apdu[0], &test_value);
- ct_test(pTest, value == test_value);
- if (value == 32767)
- break;
- }
-}
-
-void testBACnetSigned24(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- int32_t value = 0, test_value = 0;
- int len = 0;
-
- for (value = -8388607; value <= 8388607; value+=15) {
- len = encode_signed24(&apdu[0], value);
- ct_test(pTest, len == 3);
- len = decode_signed24(&apdu[0], &test_value);
- ct_test(pTest, value == test_value);
- }
-}
-
-void testBACnetSigned32(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- int32_t value = 0, test_value = 0;
- int len = 0;
-
- for (value = -2147483647; value < 0; value+=127) {
- len = encode_signed32(&apdu[0], value);
- ct_test(pTest, len == 4);
- len = decode_signed32(&apdu[0], &test_value);
- ct_test(pTest, value == test_value);
- }
- for (value = 2147483647; value > 0; value-=127) {
- len = encode_signed32(&apdu[0], value);
- ct_test(pTest, len == 4);
- len = decode_signed32(&apdu[0], &test_value);
- ct_test(pTest, value == test_value);
- }
-}
-
-void testBACnetSigned(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- int32_t value = 0, test_value = 0;
- int len = 0, test_len = 0;
-
- for (value = -2147483647; value < 0; value+=127) {
- len = encode_bacnet_signed(&apdu[0], value);
- test_len = decode_signed(&apdu[0], len, &test_value);
- ct_test(pTest, len == test_len);
- ct_test(pTest, value == test_value);
- }
- for (value = 2147483647; value > 0; value-=127) {
- len = encode_bacnet_signed(&apdu[0], value);
- test_len = decode_signed(&apdu[0], len, &test_value);
- ct_test(pTest, len == test_len);
- ct_test(pTest, value == test_value);
- }
-}
-
-void testBACnetUnsigned(Test * pTest)
-{
- uint8_t apdu[32] = { 0 };
- uint32_t value = 0, test_value = 0;
- int len = 0, test_len = 0;
-
- for (value = 0; ;value+=0xFF) {
- len = encode_bacnet_unsigned(&apdu[0], value);
- test_len = decode_unsigned(&apdu[0], len, &test_value);
- ct_test(pTest, len == test_len);
- ct_test(pTest, value == test_value);
- if (value == 0xFFFFFFFF)
- break;
- }
-}
-
-
-#ifdef TEST_BACINT
-int main(void)
-{
- Test *pTest;
- bool rc;
-
- pTest = ct_create("BACint", NULL);
- /* individual tests */
- rc = ct_addTestFunction(pTest, testBACnetUnsigned16);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetUnsigned24);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetUnsigned32);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetSigned8);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetSigned16);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetSigned24);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetSigned32);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetSigned);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetUnsigned);
- assert(rc);
- /* configure output */
- ct_setStream(pTest, stdout);
- ct_run(pTest);
- (void) ct_report(pTest);
- ct_destroy(pTest);
-
- return 0;
-}
-#endif /* TEST_DECODE */
-#endif /* TEST */
+/*####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####*/
+
+/* BACnet Integer encoding and decoding */
+
+#include
+#include
+
+int encode_unsigned16(uint8_t * apdu, uint16_t value)
+{
+#if BIG_ENDIAN
+ apdu[0] = (uint8_t)(value & 0x00ff);
+ apdu[1] = (uint8_t)((value & 0xff00) >> 8);
+#else
+ apdu[0] = (uint8_t)((value & 0xff00) >> 8);
+ apdu[1] = (uint8_t)(value & 0x00ff);
+#endif
+
+ return 2;
+}
+
+int decode_unsigned16(uint8_t * apdu, uint16_t * value)
+{
+ if (value) {
+#if BIG_ENDIAN
+ *value = (uint16_t)(apdu[0] & 0x00ff);
+ *value |= ((uint16_t)((apdu[1] << 8) & 0xff00));
+#else
+ *value = (uint16_t)((apdu[0] << 8) & 0xff00);
+ *value |= ((uint16_t)(apdu[1] & 0x00ff));
+#endif
+ }
+
+ return 2;
+}
+
+int encode_unsigned24(uint8_t * apdu, uint32_t value)
+{
+#if BIG_ENDIAN
+ apdu[0] = (uint8_t)(value & 0x0000ff);
+ apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
+ apdu[2] = (uint8_t)((value & 0xff0000) >> 16);
+#else
+ apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
+ apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
+ apdu[2] = (uint8_t)(value & 0x0000ff);
+#endif
+
+ return 3;
+}
+
+int decode_unsigned24(uint8_t * apdu, uint32_t * value)
+{
+ if (value) {
+#if BIG_ENDIAN
+ *value = (uint32_t)(apdu[0] & 0x000000ff);
+ *value |= ((uint32_t)((apdu[1] << 8) & 0x0000ff00));
+ *value |= ((uint32_t)((apdu[2] << 16) & 0x00ff0000));
+#else
+ *value = ((uint32_t)((apdu[0] << 16) & 0x00ff0000));
+ *value |= (uint32_t)((apdu[1] << 8) & 0x0000ff00);
+ *value |= ((uint32_t)(apdu[2] & 0x000000ff));
+#endif
+ }
+
+ return 3;
+}
+
+int encode_unsigned32(uint8_t * apdu, uint32_t value)
+{
+#if BIG_ENDIAN
+ apdu[0] = (uint8_t)(value & 0x000000ff);
+ apdu[1] = (uint8_t)((value & 0x0000ff00) >> 8);
+ apdu[2] = (uint8_t)((value & 0x00ff0000) >> 16);
+ apdu[3] = (uint8_t)((value & 0xff000000) >> 24);
+#else
+ 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);
+#endif
+
+ return 4;
+}
+
+int decode_unsigned32(uint8_t * apdu, uint32_t * value)
+{
+ if (value) {
+#if BIG_ENDIAN
+ *value = (uint32_t)(apdu[0] & 0x000000ff);
+ *value |= ((uint32_t)((apdu[1] << 8) & 0x0000ff00));
+ *value |= ((uint32_t)((apdu[2] << 16) & 0x00ff0000));
+ *value |= ((uint32_t)((apdu[3] << 24) & 0xff000000));
+#else
+ *value = ((uint32_t)((apdu[0] << 24) & 0xff000000));
+ *value |= ((uint32_t)((apdu[1] << 16) & 0x00ff0000));
+ *value |= ((uint32_t)((apdu[2] << 8) & 0x0000ff00));
+ *value |= ((uint32_t)(apdu[3] & 0x000000ff));
+#endif
+ }
+
+ return 4;
+}
+
+int encode_signed8(uint8_t * apdu, int8_t value)
+{
+ apdu[0] = (uint8_t)value;
+
+ return 1;
+}
+
+int decode_signed8(uint8_t * apdu, int32_t * value)
+{
+ if (value) {
+#if BIG_ENDIAN
+ /* negative - bit 7 is set */
+ if (apdu[0] & 0x80)
+ *value = 0x00FFFFFF;
+ else
+ *value = 0;
+ *value |= ((int32_t)((apdu[0] << 24) & 0xff000000));
+#else
+ /* negative - bit 7 is set */
+ if (apdu[0] & 0x80)
+ *value = 0xFFFFFF00;
+ else
+ *value = 0;
+ *value |= ((int32_t)(apdu[0] & 0x000000ff));
+#endif
+ }
+
+ return 1;
+}
+
+int encode_signed16(uint8_t * apdu, int16_t value)
+{
+#if BIG_ENDIAN
+ apdu[0] = (uint8_t)(value & 0x00ff);
+ apdu[1] = (uint8_t)((value & 0xff00) >> 8);
+#else
+ apdu[0] = (uint8_t)((value & 0xff00) >> 8);
+ apdu[1] = (uint8_t)(value & 0x00ff);
+#endif
+
+ return 2;
+}
+
+int decode_signed16(uint8_t * apdu, int32_t * value)
+{
+ if (value) {
+#if BIG_ENDIAN
+ /* negative - bit 7 is set */
+ if (apdu[0] & 0x80)
+ *value = 0x0000FFFF;
+ else
+ *value = 0;
+ *value |= ((int32_t)((apdu[0] << 24) & 0xff000000));
+ *value |= ((int32_t)((apdu[1] << 16) & 0x00ff0000));
+#else
+ /* negative - bit 7 is set */
+ if (apdu[0] & 0x80)
+ *value = 0xFFFF0000;
+ else
+ *value = 0;
+ *value |= ((int32_t)((apdu[0] << 8) & 0x0000ff00));
+ *value |= ((int32_t)(apdu[1] & 0x000000ff));
+#endif
+ }
+
+ return 2;
+}
+
+int encode_signed24(uint8_t * apdu, int32_t value)
+{
+#if BIG_ENDIAN
+ apdu[0] = (uint8_t)(value & 0x0000ff);
+ apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
+ apdu[2] = (uint8_t)((value & 0xff0000) >> 16);
+#else
+ apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
+ apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
+ apdu[2] = (uint8_t)(value & 0x0000ff);
+#endif
+
+ return 3;
+}
+
+int decode_signed24(uint8_t * apdu, int32_t * value)
+{
+ if (value) {
+#if BIG_ENDIAN
+ /* negative - bit 7 is set */
+ if (apdu[0] & 0x80)
+ *value = 0x000000FF;
+ else
+ *value = 0;
+ *value |= ((uint32_t)((apdu[0] << 8) & 0x0000ff00));
+ *value |= ((uint32_t)((apdu[1] << 16) & 0x00ff0000));
+ *value |= ((uint32_t)((apdu[2] << 24) & 0xff000000));
+#else
+ /* negative - bit 7 is set */
+ if (apdu[0] & 0x80)
+ *value = 0xFF000000;
+ else
+ *value = 0;
+ *value |= ((uint32_t)((apdu[0] << 16) & 0x00ff0000));
+ *value |= ((uint32_t)((apdu[1] << 8) & 0x0000ff00));
+ *value |= ((uint32_t)(apdu[2] & 0x000000ff));
+#endif
+ }
+
+ return 3;
+}
+
+int encode_signed32(uint8_t * apdu, int32_t value)
+{
+#if BIG_ENDIAN
+ apdu[0] = (uint8_t)(value & 0x000000ff);
+ apdu[1] = (uint8_t)((value & 0x0000ff00) >> 8);
+ apdu[2] = (uint8_t)((value & 0x00ff0000) >> 16);
+ apdu[3] = (uint8_t)((value & 0xff000000) >> 24);
+#else
+ 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);
+#endif
+
+ return 4;
+}
+
+int decode_signed32(uint8_t * apdu, int32_t * value)
+{
+ if (value) {
+#if BIG_ENDIAN
+ *value = (int32_t)(apdu[0] & 0x000000ff);
+ *value |= ((int32_t)((apdu[1] << 8) & 0x0000ff00));
+ *value |= ((int32_t)((apdu[2] << 16) & 0x00ff0000));
+ *value |= ((int32_t)((apdu[3] << 24) & 0xff000000));
+#else
+ *value = ((int32_t)((apdu[0] << 24) & 0xff000000));
+ *value |= ((int32_t)((apdu[1] << 16) & 0x00ff0000));
+ *value |= ((int32_t)((apdu[2] << 8) & 0x0000ff00));
+ *value |= ((int32_t)(apdu[3] & 0x000000ff));
+#endif
+ }
+
+ return 4;
+}
+
+/* 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 */
+int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t * value)
+{
+ if (value) {
+ switch (len_value) {
+ case 1:
+ decode_signed8(&apdu[0], value);
+ break;
+ case 2:
+ decode_signed16(&apdu[0], value);
+ break;
+ case 3:
+ decode_signed24(&apdu[0], value);
+ break;
+ case 4:
+ decode_signed32(&apdu[0], value);
+ break;
+ default:
+ *value = 0;
+ break;
+ }
+ }
+
+ return len_value;
+}
+
+/* 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 */
+int encode_bacnet_signed(uint8_t * apdu, int32_t value)
+{
+ int len = 0; /* return value */
+
+ /* don't encode the leading X'FF' or X'00' of the two's compliment.
+ That is, the first octet of any multi-octet encoded value shall
+ not be X'00' if the most significant bit (bit 7) of the second
+ octet is 0, and the first octet shall not be X'FF' if the most
+ significant bit of the second octet is 1. */
+ if ((value >= -128) && (value < 128)) {
+ len = encode_signed8(&apdu[0], (int8_t) value);
+ } else if ((value >= -32768) && (value < 32768)) {
+ len = encode_signed16(&apdu[0], (int16_t) value);
+ } else if ((value > -8388608) && (value < 8388608)) {
+ len = encode_signed24(&apdu[0], value);
+ } else {
+ len = encode_signed32(&apdu[0], value);
+ }
+
+ 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 */
+int encode_bacnet_unsigned(uint8_t * apdu, uint32_t value)
+{
+ int len = 0; /* return value */
+
+ if (value < 0x100) {
+ apdu[0] = (uint8_t) value;
+ len = 1;
+ } else if (value < 0x10000) {
+ len = encode_unsigned16(&apdu[0], (uint16_t) value);
+ } else if (value < 0x1000000) {
+ len = encode_unsigned24(&apdu[0], value);
+ } else {
+ len = encode_unsigned32(&apdu[0], value);
+ }
+
+ 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 */
+int decode_unsigned(uint8_t * apdu, uint32_t len_value, uint32_t * value)
+{
+ uint16_t unsigned16_value = 0;
+
+ if (value) {
+ switch (len_value) {
+ case 1:
+ *value = apdu[0];
+ break;
+ case 2:
+ decode_unsigned16(&apdu[0], &unsigned16_value);
+ *value = unsigned16_value;
+ break;
+ case 3:
+ decode_unsigned24(&apdu[0], value);
+ break;
+ case 4:
+ decode_unsigned32(&apdu[0], value);
+ break;
+ default:
+ *value = 0;
+ break;
+ }
+ }
+
+ return len_value;
+}
+
+/* end of decoding_encoding.c */
+#ifdef TEST
+#include
+#include
+#include
+#include "ctest.h"
+
+void testBACnetUnsigned16(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ uint16_t value = 0, test_value = 0;
+ int len = 0;
+
+ for (value = 0; ; value++) {
+ len = encode_unsigned16(&apdu[0], value);
+ ct_test(pTest, len == 2);
+ len = decode_unsigned16(&apdu[0], &test_value);
+ ct_test(pTest, value == test_value);
+ if (value == 0xFFFF)
+ break;
+ }
+}
+
+void testBACnetUnsigned24(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ uint32_t value = 0, test_value = 0;
+ int len = 0;
+
+ for (value = 0; ; value+=0xf) {
+ len = encode_unsigned24(&apdu[0], value);
+ ct_test(pTest, len == 3);
+ len = decode_unsigned24(&apdu[0], &test_value);
+ ct_test(pTest, value == test_value);
+ if (value == 0xffffff)
+ break;
+ }
+}
+
+void testBACnetUnsigned32(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ uint32_t value = 0, test_value = 0;
+ int len = 0;
+
+ for (value = 0; ; value+=0xff) {
+ len = encode_unsigned32(&apdu[0], value);
+ ct_test(pTest, len == 4);
+ len = decode_unsigned32(&apdu[0], &test_value);
+ ct_test(pTest, value == test_value);
+ if (value == 0xffffffff)
+ break;
+ }
+}
+
+void testBACnetSigned8(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ int32_t value = 0, test_value = 0;
+ int len = 0;
+
+ for (value = -127; ; value++) {
+ len = encode_signed8(&apdu[0], value);
+ ct_test(pTest, len == 1);
+ len = decode_signed8(&apdu[0], &test_value);
+ ct_test(pTest, value == test_value);
+ if (value == 127)
+ break;
+ }
+}
+
+void testBACnetSigned16(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ int32_t value = 0, test_value = 0;
+ int len = 0;
+
+ for (value = -32767; ; value++) {
+ len = encode_signed16(&apdu[0], value);
+ ct_test(pTest, len == 2);
+ len = decode_signed16(&apdu[0], &test_value);
+ ct_test(pTest, value == test_value);
+ if (value == 32767)
+ break;
+ }
+}
+
+void testBACnetSigned24(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ int32_t value = 0, test_value = 0;
+ int len = 0;
+
+ for (value = -8388607; value <= 8388607; value+=15) {
+ len = encode_signed24(&apdu[0], value);
+ ct_test(pTest, len == 3);
+ len = decode_signed24(&apdu[0], &test_value);
+ ct_test(pTest, value == test_value);
+ }
+}
+
+void testBACnetSigned32(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ int32_t value = 0, test_value = 0;
+ int len = 0;
+
+ for (value = -2147483647; value < 0; value+=127) {
+ len = encode_signed32(&apdu[0], value);
+ ct_test(pTest, len == 4);
+ len = decode_signed32(&apdu[0], &test_value);
+ ct_test(pTest, value == test_value);
+ }
+ for (value = 2147483647; value > 0; value-=127) {
+ len = encode_signed32(&apdu[0], value);
+ ct_test(pTest, len == 4);
+ len = decode_signed32(&apdu[0], &test_value);
+ ct_test(pTest, value == test_value);
+ }
+}
+
+void testBACnetSigned(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ int32_t value = 0, test_value = 0;
+ int len = 0, test_len = 0;
+
+ for (value = -2147483647; value < 0; value+=127) {
+ len = encode_bacnet_signed(&apdu[0], value);
+ test_len = decode_signed(&apdu[0], len, &test_value);
+ ct_test(pTest, len == test_len);
+ ct_test(pTest, value == test_value);
+ }
+ for (value = 2147483647; value > 0; value-=127) {
+ len = encode_bacnet_signed(&apdu[0], value);
+ test_len = decode_signed(&apdu[0], len, &test_value);
+ ct_test(pTest, len == test_len);
+ ct_test(pTest, value == test_value);
+ }
+}
+
+void testBACnetUnsigned(Test * pTest)
+{
+ uint8_t apdu[32] = { 0 };
+ uint32_t value = 0, test_value = 0;
+ int len = 0, test_len = 0;
+
+ for (value = 0; ;value+=0xFF) {
+ len = encode_bacnet_unsigned(&apdu[0], value);
+ test_len = decode_unsigned(&apdu[0], len, &test_value);
+ ct_test(pTest, len == test_len);
+ ct_test(pTest, value == test_value);
+ if (value == 0xFFFFFFFF)
+ break;
+ }
+}
+
+
+#ifdef TEST_BACINT
+int main(void)
+{
+ Test *pTest;
+ bool rc;
+
+ pTest = ct_create("BACint", NULL);
+ /* individual tests */
+ rc = ct_addTestFunction(pTest, testBACnetUnsigned16);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testBACnetUnsigned24);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testBACnetUnsigned32);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testBACnetSigned8);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testBACnetSigned16);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testBACnetSigned24);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testBACnetSigned32);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testBACnetSigned);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testBACnetUnsigned);
+ assert(rc);
+ /* configure output */
+ ct_setStream(pTest, stdout);
+ ct_run(pTest);
+ (void) ct_report(pTest);
+ ct_destroy(pTest);
+
+ return 0;
+}
+#endif /* TEST_DECODE */
+#endif /* TEST */
diff --git a/bacnet-stack/bacnet.h b/bacnet-stack/bacnet.h
index 78404f2c..5c26f8ca 100644
--- a/bacnet-stack/bacnet.h
+++ b/bacnet-stack/bacnet.h
@@ -1,76 +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 BACNET_H
-#define BACNET_H
-
-/* This file is designed to reference the entire BACnet stack library */
-
-/* core files */
-#include "config.h"
-#include "address.h"
-#include "apdu.h"
-#include "bacapp.h"
-#include "bacdcode.h"
-#include "bacdef.h"
-#include "bacenum.h"
-#include "bacerror.h"
-#include "bacstr.h"
-#include "bactext.h"
-#include "datalink.h"
-#include "indtext.h"
-#include "npdu.h"
-#include "reject.h"
-#include "tsm.h"
-
-/* services */
-#include "arf.h"
-#include "awf.h"
-#include "cov.h"
-#include "dcc.h"
-#include "iam.h"
-#include "ihave.h"
-#include "rd.h"
-#include "rp.h"
-#include "rpm.h"
-#include "timesync.h"
-#include "whohas.h"
-#include "whois.h"
-#include "wp.h"
-
-/* required object - note: developer must supply the device.c file
- since it is not included in the library. However, the library
- references the device.c members via the device.h API. */
-#include "device.h"
-
-#endif
+/*####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_H
+#define BACNET_H
+
+/* This file is designed to reference the entire BACnet stack library */
+
+/* core files */
+#include "config.h"
+#include "address.h"
+#include "apdu.h"
+#include "bacapp.h"
+#include "bacdcode.h"
+#include "bacdef.h"
+#include "bacenum.h"
+#include "bacerror.h"
+#include "bacstr.h"
+#include "bactext.h"
+#include "datalink.h"
+#include "indtext.h"
+#include "npdu.h"
+#include "reject.h"
+#include "tsm.h"
+
+/* services */
+#include "arf.h"
+#include "awf.h"
+#include "cov.h"
+#include "dcc.h"
+#include "iam.h"
+#include "ihave.h"
+#include "rd.h"
+#include "rp.h"
+#include "rpm.h"
+#include "timesync.h"
+#include "whohas.h"
+#include "whois.h"
+#include "wp.h"
+
+/* required object - note: developer must supply the device.c file
+ since it is not included in the library. However, the library
+ references the device.c members via the device.h API. */
+#include "device.h"
+
+#endif
diff --git a/bacnet-stack/bvlc.c b/bacnet-stack/bvlc.c
index 4e89cad9..c12e7bc2 100644
--- a/bacnet-stack/bvlc.c
+++ b/bacnet-stack/bvlc.c
@@ -1,731 +1,731 @@
-/*####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####*/
-
-#include /* for standard integer types uint8_t etc. */
-#include /* for the standard bool type. */
-#include /* for the standard bool type. */
-#include "bacdcode.h"
-#include "bip.h"
-#include "net.h" /* custom per port */
-
-/* Handle the BACnet Virtual Link Control (BVLC), which includes:
- BACnet Broadcast Management Device,
- Broadcast Distribution Table, and
- Foreign Device Registration */
-
-typedef struct
-{
- /* true if valid entry - false if not */
- bool valid;
- /* BACnet/IP address */
- struct in_addr dest_address;
- /* BACnet/IP port number - not always 47808=BAC0h */
- uint16_t dest_port;
- /* Broadcast Distribution Mask - stored in host byte order */
- struct in_addr broadcast_mask;
-} BBMD_TABLE_ENTRY;
-
-#define MAX_BBMD_ENTRIES 128
-static BBMD_TABLE_ENTRY BBMD_Table[MAX_BBMD_ENTRIES];
-
-/*Each device that registers as a foreign device shall be placed
-in an entry in the BBMD's Foreign Device Table (FDT). Each
-entry shall consist of the 6-octet B/IP address of the registrant;
-the 2-octet Time-to-Live value supplied at the time of
-registration; and a 2-octet value representing the number of
-seconds remaining before the BBMD will purge the registrant's FDT
-entry if no re-registration occurs. This value will be initialized
-to the 2-octet Time-to-Live value supplied at the time of
-registration.*/
-typedef struct
-{
- bool valid;
- /* BACnet/IP address */
- struct in_addr dest_address;
- /* BACnet/IP port number - not always 47808=BAC0h */
- uint16_t dest_port;
- /* seconds for valid entry lifetime */
- uint16_t time_to_live;
- /* our counter */
- time_t seconds_remaining; /* includes 30 second grace period */
-} FD_TABLE_ENTRY;
-
-#define MAX_FD_ENTRIES 128
-static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
-
-void bvlc_maintenance_timer(unsigned seconds)
-{
- unsigned i = 0;
-
- for (i = 0; i < MAX_FD_ENTRIES; i++) {
- if (FD_Table[i].valid) {
- if (FD_Table[i].seconds_remaining) {
- if (FD_Table[i].seconds_remaining < seconds) {
- FD_Table[i].seconds_remaining = 0;
- } else {
- FD_Table[i].seconds_remaining -= seconds;
- }
- if (FD_Table[i].seconds_remaining == 0) {
- FD_Table[i].valid = false;
- }
- }
- }
- }
-}
-
-int bvlc_encode_bip_address(
- uint8_t * pdu, /* buffer to store encoding */
- struct in_addr *address, /* in host format */
- uint16_t port)
-{
- int len = 0;
-
- if (pdu) {
- len = encode_unsigned32(&pdu[0], address->s_addr);
- len += encode_unsigned16(&pdu[len], port);
- }
-
- return len;
-}
-
-int bvlc_decode_bip_address(
- uint8_t * pdu, /* buffer to extract encoded address */
- struct in_addr * address, /* in host format */
- uint16_t * port)
-{
- int len = 0;
-
- if (pdu) {
- (void) decode_unsigned32(&pdu[0], &(address->s_addr));
- (void) decode_unsigned16(&pdu[4], port);
- len = 6;
- }
-
- return len;
-}
-
-/* used for both read and write entries */
-int bvlc_encode_address_entry(uint8_t * pdu,
- struct in_addr *address,
- uint16_t port,
- struct in_addr *mask)
-{
- int len = 0;
-
- if (pdu) {
- len = bvlc_encode_bip_address(pdu, address, port);
- len += encode_unsigned32(&pdu[len], mask->s_addr);
- }
-
- return len;
-}
-
-int bvlc_encode_bvlc_result(
- uint8_t * pdu,
- BACNET_BVLC_RESULT result_code)
-{
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_RESULT;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 6);
- encode_unsigned16(&pdu[4], result_code);
- }
-
- return 6;
-}
-
-int bvlc_encode_write_bdt_init(
- uint8_t * pdu,
- unsigned entries)
-{
- int len = 0;
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 4 + entries * 10);
- len = 4;
- }
-
- return len;
-}
-
-int bvlc_encode_read_bdt(
- uint8_t * pdu)
-{
- int len = 0;
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 4);
- len = 4;
- }
-
- return len;
-}
-
-int bvlc_encode_read_bdt_ack_init(
- uint8_t * pdu,
- unsigned entries)
-{
- int len = 0;
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 4 + entries * 10);
- len = 4;
- }
-
- return len;
-}
-
-int bvlc_encode_forwarded_npdu(uint8_t * pdu,
- BACNET_ADDRESS * src,
- uint8_t * npdu,
- unsigned npdu_length)
-{
- int len = 0;
-
- unsigned i; /* for loop counter */
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_FORWARDED_NPDU;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 4 + 6 + npdu_length);
- len = 4;
- for (i = 0; i < 6; i++) {
- pdu[len] = src->adr[i];
- len++;
- }
- for (i = 0; i < npdu_length; i++) {
- pdu[len] = npdu[i];
- len++;
- }
- }
-
- return len;
-}
-
-
-int bvlc_encode_register_foreign_device(uint8_t * pdu,
- uint16_t time_to_live_seconds)
-{
- int len = 0;
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_REGISTER_FOREIGN_DEVICE;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 6);
- encode_unsigned16(&pdu[2], time_to_live_seconds);
- len = 6;
- }
-
- return len;
-}
-
-int bvlc_encode_read_fdt(
- uint8_t * pdu)
-{
- int len = 0;
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 4);
- len = 4;
- }
-
- return len;
-}
-
-int bvlc_encode_read_fdt_ack_init(
- uint8_t * pdu,
- unsigned entries)
-{
- int len = 0;
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE_ACK;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 4 + entries * 10);
- len = 4;
- }
-
- return len;
-}
-
-int bvlc_encode_delete_fdt_entry(uint8_t * pdu,
- struct in_addr *address,
- uint16_t port)
-{
- int len = 0;
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- encode_unsigned16(&pdu[2], 10);
- /* FDT Entry */
- encode_unsigned32(&pdu[0], address->s_addr);
- encode_unsigned16(&pdu[4], port);
- len = 10;
- }
-
- return len;
-}
-
-int bvlc_encode_distribute_broadcast_to_network(uint8_t * pdu,
- uint8_t * npdu,
- unsigned npdu_length)
-{
- int len = 0; /* return value */
- unsigned i; /* for loop counter */
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- len = encode_unsigned16(&pdu[2], 4 + npdu_length) + 2;
- for (i = 0; i < npdu_length; i++) {
- pdu[len] = npdu[i];
- len++;
- }
- }
-
- return len;
-}
-
-int bvlc_encode_original_unicast_npdu(uint8_t * pdu,
- uint8_t * npdu,
- unsigned npdu_length)
-{
- int len = 0; /* return value */
- unsigned i = 0; /* loop counter */
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- len = encode_unsigned16(&pdu[2], 4 + npdu_length) + 2;
- for (i = 0; i < npdu_length; i++) {
- pdu[len] = npdu[i];
- len++;
- }
- }
-
- return len;
-}
-
-
-int bvlc_encode_original_broadcast_npdu(uint8_t * pdu,
- uint8_t * npdu,
- unsigned npdu_length)
-{
- int len = 0; /* return value */
- unsigned i = 0; /* loop counter */
-
- if (pdu) {
- pdu[0] = BVLL_TYPE_BACNET_IP;
- pdu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
- /* The 2-octet BVLC Length field is the length, in octets,
- of the entire BVLL message, including the two octets of the
- length field itself, most significant octet first. */
- len = encode_unsigned16(&pdu[2], 4 + npdu_length) + 2;
- for (i = 0; i < npdu_length; i++) {
- pdu[len] = npdu[i];
- len++;
- }
- }
-
- return len;
-}
-
-/* copy the source internet address to the BACnet address */
-/* FIXME: IPv6? */
-void bvlc_internet_to_bacnet_address(
- BACNET_ADDRESS * src, /* returns the BACnet source address */
- struct sockaddr_in *sin)
-{ /* source internet address */
- int len = 0;
- uint32_t address;
- uint16_t port;
-
- if (src && sin) {
- address = ntohl(sin->sin_addr.s_addr);
- len = encode_unsigned32(&src->mac[0], address);
- port = ntohs(sin->sin_port);
- len += encode_unsigned16(&src->mac[4], port);
- src->mac_len = len;
- src->net = 0;
- src->len = 0;
- }
-
- return;
-}
-
-/* copy the source internet address to the BACnet address */
-/* FIXME: IPv6? */
-/* FIXME: is sockaddr_in host or network order? */
-void bvlc_bacnet_to_internet_address(
- struct sockaddr_in *sin, /* source internet address */
- BACNET_ADDRESS * src) /* returns the BACnet source address */
-{
- int len = 0;
- uint32_t address;
- uint16_t port;
-
- if (src && sin) {
- if (src->mac_len == 6) {
- len = decode_unsigned32(&src->mac[0], &address);
- len += decode_unsigned16(&src->mac[4], &port );
- sin->sin_addr.s_addr = htonl(address);
- sin->sin_port = htons(port);
- }
- }
-
- return;
-}
-
-void bvlc_bdt_forward_npdu(
- struct sockaddr_in *sin, /* the source address */
- uint8_t * npdu, /* the NPDU */
- uint16_t npdu_length)
-{ /* length of the NPDU */
- uint8_t mtu[MAX_MPDU] = {0};
- int mtu_len = 0;
- int bytes_sent = 0;
- unsigned i = 0; /* loop counter */
- struct sockaddr_in bip_dest;
- BACNET_ADDRESS src;
-
- /* assumes that the driver has already been initialized */
- if (bip_socket() < 0) {
- return;
- }
- bvlc_internet_to_bacnet_address(&src, sin);
- mtu_len = bvlc_encode_forwarded_npdu(
- &mtu[0],
- &src,
- npdu,
- npdu_length);
- /* load destination IP address */
- bip_dest.sin_family = AF_INET;
- /* loop through the BDT and send one to each entry, except us */
- for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
- if (BBMD_Table[i].valid) {
- /* The B/IP address to which the Forwarded-NPDU message is
- sent is formed by inverting the broadcast distribution
- mask in the BDT entry and logically ORing it with the
- BBMD address of the same entry. */
- bip_dest.sin_addr.s_addr =
- htonl(((~BBMD_Table[i].broadcast_mask.s_addr) |
- BBMD_Table[i].dest_address.s_addr));
- bip_dest.sin_port = htons(BBMD_Table[i].dest_port);
- /* Send the packet */
- bytes_sent =
- sendto(bip_socket(), (char *) mtu, mtu_len, 0,
- (struct sockaddr *) &bip_dest,
- sizeof(struct sockaddr));
- }
- }
-
- return;
-}
-
-void bvlc_fdt_forward_npdu(
- struct sockaddr_in *sin, /* the source address */
- uint8_t * npdu, /* returns the NPDU */
- uint16_t max_npdu) /* amount of space available in the NPDU */
-{
-
- /* FIXME: add the code */
-}
-
-uint16_t bvlc_handler(
- BACNET_ADDRESS * src, /* returns the source address */
- uint8_t * npdu, /* returns the NPDU */
- uint16_t max_npdu, /* amount of space available in the NPDU */
- unsigned timeout) /* number of milliseconds to wait for a packet */
-{
- uint8_t buf[MAX_MPDU] = {0}; /* data */
- uint16_t pdu_len = 0; /* return value */
- fd_set read_fds;
- int max;
- struct timeval select_timeout;
- struct sockaddr_in sin = { -1 };
- socklen_t sin_len = sizeof(sin);
- int function_type = 0;
- int received_bytes;
-
- /* Make sure the socket is open */
- if (BIP_Socket < 0) {
- return 0;
- }
-
- /* we could just use a non-blocking socket, but that consumes all
- the CPU time. We can use a timeout; it is only supported as
- a select. */
- if (timeout >= 1000) {
- select_timeout.tv_sec = timeout / 1000;
- select_timeout.tv_usec =
- 1000 * (timeout - select_timeout.tv_sec * 1000);
- } else {
- select_timeout.tv_sec = 0;
- select_timeout.tv_usec = 1000 * timeout;
- }
- FD_ZERO(&read_fds);
- FD_SET((unsigned int) BIP_Socket, &read_fds);
- max = BIP_Socket;
- /* see if there is a packet for us */
- if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
- received_bytes = recvfrom(
- BIP_Socket,
- (char *) &buf[0],
- MAX_MPDU, 0,
- (struct sockaddr *) &sin, &sin_len);
- } else {
- return 0;
- }
- /* See if there is a problem */
- if (received_bytes < 0) {
- return 0;
- }
- /* no problem, just no bytes */
- if (received_bytes == 0) {
- return 0;
- }
- /* the signature of a BACnet/IP packet */
- if (buf[0] != BVLL_TYPE_BACNET_IP) {
- return 0;
- }
- function_type = buf[1];
- /* decode the length of the PDU - length is inclusive of BVLC */
- (void) decode_unsigned16(&buf[2], &npdu_len);
- /* subtract off the BVLC header */
- npdu_len -= 4;
- switch (function_type) {
- case BVLC_RESULT:
- break;
- case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
- /* Upon receipt of a BVLL Write-Broadcast-Distribution-Table
- message, a BBMD shall attempt to create or replace its BDT,
- depending on whether or not a BDT has previously existed.
- If the creation or replacement of the BDT is successful, the BBMD
- shall return a BVLC-Result message to the originating device with
- a result code of X'0000'. Otherwise, the BBMD shall return a
- BVLC-Result message to the originating device with a result code
- of X'0010' indicating that the write attempt has failed. */
- break;
- case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE:
- break;
- case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK:
- break;
- case BVLC_FORWARDED_NPDU:
- /* Upon receipt of a BVLL Forwarded-NPDU message, a BBMD shall
- process it according to whether it was received from a peer
- BBMD as the result of a directed broadcast or a unicast
- transmission. A BBMD may ascertain the method by which Forwarded-
- NPDU messages will arrive by inspecting the broadcast distribution
- mask field in its own BDT entry since all BDTs are required
- to be identical. If the message arrived via directed broadcast,
- it was also received by the other devices on the BBMD's subnet. In
- this case the BBMD merely retransmits the message directly to each
- foreign device currently in the BBMD's FDT. If the
- message arrived via a unicast transmission it has not yet been
- received by the other devices on the BBMD's subnet. In this case,
- the message is sent to the devices on the BBMD's subnet using the
- B/IP broadcast address as well as to each foreign device
- currently in the BBMD's FDT. A BBMD on a subnet with no other
- BACnet devices may omit the broadcast using the B/IP
- broadcast address. The method by which a BBMD determines whether
- or not other BACnet devices are present is a local matter. */
- bvlc_broadcast_npdu(&sin, &buf[4], npdu_len);
- bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
- break;
- case BVLC_REGISTER_FOREIGN_DEVICE:
- break;
- case BVLC_READ_FOREIGN_DEVICE_TABLE:
- break;
- case BVLC_READ_FOREIGN_DEVICE_TABLE_ACK:
- break;
- case BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY:
- break;
- case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK:
- bvlc_broadcast_forward_npdu(&sin, &buf[4], npdu_len);
- bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
- break;
- case BVLC_ORIGINAL_UNICAST_NPDU:
- /* ignore messages from me */
- if (sin.sin_addr.s_addr == BIP_Address.s_addr) {
- npdu_len = 0;
- } else {
- bvlc_internet_to_bacnet_address(src, &sin);
- if (npdu_len < max_npdu) {
- /* copy the buffer into the PDU */
- memmove(&npdu[0], &buf[4], npdu_len);
- } else {
- /* ignore packets that are too large */
- /* clients should check my max-apdu first */
- npdu_len = 0;
- }
- }
- break;
- case BVLC_ORIGINAL_BROADCAST_NPDU:
- /* Upon receipt of a BVLL Original-Broadcast-NPDU message,
- a BBMD shall construct a BVLL Forwarded-NPDU message and
- send it to each IP subnet in its BDT with the exception
- of its own. The B/IP address to which the Forwarded-NPDU
- message is sent is formed by inverting the broadcast
- distribution mask in the BDT entry and logically ORing it
- with the BBMD address of the same entry. This process
- produces either the directed broadcast address of the remote
- subnet or the unicast address of the BBMD on that subnet
- depending on the contents of the broadcast distribution
- mask. See J.4.3.2.. In addition, the received BACnet NPDU
- shall be sent directly to each foreign device currently in
- the BBMD's FDT also using the BVLL Forwarded-NPDU message. */
- bvlc_internet_to_bacnet_address(src, &sin);
- if (npdu_len < max_npdu) {
- /* copy the buffer into the PDU */
- memmove(&npdu[0], &buf[4], npdu_len);
- } else {
- /* ignore packets that are too large */
- /* clients should check my max-apdu first */
- npdu_len = 0;
- }
- /* if BDT or FDT entries exist, Forward the NPDU */
- bvlc_bdt_forward_npdu(&sin, &buf[4], npdu_len);
- bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
- break;
- default:
- break;
- }
-
- return npdu_len;
-}
-
-#ifdef TEST
-#include
-#include
-#include "ctest.h"
-
-void testBIPAddress(Test * pTest)
-{
- uint8_t apdu[50] = { 0 };
- uint32_t value = 0, test_value = 0;
- int len = 0, test_len = 0;
- struct in_addr address;
- struct in_addr test_address;
- uint16_t port = 0, test_port = 0;
-
- address.s_addr = 42;
- len = bvlc_encode_bip_address(&apdu[0],
- &address, port);
- test_len = bvlc_decode_bip_address(&apdu[0],
- &test_address, &test_port);
- ct_test(pTest, len == test_len);
- ct_test(pTest, address.s_addr == test_address.s_addr);
- ct_test(pTest, port == test_port);
-}
-
-void testInternetAddress(Test * pTest)
-{
- BACNET_ADDRESS src;
- BACNET_ADDRESS test_src;
- struct sockaddr_in sin;
- struct sockaddr_in test_sin;
-
- sin.sin_port = htons(0xBAC0);
- sin.sin_addr.s_addr = inet_addr("192.168.0.1");
- bvlc_internet_to_bacnet_address(&src, &sin);
- bvlc_bacnet_to_internet_address(&test_sin, &src);
- ct_test(pTest, sin.sin_port == test_sin.sin_port);
- ct_test(pTest, sin.sin_addr.s_addr == test_sin.sin_addr.s_addr);
-}
-
-#ifdef TEST_BVLC
-int main(void)
-{
- Test * pTest;
- bool rc;
-
- pTest = ct_create("BACnet Virtual Link Control", NULL);
- /* individual tests */
- rc = ct_addTestFunction(pTest, testBIPAddress);
- assert(rc);
- rc = ct_addTestFunction(pTest, testInternetAddress);
- assert(rc);
- /* configure output */
- ct_setStream(pTest, stdout);
- ct_run(pTest);
- (void) ct_report(pTest);
- ct_destroy(pTest);
-
- return 0;
-}
-
-#endif /* TEST_BBMD */
-#endif /* TEST */
+/*####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####*/
+
+#include /* for standard integer types uint8_t etc. */
+#include /* for the standard bool type. */
+#include /* for the standard bool type. */
+#include "bacdcode.h"
+#include "bip.h"
+#include "net.h" /* custom per port */
+
+/* Handle the BACnet Virtual Link Control (BVLC), which includes:
+ BACnet Broadcast Management Device,
+ Broadcast Distribution Table, and
+ Foreign Device Registration */
+
+typedef struct
+{
+ /* true if valid entry - false if not */
+ bool valid;
+ /* BACnet/IP address */
+ struct in_addr dest_address;
+ /* BACnet/IP port number - not always 47808=BAC0h */
+ uint16_t dest_port;
+ /* Broadcast Distribution Mask - stored in host byte order */
+ struct in_addr broadcast_mask;
+} BBMD_TABLE_ENTRY;
+
+#define MAX_BBMD_ENTRIES 128
+static BBMD_TABLE_ENTRY BBMD_Table[MAX_BBMD_ENTRIES];
+
+/*Each device that registers as a foreign device shall be placed
+in an entry in the BBMD's Foreign Device Table (FDT). Each
+entry shall consist of the 6-octet B/IP address of the registrant;
+the 2-octet Time-to-Live value supplied at the time of
+registration; and a 2-octet value representing the number of
+seconds remaining before the BBMD will purge the registrant's FDT
+entry if no re-registration occurs. This value will be initialized
+to the 2-octet Time-to-Live value supplied at the time of
+registration.*/
+typedef struct
+{
+ bool valid;
+ /* BACnet/IP address */
+ struct in_addr dest_address;
+ /* BACnet/IP port number - not always 47808=BAC0h */
+ uint16_t dest_port;
+ /* seconds for valid entry lifetime */
+ uint16_t time_to_live;
+ /* our counter */
+ time_t seconds_remaining; /* includes 30 second grace period */
+} FD_TABLE_ENTRY;
+
+#define MAX_FD_ENTRIES 128
+static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
+
+void bvlc_maintenance_timer(unsigned seconds)
+{
+ unsigned i = 0;
+
+ for (i = 0; i < MAX_FD_ENTRIES; i++) {
+ if (FD_Table[i].valid) {
+ if (FD_Table[i].seconds_remaining) {
+ if (FD_Table[i].seconds_remaining < seconds) {
+ FD_Table[i].seconds_remaining = 0;
+ } else {
+ FD_Table[i].seconds_remaining -= seconds;
+ }
+ if (FD_Table[i].seconds_remaining == 0) {
+ FD_Table[i].valid = false;
+ }
+ }
+ }
+ }
+}
+
+int bvlc_encode_bip_address(
+ uint8_t * pdu, /* buffer to store encoding */
+ struct in_addr *address, /* in host format */
+ uint16_t port)
+{
+ int len = 0;
+
+ if (pdu) {
+ len = encode_unsigned32(&pdu[0], address->s_addr);
+ len += encode_unsigned16(&pdu[len], port);
+ }
+
+ return len;
+}
+
+int bvlc_decode_bip_address(
+ uint8_t * pdu, /* buffer to extract encoded address */
+ struct in_addr * address, /* in host format */
+ uint16_t * port)
+{
+ int len = 0;
+
+ if (pdu) {
+ (void) decode_unsigned32(&pdu[0], &(address->s_addr));
+ (void) decode_unsigned16(&pdu[4], port);
+ len = 6;
+ }
+
+ return len;
+}
+
+/* used for both read and write entries */
+int bvlc_encode_address_entry(uint8_t * pdu,
+ struct in_addr *address,
+ uint16_t port,
+ struct in_addr *mask)
+{
+ int len = 0;
+
+ if (pdu) {
+ len = bvlc_encode_bip_address(pdu, address, port);
+ len += encode_unsigned32(&pdu[len], mask->s_addr);
+ }
+
+ return len;
+}
+
+int bvlc_encode_bvlc_result(
+ uint8_t * pdu,
+ BACNET_BVLC_RESULT result_code)
+{
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_RESULT;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 6);
+ encode_unsigned16(&pdu[4], result_code);
+ }
+
+ return 6;
+}
+
+int bvlc_encode_write_bdt_init(
+ uint8_t * pdu,
+ unsigned entries)
+{
+ int len = 0;
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 4 + entries * 10);
+ len = 4;
+ }
+
+ return len;
+}
+
+int bvlc_encode_read_bdt(
+ uint8_t * pdu)
+{
+ int len = 0;
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 4);
+ len = 4;
+ }
+
+ return len;
+}
+
+int bvlc_encode_read_bdt_ack_init(
+ uint8_t * pdu,
+ unsigned entries)
+{
+ int len = 0;
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 4 + entries * 10);
+ len = 4;
+ }
+
+ return len;
+}
+
+int bvlc_encode_forwarded_npdu(uint8_t * pdu,
+ BACNET_ADDRESS * src,
+ uint8_t * npdu,
+ unsigned npdu_length)
+{
+ int len = 0;
+
+ unsigned i; /* for loop counter */
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_FORWARDED_NPDU;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 4 + 6 + npdu_length);
+ len = 4;
+ for (i = 0; i < 6; i++) {
+ pdu[len] = src->adr[i];
+ len++;
+ }
+ for (i = 0; i < npdu_length; i++) {
+ pdu[len] = npdu[i];
+ len++;
+ }
+ }
+
+ return len;
+}
+
+
+int bvlc_encode_register_foreign_device(uint8_t * pdu,
+ uint16_t time_to_live_seconds)
+{
+ int len = 0;
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_REGISTER_FOREIGN_DEVICE;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 6);
+ encode_unsigned16(&pdu[2], time_to_live_seconds);
+ len = 6;
+ }
+
+ return len;
+}
+
+int bvlc_encode_read_fdt(
+ uint8_t * pdu)
+{
+ int len = 0;
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 4);
+ len = 4;
+ }
+
+ return len;
+}
+
+int bvlc_encode_read_fdt_ack_init(
+ uint8_t * pdu,
+ unsigned entries)
+{
+ int len = 0;
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE_ACK;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 4 + entries * 10);
+ len = 4;
+ }
+
+ return len;
+}
+
+int bvlc_encode_delete_fdt_entry(uint8_t * pdu,
+ struct in_addr *address,
+ uint16_t port)
+{
+ int len = 0;
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ encode_unsigned16(&pdu[2], 10);
+ /* FDT Entry */
+ encode_unsigned32(&pdu[0], address->s_addr);
+ encode_unsigned16(&pdu[4], port);
+ len = 10;
+ }
+
+ return len;
+}
+
+int bvlc_encode_distribute_broadcast_to_network(uint8_t * pdu,
+ uint8_t * npdu,
+ unsigned npdu_length)
+{
+ int len = 0; /* return value */
+ unsigned i; /* for loop counter */
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ len = encode_unsigned16(&pdu[2], 4 + npdu_length) + 2;
+ for (i = 0; i < npdu_length; i++) {
+ pdu[len] = npdu[i];
+ len++;
+ }
+ }
+
+ return len;
+}
+
+int bvlc_encode_original_unicast_npdu(uint8_t * pdu,
+ uint8_t * npdu,
+ unsigned npdu_length)
+{
+ int len = 0; /* return value */
+ unsigned i = 0; /* loop counter */
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ len = encode_unsigned16(&pdu[2], 4 + npdu_length) + 2;
+ for (i = 0; i < npdu_length; i++) {
+ pdu[len] = npdu[i];
+ len++;
+ }
+ }
+
+ return len;
+}
+
+
+int bvlc_encode_original_broadcast_npdu(uint8_t * pdu,
+ uint8_t * npdu,
+ unsigned npdu_length)
+{
+ int len = 0; /* return value */
+ unsigned i = 0; /* loop counter */
+
+ if (pdu) {
+ pdu[0] = BVLL_TYPE_BACNET_IP;
+ pdu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
+ /* The 2-octet BVLC Length field is the length, in octets,
+ of the entire BVLL message, including the two octets of the
+ length field itself, most significant octet first. */
+ len = encode_unsigned16(&pdu[2], 4 + npdu_length) + 2;
+ for (i = 0; i < npdu_length; i++) {
+ pdu[len] = npdu[i];
+ len++;
+ }
+ }
+
+ return len;
+}
+
+/* copy the source internet address to the BACnet address */
+/* FIXME: IPv6? */
+void bvlc_internet_to_bacnet_address(
+ BACNET_ADDRESS * src, /* returns the BACnet source address */
+ struct sockaddr_in *sin)
+{ /* source internet address */
+ int len = 0;
+ uint32_t address;
+ uint16_t port;
+
+ if (src && sin) {
+ address = ntohl(sin->sin_addr.s_addr);
+ len = encode_unsigned32(&src->mac[0], address);
+ port = ntohs(sin->sin_port);
+ len += encode_unsigned16(&src->mac[4], port);
+ src->mac_len = len;
+ src->net = 0;
+ src->len = 0;
+ }
+
+ return;
+}
+
+/* copy the source internet address to the BACnet address */
+/* FIXME: IPv6? */
+/* FIXME: is sockaddr_in host or network order? */
+void bvlc_bacnet_to_internet_address(
+ struct sockaddr_in *sin, /* source internet address */
+ BACNET_ADDRESS * src) /* returns the BACnet source address */
+{
+ int len = 0;
+ uint32_t address;
+ uint16_t port;
+
+ if (src && sin) {
+ if (src->mac_len == 6) {
+ len = decode_unsigned32(&src->mac[0], &address);
+ len += decode_unsigned16(&src->mac[4], &port );
+ sin->sin_addr.s_addr = htonl(address);
+ sin->sin_port = htons(port);
+ }
+ }
+
+ return;
+}
+
+void bvlc_bdt_forward_npdu(
+ struct sockaddr_in *sin, /* the source address */
+ uint8_t * npdu, /* the NPDU */
+ uint16_t npdu_length)
+{ /* length of the NPDU */
+ uint8_t mtu[MAX_MPDU] = {0};
+ int mtu_len = 0;
+ int bytes_sent = 0;
+ unsigned i = 0; /* loop counter */
+ struct sockaddr_in bip_dest;
+ BACNET_ADDRESS src;
+
+ /* assumes that the driver has already been initialized */
+ if (bip_socket() < 0) {
+ return;
+ }
+ bvlc_internet_to_bacnet_address(&src, sin);
+ mtu_len = bvlc_encode_forwarded_npdu(
+ &mtu[0],
+ &src,
+ npdu,
+ npdu_length);
+ /* load destination IP address */
+ bip_dest.sin_family = AF_INET;
+ /* loop through the BDT and send one to each entry, except us */
+ for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
+ if (BBMD_Table[i].valid) {
+ /* The B/IP address to which the Forwarded-NPDU message is
+ sent is formed by inverting the broadcast distribution
+ mask in the BDT entry and logically ORing it with the
+ BBMD address of the same entry. */
+ bip_dest.sin_addr.s_addr =
+ htonl(((~BBMD_Table[i].broadcast_mask.s_addr) |
+ BBMD_Table[i].dest_address.s_addr));
+ bip_dest.sin_port = htons(BBMD_Table[i].dest_port);
+ /* Send the packet */
+ bytes_sent =
+ sendto(bip_socket(), (char *) mtu, mtu_len, 0,
+ (struct sockaddr *) &bip_dest,
+ sizeof(struct sockaddr));
+ }
+ }
+
+ return;
+}
+
+void bvlc_fdt_forward_npdu(
+ struct sockaddr_in *sin, /* the source address */
+ uint8_t * npdu, /* returns the NPDU */
+ uint16_t max_npdu) /* amount of space available in the NPDU */
+{
+
+ /* FIXME: add the code */
+}
+
+uint16_t bvlc_handler(
+ BACNET_ADDRESS * src, /* returns the source address */
+ uint8_t * npdu, /* returns the NPDU */
+ uint16_t max_npdu, /* amount of space available in the NPDU */
+ unsigned timeout) /* number of milliseconds to wait for a packet */
+{
+ uint8_t buf[MAX_MPDU] = {0}; /* data */
+ uint16_t pdu_len = 0; /* return value */
+ fd_set read_fds;
+ int max;
+ struct timeval select_timeout;
+ struct sockaddr_in sin = { -1 };
+ socklen_t sin_len = sizeof(sin);
+ int function_type = 0;
+ int received_bytes;
+
+ /* Make sure the socket is open */
+ if (BIP_Socket < 0) {
+ return 0;
+ }
+
+ /* we could just use a non-blocking socket, but that consumes all
+ the CPU time. We can use a timeout; it is only supported as
+ a select. */
+ if (timeout >= 1000) {
+ select_timeout.tv_sec = timeout / 1000;
+ select_timeout.tv_usec =
+ 1000 * (timeout - select_timeout.tv_sec * 1000);
+ } else {
+ select_timeout.tv_sec = 0;
+ select_timeout.tv_usec = 1000 * timeout;
+ }
+ FD_ZERO(&read_fds);
+ FD_SET((unsigned int) BIP_Socket, &read_fds);
+ max = BIP_Socket;
+ /* see if there is a packet for us */
+ if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
+ received_bytes = recvfrom(
+ BIP_Socket,
+ (char *) &buf[0],
+ MAX_MPDU, 0,
+ (struct sockaddr *) &sin, &sin_len);
+ } else {
+ return 0;
+ }
+ /* See if there is a problem */
+ if (received_bytes < 0) {
+ return 0;
+ }
+ /* no problem, just no bytes */
+ if (received_bytes == 0) {
+ return 0;
+ }
+ /* the signature of a BACnet/IP packet */
+ if (buf[0] != BVLL_TYPE_BACNET_IP) {
+ return 0;
+ }
+ function_type = buf[1];
+ /* decode the length of the PDU - length is inclusive of BVLC */
+ (void) decode_unsigned16(&buf[2], &npdu_len);
+ /* subtract off the BVLC header */
+ npdu_len -= 4;
+ switch (function_type) {
+ case BVLC_RESULT:
+ break;
+ case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
+ /* Upon receipt of a BVLL Write-Broadcast-Distribution-Table
+ message, a BBMD shall attempt to create or replace its BDT,
+ depending on whether or not a BDT has previously existed.
+ If the creation or replacement of the BDT is successful, the BBMD
+ shall return a BVLC-Result message to the originating device with
+ a result code of X'0000'. Otherwise, the BBMD shall return a
+ BVLC-Result message to the originating device with a result code
+ of X'0010' indicating that the write attempt has failed. */
+ break;
+ case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE:
+ break;
+ case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK:
+ break;
+ case BVLC_FORWARDED_NPDU:
+ /* Upon receipt of a BVLL Forwarded-NPDU message, a BBMD shall
+ process it according to whether it was received from a peer
+ BBMD as the result of a directed broadcast or a unicast
+ transmission. A BBMD may ascertain the method by which Forwarded-
+ NPDU messages will arrive by inspecting the broadcast distribution
+ mask field in its own BDT entry since all BDTs are required
+ to be identical. If the message arrived via directed broadcast,
+ it was also received by the other devices on the BBMD's subnet. In
+ this case the BBMD merely retransmits the message directly to each
+ foreign device currently in the BBMD's FDT. If the
+ message arrived via a unicast transmission it has not yet been
+ received by the other devices on the BBMD's subnet. In this case,
+ the message is sent to the devices on the BBMD's subnet using the
+ B/IP broadcast address as well as to each foreign device
+ currently in the BBMD's FDT. A BBMD on a subnet with no other
+ BACnet devices may omit the broadcast using the B/IP
+ broadcast address. The method by which a BBMD determines whether
+ or not other BACnet devices are present is a local matter. */
+ bvlc_broadcast_npdu(&sin, &buf[4], npdu_len);
+ bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
+ break;
+ case BVLC_REGISTER_FOREIGN_DEVICE:
+ break;
+ case BVLC_READ_FOREIGN_DEVICE_TABLE:
+ break;
+ case BVLC_READ_FOREIGN_DEVICE_TABLE_ACK:
+ break;
+ case BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY:
+ break;
+ case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK:
+ bvlc_broadcast_forward_npdu(&sin, &buf[4], npdu_len);
+ bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
+ break;
+ case BVLC_ORIGINAL_UNICAST_NPDU:
+ /* ignore messages from me */
+ if (sin.sin_addr.s_addr == BIP_Address.s_addr) {
+ npdu_len = 0;
+ } else {
+ bvlc_internet_to_bacnet_address(src, &sin);
+ if (npdu_len < max_npdu) {
+ /* copy the buffer into the PDU */
+ memmove(&npdu[0], &buf[4], npdu_len);
+ } else {
+ /* ignore packets that are too large */
+ /* clients should check my max-apdu first */
+ npdu_len = 0;
+ }
+ }
+ break;
+ case BVLC_ORIGINAL_BROADCAST_NPDU:
+ /* Upon receipt of a BVLL Original-Broadcast-NPDU message,
+ a BBMD shall construct a BVLL Forwarded-NPDU message and
+ send it to each IP subnet in its BDT with the exception
+ of its own. The B/IP address to which the Forwarded-NPDU
+ message is sent is formed by inverting the broadcast
+ distribution mask in the BDT entry and logically ORing it
+ with the BBMD address of the same entry. This process
+ produces either the directed broadcast address of the remote
+ subnet or the unicast address of the BBMD on that subnet
+ depending on the contents of the broadcast distribution
+ mask. See J.4.3.2.. In addition, the received BACnet NPDU
+ shall be sent directly to each foreign device currently in
+ the BBMD's FDT also using the BVLL Forwarded-NPDU message. */
+ bvlc_internet_to_bacnet_address(src, &sin);
+ if (npdu_len < max_npdu) {
+ /* copy the buffer into the PDU */
+ memmove(&npdu[0], &buf[4], npdu_len);
+ } else {
+ /* ignore packets that are too large */
+ /* clients should check my max-apdu first */
+ npdu_len = 0;
+ }
+ /* if BDT or FDT entries exist, Forward the NPDU */
+ bvlc_bdt_forward_npdu(&sin, &buf[4], npdu_len);
+ bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
+ break;
+ default:
+ break;
+ }
+
+ return npdu_len;
+}
+
+#ifdef TEST
+#include
+#include
+#include "ctest.h"
+
+void testBIPAddress(Test * pTest)
+{
+ uint8_t apdu[50] = { 0 };
+ uint32_t value = 0, test_value = 0;
+ int len = 0, test_len = 0;
+ struct in_addr address;
+ struct in_addr test_address;
+ uint16_t port = 0, test_port = 0;
+
+ address.s_addr = 42;
+ len = bvlc_encode_bip_address(&apdu[0],
+ &address, port);
+ test_len = bvlc_decode_bip_address(&apdu[0],
+ &test_address, &test_port);
+ ct_test(pTest, len == test_len);
+ ct_test(pTest, address.s_addr == test_address.s_addr);
+ ct_test(pTest, port == test_port);
+}
+
+void testInternetAddress(Test * pTest)
+{
+ BACNET_ADDRESS src;
+ BACNET_ADDRESS test_src;
+ struct sockaddr_in sin;
+ struct sockaddr_in test_sin;
+
+ sin.sin_port = htons(0xBAC0);
+ sin.sin_addr.s_addr = inet_addr("192.168.0.1");
+ bvlc_internet_to_bacnet_address(&src, &sin);
+ bvlc_bacnet_to_internet_address(&test_sin, &src);
+ ct_test(pTest, sin.sin_port == test_sin.sin_port);
+ ct_test(pTest, sin.sin_addr.s_addr == test_sin.sin_addr.s_addr);
+}
+
+#ifdef TEST_BVLC
+int main(void)
+{
+ Test * pTest;
+ bool rc;
+
+ pTest = ct_create("BACnet Virtual Link Control", NULL);
+ /* individual tests */
+ rc = ct_addTestFunction(pTest, testBIPAddress);
+ assert(rc);
+ rc = ct_addTestFunction(pTest, testInternetAddress);
+ assert(rc);
+ /* configure output */
+ ct_setStream(pTest, stdout);
+ ct_run(pTest);
+ (void) ct_report(pTest);
+ ct_destroy(pTest);
+
+ return 0;
+}
+
+#endif /* TEST_BBMD */
+#endif /* TEST */
diff --git a/bacnet-stack/bvlc.h b/bacnet-stack/bvlc.h
index 3b2756e5..849d2d1e 100644
--- a/bacnet-stack/bvlc.h
+++ b/bacnet-stack/bvlc.h
@@ -49,4 +49,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
-#endif /*
*/
+#endif /* */
+
diff --git a/bacnet-stack/cov.c b/bacnet-stack/cov.c
index 08fa8b50..97c26a4f 100644
--- a/bacnet-stack/cov.c
+++ b/bacnet-stack/cov.c
@@ -840,9 +840,9 @@ void testCOVSubscribeData(Test * pTest,
test_data->monitoredObjectIdentifier.instance ==
data->monitoredObjectIdentifier.instance);
ct_test(pTest,
- test_data->cancellationRequest == data->cancellationRequest);
- if (test_data->cancellationRequest != data->cancellationRequest) {
- printf("cancellation request failed!\n");
+ test_data->cancellationRequest == data->cancellationRequest);
+ if (test_data->cancellationRequest != data->cancellationRequest) {
+ printf("cancellation request failed!\n");
}
if (!test_data->cancellationRequest) {
ct_test(pTest,
diff --git a/bacnet-stack/datetime.c b/bacnet-stack/datetime.c
index 14226fa6..fdbf60a6 100644
--- a/bacnet-stack/datetime.c
+++ b/bacnet-stack/datetime.c
@@ -354,7 +354,7 @@ bool datetime_wildcard(BACNET_DATE_TIME * bdatetime)
return wildcard_present;
}
-
+
void datetime_date_wildcard_set(BACNET_DATE * bdate)
{
if (bdate) {
@@ -364,7 +364,7 @@ void datetime_date_wildcard_set(BACNET_DATE * bdate)
bdate->wday = 0xFF;
}
}
-
+
void datetime_time_wildcard_set(BACNET_TIME * btime)
{
if (btime) {
diff --git a/bacnet-stack/datetime.h b/bacnet-stack/datetime.h
index dc3f7fcf..49f7f160 100644
--- a/bacnet-stack/datetime.h
+++ b/bacnet-stack/datetime.h
@@ -104,7 +104,7 @@ extern "C" {
/* date and time wildcards */
bool datetime_wildcard(BACNET_DATE_TIME * bdatetime);
- void datetime_wildcard_set(BACNET_DATE_TIME * bdatetime);
+ void datetime_wildcard_set(BACNET_DATE_TIME * bdatetime);
void datetime_date_wildcard_set(BACNET_DATE * bdate);
void datetime_time_wildcard_set(BACNET_TIME * btime);
diff --git a/bacnet-stack/demo/object/lc.c b/bacnet-stack/demo/object/lc.c
index 1174792d..3b2e7c92 100644
--- a/bacnet-stack/demo/object/lc.c
+++ b/bacnet-stack/demo/object/lc.c
@@ -400,15 +400,15 @@ void Load_Control_State_Machine(int object_index)
{
unsigned i = 0; /* loop counter */
int diff = 0; /* used for datetime comparison */
-
+
/* is the state machine enabled? */
- if (!Load_Control_Enable[object_index]) {
+ if (!Load_Control_Enable[object_index]) {
Load_Control_State[object_index] = SHED_INACTIVE;
return;
- }
-
+ }
+
switch (Load_Control_State[object_index]) {
- case SHED_REQUEST_PENDING:
+ case SHED_REQUEST_PENDING:
if (Load_Control_Request_Written[object_index]) {
Load_Control_Request_Written[object_index] = false;
/* request to cancel using default values? */
@@ -996,195 +996,195 @@ static void Load_Control_WriteProperty_Request_Shed_Percent(Test * pTest,
int instance, unsigned percent)
{
bool status = false;
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value;
BACNET_WRITE_PROPERTY_DATA wp_data;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
wp_data.object_type = OBJECT_LOAD_CONTROL;
- wp_data.object_instance = instance;
- wp_data.array_index = BACNET_ARRAY_ALL;
- wp_data.priority = BACNET_NO_PRIORITY;
- wp_data.object_property = PROP_REQUESTED_SHED_LEVEL;
- value.context_specific = true;
- value.context_tag = 0;
- value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
- value.type.Unsigned_Int = percent;
- wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[0], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- status = Load_Control_Write_Property(&wp_data,
+ wp_data.object_instance = instance;
+ wp_data.array_index = BACNET_ARRAY_ALL;
+ wp_data.priority = BACNET_NO_PRIORITY;
+ wp_data.object_property = PROP_REQUESTED_SHED_LEVEL;
+ value.context_specific = true;
+ value.context_tag = 0;
+ value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
+ value.type.Unsigned_Int = percent;
+ wp_data.application_data_len =
+ bacapp_encode_data(&wp_data.application_data[0], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ status = Load_Control_Write_Property(&wp_data,
&error_class, &error_code);
- ct_test(pTest, status == true);
+ ct_test(pTest, status == true);
}
-#endif
+#endif
static void Load_Control_WriteProperty_Request_Shed_Level(Test * pTest,
int instance, unsigned level)
{
bool status = false;
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value;
BACNET_WRITE_PROPERTY_DATA wp_data;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
wp_data.object_type = OBJECT_LOAD_CONTROL;
- wp_data.object_instance = instance;
- wp_data.array_index = BACNET_ARRAY_ALL;
- wp_data.priority = BACNET_NO_PRIORITY;
- wp_data.object_property = PROP_REQUESTED_SHED_LEVEL;
- value.context_specific = true;
- value.context_tag = 1;
- value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
- value.type.Unsigned_Int = level;
- wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[0], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- status = Load_Control_Write_Property(&wp_data,
+ wp_data.object_instance = instance;
+ wp_data.array_index = BACNET_ARRAY_ALL;
+ wp_data.priority = BACNET_NO_PRIORITY;
+ wp_data.object_property = PROP_REQUESTED_SHED_LEVEL;
+ value.context_specific = true;
+ value.context_tag = 1;
+ value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
+ value.type.Unsigned_Int = level;
+ wp_data.application_data_len =
+ bacapp_encode_data(&wp_data.application_data[0], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ status = Load_Control_Write_Property(&wp_data,
&error_class, &error_code);
- ct_test(pTest, status == true);
-}
+ ct_test(pTest, status == true);
+}
#if 0
static void Load_Control_WriteProperty_Request_Shed_Amount(Test * pTest,
int instance, float amount)
{
bool status = false;
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value;
BACNET_WRITE_PROPERTY_DATA wp_data;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
wp_data.object_type = OBJECT_LOAD_CONTROL;
- wp_data.object_instance = instance;
- wp_data.array_index = BACNET_ARRAY_ALL;
- wp_data.priority = BACNET_NO_PRIORITY;
- wp_data.object_property = PROP_REQUESTED_SHED_LEVEL;
- value.context_specific = true;
- value.context_tag = 2;
- value.tag = BACNET_APPLICATION_TAG_REAL;
- value.type.Real = amount;
- wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[0], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- status = Load_Control_Write_Property(&wp_data,
+ wp_data.object_instance = instance;
+ wp_data.array_index = BACNET_ARRAY_ALL;
+ wp_data.priority = BACNET_NO_PRIORITY;
+ wp_data.object_property = PROP_REQUESTED_SHED_LEVEL;
+ value.context_specific = true;
+ value.context_tag = 2;
+ value.tag = BACNET_APPLICATION_TAG_REAL;
+ value.type.Real = amount;
+ wp_data.application_data_len =
+ bacapp_encode_data(&wp_data.application_data[0], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ status = Load_Control_Write_Property(&wp_data,
&error_class, &error_code);
- ct_test(pTest, status == true);
+ ct_test(pTest, status == true);
}
-#endif
+#endif
static void Load_Control_WriteProperty_Enable(Test * pTest, int instance,
bool enable)
{
bool status = false;
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value;
BACNET_WRITE_PROPERTY_DATA wp_data;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
wp_data.object_type = OBJECT_LOAD_CONTROL;
- wp_data.object_instance = instance;
- wp_data.array_index = BACNET_ARRAY_ALL;
- wp_data.priority = BACNET_NO_PRIORITY;
- /* Set Enable=TRUE */
- wp_data.object_property = PROP_ENABLE;
- value.context_specific = false;
- value.context_tag = 0;
- value.tag = BACNET_APPLICATION_TAG_BOOLEAN;
- value.type.Boolean = enable;
- wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[0], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- status = Load_Control_Write_Property(&wp_data,
+ wp_data.object_instance = instance;
+ wp_data.array_index = BACNET_ARRAY_ALL;
+ wp_data.priority = BACNET_NO_PRIORITY;
+ /* Set Enable=TRUE */
+ wp_data.object_property = PROP_ENABLE;
+ value.context_specific = false;
+ value.context_tag = 0;
+ value.tag = BACNET_APPLICATION_TAG_BOOLEAN;
+ value.type.Boolean = enable;
+ wp_data.application_data_len =
+ bacapp_encode_data(&wp_data.application_data[0], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ status = Load_Control_Write_Property(&wp_data,
&error_class, &error_code);
- ct_test(pTest, status == true);
-}
+ ct_test(pTest, status == true);
+}
static void Load_Control_WriteProperty_Shed_Duration(Test * pTest,
int instance, unsigned duration)
{
bool status = false;
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value;
BACNET_WRITE_PROPERTY_DATA wp_data;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
wp_data.object_type = OBJECT_LOAD_CONTROL;
- wp_data.object_instance = instance;
- wp_data.array_index = BACNET_ARRAY_ALL;
- wp_data.priority = BACNET_NO_PRIORITY;
- wp_data.object_property = PROP_SHED_DURATION;
- value.context_specific = false;
- value.context_tag = 0;
- value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
- value.type.Unsigned_Int = duration;
- wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[0], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- status = Load_Control_Write_Property(&wp_data,
+ wp_data.object_instance = instance;
+ wp_data.array_index = BACNET_ARRAY_ALL;
+ wp_data.priority = BACNET_NO_PRIORITY;
+ wp_data.object_property = PROP_SHED_DURATION;
+ value.context_specific = false;
+ value.context_tag = 0;
+ value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
+ value.type.Unsigned_Int = duration;
+ wp_data.application_data_len =
+ bacapp_encode_data(&wp_data.application_data[0], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ status = Load_Control_Write_Property(&wp_data,
&error_class, &error_code);
- ct_test(pTest, status == true);
-}
+ ct_test(pTest, status == true);
+}
static void Load_Control_WriteProperty_Duty_Window(Test * pTest,
int instance, unsigned duration)
{
bool status = false;
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value;
BACNET_WRITE_PROPERTY_DATA wp_data;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
wp_data.object_type = OBJECT_LOAD_CONTROL;
- wp_data.object_instance = instance;
- wp_data.array_index = BACNET_ARRAY_ALL;
- wp_data.priority = BACNET_NO_PRIORITY;
- wp_data.object_property = PROP_DUTY_WINDOW;
- value.context_specific = false;
- value.context_tag = 0;
- value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
- value.type.Unsigned_Int = duration;
- wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[0], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- status = Load_Control_Write_Property(&wp_data,
+ wp_data.object_instance = instance;
+ wp_data.array_index = BACNET_ARRAY_ALL;
+ wp_data.priority = BACNET_NO_PRIORITY;
+ wp_data.object_property = PROP_DUTY_WINDOW;
+ value.context_specific = false;
+ value.context_tag = 0;
+ value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
+ value.type.Unsigned_Int = duration;
+ wp_data.application_data_len =
+ bacapp_encode_data(&wp_data.application_data[0], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ status = Load_Control_Write_Property(&wp_data,
&error_class, &error_code);
- ct_test(pTest, status == true);
-}
+ ct_test(pTest, status == true);
+}
static void Load_Control_WriteProperty_Start_Time_Wildcards(Test * pTest,
int instance)
{
int len = 0;
bool status = false;
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value;
BACNET_WRITE_PROPERTY_DATA wp_data;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
wp_data.object_type = OBJECT_LOAD_CONTROL;
- wp_data.object_instance = instance;
- wp_data.array_index = BACNET_ARRAY_ALL;
- wp_data.priority = BACNET_NO_PRIORITY;
- wp_data.object_property = PROP_START_TIME;
- value.context_specific = false;
- value.context_tag = 0;
- value.tag = BACNET_APPLICATION_TAG_DATE;
+ wp_data.object_instance = instance;
+ wp_data.array_index = BACNET_ARRAY_ALL;
+ wp_data.priority = BACNET_NO_PRIORITY;
+ wp_data.object_property = PROP_START_TIME;
+ value.context_specific = false;
+ value.context_tag = 0;
+ value.tag = BACNET_APPLICATION_TAG_DATE;
datetime_date_wildcard_set(&value.type.Date);
- wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[0], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- len = wp_data.application_data_len;
- value.tag = BACNET_APPLICATION_TAG_TIME;
+ wp_data.application_data_len =
+ bacapp_encode_data(&wp_data.application_data[0], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ len = wp_data.application_data_len;
+ value.tag = BACNET_APPLICATION_TAG_TIME;
datetime_time_wildcard_set(&value.type.Time);
- wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[len], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- wp_data.application_data_len += len;
- status = Load_Control_Write_Property(&wp_data,
+ wp_data.application_data_len =
+ bacapp_encode_data(&wp_data.application_data[len], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ wp_data.application_data_len += len;
+ status = Load_Control_Write_Property(&wp_data,
&error_class, &error_code);
- ct_test(pTest, status == true);
-}
+ ct_test(pTest, status == true);
+}
static void Load_Control_WriteProperty_Start_Time(Test * pTest, int instance,
uint16_t year, uint8_t month, uint8_t day,
@@ -1192,38 +1192,38 @@ static void Load_Control_WriteProperty_Start_Time(Test * pTest, int instance,
{
int len = 0;
bool status = false;
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value;
BACNET_WRITE_PROPERTY_DATA wp_data;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
wp_data.object_type = OBJECT_LOAD_CONTROL;
- wp_data.object_instance = instance;
- wp_data.array_index = BACNET_ARRAY_ALL;
- wp_data.priority = BACNET_NO_PRIORITY;
- wp_data.object_property = PROP_START_TIME;
- value.context_specific = false;
- value.context_tag = 0;
- value.tag = BACNET_APPLICATION_TAG_DATE;
+ wp_data.object_instance = instance;
+ wp_data.array_index = BACNET_ARRAY_ALL;
+ wp_data.priority = BACNET_NO_PRIORITY;
+ wp_data.object_property = PROP_START_TIME;
+ value.context_specific = false;
+ value.context_tag = 0;
+ value.tag = BACNET_APPLICATION_TAG_DATE;
datetime_set_date(&value.type.Date, year, month, day);
wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[0], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- len = wp_data.application_data_len;
- value.tag = BACNET_APPLICATION_TAG_TIME;
+ bacapp_encode_data(&wp_data.application_data[0], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ len = wp_data.application_data_len;
+ value.tag = BACNET_APPLICATION_TAG_TIME;
datetime_set_time(&value.type.Time, hour, minute, seconds, hundredths);
wp_data.application_data_len =
- bacapp_encode_data(&wp_data.application_data[len], &value);
- ct_test(pTest, wp_data.application_data_len > 0);
- wp_data.application_data_len += len;
- status = Load_Control_Write_Property(&wp_data,
+ bacapp_encode_data(&wp_data.application_data[len], &value);
+ ct_test(pTest, wp_data.application_data_len > 0);
+ wp_data.application_data_len += len;
+ status = Load_Control_Write_Property(&wp_data,
&error_class, &error_code);
- ct_test(pTest, status == true);
-}
+ ct_test(pTest, status == true);
+}
void testLoadControlStateMachine(Test * pTest)
{
- unsigned i = 0, j = 0;
+ unsigned i = 0, j = 0;
uint8_t level = 0;
Load_Control_Init();
@@ -1233,13 +1233,13 @@ void testLoadControlStateMachine(Test * pTest)
for (i = 0; i < MAX_LOAD_CONTROLS; i++) {
ct_test(pTest, Load_Control_State[i] == SHED_INACTIVE);
}
- }
- /* SHED_REQUEST_PENDING */
- /* CancelShed - Start time has wildcards */
- Load_Control_WriteProperty_Enable(pTest, 0, true);
- Load_Control_WriteProperty_Shed_Duration(pTest, 0, 60);
- Load_Control_WriteProperty_Start_Time_Wildcards(pTest, 0);
- Load_Control_State_Machine(0);
+ }
+ /* SHED_REQUEST_PENDING */
+ /* CancelShed - Start time has wildcards */
+ Load_Control_WriteProperty_Enable(pTest, 0, true);
+ Load_Control_WriteProperty_Shed_Duration(pTest, 0, 60);
+ Load_Control_WriteProperty_Start_Time_Wildcards(pTest, 0);
+ Load_Control_State_Machine(0);
ct_test(pTest, Load_Control_State[0] == SHED_REQUEST_PENDING);
Load_Control_State_Machine(0);
ct_test(pTest, Load_Control_State[0] == SHED_INACTIVE);
diff --git a/bacnet-stack/demo/object/lo.c b/bacnet-stack/demo/object/lo.c
index b8d7d62d..6708b214 100644
--- a/bacnet-stack/demo/object/lo.c
+++ b/bacnet-stack/demo/object/lo.c
@@ -1,625 +1,625 @@
-/**************************************************************************
-*
-* Copyright (C) 2007 Steve Karg
-*
-* 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.
-*
-*********************************************************************/
-
-/* Lighting Output Objects - customize for your use */
-
-#include
-#include
-#include
-#include "bacdef.h"
-#include "bacdcode.h"
-#include "bacenum.h"
-#include "bacapp.h"
-#include "config.h" /* the custom stuff */
-#include "wp.h"
-
-#define MAX_LIGHTING_OUTPUTS 5
-
-/* we choose to have a NULL level in our system represented by */
-/* a particular value. When the priorities are not in use, they */
-/* will be relinquished (i.e. set to the NULL level). */
-#define LIGHTING_LEVEL_NULL 255
-/* When all the priorities are level null, the present value returns */
-/* the Relinquish Default value */
-#define LIGHTING_RELINQUISH_DEFAULT 0
-
-/* note: although the standard specifies REAL values for some
- of the optional parameters, we represent them interally as
- integers. */
-typedef struct LightingCommand {
- BACNET_LIGHTING_OPERATION operation;
- uint8_t level; /* 0..100 percent, 255=not used */
- uint8_t ramp_rate; /* 0..100 percent-per-second, 255=not used */
- uint8_t step_increment; /* 0..100 amount to step, 255=not used */
- uint16_t fade_time; /* 1..65535 seconds to transition, 0=not used */
- uint16_t duration; /* 1..65535 minutes until relinquish, 0=not used */
-} BACNET_LIGHTING_COMMAND;
-
-/* Here is our Priority Array. They are supposed to be Real, but */
-/* we might not have that kind of memory, so we will use a single byte */
-/* and load a Real for returning the value when asked. */
-static uint8_t
- Lighting_Output_Level[MAX_LIGHTING_OUTPUTS][BACNET_MAX_PRIORITY];
-/* The Progress_Value tracks changes such as ramp and fade */
-static uint8_t Lighting_Output_Progress[MAX_LIGHTING_OUTPUTS];
-/* The minimum and maximum present values are used for clamping */
-static uint8_t Lighting_Output_Min_Present_Value[MAX_LIGHTING_OUTPUTS];
-static uint8_t Lighting_Output_Max_Present_Value[MAX_LIGHTING_OUTPUTS];
-/* Writable out-of-service allows others to play with our Present Value */
-/* without changing the physical output */
-static bool Lighting_Output_Out_Of_Service[MAX_LIGHTING_OUTPUTS];
-/* the lighting command is what we are doing */
-static uint8_t Lighting_Command_Priority = 16;
-static BACNET_LIGHTING_COMMAND Lighting_Command[MAX_LIGHTING_OUTPUTS];
-/* we need to have our arrays initialized before answering any calls */
-static bool Lighting_Output_Initialized = false;
-
-int Lighting_Output_Encode_Lighting_Command(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 */
- float real_value = 0.0;
- uint32_t unsigned_value = 0;
-
- if (apdu) {
- len = encode_context_enumerated(&apdu[apdu_len], 0,
- data->operation);
- apdu_len += len;
- /* optional level? */
- if (data->level != 255) {
- real_value = data->level;
- len = encode_context_real(&apdu[apdu_len], 1,
- real_value);
- apdu_len += len;
- }
- /* optional ramp-rate */
- if (data->ramp_rate != 255) {
- real_value = data->ramp_rate;
- len = encode_context_real(&apdu[apdu_len], 2,
- real_value);
- apdu_len += len;
- }
- /* optional step increment */
- if (data->step_increment != 255) {
- real_value = data->step_increment;
- len = encode_context_real(&apdu[apdu_len], 3,
- real_value);
- apdu_len += len;
- }
- /* optional fade time */
- if (data->fade_time != 0) {
- real_value = data->fade_time;
- len = encode_context_real(&apdu[apdu_len], 4,
- real_value);
- apdu_len += len;
- }
- /* optional duration */
- if (data->duration != 0) {
- unsigned_value = data->duration;
- len = encode_context_unsigned(&apdu[apdu_len], 5,
- unsigned_value);
- apdu_len += len;
- }
- }
-
- return apdu_len;
-}
-
-int Lighting_Output_Decode_Lighting_Command(uint8_t * apdu,
- unsigned apdu_max_len, BACNET_LIGHTING_COMMAND * data)
-{
- int len = 0;
- int apdu_len = 0;
- int tag_len = 0;
- uint8_t tag_number = 0;
- uint32_t len_value_type = 0;
- int type = 0; /* for decoding */
- int property = 0; /* for decoding */
- uint32_t unsigned_value = 0;
- int i = 0; /* loop counter */
- float real_value = 0.0;
-
- /* check for value pointers */
- if (apdu_len && data) {
- /* Tag 0: operation */
- if (!decode_is_context_tag(&apdu[apdu_len], 0))
- return -1;
- len = decode_tag_number_and_value(&apdu[apdu_len],
- &tag_number, &len_value_type);
- apdu_len += len;
- len = decode_enumerated(&apdu[apdu_len], len_value_type, &data->operation);
- apdu_len += len;
- /* Tag 1: level - OPTIONAL */
- if (decode_is_context_tag(&apdu[apdu_len], 1)) {
- len = decode_tag_number_and_value(&apdu[apdu_len],
- &tag_number, &len_value_type);
- apdu_len += len;
- len = decode_real(&apdu[apdu_len], &real_value);
- apdu_len += len;
- data->level = real_value;
- /* FIXME: are we going to flag errors in decoding values here? */
- }
- /* FIXME: finish me! */
- /* Tag 2: */
-
- }
-
- return len;
-}
-
-
-void Lighting_Output_Init(void)
-{
- unsigned i, j;
-
- if (!Lighting_Output_Initialized) {
- Lighting_Output_Initialized = true;
-
- /* initialize all the analog output priority arrays to NULL */
- for (i = 0; i < MAX_LIGHTING_OUTPUTS; i++) {
- for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
- Lighting_Output_Level[i][j] = LIGHTING_LEVEL_NULL;
- }
- Lighting_Command[i].operation = BACNET_LIGHTS_STOP;
- Lighting_Output_Out_Of_Service[i] = false;
- Lighting_Output_Progress[i] = LIGHTING_RELINQUISH_DEFAULT;
- Lighting_Output_Min_Present_Value[i] = 0;
- Lighting_Output_Max_Present_Value[i] = 100;
- }
- }
-
- return;
-}
-
-/* we simply have 0-n object instances. Yours might be */
-/* more complex, and then you need validate that the */
-/* given instance exists */
-bool Lighting_Output_Valid_Instance(uint32_t object_instance)
-{
- Lighting_Output_Init();
- if (object_instance < MAX_LIGHTING_OUTPUTS)
- return true;
-
- return false;
-}
-
-/* we simply have 0-n object instances. Yours might be */
-/* more complex, and then count how many you have */
-unsigned Lighting_Output_Count(void)
-{
- Lighting_Output_Init();
- return MAX_LIGHTING_OUTPUTS;
-}
-
-/* we simply have 0-n object instances. Yours might be */
-/* more complex, and then you need to return the instance */
-/* that correlates to the correct index */
-uint32_t Lighting_Output_Index_To_Instance(unsigned index)
-{
- Lighting_Output_Init();
- return index;
-}
-
-/* we simply have 0-n object instances. Yours might be */
-/* more complex, and then you need to return the index */
-/* that correlates to the correct instance number */
-unsigned Lighting_Output_Instance_To_Index(uint32_t object_instance)
-{
- unsigned index = MAX_LIGHTING_OUTPUTS;
-
- Lighting_Output_Init();
- if (object_instance < MAX_LIGHTING_OUTPUTS)
- index = object_instance;
-
- return index;
-}
-
-float Lighting_Output_Present_Value(uint32_t object_instance)
-{
- float value = LIGHTING_RELINQUISH_DEFAULT;
- unsigned index = 0;
- unsigned i = 0;
-
- Lighting_Output_Init();
- index = Lighting_Output_Instance_To_Index(object_instance);
- if (index < MAX_LIGHTING_OUTPUTS) {
- for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
- if (Lighting_Output_Level[index][i] != LIGHTING_LEVEL_NULL) {
- value = Lighting_Output_Level[index][i];
- break;
- }
- }
- }
-
- return value;
-}
-
-unsigned Lighting_Output_Present_Value_Priority(uint32_t object_instance)
-{
- unsigned index = 0; /* instance to index conversion */
- unsigned i = 0; /* loop counter */
- unsigned priority = 0; /* return value */
-
- Lighting_Output_Init();
- index = Lighting_Output_Instance_To_Index(object_instance);
- if (index < MAX_LIGHTING_OUTPUTS) {
- for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
- if (Lighting_Output_Level[index][i] != LIGHTING_LEVEL_NULL) {
- priority = i + 1;
- break;
- }
- }
- }
-
- return priority;
-}
-
-bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
- float value, unsigned priority)
-{
- unsigned index = 0;
- bool status = false;
-
- index = Lighting_Output_Instance_To_Index(object_instance);
- if (index < MAX_LIGHTING_OUTPUTS) {
- if (priority && (priority <= BACNET_MAX_PRIORITY) &&
- (priority != 6 /* reserved */ ) &&
- (value >= 0.0) && (value <= 100.0)) {
- Lighting_Output_Level[index][priority-1] = (uint8_t) value;
- /* Note: you could set the physical output here to the next
- highest priority, or to the relinquish default if no
- priorities are set.
- However, if Out of Service is TRUE, then don't set the
- physical output. This comment may apply to the
- main loop (i.e. check out of service before changing output) */
- status = true;
- }
- }
-
- return status;
-}
-
-bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
- int priority)
-{
- unsigned index = 0;
- bool status = false;
-
- index = Lighting_Output_Instance_To_Index(object_instance);
- if (index < MAX_LIGHTING_OUTPUTS) {
- if (priority && (priority <= BACNET_MAX_PRIORITY) &&
- (priority != 6 /* reserved */ )) {
- Lighting_Output_Level[index][priority-1] = LIGHTING_LEVEL_NULL;
- /* Note: you could set the physical output here to the next
- highest priority, or to the relinquish default if no
- priorities are set.
- However, if Out of Service is TRUE, then don't set the
- physical output. This comment may apply to the
- main loop (i.e. check out of service before changing output) */
- status = true;
- }
- }
-
- return status;
-}
-
-float Lighting_Output_Progress_Value(uint32_t object_instance)
-{
- float value = LIGHTING_RELINQUISH_DEFAULT;
- unsigned index = 0;
-
- Lighting_Output_Init();
- index = Lighting_Output_Instance_To_Index(object_instance);
- if (index < MAX_LIGHTING_OUTPUTS) {
- value = Lighting_Output_Progress[index];
- }
-
- return value;
-}
-
-/* note: the object name must be unique within this device */
-char *Lighting_Output_Name(uint32_t object_instance)
-{
- static char text_string[32] = ""; /* okay for single thread */
-
- if (object_instance < MAX_LIGHTING_OUTPUTS) {
- sprintf(text_string, "LIGHTING OUTPUT %u", object_instance);
- return text_string;
- }
-
- return NULL;
-}
-
-/* return apdu len, or -1 on error */
-int Lighting_Output_Encode_Property_APDU(uint8_t * apdu,
- uint32_t object_instance,
- BACNET_PROPERTY_ID property,
- int32_t array_index,
- BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
-{
- int len = 0;
- int apdu_len = 0; /* return value */
- BACNET_BIT_STRING bit_string;
- BACNET_CHARACTER_STRING char_string;
- float real_value = (float) 1.414;
- unsigned object_index = 0;
- unsigned i = 0;
- bool state = false;
-
- Lighting_Output_Init();
- switch (property) {
- case PROP_OBJECT_IDENTIFIER:
- apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_LIGHTING_OUTPUT,
- object_instance);
- break;
- case PROP_OBJECT_NAME:
- case PROP_DESCRIPTION:
- /* object name must be unique in this device. */
- /* FIXME: description could be writable and different than object name */
- characterstring_init_ansi(&char_string,
- Lighting_Output_Name(object_instance));
- apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
- break;
- case PROP_OBJECT_TYPE:
- apdu_len =
- encode_tagged_enumerated(&apdu[0], OBJECT_LIGHTING_OUTPUT);
- break;
- case PROP_PRESENT_VALUE:
- real_value = Lighting_Output_Present_Value(object_instance);
- apdu_len = encode_tagged_real(&apdu[0], real_value);
- break;
- case PROP_PROGRESS_VALUE:
- real_value = Lighting_Output_Progress_Value(object_instance);
- apdu_len = encode_tagged_real(&apdu[0], real_value);
- break;
- case PROP_LIGHTING_COMMAND:
- apdu_len = Lighting_Output_Encode_Lighting_Command(&apdu[0],
- &Lighting_Command[object_instance]);
- break;
- case PROP_STATUS_FLAGS:
- bitstring_init(&bit_string);
- bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
- apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
- break;
- case PROP_EVENT_STATE:
- apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
- break;
- case PROP_OUT_OF_SERVICE:
- object_index = Lighting_Output_Instance_To_Index(object_instance);
- state = Lighting_Output_Out_Of_Service[object_index];
- apdu_len = encode_tagged_boolean(&apdu[0], state);
- break;
- case PROP_UNITS:
- apdu_len = encode_tagged_enumerated(&apdu[0], UNITS_PERCENT);
- break;
- case PROP_PRIORITY_ARRAY:
- /* Array element zero is the number of elements in the array */
- if (array_index == 0)
- apdu_len =
- encode_tagged_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
- /* if no index was specified, then try to encode the entire list */
- /* into one packet. */
- else if (array_index == BACNET_ARRAY_ALL) {
- object_index =
- Lighting_Output_Instance_To_Index(object_instance);
- for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
- /* FIXME: check if we have room before adding it to APDU */
- if (Lighting_Output_Level[object_index][i] == LIGHTING_LEVEL_NULL)
- len = encode_tagged_null(&apdu[apdu_len]);
- else {
- real_value = Lighting_Output_Level[object_index][i];
- len = encode_tagged_real(&apdu[apdu_len], real_value);
- }
- /* add it if we have room */
- if ((apdu_len + len) < MAX_APDU)
- apdu_len += len;
- else {
- *error_class = ERROR_CLASS_SERVICES;
- *error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
- apdu_len = -1;
- break;
- }
- }
- } else {
- object_index =
- Lighting_Output_Instance_To_Index(object_instance);
- if (array_index <= BACNET_MAX_PRIORITY) {
- if (Lighting_Output_Level[object_index][array_index - 1] ==
- LIGHTING_LEVEL_NULL)
- apdu_len = encode_tagged_null(&apdu[0]);
- else {
- real_value =
- Lighting_Output_Level[object_index][array_index - 1];
- apdu_len = encode_tagged_real(&apdu[0], real_value);
- }
- } else {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
- apdu_len = -1;
- }
- }
-
- break;
- case PROP_RELINQUISH_DEFAULT:
- real_value = LIGHTING_RELINQUISH_DEFAULT;
- apdu_len = encode_tagged_real(&apdu[0], real_value);
- break;
- default:
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_UNKNOWN_PROPERTY;
- apdu_len = -1;
- break;
- }
-
- return apdu_len;
-}
-
-/* returns true if successful */
-bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
- BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
-{
- bool status = false; /* return value */
- unsigned int object_index = 0;
- uint8_t level = LIGHTING_LEVEL_NULL;
- int len = 0;
- BACNET_APPLICATION_DATA_VALUE value;
-
- Lighting_Output_Init();
- if (!Lighting_Output_Valid_Instance(wp_data->object_instance)) {
- *error_class = ERROR_CLASS_OBJECT;
- *error_code = ERROR_CODE_UNKNOWN_OBJECT;
- return false;
- }
- /* decode the some of the request */
- len = bacapp_decode_application_data(wp_data->application_data,
- wp_data->application_data_len, &value);
- /* FIXME: len < application_data_len: more data? */
- /* FIXME: len == 0: unable to decode? */
- switch (wp_data->object_property) {
- case PROP_PRESENT_VALUE:
- if (value.tag == BACNET_APPLICATION_TAG_REAL) {
- /* Command priority 6 is reserved for use by Minimum On/Off
- algorithm and may not be used for other purposes in any
- object. */
- status =
- Lighting_Output_Present_Value_Set(wp_data->object_instance,
- value.type.Real, wp_data->priority);
- if (wp_data->priority == 6) {
- /* Command priority 6 is reserved for use by Minimum On/Off
- algorithm and may not be used for other purposes in any
- object. */
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
- } else if (!status) {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
- }
- } else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
- level = LIGHTING_LEVEL_NULL;
- object_index =
- Lighting_Output_Instance_To_Index(wp_data->object_instance);
- status =
- Lighting_Output_Present_Value_Relinquish(wp_data->
- object_instance, wp_data->priority);
- if (wp_data->priority == 6) {
- /* Command priority 6 is reserved for use by Minimum On/Off
- algorithm and may not be used for other purposes in any
- object. */
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
- } else if (!status) {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
- }
- } else {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_INVALID_DATA_TYPE;
- }
- break;
- case PROP_LIGHTING_COMMAND:
- /* FIXME: error checking? */
- Lighting_Output_Decode_Lighting_Command(wp_data->application_data,
- wp_data->application_data_len,
- &Lighting_Command[wp_data->object_instance]);
- break;
- case PROP_OUT_OF_SERVICE:
- if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
- object_index =
- Lighting_Output_Instance_To_Index(wp_data->object_instance);
- Lighting_Output_Out_Of_Service[object_index] =
- value.type.Boolean;
- status = true;
- } else {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_INVALID_DATA_TYPE;
- }
- break;
- default:
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
- break;
- }
-
- return status;
-}
-
-
-#ifdef TEST
-#include
-#include
-#include "ctest.h"
-
-void testLightingOutput(Test * pTest)
-{
- uint8_t apdu[MAX_APDU] = { 0 };
- int len = 0;
- uint32_t len_value = 0;
- uint8_t tag_number = 0;
- BACNET_OBJECT_TYPE decoded_type = OBJECT_LIGHTING_OUTPUT;
- uint32_t decoded_instance = 0;
- uint32_t instance = 123;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
-
-
- len = Lighting_Output_Encode_Property_APDU(&apdu[0],
- instance,
- PROP_OBJECT_IDENTIFIER,
- BACNET_ARRAY_ALL, &error_class, &error_code);
- ct_test(pTest, len != 0);
- len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
- ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
- len = decode_object_id(&apdu[len],
- (int *) &decoded_type, &decoded_instance);
- ct_test(pTest, decoded_type == OBJECT_LIGHTING_OUTPUT);
- ct_test(pTest, decoded_instance == instance);
-
- return;
-}
-
-#ifdef TEST_LIGHTING_OUTPUT
-int main(void)
-{
- Test *pTest;
- bool rc;
-
- pTest = ct_create("BACnet Lighting Output", NULL);
- /* individual tests */
- rc = ct_addTestFunction(pTest, testLightingOutput);
- assert(rc);
-
- ct_setStream(pTest, stdout);
- ct_run(pTest);
- (void) ct_report(pTest);
- ct_destroy(pTest);
-
- return 0;
-}
-#endif /* TEST_LIGHTING_INPUT */
-#endif /* TEST */
+/**************************************************************************
+*
+* Copyright (C) 2007 Steve Karg
+*
+* 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.
+*
+*********************************************************************/
+
+/* Lighting Output Objects - customize for your use */
+
+#include
+#include
+#include
+#include "bacdef.h"
+#include "bacdcode.h"
+#include "bacenum.h"
+#include "bacapp.h"
+#include "config.h" /* the custom stuff */
+#include "wp.h"
+
+#define MAX_LIGHTING_OUTPUTS 5
+
+/* we choose to have a NULL level in our system represented by */
+/* a particular value. When the priorities are not in use, they */
+/* will be relinquished (i.e. set to the NULL level). */
+#define LIGHTING_LEVEL_NULL 255
+/* When all the priorities are level null, the present value returns */
+/* the Relinquish Default value */
+#define LIGHTING_RELINQUISH_DEFAULT 0
+
+/* note: although the standard specifies REAL values for some
+ of the optional parameters, we represent them interally as
+ integers. */
+typedef struct LightingCommand {
+ BACNET_LIGHTING_OPERATION operation;
+ uint8_t level; /* 0..100 percent, 255=not used */
+ uint8_t ramp_rate; /* 0..100 percent-per-second, 255=not used */
+ uint8_t step_increment; /* 0..100 amount to step, 255=not used */
+ uint16_t fade_time; /* 1..65535 seconds to transition, 0=not used */
+ uint16_t duration; /* 1..65535 minutes until relinquish, 0=not used */
+} BACNET_LIGHTING_COMMAND;
+
+/* Here is our Priority Array. They are supposed to be Real, but */
+/* we might not have that kind of memory, so we will use a single byte */
+/* and load a Real for returning the value when asked. */
+static uint8_t
+ Lighting_Output_Level[MAX_LIGHTING_OUTPUTS][BACNET_MAX_PRIORITY];
+/* The Progress_Value tracks changes such as ramp and fade */
+static uint8_t Lighting_Output_Progress[MAX_LIGHTING_OUTPUTS];
+/* The minimum and maximum present values are used for clamping */
+static uint8_t Lighting_Output_Min_Present_Value[MAX_LIGHTING_OUTPUTS];
+static uint8_t Lighting_Output_Max_Present_Value[MAX_LIGHTING_OUTPUTS];
+/* Writable out-of-service allows others to play with our Present Value */
+/* without changing the physical output */
+static bool Lighting_Output_Out_Of_Service[MAX_LIGHTING_OUTPUTS];
+/* the lighting command is what we are doing */
+static uint8_t Lighting_Command_Priority = 16;
+static BACNET_LIGHTING_COMMAND Lighting_Command[MAX_LIGHTING_OUTPUTS];
+/* we need to have our arrays initialized before answering any calls */
+static bool Lighting_Output_Initialized = false;
+
+int Lighting_Output_Encode_Lighting_Command(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 */
+ float real_value = 0.0;
+ uint32_t unsigned_value = 0;
+
+ if (apdu) {
+ len = encode_context_enumerated(&apdu[apdu_len], 0,
+ data->operation);
+ apdu_len += len;
+ /* optional level? */
+ if (data->level != 255) {
+ real_value = data->level;
+ len = encode_context_real(&apdu[apdu_len], 1,
+ real_value);
+ apdu_len += len;
+ }
+ /* optional ramp-rate */
+ if (data->ramp_rate != 255) {
+ real_value = data->ramp_rate;
+ len = encode_context_real(&apdu[apdu_len], 2,
+ real_value);
+ apdu_len += len;
+ }
+ /* optional step increment */
+ if (data->step_increment != 255) {
+ real_value = data->step_increment;
+ len = encode_context_real(&apdu[apdu_len], 3,
+ real_value);
+ apdu_len += len;
+ }
+ /* optional fade time */
+ if (data->fade_time != 0) {
+ real_value = data->fade_time;
+ len = encode_context_real(&apdu[apdu_len], 4,
+ real_value);
+ apdu_len += len;
+ }
+ /* optional duration */
+ if (data->duration != 0) {
+ unsigned_value = data->duration;
+ len = encode_context_unsigned(&apdu[apdu_len], 5,
+ unsigned_value);
+ apdu_len += len;
+ }
+ }
+
+ return apdu_len;
+}
+
+int Lighting_Output_Decode_Lighting_Command(uint8_t * apdu,
+ unsigned apdu_max_len, BACNET_LIGHTING_COMMAND * data)
+{
+ int len = 0;
+ int apdu_len = 0;
+ int tag_len = 0;
+ uint8_t tag_number = 0;
+ uint32_t len_value_type = 0;
+ int type = 0; /* for decoding */
+ int property = 0; /* for decoding */
+ uint32_t unsigned_value = 0;
+ int i = 0; /* loop counter */
+ float real_value = 0.0;
+
+ /* check for value pointers */
+ if (apdu_len && data) {
+ /* Tag 0: operation */
+ if (!decode_is_context_tag(&apdu[apdu_len], 0))
+ return -1;
+ len = decode_tag_number_and_value(&apdu[apdu_len],
+ &tag_number, &len_value_type);
+ apdu_len += len;
+ len = decode_enumerated(&apdu[apdu_len], len_value_type, &data->operation);
+ apdu_len += len;
+ /* Tag 1: level - OPTIONAL */
+ if (decode_is_context_tag(&apdu[apdu_len], 1)) {
+ len = decode_tag_number_and_value(&apdu[apdu_len],
+ &tag_number, &len_value_type);
+ apdu_len += len;
+ len = decode_real(&apdu[apdu_len], &real_value);
+ apdu_len += len;
+ data->level = real_value;
+ /* FIXME: are we going to flag errors in decoding values here? */
+ }
+ /* FIXME: finish me! */
+ /* Tag 2: */
+
+ }
+
+ return len;
+}
+
+
+void Lighting_Output_Init(void)
+{
+ unsigned i, j;
+
+ if (!Lighting_Output_Initialized) {
+ Lighting_Output_Initialized = true;
+
+ /* initialize all the analog output priority arrays to NULL */
+ for (i = 0; i < MAX_LIGHTING_OUTPUTS; i++) {
+ for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
+ Lighting_Output_Level[i][j] = LIGHTING_LEVEL_NULL;
+ }
+ Lighting_Command[i].operation = BACNET_LIGHTS_STOP;
+ Lighting_Output_Out_Of_Service[i] = false;
+ Lighting_Output_Progress[i] = LIGHTING_RELINQUISH_DEFAULT;
+ Lighting_Output_Min_Present_Value[i] = 0;
+ Lighting_Output_Max_Present_Value[i] = 100;
+ }
+ }
+
+ return;
+}
+
+/* we simply have 0-n object instances. Yours might be */
+/* more complex, and then you need validate that the */
+/* given instance exists */
+bool Lighting_Output_Valid_Instance(uint32_t object_instance)
+{
+ Lighting_Output_Init();
+ if (object_instance < MAX_LIGHTING_OUTPUTS)
+ return true;
+
+ return false;
+}
+
+/* we simply have 0-n object instances. Yours might be */
+/* more complex, and then count how many you have */
+unsigned Lighting_Output_Count(void)
+{
+ Lighting_Output_Init();
+ return MAX_LIGHTING_OUTPUTS;
+}
+
+/* we simply have 0-n object instances. Yours might be */
+/* more complex, and then you need to return the instance */
+/* that correlates to the correct index */
+uint32_t Lighting_Output_Index_To_Instance(unsigned index)
+{
+ Lighting_Output_Init();
+ return index;
+}
+
+/* we simply have 0-n object instances. Yours might be */
+/* more complex, and then you need to return the index */
+/* that correlates to the correct instance number */
+unsigned Lighting_Output_Instance_To_Index(uint32_t object_instance)
+{
+ unsigned index = MAX_LIGHTING_OUTPUTS;
+
+ Lighting_Output_Init();
+ if (object_instance < MAX_LIGHTING_OUTPUTS)
+ index = object_instance;
+
+ return index;
+}
+
+float Lighting_Output_Present_Value(uint32_t object_instance)
+{
+ float value = LIGHTING_RELINQUISH_DEFAULT;
+ unsigned index = 0;
+ unsigned i = 0;
+
+ Lighting_Output_Init();
+ index = Lighting_Output_Instance_To_Index(object_instance);
+ if (index < MAX_LIGHTING_OUTPUTS) {
+ for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
+ if (Lighting_Output_Level[index][i] != LIGHTING_LEVEL_NULL) {
+ value = Lighting_Output_Level[index][i];
+ break;
+ }
+ }
+ }
+
+ return value;
+}
+
+unsigned Lighting_Output_Present_Value_Priority(uint32_t object_instance)
+{
+ unsigned index = 0; /* instance to index conversion */
+ unsigned i = 0; /* loop counter */
+ unsigned priority = 0; /* return value */
+
+ Lighting_Output_Init();
+ index = Lighting_Output_Instance_To_Index(object_instance);
+ if (index < MAX_LIGHTING_OUTPUTS) {
+ for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
+ if (Lighting_Output_Level[index][i] != LIGHTING_LEVEL_NULL) {
+ priority = i + 1;
+ break;
+ }
+ }
+ }
+
+ return priority;
+}
+
+bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
+ float value, unsigned priority)
+{
+ unsigned index = 0;
+ bool status = false;
+
+ index = Lighting_Output_Instance_To_Index(object_instance);
+ if (index < MAX_LIGHTING_OUTPUTS) {
+ if (priority && (priority <= BACNET_MAX_PRIORITY) &&
+ (priority != 6 /* reserved */ ) &&
+ (value >= 0.0) && (value <= 100.0)) {
+ Lighting_Output_Level[index][priority-1] = (uint8_t) value;
+ /* Note: you could set the physical output here to the next
+ highest priority, or to the relinquish default if no
+ priorities are set.
+ However, if Out of Service is TRUE, then don't set the
+ physical output. This comment may apply to the
+ main loop (i.e. check out of service before changing output) */
+ status = true;
+ }
+ }
+
+ return status;
+}
+
+bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
+ int priority)
+{
+ unsigned index = 0;
+ bool status = false;
+
+ index = Lighting_Output_Instance_To_Index(object_instance);
+ if (index < MAX_LIGHTING_OUTPUTS) {
+ if (priority && (priority <= BACNET_MAX_PRIORITY) &&
+ (priority != 6 /* reserved */ )) {
+ Lighting_Output_Level[index][priority-1] = LIGHTING_LEVEL_NULL;
+ /* Note: you could set the physical output here to the next
+ highest priority, or to the relinquish default if no
+ priorities are set.
+ However, if Out of Service is TRUE, then don't set the
+ physical output. This comment may apply to the
+ main loop (i.e. check out of service before changing output) */
+ status = true;
+ }
+ }
+
+ return status;
+}
+
+float Lighting_Output_Progress_Value(uint32_t object_instance)
+{
+ float value = LIGHTING_RELINQUISH_DEFAULT;
+ unsigned index = 0;
+
+ Lighting_Output_Init();
+ index = Lighting_Output_Instance_To_Index(object_instance);
+ if (index < MAX_LIGHTING_OUTPUTS) {
+ value = Lighting_Output_Progress[index];
+ }
+
+ return value;
+}
+
+/* note: the object name must be unique within this device */
+char *Lighting_Output_Name(uint32_t object_instance)
+{
+ static char text_string[32] = ""; /* okay for single thread */
+
+ if (object_instance < MAX_LIGHTING_OUTPUTS) {
+ sprintf(text_string, "LIGHTING OUTPUT %u", object_instance);
+ return text_string;
+ }
+
+ return NULL;
+}
+
+/* return apdu len, or -1 on error */
+int Lighting_Output_Encode_Property_APDU(uint8_t * apdu,
+ uint32_t object_instance,
+ BACNET_PROPERTY_ID property,
+ int32_t array_index,
+ BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
+{
+ int len = 0;
+ int apdu_len = 0; /* return value */
+ BACNET_BIT_STRING bit_string;
+ BACNET_CHARACTER_STRING char_string;
+ float real_value = (float) 1.414;
+ unsigned object_index = 0;
+ unsigned i = 0;
+ bool state = false;
+
+ Lighting_Output_Init();
+ switch (property) {
+ case PROP_OBJECT_IDENTIFIER:
+ apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_LIGHTING_OUTPUT,
+ object_instance);
+ break;
+ case PROP_OBJECT_NAME:
+ case PROP_DESCRIPTION:
+ /* object name must be unique in this device. */
+ /* FIXME: description could be writable and different than object name */
+ characterstring_init_ansi(&char_string,
+ Lighting_Output_Name(object_instance));
+ apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
+ break;
+ case PROP_OBJECT_TYPE:
+ apdu_len =
+ encode_tagged_enumerated(&apdu[0], OBJECT_LIGHTING_OUTPUT);
+ break;
+ case PROP_PRESENT_VALUE:
+ real_value = Lighting_Output_Present_Value(object_instance);
+ apdu_len = encode_tagged_real(&apdu[0], real_value);
+ break;
+ case PROP_PROGRESS_VALUE:
+ real_value = Lighting_Output_Progress_Value(object_instance);
+ apdu_len = encode_tagged_real(&apdu[0], real_value);
+ break;
+ case PROP_LIGHTING_COMMAND:
+ apdu_len = Lighting_Output_Encode_Lighting_Command(&apdu[0],
+ &Lighting_Command[object_instance]);
+ break;
+ case PROP_STATUS_FLAGS:
+ bitstring_init(&bit_string);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
+ apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
+ break;
+ case PROP_EVENT_STATE:
+ apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
+ break;
+ case PROP_OUT_OF_SERVICE:
+ object_index = Lighting_Output_Instance_To_Index(object_instance);
+ state = Lighting_Output_Out_Of_Service[object_index];
+ apdu_len = encode_tagged_boolean(&apdu[0], state);
+ break;
+ case PROP_UNITS:
+ apdu_len = encode_tagged_enumerated(&apdu[0], UNITS_PERCENT);
+ break;
+ case PROP_PRIORITY_ARRAY:
+ /* Array element zero is the number of elements in the array */
+ if (array_index == 0)
+ apdu_len =
+ encode_tagged_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
+ /* if no index was specified, then try to encode the entire list */
+ /* into one packet. */
+ else if (array_index == BACNET_ARRAY_ALL) {
+ object_index =
+ Lighting_Output_Instance_To_Index(object_instance);
+ for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
+ /* FIXME: check if we have room before adding it to APDU */
+ if (Lighting_Output_Level[object_index][i] == LIGHTING_LEVEL_NULL)
+ len = encode_tagged_null(&apdu[apdu_len]);
+ else {
+ real_value = Lighting_Output_Level[object_index][i];
+ len = encode_tagged_real(&apdu[apdu_len], real_value);
+ }
+ /* add it if we have room */
+ if ((apdu_len + len) < MAX_APDU)
+ apdu_len += len;
+ else {
+ *error_class = ERROR_CLASS_SERVICES;
+ *error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
+ apdu_len = -1;
+ break;
+ }
+ }
+ } else {
+ object_index =
+ Lighting_Output_Instance_To_Index(object_instance);
+ if (array_index <= BACNET_MAX_PRIORITY) {
+ if (Lighting_Output_Level[object_index][array_index - 1] ==
+ LIGHTING_LEVEL_NULL)
+ apdu_len = encode_tagged_null(&apdu[0]);
+ else {
+ real_value =
+ Lighting_Output_Level[object_index][array_index - 1];
+ apdu_len = encode_tagged_real(&apdu[0], real_value);
+ }
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
+ apdu_len = -1;
+ }
+ }
+
+ break;
+ case PROP_RELINQUISH_DEFAULT:
+ real_value = LIGHTING_RELINQUISH_DEFAULT;
+ apdu_len = encode_tagged_real(&apdu[0], real_value);
+ break;
+ default:
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_UNKNOWN_PROPERTY;
+ apdu_len = -1;
+ break;
+ }
+
+ return apdu_len;
+}
+
+/* returns true if successful */
+bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
+ BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
+{
+ bool status = false; /* return value */
+ unsigned int object_index = 0;
+ uint8_t level = LIGHTING_LEVEL_NULL;
+ int len = 0;
+ BACNET_APPLICATION_DATA_VALUE value;
+
+ Lighting_Output_Init();
+ if (!Lighting_Output_Valid_Instance(wp_data->object_instance)) {
+ *error_class = ERROR_CLASS_OBJECT;
+ *error_code = ERROR_CODE_UNKNOWN_OBJECT;
+ return false;
+ }
+ /* decode the some of the request */
+ len = bacapp_decode_application_data(wp_data->application_data,
+ wp_data->application_data_len, &value);
+ /* FIXME: len < application_data_len: more data? */
+ /* FIXME: len == 0: unable to decode? */
+ switch (wp_data->object_property) {
+ case PROP_PRESENT_VALUE:
+ if (value.tag == BACNET_APPLICATION_TAG_REAL) {
+ /* Command priority 6 is reserved for use by Minimum On/Off
+ algorithm and may not be used for other purposes in any
+ object. */
+ status =
+ Lighting_Output_Present_Value_Set(wp_data->object_instance,
+ value.type.Real, wp_data->priority);
+ if (wp_data->priority == 6) {
+ /* Command priority 6 is reserved for use by Minimum On/Off
+ algorithm and may not be used for other purposes in any
+ object. */
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
+ } else if (!status) {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ } else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
+ level = LIGHTING_LEVEL_NULL;
+ object_index =
+ Lighting_Output_Instance_To_Index(wp_data->object_instance);
+ status =
+ Lighting_Output_Present_Value_Relinquish(wp_data->
+ object_instance, wp_data->priority);
+ if (wp_data->priority == 6) {
+ /* Command priority 6 is reserved for use by Minimum On/Off
+ algorithm and may not be used for other purposes in any
+ object. */
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
+ } else if (!status) {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+ case PROP_LIGHTING_COMMAND:
+ /* FIXME: error checking? */
+ Lighting_Output_Decode_Lighting_Command(wp_data->application_data,
+ wp_data->application_data_len,
+ &Lighting_Command[wp_data->object_instance]);
+ break;
+ case PROP_OUT_OF_SERVICE:
+ if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
+ object_index =
+ Lighting_Output_Instance_To_Index(wp_data->object_instance);
+ Lighting_Output_Out_Of_Service[object_index] =
+ value.type.Boolean;
+ status = true;
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+ default:
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
+ break;
+ }
+
+ return status;
+}
+
+
+#ifdef TEST
+#include
+#include
+#include "ctest.h"
+
+void testLightingOutput(Test * pTest)
+{
+ uint8_t apdu[MAX_APDU] = { 0 };
+ int len = 0;
+ uint32_t len_value = 0;
+ uint8_t tag_number = 0;
+ BACNET_OBJECT_TYPE decoded_type = OBJECT_LIGHTING_OUTPUT;
+ uint32_t decoded_instance = 0;
+ uint32_t instance = 123;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
+
+
+ len = Lighting_Output_Encode_Property_APDU(&apdu[0],
+ instance,
+ PROP_OBJECT_IDENTIFIER,
+ BACNET_ARRAY_ALL, &error_class, &error_code);
+ ct_test(pTest, len != 0);
+ len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
+ ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
+ len = decode_object_id(&apdu[len],
+ (int *) &decoded_type, &decoded_instance);
+ ct_test(pTest, decoded_type == OBJECT_LIGHTING_OUTPUT);
+ ct_test(pTest, decoded_instance == instance);
+
+ return;
+}
+
+#ifdef TEST_LIGHTING_OUTPUT
+int main(void)
+{
+ Test *pTest;
+ bool rc;
+
+ pTest = ct_create("BACnet Lighting Output", NULL);
+ /* individual tests */
+ rc = ct_addTestFunction(pTest, testLightingOutput);
+ assert(rc);
+
+ ct_setStream(pTest, stdout);
+ ct_run(pTest);
+ (void) ct_report(pTest);
+ ct_destroy(pTest);
+
+ return 0;
+}
+#endif /* TEST_LIGHTING_INPUT */
+#endif /* TEST */
diff --git a/bacnet-stack/demo/object/lsp.c b/bacnet-stack/demo/object/lsp.c
index 703764f6..9d849d09 100644
--- a/bacnet-stack/demo/object/lsp.c
+++ b/bacnet-stack/demo/object/lsp.c
@@ -159,7 +159,8 @@ int Life_Safety_Point_Encode_Property_APDU(uint8_t * apdu,
unsigned object_index = 0;
bool state = false;
BACNET_RELIABILITY reliability = RELIABILITY_NO_FAULT_DETECTED;
-
(void) array_index; /* currently not used */
+
+ (void) array_index; /* currently not used */
Life_Safety_Point_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
@@ -354,3 +355,4 @@ int main(void)
}
#endif /* TEST_LIFE_SAFETY_POINT */
#endif /* TEST */
+
diff --git a/bacnet-stack/demo/server/epics_vts3.tpi b/bacnet-stack/demo/server/epics_vts3.tpi
index 487ea5e4..e5c056ed 100644
--- a/bacnet-stack/demo/server/epics_vts3.tpi
+++ b/bacnet-stack/demo/server/epics_vts3.tpi
@@ -1,759 +1,759 @@
-PICS 0
-BACnet Protocol Implementation Conformance Statement
-
---
---
--- BACnet Stack Demo
--- bacnet.sourceforge.net
--- Author: Steve Karg
---
---
-
-Vendor Name: "ASHRAE"
-Product Name: "SimpleServer"
-Product Model Number: "GNU"
-Product Description: "server"
-
-BIBBs Supported:
-{
--- The BIBBs may be any of:
--- DS-RP-A
- DS-RP-B
--- DS-RPM-A DS-RPM-B
--- DS-RPC-A DS-RPC-B
--- DS-WP-A
- DS-WP-B
--- DS-WPM-A DS-WPM-B
--- DS-COV-A DS-COV-B
--- DS-COVP-A DS-COVP-B
--- DS-COVU-A DS-COVU-B
--- AE-N-A AE-N-I-B AE-N-E-B
--- AE-ACK-A AE-ACK-B
--- AE-ASUM-A AE-ASUM-B
--- AE-ESUM-A AE-ESUM-B
--- AE-INFO-A AE-INFO-B
--- AE-LS-A AE-LS-B
--- SCHED-A SCHED-I-B SCHED-E-B
--- T-VMT-A T-VMT-I-B T-VMT-E-B
--- T-ATR-A T-ATR-B
--- DM-DDB-A
- DM-DDB-B
--- DM-DOB-A
- DM-DOB-B
--- DM-DCC-A
- DM-DCC-B
--- DM-PT-A DM-PT-B
--- DM-TM-A DM-TM-B
--- DM-TS-A
- DM-TS-B
--- DM-UTC-A
- DM-UTC-B
--- DM-RD-A
- DM-RD-B
--- DM-BR-A DM-BR-B
--- DM-R-A DM-R-B
--- DM-LM-A DM-LM-B
--- DM-OCD-A DM-OCD-B
--- DM-VT-A DM-VT-B
--- NM-CE-A NM-CE-B
--- NM-RC-A NM-RC-B
-}
-
-BACnet Standard Application Services Supported:
-{
--- AcknowledgeAlarm Initiate Execute
--- ConfirmedCOVNotification Initiate Execute
- UnconfirmedCOVNotification Initiate
--- ConfirmedEventNotification Initiate Execute
--- UnconfirmedEventNotification Initiate Execute
--- GetAlarmSummary Initiate Execute
--- GetEnrollmentSummary Initiate Execute
- AtomicReadFile Initiate Execute
--- AtomicWriteFile Initiate Execute
--- AddListElement Initiate Execute
--- RemoveListElement Initiate Execute
--- CreateObject Initiate Execute
--- DeleteObject Initiate Execute
- ReadProperty Initiate Execute
--- ReadpropertyConditional Initiate Execute
--- ReadPropertyMultiple Initiate Execute
--- SubscribeCOV Initiate Execute
- WriteProperty Initiate Execute
--- WritePropertyMultiple Initiate Execute
- DeviceCommunicationControl Initiate Execute
--- ConfirmedPrivateTransfer Initiate Execute
--- UnconfirmedPrivateTransfer Initiate Execute
- TimeSynchronization Initiate Execute
- Who-Has Initiate Execute
- I-Have Initiate
- Who-Is Initiate Execute
- I-Am Initiate
--- VT-Open Initiate Execute
--- VT-Close Initiate Execute
--- VT-Data Initiate Execute
--- ConfirmedTextMessage Initiate Execute
--- UnconfirmedTextMessage Initiate Execute
- ReinitializeDevice Initiate Execute
--- RequestKey Initiate Execute
--- Authenticate Initiate Execute
- UTCTimeSynchronization Initiate Execute
--- ReadRange Initiate Execute
--- GetEventInformation Initiate Execute
--- LifeSafetyOperation Initiate Execute
--- SubscribeCOVProperty Initiate Execute
--- RequestKey Initiate Execute
--- Authenticate Initiate Execute
-}
-
-Standard Object-Types Supported:
-{
- Analog Input
- Analog Output
- Analog Value
--- Averaging Createable Deleteable
- Binary Input
- Binary Output
- Binary Value
--- Calendar Createable Deleteable
--- Command Createable Deleteable
- Device
--- Event Enrollment Createable Deleteable
- File
--- Group Createable Deleteable
--- Loop Createable Deleteable
--- Multi-state Input Createable Deleteable
-Multi-state Output
--- Multi-state Value Createable Deleteable
--- Notification Class Createable Deleteable
--- Program Createable Deleteable
--- Schedule Createable Deleteable
- Life Safety Point
--- Life Safety Zone Createable Deleteable
--- Trend Log Createable Deleteable
- Load Control
-}
-
-Data Link Layer Option:
-{
--- ISO 8802-3, 10BASE5
--- ISO 8802-3, 10BASE2
--- ISO 8802-3, 10BASET
--- ISO 8802-3, Fiber
--- ARCNET, coax star
--- ARCNET, coax bus
--- ARCNET, twisted pair star
--- ARCNET, twisted pair bus
--- ARCNET, fiber star
--- MS/TP master. Baud rate(s): 9600
--- MS/TP slave. Baud rate(s): 9600
--- Point-To-Point. Modem, Baud rate(s): 14.4k
--- Point-To-Point. Modem, Autobaud range: 9600 to 28.8k
- BACnet/IP, 'DIX' Ethernet
--- BACnet/IP, PPP
--- Other
-}
-
-Character Sets Supported:
-{
- ANSI X3.4
--- Other Character Sets not supported
--- IBM/Microsoft DBCS
--- JIS C 6226
--- ISO 10646 (ICS-4)
--- ISO 10646 (UCS2)
-}
-
-Special Functionality:
-{
- Maximum APDU size in octets: 480 -- Arcnet Maximum 501 less NL Header
--- Maximum APDU size in octets: 480
--- Segmented Requests Supported, window size: 1
--- Segmented Responses Supported, window size: 1
--- Router
-}
-
-List of Objects in test device:
-{
- {
- object-identifier: (device,123)
- object-name: "SimpleServer"
- object-type: device
- system-status: operational
- vendor-name: "ASHRAE"
- vendor-identifier: 0
- model-name: "GNU"
- firmware-revision: "1.0"
- application-software-version: "1.0"
- protocol-version: 1
- protocol-revision: 5
- protocol-conformance-class: 1
- protocol-services-supported: (F,F,F,F,F,F,T,F,F,F,F,F,T,F,F,T,F,T,F,F,T,F,F,F,F,F,F,F,F,F,F,F,T,T,T,F,T,F,F,F)
- protocol-object-types-supported: (T,T,T,T,T,T,F,F,T,F,T,F,F,F,T,F,F,F,F,F,F,T,F,F,F)
- max-apdu-length-accepted: 480
- segmentation-supported: no-segmentation
- apdu-timeout: 3000
- number-of-apdu-retries: 3
- device-address-binding: ?
- local-time: ?
- local-date: ?
- utc-offset: ?
- daylight-savings-status: ?
- database-revision: ?
- object-list: {
- (device,123),(analog-input,0),(analog-input,1),
- (analog-input,2),(analog-input,3),(analog-input,4),
- (analog-input,5),(analog-input,6),(analog-output,0),
- (analog-output,1),(analog-output,2),(analog-output,3),
- (analog-value,0),(analog-value,1),(analog-value,2),
- (analog-value,3),(binary-input,0),(binary-input,1),
- (binary-input,2),(binary-input,3),(binary-input,4),
- (binary-output,0),(binary-output,1),(binary-output,2),
- (binary-output,3),(binary-output,4),(binary-output,5),
- (binary-value,0),(binary-value,1),(life-safety-point,0),
- (life-safety-point,1),(life-safety-point,2),(life-safety-point,3),
- (life-safety-point,4),(life-safety-point,5),(life-safety-point,6),
- (multi-state-output,0),(multi-state-output,1),(multi-state-output,2),
- (multi-state-output,3),(file,0),(file,1),
- (file,2)
- }
- },
- {
- object-identifier: (analog-input,0)
- object-name: "ANALOG INPUT 0"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "ANALOG INPUT 0"
- },
- {
- object-identifier: (analog-input,1)
- object-name: "ANALOG INPUT 1"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "ANALOG INPUT 1"
- },
- {
- object-identifier: (analog-input,2)
- object-name: "ANALOG INPUT 2"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "ANALOG INPUT 2"
- },
- {
- object-identifier: (analog-input,3)
- object-name: "ANALOG INPUT 3"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "ANALOG INPUT 3"
- },
- {
- object-identifier: (analog-input,4)
- object-name: "ANALOG INPUT 4"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "ANALOG INPUT 4"
- },
- {
- object-identifier: (analog-input,5)
- object-name: "ANALOG INPUT 5"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "ANALOG INPUT 5"
- },
- {
- object-identifier: (analog-input,6)
- object-name: "ANALOG INPUT 6"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "ANALOG INPUT 6"
- },
- {
- object-identifier: (analog-output,0)
- object-name: "ANALOG OUTPUT 0"
- object-type: analog-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: 0.000000
- description: "ANALOG OUTPUT 0"
- },
- {
- object-identifier: (analog-output,1)
- object-name: "ANALOG OUTPUT 1"
- object-type: analog-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: 0.000000
- description: "ANALOG OUTPUT 1"
- },
- {
- object-identifier: (analog-output,2)
- object-name: "ANALOG OUTPUT 2"
- object-type: analog-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: 0.000000
- description: "ANALOG OUTPUT 2"
- },
- {
- object-identifier: (analog-output,3)
- object-name: "ANALOG OUTPUT 3"
- object-type: analog-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: 0.000000
- description: "ANALOG OUTPUT 3"
- },
- {
- object-identifier: (analog-value,0)
- object-name: "ANALOG VALUE 0"
- object-type: analog-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- relinquish-default: 0.000000
- description: "ANALOG VALUE 0"
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: 0.000000
- },
- {
- object-identifier: (analog-value,1)
- object-name: "ANALOG VALUE 1"
- object-type: analog-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- relinquish-default: 0.000000
- description: "ANALOG VALUE 1"
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: 0.000000
- },
- {
- object-identifier: (analog-value,2)
- object-name: "ANALOG VALUE 2"
- object-type: analog-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- relinquish-default: 0.000000
- description: "ANALOG VALUE 2"
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: 0.000000
- },
- {
- object-identifier: (analog-value,3)
- object-name: "ANALOG VALUE 3"
- object-type: analog-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- relinquish-default: 0.000000
- description: "ANALOG VALUE 3"
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: 0.000000
- },
- {
- object-identifier: (binary-input,0)
- object-name: "BINARY INPUT 0"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BINARY INPUT 0"
- },
- {
- object-identifier: (binary-input,1)
- object-name: "BINARY INPUT 1"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BINARY INPUT 1"
- },
- {
- object-identifier: (binary-input,2)
- object-name: "BINARY INPUT 2"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BINARY INPUT 2"
- },
- {
- object-identifier: (binary-input,3)
- object-name: "BINARY INPUT 3"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BINARY INPUT 3"
- },
- {
- object-identifier: (binary-input,4)
- object-name: "BINARY INPUT 4"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BINARY INPUT 4"
- },
- {
- object-identifier: (binary-output,0)
- object-name: "BINARY OUTPUT 0"
- object-type: binary-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- description: "BINARY OUTPUT 0"
- },
- {
- object-identifier: (binary-output,1)
- object-name: "BINARY OUTPUT 1"
- object-type: binary-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- description: "BINARY OUTPUT 1"
- },
- {
- object-identifier: (binary-output,2)
- object-name: "BINARY OUTPUT 2"
- object-type: binary-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- description: "BINARY OUTPUT 2"
- },
- {
- object-identifier: (binary-output,3)
- object-name: "BINARY OUTPUT 3"
- object-type: binary-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- description: "BINARY OUTPUT 3"
- },
- {
- object-identifier: (binary-output,4)
- object-name: "BINARY OUTPUT 4"
- object-type: binary-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- description: "BINARY OUTPUT 4"
- },
- {
- object-identifier: (binary-output,5)
- object-name: "BINARY OUTPUT 5"
- object-type: binary-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- description: "BINARY OUTPUT 5"
- },
- {
- object-identifier: (binary-value,0)
- object-name: "BINARY VALUE 0"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BINARY VALUE 0"
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- },
- {
- object-identifier: (binary-value,1)
- object-name: "BINARY VALUE 1"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BINARY VALUE 1"
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- },
- {
- object-identifier: (life-safety-point,0)
- object-name: "LS POINT 0"
- object-type: life-safety-point
- description: "LS POINT 0"
- present-value: ?
- device-type: ?
- status-flags: (F,F,F,F)
- event-state: normal
- reliability: ?
- out-of-service: F
- mode: ? W
- silenced: ?
- operation-expected: ?
- },
- {
- object-identifier: (life-safety-point,1)
- object-name: "LS POINT 1"
- object-type: life-safety-point
- description: "LS POINT 1"
- present-value: ?
- device-type: ?
- status-flags: (F,F,F,F)
- event-state: normal
- reliability: ?
- out-of-service: F
- mode: ? W
- silenced: ?
- operation-expected: ?
- },
- {
- object-identifier: (life-safety-point,2)
- object-name: "LS POINT 2"
- object-type: life-safety-point
- description: "LS POINT 2"
- present-value: ?
- device-type: ?
- status-flags: (F,F,F,F)
- event-state: normal
- reliability: ?
- out-of-service: F
- mode: ? W
- silenced: ?
- operation-expected: ?
- },
- {
- object-identifier: (life-safety-point,3)
- object-name: "LS POINT 3"
- object-type: life-safety-point
- description: "LS POINT 3"
- present-value: ?
- device-type: ?
- status-flags: (F,F,F,F)
- event-state: normal
- reliability: ?
- out-of-service: F
- mode: ? W
- silenced: ?
- operation-expected: ?
- },
- {
- object-identifier: (life-safety-point,4)
- object-name: "LS POINT 4"
- object-type: life-safety-point
- description: "LS POINT 4"
- present-value: ?
- device-type: ?
- status-flags: (F,F,F,F)
- event-state: normal
- reliability: ?
- out-of-service: F
- mode: ? W
- silenced: ?
- operation-expected: ?
- },
- {
- object-identifier: (life-safety-point,5)
- object-name: "LS POINT 5"
- object-type: life-safety-point
- description: "LS POINT 5"
- present-value: ?
- device-type: ?
- status-flags: (F,F,F,F)
- event-state: normal
- reliability: ?
- out-of-service: F
- mode: ? W
- silenced: ?
- operation-expected: ?
- },
- {
- object-identifier: (life-safety-point,6)
- object-name: "LS POINT 6"
- object-type: life-safety-point
- description: "LS POINT 6"
- present-value: ?
- device-type: ?
- status-flags: (F,F,F,F)
- event-state: normal
- reliability: ?
- out-of-service: F
- mode: ? W
- silenced: ?
- operation-expected: ?
- },
- {
- object-identifier: (multi-state-output,0)
- object-name: "MULTISTATE OUTPUT 0"
- object-type: multi-state-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- number-of-states: 254
- description: "MULTISTATE OUTPUT 0"
- },
- {
- object-identifier: (multi-state-output,1)
- object-name: "MULTISTATE OUTPUT 1"
- object-type: multi-state-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- number-of-states: 254
- description: "MULTISTATE OUTPUT 1"
- },
- {
- object-identifier: (multi-state-output,2)
- object-name: "MULTISTATE OUTPUT 2"
- object-type: multi-state-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- number-of-states: 254
- description: "MULTISTATE OUTPUT 2"
- },
- {
- object-identifier: (multi-state-output,3)
- object-name: "MULTISTATE OUTPUT 3"
- object-type: multi-state-output
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
- relinquish-default: inactive
- number-of-states: 254
- description: "MULTISTATE OUTPUT 3"
- },
- {
- object-identifier: (file,0)
- object-name: "FILE 0"
- object-type: file
- file-type: "TEXT"
- file-size: 0
- modification-date: ?
- archive: ? W
- read-only: T
- file-access-method: stream-access
- description: "test.log"
- },
- {
- object-identifier: (file,1)
- object-name: "FILE 1"
- object-type: file
- file-type: "TEXT"
- file-size: 0
- modification-date: ?
- archive: ? W
- read-only: T
- file-access-method: stream-access
- description: "script.txt"
- },
- {
- object-identifier: (file,2)
- object-name: "FILE 2"
- object-type: file
- file-type: "TEXT"
- file-size: 39582
- modification-date: ?
- archive: ? W
- read-only: T
- file-access-method: stream-access
- description: "bacenum.h"
- }
-}
-
-End of BACnet Protocol Implementation Conformance Statement
-
-
+PICS 0
+BACnet Protocol Implementation Conformance Statement
+
+--
+--
+-- BACnet Stack Demo
+-- bacnet.sourceforge.net
+-- Author: Steve Karg
+--
+--
+
+Vendor Name: "ASHRAE"
+Product Name: "SimpleServer"
+Product Model Number: "GNU"
+Product Description: "server"
+
+BIBBs Supported:
+{
+-- The BIBBs may be any of:
+-- DS-RP-A
+ DS-RP-B
+-- DS-RPM-A DS-RPM-B
+-- DS-RPC-A DS-RPC-B
+-- DS-WP-A
+ DS-WP-B
+-- DS-WPM-A DS-WPM-B
+-- DS-COV-A DS-COV-B
+-- DS-COVP-A DS-COVP-B
+-- DS-COVU-A DS-COVU-B
+-- AE-N-A AE-N-I-B AE-N-E-B
+-- AE-ACK-A AE-ACK-B
+-- AE-ASUM-A AE-ASUM-B
+-- AE-ESUM-A AE-ESUM-B
+-- AE-INFO-A AE-INFO-B
+-- AE-LS-A AE-LS-B
+-- SCHED-A SCHED-I-B SCHED-E-B
+-- T-VMT-A T-VMT-I-B T-VMT-E-B
+-- T-ATR-A T-ATR-B
+-- DM-DDB-A
+ DM-DDB-B
+-- DM-DOB-A
+ DM-DOB-B
+-- DM-DCC-A
+ DM-DCC-B
+-- DM-PT-A DM-PT-B
+-- DM-TM-A DM-TM-B
+-- DM-TS-A
+ DM-TS-B
+-- DM-UTC-A
+ DM-UTC-B
+-- DM-RD-A
+ DM-RD-B
+-- DM-BR-A DM-BR-B
+-- DM-R-A DM-R-B
+-- DM-LM-A DM-LM-B
+-- DM-OCD-A DM-OCD-B
+-- DM-VT-A DM-VT-B
+-- NM-CE-A NM-CE-B
+-- NM-RC-A NM-RC-B
+}
+
+BACnet Standard Application Services Supported:
+{
+-- AcknowledgeAlarm Initiate Execute
+-- ConfirmedCOVNotification Initiate Execute
+ UnconfirmedCOVNotification Initiate
+-- ConfirmedEventNotification Initiate Execute
+-- UnconfirmedEventNotification Initiate Execute
+-- GetAlarmSummary Initiate Execute
+-- GetEnrollmentSummary Initiate Execute
+ AtomicReadFile Initiate Execute
+-- AtomicWriteFile Initiate Execute
+-- AddListElement Initiate Execute
+-- RemoveListElement Initiate Execute
+-- CreateObject Initiate Execute
+-- DeleteObject Initiate Execute
+ ReadProperty Initiate Execute
+-- ReadpropertyConditional Initiate Execute
+-- ReadPropertyMultiple Initiate Execute
+-- SubscribeCOV Initiate Execute
+ WriteProperty Initiate Execute
+-- WritePropertyMultiple Initiate Execute
+ DeviceCommunicationControl Initiate Execute
+-- ConfirmedPrivateTransfer Initiate Execute
+-- UnconfirmedPrivateTransfer Initiate Execute
+ TimeSynchronization Initiate Execute
+ Who-Has Initiate Execute
+ I-Have Initiate
+ Who-Is Initiate Execute
+ I-Am Initiate
+-- VT-Open Initiate Execute
+-- VT-Close Initiate Execute
+-- VT-Data Initiate Execute
+-- ConfirmedTextMessage Initiate Execute
+-- UnconfirmedTextMessage Initiate Execute
+ ReinitializeDevice Initiate Execute
+-- RequestKey Initiate Execute
+-- Authenticate Initiate Execute
+ UTCTimeSynchronization Initiate Execute
+-- ReadRange Initiate Execute
+-- GetEventInformation Initiate Execute
+-- LifeSafetyOperation Initiate Execute
+-- SubscribeCOVProperty Initiate Execute
+-- RequestKey Initiate Execute
+-- Authenticate Initiate Execute
+}
+
+Standard Object-Types Supported:
+{
+ Analog Input
+ Analog Output
+ Analog Value
+-- Averaging Createable Deleteable
+ Binary Input
+ Binary Output
+ Binary Value
+-- Calendar Createable Deleteable
+-- Command Createable Deleteable
+ Device
+-- Event Enrollment Createable Deleteable
+ File
+-- Group Createable Deleteable
+-- Loop Createable Deleteable
+-- Multi-state Input Createable Deleteable
+Multi-state Output
+-- Multi-state Value Createable Deleteable
+-- Notification Class Createable Deleteable
+-- Program Createable Deleteable
+-- Schedule Createable Deleteable
+ Life Safety Point
+-- Life Safety Zone Createable Deleteable
+-- Trend Log Createable Deleteable
+ Load Control
+}
+
+Data Link Layer Option:
+{
+-- ISO 8802-3, 10BASE5
+-- ISO 8802-3, 10BASE2
+-- ISO 8802-3, 10BASET
+-- ISO 8802-3, Fiber
+-- ARCNET, coax star
+-- ARCNET, coax bus
+-- ARCNET, twisted pair star
+-- ARCNET, twisted pair bus
+-- ARCNET, fiber star
+-- MS/TP master. Baud rate(s): 9600
+-- MS/TP slave. Baud rate(s): 9600
+-- Point-To-Point. Modem, Baud rate(s): 14.4k
+-- Point-To-Point. Modem, Autobaud range: 9600 to 28.8k
+ BACnet/IP, 'DIX' Ethernet
+-- BACnet/IP, PPP
+-- Other
+}
+
+Character Sets Supported:
+{
+ ANSI X3.4
+-- Other Character Sets not supported
+-- IBM/Microsoft DBCS
+-- JIS C 6226
+-- ISO 10646 (ICS-4)
+-- ISO 10646 (UCS2)
+}
+
+Special Functionality:
+{
+ Maximum APDU size in octets: 480 -- Arcnet Maximum 501 less NL Header
+-- Maximum APDU size in octets: 480
+-- Segmented Requests Supported, window size: 1
+-- Segmented Responses Supported, window size: 1
+-- Router
+}
+
+List of Objects in test device:
+{
+ {
+ object-identifier: (device,123)
+ object-name: "SimpleServer"
+ object-type: device
+ system-status: operational
+ vendor-name: "ASHRAE"
+ vendor-identifier: 0
+ model-name: "GNU"
+ firmware-revision: "1.0"
+ application-software-version: "1.0"
+ protocol-version: 1
+ protocol-revision: 5
+ protocol-conformance-class: 1
+ protocol-services-supported: (F,F,F,F,F,F,T,F,F,F,F,F,T,F,F,T,F,T,F,F,T,F,F,F,F,F,F,F,F,F,F,F,T,T,T,F,T,F,F,F)
+ protocol-object-types-supported: (T,T,T,T,T,T,F,F,T,F,T,F,F,F,T,F,F,F,F,F,F,T,F,F,F)
+ max-apdu-length-accepted: 480
+ segmentation-supported: no-segmentation
+ apdu-timeout: 3000
+ number-of-apdu-retries: 3
+ device-address-binding: ?
+ local-time: ?
+ local-date: ?
+ utc-offset: ?
+ daylight-savings-status: ?
+ database-revision: ?
+ object-list: {
+ (device,123),(analog-input,0),(analog-input,1),
+ (analog-input,2),(analog-input,3),(analog-input,4),
+ (analog-input,5),(analog-input,6),(analog-output,0),
+ (analog-output,1),(analog-output,2),(analog-output,3),
+ (analog-value,0),(analog-value,1),(analog-value,2),
+ (analog-value,3),(binary-input,0),(binary-input,1),
+ (binary-input,2),(binary-input,3),(binary-input,4),
+ (binary-output,0),(binary-output,1),(binary-output,2),
+ (binary-output,3),(binary-output,4),(binary-output,5),
+ (binary-value,0),(binary-value,1),(life-safety-point,0),
+ (life-safety-point,1),(life-safety-point,2),(life-safety-point,3),
+ (life-safety-point,4),(life-safety-point,5),(life-safety-point,6),
+ (multi-state-output,0),(multi-state-output,1),(multi-state-output,2),
+ (multi-state-output,3),(file,0),(file,1),
+ (file,2)
+ }
+ },
+ {
+ object-identifier: (analog-input,0)
+ object-name: "ANALOG INPUT 0"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "ANALOG INPUT 0"
+ },
+ {
+ object-identifier: (analog-input,1)
+ object-name: "ANALOG INPUT 1"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "ANALOG INPUT 1"
+ },
+ {
+ object-identifier: (analog-input,2)
+ object-name: "ANALOG INPUT 2"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "ANALOG INPUT 2"
+ },
+ {
+ object-identifier: (analog-input,3)
+ object-name: "ANALOG INPUT 3"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "ANALOG INPUT 3"
+ },
+ {
+ object-identifier: (analog-input,4)
+ object-name: "ANALOG INPUT 4"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "ANALOG INPUT 4"
+ },
+ {
+ object-identifier: (analog-input,5)
+ object-name: "ANALOG INPUT 5"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "ANALOG INPUT 5"
+ },
+ {
+ object-identifier: (analog-input,6)
+ object-name: "ANALOG INPUT 6"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "ANALOG INPUT 6"
+ },
+ {
+ object-identifier: (analog-output,0)
+ object-name: "ANALOG OUTPUT 0"
+ object-type: analog-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: 0.000000
+ description: "ANALOG OUTPUT 0"
+ },
+ {
+ object-identifier: (analog-output,1)
+ object-name: "ANALOG OUTPUT 1"
+ object-type: analog-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: 0.000000
+ description: "ANALOG OUTPUT 1"
+ },
+ {
+ object-identifier: (analog-output,2)
+ object-name: "ANALOG OUTPUT 2"
+ object-type: analog-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: 0.000000
+ description: "ANALOG OUTPUT 2"
+ },
+ {
+ object-identifier: (analog-output,3)
+ object-name: "ANALOG OUTPUT 3"
+ object-type: analog-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: 0.000000
+ description: "ANALOG OUTPUT 3"
+ },
+ {
+ object-identifier: (analog-value,0)
+ object-name: "ANALOG VALUE 0"
+ object-type: analog-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ relinquish-default: 0.000000
+ description: "ANALOG VALUE 0"
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: 0.000000
+ },
+ {
+ object-identifier: (analog-value,1)
+ object-name: "ANALOG VALUE 1"
+ object-type: analog-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ relinquish-default: 0.000000
+ description: "ANALOG VALUE 1"
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: 0.000000
+ },
+ {
+ object-identifier: (analog-value,2)
+ object-name: "ANALOG VALUE 2"
+ object-type: analog-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ relinquish-default: 0.000000
+ description: "ANALOG VALUE 2"
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: 0.000000
+ },
+ {
+ object-identifier: (analog-value,3)
+ object-name: "ANALOG VALUE 3"
+ object-type: analog-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ relinquish-default: 0.000000
+ description: "ANALOG VALUE 3"
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: 0.000000
+ },
+ {
+ object-identifier: (binary-input,0)
+ object-name: "BINARY INPUT 0"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BINARY INPUT 0"
+ },
+ {
+ object-identifier: (binary-input,1)
+ object-name: "BINARY INPUT 1"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BINARY INPUT 1"
+ },
+ {
+ object-identifier: (binary-input,2)
+ object-name: "BINARY INPUT 2"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BINARY INPUT 2"
+ },
+ {
+ object-identifier: (binary-input,3)
+ object-name: "BINARY INPUT 3"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BINARY INPUT 3"
+ },
+ {
+ object-identifier: (binary-input,4)
+ object-name: "BINARY INPUT 4"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BINARY INPUT 4"
+ },
+ {
+ object-identifier: (binary-output,0)
+ object-name: "BINARY OUTPUT 0"
+ object-type: binary-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ description: "BINARY OUTPUT 0"
+ },
+ {
+ object-identifier: (binary-output,1)
+ object-name: "BINARY OUTPUT 1"
+ object-type: binary-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ description: "BINARY OUTPUT 1"
+ },
+ {
+ object-identifier: (binary-output,2)
+ object-name: "BINARY OUTPUT 2"
+ object-type: binary-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ description: "BINARY OUTPUT 2"
+ },
+ {
+ object-identifier: (binary-output,3)
+ object-name: "BINARY OUTPUT 3"
+ object-type: binary-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ description: "BINARY OUTPUT 3"
+ },
+ {
+ object-identifier: (binary-output,4)
+ object-name: "BINARY OUTPUT 4"
+ object-type: binary-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ description: "BINARY OUTPUT 4"
+ },
+ {
+ object-identifier: (binary-output,5)
+ object-name: "BINARY OUTPUT 5"
+ object-type: binary-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ description: "BINARY OUTPUT 5"
+ },
+ {
+ object-identifier: (binary-value,0)
+ object-name: "BINARY VALUE 0"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BINARY VALUE 0"
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ },
+ {
+ object-identifier: (binary-value,1)
+ object-name: "BINARY VALUE 1"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BINARY VALUE 1"
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ },
+ {
+ object-identifier: (life-safety-point,0)
+ object-name: "LS POINT 0"
+ object-type: life-safety-point
+ description: "LS POINT 0"
+ present-value: ?
+ device-type: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ reliability: ?
+ out-of-service: F
+ mode: ? W
+ silenced: ?
+ operation-expected: ?
+ },
+ {
+ object-identifier: (life-safety-point,1)
+ object-name: "LS POINT 1"
+ object-type: life-safety-point
+ description: "LS POINT 1"
+ present-value: ?
+ device-type: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ reliability: ?
+ out-of-service: F
+ mode: ? W
+ silenced: ?
+ operation-expected: ?
+ },
+ {
+ object-identifier: (life-safety-point,2)
+ object-name: "LS POINT 2"
+ object-type: life-safety-point
+ description: "LS POINT 2"
+ present-value: ?
+ device-type: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ reliability: ?
+ out-of-service: F
+ mode: ? W
+ silenced: ?
+ operation-expected: ?
+ },
+ {
+ object-identifier: (life-safety-point,3)
+ object-name: "LS POINT 3"
+ object-type: life-safety-point
+ description: "LS POINT 3"
+ present-value: ?
+ device-type: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ reliability: ?
+ out-of-service: F
+ mode: ? W
+ silenced: ?
+ operation-expected: ?
+ },
+ {
+ object-identifier: (life-safety-point,4)
+ object-name: "LS POINT 4"
+ object-type: life-safety-point
+ description: "LS POINT 4"
+ present-value: ?
+ device-type: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ reliability: ?
+ out-of-service: F
+ mode: ? W
+ silenced: ?
+ operation-expected: ?
+ },
+ {
+ object-identifier: (life-safety-point,5)
+ object-name: "LS POINT 5"
+ object-type: life-safety-point
+ description: "LS POINT 5"
+ present-value: ?
+ device-type: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ reliability: ?
+ out-of-service: F
+ mode: ? W
+ silenced: ?
+ operation-expected: ?
+ },
+ {
+ object-identifier: (life-safety-point,6)
+ object-name: "LS POINT 6"
+ object-type: life-safety-point
+ description: "LS POINT 6"
+ present-value: ?
+ device-type: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ reliability: ?
+ out-of-service: F
+ mode: ? W
+ silenced: ?
+ operation-expected: ?
+ },
+ {
+ object-identifier: (multi-state-output,0)
+ object-name: "MULTISTATE OUTPUT 0"
+ object-type: multi-state-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ number-of-states: 254
+ description: "MULTISTATE OUTPUT 0"
+ },
+ {
+ object-identifier: (multi-state-output,1)
+ object-name: "MULTISTATE OUTPUT 1"
+ object-type: multi-state-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ number-of-states: 254
+ description: "MULTISTATE OUTPUT 1"
+ },
+ {
+ object-identifier: (multi-state-output,2)
+ object-name: "MULTISTATE OUTPUT 2"
+ object-type: multi-state-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ number-of-states: 254
+ description: "MULTISTATE OUTPUT 2"
+ },
+ {
+ object-identifier: (multi-state-output,3)
+ object-name: "MULTISTATE OUTPUT 3"
+ object-type: multi-state-output
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ priority-array: {?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?}
+ relinquish-default: inactive
+ number-of-states: 254
+ description: "MULTISTATE OUTPUT 3"
+ },
+ {
+ object-identifier: (file,0)
+ object-name: "FILE 0"
+ object-type: file
+ file-type: "TEXT"
+ file-size: 0
+ modification-date: ?
+ archive: ? W
+ read-only: T
+ file-access-method: stream-access
+ description: "test.log"
+ },
+ {
+ object-identifier: (file,1)
+ object-name: "FILE 1"
+ object-type: file
+ file-type: "TEXT"
+ file-size: 0
+ modification-date: ?
+ archive: ? W
+ read-only: T
+ file-access-method: stream-access
+ description: "script.txt"
+ },
+ {
+ object-identifier: (file,2)
+ object-name: "FILE 2"
+ object-type: file
+ file-type: "TEXT"
+ file-size: 39582
+ modification-date: ?
+ archive: ? W
+ read-only: T
+ file-access-method: stream-access
+ description: "bacenum.h"
+ }
+}
+
+End of BACnet Protocol Implementation Conformance Statement
+
+
diff --git a/bacnet-stack/demo/ucov/Makefile b/bacnet-stack/demo/ucov/Makefile
index ec29af06..d5ceae3e 100644
--- a/bacnet-stack/demo/ucov/Makefile
+++ b/bacnet-stack/demo/ucov/Makefile
@@ -1,88 +1,88 @@
-#Makefile to build BACnet Application for the Linux Port
-CC = gcc
-BASEDIR = .
-#CFLAGS = -Wall -I.
-# -g for debugging with gdb
-#CFLAGS = -Wall -I. -O2 -g
-# Note: you can strip out symbols using the strip command
-# to get an idea of how big the compile really is.
-
-# Configure the BACnet Datalink Layer
-#BACDL_DEFINE=-DBACDL_ETHERNET=1
-#BACDL_DEFINE=-DBACDL_ARCNET=1
-BACDL_DEFINE=-DBACDL_BIP=1
-BACNET_DEFINES=-DBACFILE=1 -DTSM_ENABLED=0 -DBIG_ENDIAN=0 -DPRINT_ENABLED=1
-DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
-
-BACNET_PORT = ../../ports/linux
-BACNET_OBJECT = ../object
-BACNET_HANDLER = ../handler
-BACNET_ROOT = ../..
-INCLUDES = -I$(BACNET_ROOT) -I$(BACNET_PORT) -I$(BACNET_OBJECT) -I$(BACNET_HANDLER)
-
-CFLAGS = -Wall -g $(INCLUDES) $(DEFINES)
-
-TARGET = bacucov
-
-SRCS = main.c \
- $(BACNET_PORT)/bip-init.c \
- $(BACNET_PORT)/ethernet.c \
- $(BACNET_PORT)/arcnet.c \
- $(BACNET_ROOT)/bip.c \
- $(BACNET_HANDLER)/txbuf.c \
- $(BACNET_HANDLER)/noserv.c \
- $(BACNET_HANDLER)/h_whois.c \
- $(BACNET_HANDLER)/h_rp.c \
- $(BACNET_HANDLER)/h_iam.c \
- $(BACNET_OBJECT)/device.c \
- $(BACNET_OBJECT)/ai.c \
- $(BACNET_OBJECT)/ao.c \
- $(BACNET_OBJECT)/av.c \
- $(BACNET_OBJECT)/bi.c \
- $(BACNET_OBJECT)/bo.c \
- $(BACNET_OBJECT)/bv.c \
- $(BACNET_OBJECT)/lc.c \
- $(BACNET_OBJECT)/lsp.c \
- $(BACNET_OBJECT)/mso.c \
- $(BACNET_OBJECT)/bacfile.c \
- $(BACNET_ROOT)/filename.c \
- $(BACNET_ROOT)/rp.c \
- $(BACNET_ROOT)/wp.c \
- $(BACNET_ROOT)/bacdcode.c \
- $(BACNET_ROOT)/bacapp.c \
- $(BACNET_ROOT)/bacprop.c \
- $(BACNET_ROOT)/bacstr.c \
- $(BACNET_ROOT)/bactext.c \
- $(BACNET_ROOT)/indtext.c \
- $(BACNET_ROOT)/datetime.c \
- $(BACNET_ROOT)/whois.c \
- $(BACNET_ROOT)/iam.c \
- $(BACNET_ROOT)/address.c \
- $(BACNET_ROOT)/arf.c \
- $(BACNET_ROOT)/cov.c \
- $(BACNET_ROOT)/dcc.c \
- $(BACNET_ROOT)/abort.c \
- $(BACNET_ROOT)/reject.c \
- $(BACNET_ROOT)/bacerror.c \
- $(BACNET_ROOT)/apdu.c \
- $(BACNET_ROOT)/npdu.c
-
-OBJS = ${SRCS:.c=.o}
-
-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 ports/linux/*.bak *.1 *.ini
-
-include: .depend
-
+#Makefile to build BACnet Application for the Linux Port
+CC = gcc
+BASEDIR = .
+#CFLAGS = -Wall -I.
+# -g for debugging with gdb
+#CFLAGS = -Wall -I. -O2 -g
+# Note: you can strip out symbols using the strip command
+# to get an idea of how big the compile really is.
+
+# Configure the BACnet Datalink Layer
+#BACDL_DEFINE=-DBACDL_ETHERNET=1
+#BACDL_DEFINE=-DBACDL_ARCNET=1
+BACDL_DEFINE=-DBACDL_BIP=1
+BACNET_DEFINES=-DBACFILE=1 -DTSM_ENABLED=0 -DBIG_ENDIAN=0 -DPRINT_ENABLED=1
+DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
+
+BACNET_PORT = ../../ports/linux
+BACNET_OBJECT = ../object
+BACNET_HANDLER = ../handler
+BACNET_ROOT = ../..
+INCLUDES = -I$(BACNET_ROOT) -I$(BACNET_PORT) -I$(BACNET_OBJECT) -I$(BACNET_HANDLER)
+
+CFLAGS = -Wall -g $(INCLUDES) $(DEFINES)
+
+TARGET = bacucov
+
+SRCS = main.c \
+ $(BACNET_PORT)/bip-init.c \
+ $(BACNET_PORT)/ethernet.c \
+ $(BACNET_PORT)/arcnet.c \
+ $(BACNET_ROOT)/bip.c \
+ $(BACNET_HANDLER)/txbuf.c \
+ $(BACNET_HANDLER)/noserv.c \
+ $(BACNET_HANDLER)/h_whois.c \
+ $(BACNET_HANDLER)/h_rp.c \
+ $(BACNET_HANDLER)/h_iam.c \
+ $(BACNET_OBJECT)/device.c \
+ $(BACNET_OBJECT)/ai.c \
+ $(BACNET_OBJECT)/ao.c \
+ $(BACNET_OBJECT)/av.c \
+ $(BACNET_OBJECT)/bi.c \
+ $(BACNET_OBJECT)/bo.c \
+ $(BACNET_OBJECT)/bv.c \
+ $(BACNET_OBJECT)/lc.c \
+ $(BACNET_OBJECT)/lsp.c \
+ $(BACNET_OBJECT)/mso.c \
+ $(BACNET_OBJECT)/bacfile.c \
+ $(BACNET_ROOT)/filename.c \
+ $(BACNET_ROOT)/rp.c \
+ $(BACNET_ROOT)/wp.c \
+ $(BACNET_ROOT)/bacdcode.c \
+ $(BACNET_ROOT)/bacapp.c \
+ $(BACNET_ROOT)/bacprop.c \
+ $(BACNET_ROOT)/bacstr.c \
+ $(BACNET_ROOT)/bactext.c \
+ $(BACNET_ROOT)/indtext.c \
+ $(BACNET_ROOT)/datetime.c \
+ $(BACNET_ROOT)/whois.c \
+ $(BACNET_ROOT)/iam.c \
+ $(BACNET_ROOT)/address.c \
+ $(BACNET_ROOT)/arf.c \
+ $(BACNET_ROOT)/cov.c \
+ $(BACNET_ROOT)/dcc.c \
+ $(BACNET_ROOT)/abort.c \
+ $(BACNET_ROOT)/reject.c \
+ $(BACNET_ROOT)/bacerror.c \
+ $(BACNET_ROOT)/apdu.c \
+ $(BACNET_ROOT)/npdu.c
+
+OBJS = ${SRCS:.c=.o}
+
+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 ports/linux/*.bak *.1 *.ini
+
+include: .depend
+
diff --git a/bacnet-stack/demo/ucov/main.c b/bacnet-stack/demo/ucov/main.c
index fabd8d42..1d4b399e 100644
--- a/bacnet-stack/demo/ucov/main.c
+++ b/bacnet-stack/demo/ucov/main.c
@@ -204,9 +204,9 @@ int main(int argc, char *argv[])
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
- Init_Service_Handlers();
- if (!datalink_init(NULL))
- return 1;
+ Init_Service_Handlers();
+ if (!datalink_init(NULL))
+ return 1;
/* only one value in our value list */
cov_data.listOfValues.next = NULL;
ucov_notify_send(&Handler_Transmit_Buffer[0], &cov_data);
diff --git a/bacnet-stack/demo/ucov/makefile.b32 b/bacnet-stack/demo/ucov/makefile.b32
index 3ca3a77d..da5c3b94 100644
--- a/bacnet-stack/demo/ucov/makefile.b32
+++ b/bacnet-stack/demo/ucov/makefile.b32
@@ -1,153 +1,153 @@
-#
-# Simple makefile to build an executable for Win32
-#
-# This makefile assumes Borland bcc32 development environment
-# on Windows NT/9x/2000/XP
-#
-
-!ifndef BORLAND_DIR
-BORLAND_DIR_Not_Defined:
- @echo .
- @echo You must define environment variable BORLAND_DIR to compile.
-!endif
-
-PRODUCT = bacucov
-PRODUCT_EXE = $(PRODUCT).exe
-
-# Choose the Data Link Layer to Enable
-DEFINES = -DBACDL_BIP=1;TSM_ENABLED=0;BIG_ENDIAN=0;PRINT_ENABLED=1
-
-SRCS = main.c \
- ..\..\ports\win32\bip-init.c \
- ..\..\filename.c \
- ..\..\bip.c \
- ..\..\demo\handler\txbuf.c \
- ..\..\demo\handler\noserv.c \
- ..\..\demo\handler\h_whois.c \
- ..\..\demo\handler\h_iam.c \
- ..\..\demo\handler\h_rp.c \
- ..\..\bacdcode.c \
- ..\..\bacapp.c \
- ..\..\bacstr.c \
- ..\..\bactext.c \
- ..\..\indtext.c \
- ..\..\datetime.c \
- ..\..\whois.c \
- ..\..\iam.c \
- ..\..\rp.c \
- ..\..\wp.c \
- ..\..\arf.c \
- ..\..\awf.c \
- ..\..\cov.c \
- ..\..\dcc.c \
- ..\..\demo\object\bacfile.c \
- ..\..\demo\object\device.c \
- ..\..\demo\object\ai.c \
- ..\..\demo\object\ao.c \
- ..\..\demo\object\av.c \
- ..\..\demo\object\bi.c \
- ..\..\demo\object\bo.c \
- ..\..\demo\object\bv.c \
- ..\..\demo\object\lc.c \
- ..\..\demo\object\lsp.c \
- ..\..\demo\object\mso.c \
- ..\..\address.c \
- ..\..\abort.c \
- ..\..\reject.c \
- ..\..\bacerror.c \
- ..\..\apdu.c \
- ..\..\npdu.c
-
-OBJS = $(SRCS:.c=.obj)
-
-# Compiler definitions
-#
-CC = $(BORLAND_DIR)\bin\bcc32 +bcc32.cfg
-#LINK = $(BORLAND_DIR)\bin\tlink32
-LINK = $(BORLAND_DIR)\bin\ilink32
-TLIB = $(BORLAND_DIR)\bin\tlib
-
-#
-# Include directories
-#
-CC_DIR = $(BORLAND_DIR)\BIN
-INCL_DIRS = -I$(BORLAND_DIR)\include;..\..\;..\..\demo\object\;..\..\demo\handler\;..\..\ports\win32\;.
-
-CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
-
-# Libraries
-#
-C_LIB_DIR = $(BORLAND_DIR)\lib
-
-LIBS = $(C_LIB_DIR)\IMPORT32.lib \
-$(C_LIB_DIR)\CW32MT.lib
-
-#
-# Main target
-#
-# This should be the first one in the makefile
-
-all : bcc32.cfg $(PRODUCT_EXE)
-
-install: $(PRODUCT_EXE)
- copy $(PRODUCT_EXE) ..\..\utils\$(PRODUCT_EXE)
-
-# Linker specific: the link below is for BCC linker/compiler. If you link
-# with a different linker - please change accordingly.
-#
-
-# need a temp response file (@&&) because command line is too long
-$(PRODUCT_EXE) : $(OBJS)
- @echo Running Linker for $(PRODUCT_EXE)
- $(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with |
- $(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
- $<
- $*.map
- $(LIBS)
-| # end of temp response file
-
-#
-# Utilities
-
-clean :
- @echo Deleting obj files, $(PRODUCT_EXE) and map files.
-# del $(OBJS) # command too long, bummer!
- del *.obj
- del ..\..\*.obj
- del ..\..\demo\handler\*.obj
- del ..\..\demo\object\*.obj
- del ..\..\ports\win32\*.obj
- del $(PRODUCT_EXE)
- del *.map
- del bcc32.cfg
-
-#
-# Generic rules
-#
-.SUFFIXES: .cpp .c .sbr .obj
-
-#
-# cc generic rule
-#
-.c.obj:
- $(CC) -o$@ $<
-
-# Compiler configuration file
-bcc32.cfg :
- Copy &&|
-$(CFLAGS)
--c
--y #include line numbers in OBJ's
--v #include debug info
--w+ #turn on all warnings
--Od #disable all optimizations
-#-a4 #32 bit data alignment
-#-M # generate link map
-#-ls # linker options
-#-WM- #not multithread
--WM #multithread
--w-aus # ignore warning assigned a value that is never used
--w-sig # ignore warning conversion may lose sig digits
-| $@
-
-# EOF: makefile
+#
+# Simple makefile to build an executable for Win32
+#
+# This makefile assumes Borland bcc32 development environment
+# on Windows NT/9x/2000/XP
+#
+
+!ifndef BORLAND_DIR
+BORLAND_DIR_Not_Defined:
+ @echo .
+ @echo You must define environment variable BORLAND_DIR to compile.
+!endif
+
+PRODUCT = bacucov
+PRODUCT_EXE = $(PRODUCT).exe
+
+# Choose the Data Link Layer to Enable
+DEFINES = -DBACDL_BIP=1;TSM_ENABLED=0;BIG_ENDIAN=0;PRINT_ENABLED=1
+
+SRCS = main.c \
+ ..\..\ports\win32\bip-init.c \
+ ..\..\filename.c \
+ ..\..\bip.c \
+ ..\..\demo\handler\txbuf.c \
+ ..\..\demo\handler\noserv.c \
+ ..\..\demo\handler\h_whois.c \
+ ..\..\demo\handler\h_iam.c \
+ ..\..\demo\handler\h_rp.c \
+ ..\..\bacdcode.c \
+ ..\..\bacapp.c \
+ ..\..\bacstr.c \
+ ..\..\bactext.c \
+ ..\..\indtext.c \
+ ..\..\datetime.c \
+ ..\..\whois.c \
+ ..\..\iam.c \
+ ..\..\rp.c \
+ ..\..\wp.c \
+ ..\..\arf.c \
+ ..\..\awf.c \
+ ..\..\cov.c \
+ ..\..\dcc.c \
+ ..\..\demo\object\bacfile.c \
+ ..\..\demo\object\device.c \
+ ..\..\demo\object\ai.c \
+ ..\..\demo\object\ao.c \
+ ..\..\demo\object\av.c \
+ ..\..\demo\object\bi.c \
+ ..\..\demo\object\bo.c \
+ ..\..\demo\object\bv.c \
+ ..\..\demo\object\lc.c \
+ ..\..\demo\object\lsp.c \
+ ..\..\demo\object\mso.c \
+ ..\..\address.c \
+ ..\..\abort.c \
+ ..\..\reject.c \
+ ..\..\bacerror.c \
+ ..\..\apdu.c \
+ ..\..\npdu.c
+
+OBJS = $(SRCS:.c=.obj)
+
+# Compiler definitions
+#
+CC = $(BORLAND_DIR)\bin\bcc32 +bcc32.cfg
+#LINK = $(BORLAND_DIR)\bin\tlink32
+LINK = $(BORLAND_DIR)\bin\ilink32
+TLIB = $(BORLAND_DIR)\bin\tlib
+
+#
+# Include directories
+#
+CC_DIR = $(BORLAND_DIR)\BIN
+INCL_DIRS = -I$(BORLAND_DIR)\include;..\..\;..\..\demo\object\;..\..\demo\handler\;..\..\ports\win32\;.
+
+CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
+
+# Libraries
+#
+C_LIB_DIR = $(BORLAND_DIR)\lib
+
+LIBS = $(C_LIB_DIR)\IMPORT32.lib \
+$(C_LIB_DIR)\CW32MT.lib
+
+#
+# Main target
+#
+# This should be the first one in the makefile
+
+all : bcc32.cfg $(PRODUCT_EXE)
+
+install: $(PRODUCT_EXE)
+ copy $(PRODUCT_EXE) ..\..\utils\$(PRODUCT_EXE)
+
+# Linker specific: the link below is for BCC linker/compiler. If you link
+# with a different linker - please change accordingly.
+#
+
+# need a temp response file (@&&) because command line is too long
+$(PRODUCT_EXE) : $(OBJS)
+ @echo Running Linker for $(PRODUCT_EXE)
+ $(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with |
+ $(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
+ $<
+ $*.map
+ $(LIBS)
+| # end of temp response file
+
+#
+# Utilities
+
+clean :
+ @echo Deleting obj files, $(PRODUCT_EXE) and map files.
+# del $(OBJS) # command too long, bummer!
+ del *.obj
+ del ..\..\*.obj
+ del ..\..\demo\handler\*.obj
+ del ..\..\demo\object\*.obj
+ del ..\..\ports\win32\*.obj
+ del $(PRODUCT_EXE)
+ del *.map
+ del bcc32.cfg
+
+#
+# Generic rules
+#
+.SUFFIXES: .cpp .c .sbr .obj
+
+#
+# cc generic rule
+#
+.c.obj:
+ $(CC) -o$@ $<
+
+# Compiler configuration file
+bcc32.cfg :
+ Copy &&|
+$(CFLAGS)
+-c
+-y #include line numbers in OBJ's
+-v #include debug info
+-w+ #turn on all warnings
+-Od #disable all optimizations
+#-a4 #32 bit data alignment
+#-M # generate link map
+#-ls # linker options
+#-WM- #not multithread
+-WM #multithread
+-w-aus # ignore warning assigned a value that is never used
+-w-sig # ignore warning conversion may lose sig digits
+| $@
+
+# EOF: makefile
diff --git a/bacnet-stack/demo/writeprop/main.c b/bacnet-stack/demo/writeprop/main.c
index 9ad374d7..195ea8db 100644
--- a/bacnet-stack/demo/writeprop/main.c
+++ b/bacnet-stack/demo/writeprop/main.c
@@ -310,8 +310,8 @@ int main(int argc, char *argv[])
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
- if (!datalink_init(NULL))
- return 1;
+ if (!datalink_init(NULL))
+ return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
diff --git a/bacnet-stack/doc/README.codeblocks b/bacnet-stack/doc/README.codeblocks
index 53afc2c5..44d86d2c 100644
--- a/bacnet-stack/doc/README.codeblocks
+++ b/bacnet-stack/doc/README.codeblocks
@@ -1,10 +1,10 @@
-BACnet Stack @ SourceForge.net
-Build using Code Blocks
-
-Q1: GNU GCC Compiler, undefined reference to closesocket
-
-A1: Under Project->Build Options->Linker settings,
-add "ws2_32" to Link Libraries.
-
-
-
+BACnet Stack @ SourceForge.net
+Build using Code Blocks
+
+Q1: GNU GCC Compiler, undefined reference to closesocket
+
+A1: Under Project->Build Options->Linker settings,
+add "ws2_32" to Link Libraries.
+
+
+
diff --git a/bacnet-stack/doc/README.msvs b/bacnet-stack/doc/README.msvs
index 4f0f5e8f..4a34905e 100644
--- a/bacnet-stack/doc/README.msvs
+++ b/bacnet-stack/doc/README.msvs
@@ -1,7 +1,7 @@
-BACnet Stack - SourceForge.net
-Build for Visual Studio 2005 Express Edition
-
-Q1: Cannot open include file: 'winsock2.h'
-
-A1: Install the Microsoft Platform SDK:
-http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/default.aspx
+BACnet Stack - SourceForge.net
+Build for Visual Studio 2005 Express Edition
+
+Q1: Cannot open include file: 'winsock2.h'
+
+A1: Install the Microsoft Platform SDK:
+http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/default.aspx
diff --git a/bacnet-stack/doc/README.todo b/bacnet-stack/doc/README.todo
index 8f3043ce..a05812b7 100644
--- a/bacnet-stack/doc/README.todo
+++ b/bacnet-stack/doc/README.todo
@@ -1,27 +1,27 @@
-To Do List - BACnet Stack at SourceForge
-
-For this release, here are some things to do:
-
-1. Change bip_init to datalink_init in demos (done, STK)
-2. Change demos main file to main.c (done, STK)
-3. Add parameter passing for IP address or interface for
- multi homed systems. (done, STK)
-4. Validate the unit tests compile after BIG_ENDIAN change. (done,STK)
-5. Add arcnet.c and ethernet.c to all the linux Makefiles (done, STK)
-6. Refactor Makefile DEFINES like demo/server/Makefile. (done, STK)
-
-For a later release, here are some things to do:
-
-1. Finish demo/epics/main.c - EPICS demo
-2. Finish demo/object/lo.c - Lighting Output object demo
-3. Complete bvlc.c and use it instead of or in compliment to bip.c
-4. Complete demo for ReadPropertyMultiple from rpm.c
-5. Add HTTP demo like bacnet4linux
-6. Add subscribe to change of value support in server demo
-7. Add hooks to increment Database_Revision property
-8. Add BBMD and FD support to server example for BACnet/IP.
-9. Add Foreign Device registration options to client examples.
-A. Change bip.c to not use extra buffer (shift data)
-B. Finish subscribe COV support in server demo.
-C. Add Visual Studio 2005 makefiles or projects for demos.
-D. Add Code::Blocks projects for demos.
+To Do List - BACnet Stack at SourceForge
+
+For this release, here are some things to do:
+
+1. Change bip_init to datalink_init in demos (done, STK)
+2. Change demos main file to main.c (done, STK)
+3. Add parameter passing for IP address or interface for
+ multi homed systems. (done, STK)
+4. Validate the unit tests compile after BIG_ENDIAN change. (done,STK)
+5. Add arcnet.c and ethernet.c to all the linux Makefiles (done, STK)
+6. Refactor Makefile DEFINES like demo/server/Makefile. (done, STK)
+
+For a later release, here are some things to do:
+
+1. Finish demo/epics/main.c - EPICS demo
+2. Finish demo/object/lo.c - Lighting Output object demo
+3. Complete bvlc.c and use it instead of or in compliment to bip.c
+4. Complete demo for ReadPropertyMultiple from rpm.c
+5. Add HTTP demo like bacnet4linux
+6. Add subscribe to change of value support in server demo
+7. Add hooks to increment Database_Revision property
+8. Add BBMD and FD support to server example for BACnet/IP.
+9. Add Foreign Device registration options to client examples.
+A. Change bip.c to not use extra buffer (shift data)
+B. Finish subscribe COV support in server demo.
+C. Add Visual Studio 2005 makefiles or projects for demos.
+D. Add Code::Blocks projects for demos.
diff --git a/bacnet-stack/doc/htdocs/index.html b/bacnet-stack/doc/htdocs/index.html
index a40309e3..48ae0b9c 100644
--- a/bacnet-stack/doc/htdocs/index.html
+++ b/bacnet-stack/doc/htdocs/index.html
@@ -1,436 +1,436 @@
-
-
-
-
- BACnet stack - open source BACnet protocol stack
-
-
- BACnet Stack
- An open source BACnet protocol stack for embedded systems
-
- About this Project
- This BACnet protocol stack library
- provides a BACnet application layer, network layer and media access (MAC)
+
+
+
+
+ BACnet stack - open source BACnet protocol stack
+
+
+ BACnet Stack
+ An open source BACnet protocol stack for embedded systems
+
+ About this Project
+ This BACnet protocol stack library
+ provides a BACnet application layer, network layer and media access (MAC)
layer communications services. It is an open source, royalty-free library
for an embedded system, Windows, Linux, or other operating system. Example
- BACnet client and server applications are included.
-
- BACnet - A Data Communication Protocol for Building
- Automation and Control Networks - see bacnet.org. BACnet is a standard data
- communication protocol for Building Automation and Control Networks. BACnet
- is an open protocol, which means anyone can contribute to the standard, and
- anyone may use it. The only caveat is that the BACnet standard document
- itself is copyrighted by ASHRAE, and they sell the document to help defray
- costs of developing and maintaining the standard (just like IEEE or ANSI or
- ISO).
-
- For software developers, the BACnet protocol is a standard way to send and
- receive messages on the wire containing data that is understood by other
- BACnet compliant devices. The BACnet standard defines a standard way to
- communicate over a number of wires, known as Data Link/Physical Layers:
- Ethernet, EIA-485, EIA-232, ARCNET, and LonTalk. The BACnet standard also
- defines a standard way to communicate using UDP, IP and HTTP (Web
- Services).
-
- There are other open source projects for BACnet:
-
- - VTS - visual test shell for
- Win32, used for Visually testing a BACnet implementation. It also includes
- a detailed network sniffer for BACnet messages, and the ability to send
- any BACnet services. The source code is in the public domain.
- - Wireshark - an open source,
- cross platform protocol analyzer with BACnet support. The detailed BACnet
- support began in version 0.10.11 released on May 4, 2005 when Wireshark
- was known as Ethereal.
- - BACnet4Linux - an
- LGPL BACnet application that requires Linux as the OS.
- - BACnet Firewall Router -an
- application that combines BACnet routing capability with traffic management
- functions to carefully control access to building automation and control
- networks.
- - BACpypes - a
- BACnet stack written in Python.
-
-
- There are also commercial BACnet protocol source code libraries for BACnet
- that are designed for embedded use:
-
- - CimetricsTM - has a source library
- called BACstac/32 as part of their BACNet Protocol Stack SDK.
- - Polarsoft - has a
- protocol stack source library for embedded use called FreeRangeTM and PolarSoft® FreeRange VSB (Very
- Small BACnet stack).
- - SCADA Engine - The BACnet
- Linux Server is a complete BACnet Device running on the linux platform.
- The entire source code is available for custom applications and has been
- written in ANSI C which has been succesfully ported to Unix,
- VxWorks etc.
-
-
- Licensing
- Our BACnet protocol stack implementation is specifically designed for the
- embedded BACnet appliance, using a GPL with exception license (like eCos),
- which means that any changes to the core code that are distributed are
- made available, but the BACnet library can be linked to
- proprietary code without it becoming licensed under the GPL.
+ BACnet client and server applications are included.
+
+ BACnet - A Data Communication Protocol for Building
+ Automation and Control Networks - see bacnet.org. BACnet is a standard data
+ communication protocol for Building Automation and Control Networks. BACnet
+ is an open protocol, which means anyone can contribute to the standard, and
+ anyone may use it. The only caveat is that the BACnet standard document
+ itself is copyrighted by ASHRAE, and they sell the document to help defray
+ costs of developing and maintaining the standard (just like IEEE or ANSI or
+ ISO).
+
+ For software developers, the BACnet protocol is a standard way to send and
+ receive messages on the wire containing data that is understood by other
+ BACnet compliant devices. The BACnet standard defines a standard way to
+ communicate over a number of wires, known as Data Link/Physical Layers:
+ Ethernet, EIA-485, EIA-232, ARCNET, and LonTalk. The BACnet standard also
+ defines a standard way to communicate using UDP, IP and HTTP (Web
+ Services).
+
+ There are other open source projects for BACnet:
+
+ - VTS - visual test shell for
+ Win32, used for Visually testing a BACnet implementation. It also includes
+ a detailed network sniffer for BACnet messages, and the ability to send
+ any BACnet services. The source code is in the public domain.
+ - Wireshark - an open source,
+ cross platform protocol analyzer with BACnet support. The detailed BACnet
+ support began in version 0.10.11 released on May 4, 2005 when Wireshark
+ was known as Ethereal.
+ - BACnet4Linux - an
+ LGPL BACnet application that requires Linux as the OS.
+ - BACnet Firewall Router -an
+ application that combines BACnet routing capability with traffic management
+ functions to carefully control access to building automation and control
+ networks.
+ - BACpypes - a
+ BACnet stack written in Python.
+
+
+ There are also commercial BACnet protocol source code libraries for BACnet
+ that are designed for embedded use:
+
+ - CimetricsTM - has a source library
+ called BACstac/32 as part of their BACNet Protocol Stack SDK.
+ - Polarsoft - has a
+ protocol stack source library for embedded use called FreeRangeTM and PolarSoft® FreeRange VSB (Very
+ Small BACnet stack).
+ - SCADA Engine - The BACnet
+ Linux Server is a complete BACnet Device running on the linux platform.
+ The entire source code is available for custom applications and has been
+ written in ANSI C which has been succesfully ported to Unix,
+ VxWorks etc.
+
+
+ Licensing
+ Our BACnet protocol stack implementation is specifically designed for the
+ embedded BACnet appliance, using a GPL with exception license (like eCos),
+ which means that any changes to the core code that are distributed are
+ made available, but the BACnet library can be linked to
+ proprietary code without it becoming licensed under the GPL.
See the eCos license overview for
- easy to read details about this exception to the GPL.
- The license does not require users to release the source code of any
+ easy to read details about this exception to the GPL.
+ The license does not require users to release the source code of any
applications that are developed with this BACnet stack - only portions of
the BACnet stack that have been modified. Note that those files in this
BACnet stack that are expected to be modified are licensed using the
- MIT License.
-
-
The text of the GPL exception included in each source file is as
- follows:
-
-
- "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."
-
-
- The source code
- The source code is written in C for portability, and includes
- unit tests (PC based unit tests) and example application code.
- Since the code is designed to be
- portable, it compiles with GCC as well as other compilers,
- such as Borland C++, Visual C++, MinGW, Code Warrior, or MicroChip C18.
- The source code is also designed to be readable, understandable,
- and most importantly, easy to use.
-
- The BACnet protocol is an ASHRAE/ANSI/ISO standard, so this library
- adheres to that standard. BACnet has no royalties or licensing restrictions,
- and registration for a BACnet
- vendor ID is free.
-
- What the code does
-
- The BACnet stack comes with example applications
- that can be run under Linux, Win32, RTOS-32, and just about any embedded
- microcontroller.
-
- The BACnet stack includes unit tests can be run in a command shell on Linux using the
- unittest.sh script, or using individual .mak files. They were tested under
- Debian GNU/Linux and Ubuntu Linux.
-
- The BACnet stack was functionally tested
- using VTS (Visual Test Shell),
- another project hosted on SourceForge, as well as various BACnet controllers,
- BACnet workstations, and through BACnet routers.
-
-
Using a master Makefile in the project root directory, a dozen or so
- demo applications can be created that run under Linux or Win32.
- Linux supports BACnet Ethernet, BACnet/IP, or ARCNET data link layer
- for communication, and BACnet/IP is supported under Win32. BACnet Ethernet
- can also be used under Win32 with the WinPcap library.
- Root priveleges are required to run the Ethernet or ARCNET interfaces
- on Linux, but not needed to run BACnet/IP.
-
-
- $ make clean all
- $ demo/server/bacsrv 123
- BACnet Server Demo - Device #123
-
- $ demo/readprop/bacrp
- bacrp device-instance object-type object-instance property [index]
-
- $ demo/writeprop/bacwp
- bacwp device-instance object-type object-instance property tag value [priority] [index]
-
- $ demo/readfile/bacarf
- bacarf device-instance file-instance local-name
-
- $ demo/writefile/bacawf
- bacawf device-instance file-instance local-name
-
- $ demo/reinit/bacrd
- Usage: bacrd device-instance state [password]
- Send BACnet ReinitializeDevice service to device.
-
- $ demo/whohas/bacwh
- Usage: bacwh object-type object-instance | object-name
- Send BACnet WhoHas request to devices, and wait for responses.
-
- $ demo/dcc/bacdcc
- Usage: bacdcc device-instance state timeout [password]
- Send BACnet DeviceCommunicationControl service to device.
-
- $ demo/timesync/bacts
- Received TimeSyncronization Request
- 2006/8/30 07:10:45.00
-
- $ demo/ucov/bacucov
- Usage: bacucov pid device-id object-type object-instance time property tag value [priority] [index]
-
- $ demo/whois/bacwi
- Usage: bacwi device-instance | device-instance-min device-instance-max
- Send BACnet WhoIs request to devices, and wait for responses.
-
- The device-instance can be 0 to 4194303, or -1 for ALL.
- The device-instance can also be specified as a range.
-
-
-
- The demos can be compiled under Win32 using Borland C++ or
- Microsoft Visual C++, both of which
- are free (as in beer) command line compilers. Be sure to pick up the free
- patches (service packs) for the Borland C++ compiler (SP1, SP2), as well as the free turbo debugger. It might also be possible to create Win32 projects using the free Visual Studio Express Edition or MinGW - Minimalist GNU for Windows, but I have haven't tried it. I have used Code::Blocks for compiling the unit tests using the MinGW compiler, but have not tried to get the demos working with MinGW. I have used Code::Blocks with the Borland C++ compiler and it successfully compiles the code.
-
- There is a Makefile in the ports/rtos32 directory, and a sample
- application that runs under RTOS-32.
- It currently uses the BACnet/IP data link layer for communication, and also
- has an MS/TP datalink layer sample application.
- It compiles using Borland C++.
-
- There is a project in the ports/pic18f6720 directory, and a sample
- application that can be build using MP-Lab
+ MIT License.
+
+
The text of the GPL exception included in each source file is as
+ follows:
+
+
+ "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."
+
+
+ The source code
+ The source code is written in C for portability, and includes
+ unit tests (PC based unit tests) and example application code.
+ Since the code is designed to be
+ portable, it compiles with GCC as well as other compilers,
+ such as Borland C++, Visual C++, MinGW, Code Warrior, or MicroChip C18.
+ The source code is also designed to be readable, understandable,
+ and most importantly, easy to use.
+
+ The BACnet protocol is an ASHRAE/ANSI/ISO standard, so this library
+ adheres to that standard. BACnet has no royalties or licensing restrictions,
+ and registration for a BACnet
+ vendor ID is free.
+
+ What the code does
+
+ The BACnet stack comes with example applications
+ that can be run under Linux, Win32, RTOS-32, and just about any embedded
+ microcontroller.
+
+ The BACnet stack includes unit tests can be run in a command shell on Linux using the
+ unittest.sh script, or using individual .mak files. They were tested under
+ Debian GNU/Linux and Ubuntu Linux.
+
+ The BACnet stack was functionally tested
+ using VTS (Visual Test Shell),
+ another project hosted on SourceForge, as well as various BACnet controllers,
+ BACnet workstations, and through BACnet routers.
+
+
Using a master Makefile in the project root directory, a dozen or so
+ demo applications can be created that run under Linux or Win32.
+ Linux supports BACnet Ethernet, BACnet/IP, or ARCNET data link layer
+ for communication, and BACnet/IP is supported under Win32. BACnet Ethernet
+ can also be used under Win32 with the WinPcap library.
+ Root priveleges are required to run the Ethernet or ARCNET interfaces
+ on Linux, but not needed to run BACnet/IP.
+
+
+ $ make clean all
+ $ demo/server/bacsrv 123
+ BACnet Server Demo - Device #123
+
+ $ demo/readprop/bacrp
+ bacrp device-instance object-type object-instance property [index]
+
+ $ demo/writeprop/bacwp
+ bacwp device-instance object-type object-instance property tag value [priority] [index]
+
+ $ demo/readfile/bacarf
+ bacarf device-instance file-instance local-name
+
+ $ demo/writefile/bacawf
+ bacawf device-instance file-instance local-name
+
+ $ demo/reinit/bacrd
+ Usage: bacrd device-instance state [password]
+ Send BACnet ReinitializeDevice service to device.
+
+ $ demo/whohas/bacwh
+ Usage: bacwh object-type object-instance | object-name
+ Send BACnet WhoHas request to devices, and wait for responses.
+
+ $ demo/dcc/bacdcc
+ Usage: bacdcc device-instance state timeout [password]
+ Send BACnet DeviceCommunicationControl service to device.
+
+ $ demo/timesync/bacts
+ Received TimeSyncronization Request
+ 2006/8/30 07:10:45.00
+
+ $ demo/ucov/bacucov
+ Usage: bacucov pid device-id object-type object-instance time property tag value [priority] [index]
+
+ $ demo/whois/bacwi
+ Usage: bacwi device-instance | device-instance-min device-instance-max
+ Send BACnet WhoIs request to devices, and wait for responses.
+
+ The device-instance can be 0 to 4194303, or -1 for ALL.
+ The device-instance can also be specified as a range.
+
+
+
+ The demos can be compiled under Win32 using Borland C++ or
+ Microsoft Visual C++, both of which
+ are free (as in beer) command line compilers. Be sure to pick up the free
+ patches (service packs) for the Borland C++ compiler (SP1, SP2), as well as the free turbo debugger. It might also be possible to create Win32 projects using the free Visual Studio Express Edition or MinGW - Minimalist GNU for Windows, but I have haven't tried it. I have used Code::Blocks for compiling the unit tests using the MinGW compiler, but have not tried to get the demos working with MinGW. I have used Code::Blocks with the Borland C++ compiler and it successfully compiles the code.
+
+ There is a Makefile in the ports/rtos32 directory, and a sample
+ application that runs under RTOS-32.
+ It currently uses the BACnet/IP data link layer for communication, and also
+ has an MS/TP datalink layer sample application.
+ It compiles using Borland C++.
+
+ There is a project in the ports/pic18f6720 directory, and a sample
+ application that can be build using MP-Lab
and the Microchip compiler MCC18. The datalink layer uses BACnet MS/TP
- and the example uses several different objects and services.
-
-
-
- BACnet services supported matrix
- The BACnet stack currently implements the following services listed in the
- the table. We plan to add the rest of the services as we go.
- With the services that are implemented, you could build a BACnet device
- that meets the standardized profile for a BACnet Smart Sensor,
- BACnet Smart Actuator, or a BACnet Application Specific Controller.
-
- | BACnet Service |
- Initiate |
- Execute |
-
-
- | Who Is |
- Yes |
- Yes |
-
-
- | I Am |
- Yes |
- Yes |
-
-
- | Who Has |
- Yes |
- Yes |
-
-
- | I Have |
- Yes |
- Yes |
-
-
- | Read Property |
- Yes |
- Yes |
-
-
- | Write Property |
- Yes |
- Yes |
-
-
- | Device Communication Control |
- Yes |
- Yes |
-
-
- | ReinitializeDevice |
- Yes |
- Yes |
-
-
- | Atomic Read File |
- Yes |
- Yes |
-
-
- | Atomic Write File |
- Yes |
- Yes |
-
-
- | Time Synchronization |
- Yes |
- Yes |
-
-
- | UTC Time Synchronization |
- Yes |
- Yes |
-
-
- | Subscribe COV |
- - |
- - |
-
-
- | Confirmed COV Notification |
- Yes |
- Yes |
-
-
- | Unconfirmed COV Notification |
- Yes |
- Yes |
-
-
- | Read Property Multiple |
- - |
- - |
-
-
- | Read Property Conditional |
- - |
- - |
-
-
- | Read Range |
- - |
- - |
-
-
- | Write Property Multiple |
- - |
- - |
-
-
- | Get Alarm Summary |
- - |
- - |
-
-
- | Get Event Information |
- - |
- - |
-
-
- | Get Enrollment Summary |
- - |
- - |
-
-
- | Acknowledge Alarm |
- - |
- - |
-
-
- | Confirmed Event Notification |
- - |
- - |
-
-
- | Unconfirmed Event Notification |
- - |
- - |
-
-
- | Unconfirmed Text Message |
- - |
- - |
-
-
- | Confirmed Text Message |
- - |
- - |
-
-
- | Add List Element |
- - |
- - |
-
-
- | Remove List Element |
- - |
- - |
-
-
- | Create Object |
- - |
- - |
-
-
- | Delete Object |
- - |
- - |
-
-
- | Unconfirmed Private Transfer |
- - |
- - |
-
-
- | Confirmed Private Transfer |
- - |
- - |
-
-
- | VT Open |
- - |
- - |
-
-
- | VT Data |
- - |
- - |
-
-
- | VT Close |
- - |
- - |
-
-
-
-
- BACnet Objects
-
- The BACnet stack currently implements a Device Object, and
- handles all of the ReadProperty inquiries for the required
- Device Object properties. The stack handles Who-Is inquiries
- with an I-Am, WhoHas with I-Have, and handles reject messages for
- services not currently supported. There is built in handling for
- DeviceCommunicationControl.
-
- The example handlers interact with example objects, including
- Analog Input, Analog Output, Analog Value, Binary Input,
- Binary Output, Binary Value, Load Control, Life Safety Point,
- and Multi-state Output objects.
- The objects can be accessed using WriteProperty,
- ReadProperty, or Who-Has services. Adding other BACnet objects
- is only a matter of setting up ReadProperty, WriteProperty, or
- I-Have handling for the required properties and any other
- properties that you want to support.
-
- File Objects are conditionally included in the demonstation
- applications. The files can be access using WriteProperty,
- ReadProperty, Who-Has, AtomicWriteFile, or AtomicReadFile services.
-
- Getting Involved
-
- If you want to help out on this project, join the developers mailing list, introduce yourself, and tell us what you would like to do.
- If you are trying to implement a BACnet device or service using this project,
- you are welcome to join the developers mailing list as well.
-
- More details about the project can be found on
- the BACnet Source Forge Project Page
-
- There is documentation that describes the mechanisms in the BACnet Stack.
- I wrote up some answers to some frequently asked questions. Of course,
- there are a handful of text files in the doc directory of the project.
-
- BACnet
+ and the example uses several different objects and services.
+
+
+
+ BACnet services supported matrix
+ The BACnet stack currently implements the following services listed in the
+ the table. We plan to add the rest of the services as we go.
+ With the services that are implemented, you could build a BACnet device
+ that meets the standardized profile for a BACnet Smart Sensor,
+ BACnet Smart Actuator, or a BACnet Application Specific Controller.
+
+ | BACnet Service |
+ Initiate |
+ Execute |
+
+
+ | Who Is |
+ Yes |
+ Yes |
+
+
+ | I Am |
+ Yes |
+ Yes |
+
+
+ | Who Has |
+ Yes |
+ Yes |
+
+
+ | I Have |
+ Yes |
+ Yes |
+
+
+ | Read Property |
+ Yes |
+ Yes |
+
+
+ | Write Property |
+ Yes |
+ Yes |
+
+
+ | Device Communication Control |
+ Yes |
+ Yes |
+
+
+ | ReinitializeDevice |
+ Yes |
+ Yes |
+
+
+ | Atomic Read File |
+ Yes |
+ Yes |
+
+
+ | Atomic Write File |
+ Yes |
+ Yes |
+
+
+ | Time Synchronization |
+ Yes |
+ Yes |
+
+
+ | UTC Time Synchronization |
+ Yes |
+ Yes |
+
+
+ | Subscribe COV |
+ - |
+ - |
+
+
+ | Confirmed COV Notification |
+ Yes |
+ Yes |
+
+
+ | Unconfirmed COV Notification |
+ Yes |
+ Yes |
+
+
+ | Read Property Multiple |
+ - |
+ - |
+
+
+ | Read Property Conditional |
+ - |
+ - |
+
+
+ | Read Range |
+ - |
+ - |
+
+
+ | Write Property Multiple |
+ - |
+ - |
+
+
+ | Get Alarm Summary |
+ - |
+ - |
+
+
+ | Get Event Information |
+ - |
+ - |
+
+
+ | Get Enrollment Summary |
+ - |
+ - |
+
+
+ | Acknowledge Alarm |
+ - |
+ - |
+
+
+ | Confirmed Event Notification |
+ - |
+ - |
+
+
+ | Unconfirmed Event Notification |
+ - |
+ - |
+
+
+ | Unconfirmed Text Message |
+ - |
+ - |
+
+
+ | Confirmed Text Message |
+ - |
+ - |
+
+
+ | Add List Element |
+ - |
+ - |
+
+
+ | Remove List Element |
+ - |
+ - |
+
+
+ | Create Object |
+ - |
+ - |
+
+
+ | Delete Object |
+ - |
+ - |
+
+
+ | Unconfirmed Private Transfer |
+ - |
+ - |
+
+
+ | Confirmed Private Transfer |
+ - |
+ - |
+
+
+ | VT Open |
+ - |
+ - |
+
+
+ | VT Data |
+ - |
+ - |
+
+
+ | VT Close |
+ - |
+ - |
+
+
+
+
+ BACnet Objects
+
+ The BACnet stack currently implements a Device Object, and
+ handles all of the ReadProperty inquiries for the required
+ Device Object properties. The stack handles Who-Is inquiries
+ with an I-Am, WhoHas with I-Have, and handles reject messages for
+ services not currently supported. There is built in handling for
+ DeviceCommunicationControl.
+
+ The example handlers interact with example objects, including
+ Analog Input, Analog Output, Analog Value, Binary Input,
+ Binary Output, Binary Value, Load Control, Life Safety Point,
+ and Multi-state Output objects.
+ The objects can be accessed using WriteProperty,
+ ReadProperty, or Who-Has services. Adding other BACnet objects
+ is only a matter of setting up ReadProperty, WriteProperty, or
+ I-Have handling for the required properties and any other
+ properties that you want to support.
+
+ File Objects are conditionally included in the demonstation
+ applications. The files can be access using WriteProperty,
+ ReadProperty, Who-Has, AtomicWriteFile, or AtomicReadFile services.
+
+ Getting Involved
+
+ If you want to help out on this project, join the developers mailing list, introduce yourself, and tell us what you would like to do.
+ If you are trying to implement a BACnet device or service using this project,
+ you are welcome to join the developers mailing list as well.
+
+ More details about the project can be found on
+ the BACnet Source Forge Project Page
+
+ There is documentation that describes the mechanisms in the BACnet Stack.
+ I wrote up some answers to some frequently asked questions. Of course,
+ there are a handful of text files in the doc directory of the project.
+
+ BACnet
Stack released files download
You can get the latest BACnet protocol stack source code using
@@ -449,64 +449,64 @@
or
svn co https://bacnet.svn.sourceforge.net/svnroot/bacnet/tags/bacnet-stack-0-3-0/
-
-
BACnet Developer Resources
-
-There are a number of resources that can help you develop a BACnet product or project.
-
-
- - VTS - visual test shell for
- Win32, used for Visually testing a BACnet implementation. It also includes
- a detailed network sniffer for BACnet messages, and the ability to send
- any BACnet services. The source code is in the public domain.
- - Wireshark - an open source,
- cross platform protocol analyzer with BACnet support. The detailed BACnet
- support in began in version 0.10.11 released on May 4, 2005 when Wireshark
- was known as Ethereal.
- - Ubuntu Linux or
- Debian Linux - my
- development platforms of choice.
- Linux makes a great development platform
- because all the necessary development tools are included.
- - Code::Blocks - a free cross-platform
+
+
BACnet Developer Resources
+
+There are a number of resources that can help you develop a BACnet product or project.
+
+
+ - VTS - visual test shell for
+ Win32, used for Visually testing a BACnet implementation. It also includes
+ a detailed network sniffer for BACnet messages, and the ability to send
+ any BACnet services. The source code is in the public domain.
+ - Wireshark - an open source,
+ cross platform protocol analyzer with BACnet support. The detailed BACnet
+ support in began in version 0.10.11 released on May 4, 2005 when Wireshark
+ was known as Ethereal.
+ - Ubuntu Linux or
+ Debian Linux - my
+ development platforms of choice.
+ Linux makes a great development platform
+ because all the necessary development tools are included.
+ - Code::Blocks - a free cross-platform
open source C/C++ IDE. Includes the MinGW compiler for Win32.
- - Win32 development can use Borland C++ or
+
- Win32 development can use Borland C++ or
Microsoft Visual C++,
- both of which are free (as in beer) command line compilers. Be sure to pick up the free
+ both of which are free (as in beer) command line compilers. Be sure to pick up the free
patches (service packs) for the Borland C++ compiler
(SP1,
SP2),
- as well as the free turbo debugger.
-
-
-BACnet Developer Help
-
-BACnet International Developer Resources
-
-Products and Projects that use this BACnet Stack
-
-Did you develop a product using this BACnet stack? Let us know, and you
-can get a little recognition for your hard work!
-
-SCInterface™ = Sensor Control Interface - middleware
- platform for managing legacy and modern-day sensors through a centralized
- interface
-
-BACnetSim - a
-portable implementation of the BACnet data communication protocol.
-BACnetSim is meant for embedded devices and use MS/TP as the media
-access layer. BACnetSim is a fork of bacnet-stack-0.0.1
-
-
-
-
-
- ASHRAE® and
- BACnet® are registered trademarks of the American
- Society of Heating, Refrigerating and Air-Conditioning Engineers, Inc.,
- 1791 Tullie Circle NE, Atlanta, GA 30329.
- Website updated 2-Apr-2007 by Steve Karg
-
-
+ as well as the free turbo debugger.
+
+
+BACnet Developer Help
+
+BACnet International Developer Resources
+
+Products and Projects that use this BACnet Stack
+
+Did you develop a product using this BACnet stack? Let us know, and you
+can get a little recognition for your hard work!
+
+SCInterface™ = Sensor Control Interface - middleware
+ platform for managing legacy and modern-day sensors through a centralized
+ interface
+
+BACnetSim - a
+portable implementation of the BACnet data communication protocol.
+BACnetSim is meant for embedded devices and use MS/TP as the media
+access layer. BACnetSim is a fork of bacnet-stack-0.0.1
+
+
+
+
+
+ ASHRAE® and
+ BACnet® are registered trademarks of the American
+ Society of Heating, Refrigerating and Air-Conditioning Engineers, Inc.,
+ 1791 Tullie Circle NE, Atlanta, GA 30329.
+ Website updated 2-Apr-2007 by Steve Karg
+
+
diff --git a/bacnet-stack/ports/pic18f6720/ai.c b/bacnet-stack/ports/pic18f6720/ai.c
index 31adc66b..7115a11b 100644
--- a/bacnet-stack/ports/pic18f6720/ai.c
+++ b/bacnet-stack/ports/pic18f6720/ai.c
@@ -1,200 +1,200 @@
-/**************************************************************************
-*
-* Copyright (C) 2005 Steve Karg
-*
-* 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.
-*
-*********************************************************************/
-
-/* Analog Input Objects customize for your use */
-
-#include
-#include
-#include
-#include "bacdef.h"
-#include "bacdcode.h"
-#include "bacenum.h"
-#include "config.h"
-
-/* Analog Input = Photocell */
-#define MAX_ANALOG_INPUTS 2
-
-static uint8_t Present_Value[MAX_ANALOG_INPUTS];
-
-/* we simply have 0-n object instances. Yours might be */
-/* more complex, and then you need validate that the */
-/* given instance exists */
-bool Analog_Input_Valid_Instance(uint32_t object_instance)
-{
- if (object_instance < MAX_ANALOG_INPUTS)
- return true;
-
- return false;
-}
-
-/* we simply have 0-n object instances. */
-unsigned Analog_Input_Count(void)
-{
- return MAX_ANALOG_INPUTS;
-}
-
-/* we simply have 0-n object instances. */
-uint32_t Analog_Input_Index_To_Instance(unsigned index)
-{
- return index;
-}
-
-char *Analog_Input_Name(uint32_t object_instance)
-{
- static char text_string[16] = ""; /* okay for single thread */
-
- if (object_instance < MAX_ANALOG_INPUTS) {
- sprintf(text_string, "AI-%lu", object_instance);
- return text_string;
- }
-
- return NULL;
-}
-
-static float Analog_Input_Present_Value(uint32_t object_instance)
-{
- float value = 0.0;
-
- if (object_instance < MAX_ANALOG_INPUTS)
- value = Present_Value[object_instance];
-
- return value;
-}
-
-/* return apdu length, or -1 on error */
-/* assumption - object has already exists */
-int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
- uint32_t object_instance,
- BACNET_PROPERTY_ID property,
- int32_t array_index,
- BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
-{
- int apdu_len = 0; /* return value */
- BACNET_BIT_STRING bit_string;
- BACNET_CHARACTER_STRING char_string;
-
- (void) array_index;
- switch (property) {
- case PROP_OBJECT_IDENTIFIER:
- apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
- object_instance);
- break;
- /* note: Name and Description don't have to be the same.
- You could make Description writable and different */
- case PROP_OBJECT_NAME:
- case PROP_DESCRIPTION:
- characterstring_init_ansi(&char_string,
- Analog_Input_Name(object_instance));
- apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
- break;
- case PROP_OBJECT_TYPE:
- apdu_len = encode_tagged_enumerated(&apdu[0],
- OBJECT_ANALOG_INPUT);
- break;
- case PROP_PRESENT_VALUE:
- apdu_len = encode_tagged_real(&apdu[0],
- Analog_Input_Present_Value(object_instance));
- break;
- case PROP_STATUS_FLAGS:
- bitstring_init(&bit_string);
- bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
- apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
- break;
- case PROP_EVENT_STATE:
- apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
- break;
- case PROP_OUT_OF_SERVICE:
- apdu_len = encode_tagged_boolean(&apdu[0], false);
- break;
- case PROP_UNITS:
- apdu_len = encode_tagged_enumerated(&apdu[0], UNITS_PERCENT);
- break;
- default:
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_UNKNOWN_PROPERTY;
- apdu_len = -1;
- break;
- }
-
- return apdu_len;
-}
-
-#ifdef TEST
-#include
-#include
-#include "ctest.h"
-
-void testAnalogInput(Test * pTest)
-{
- uint8_t apdu[MAX_APDU] = { 0 };
- int len = 0;
- uint32_t len_value = 0;
- uint8_t tag_number = 0;
- BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
- uint32_t decoded_instance = 0;
- uint32_t instance = 123;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
-
-
- /* FIXME: we should do a lot more testing here... */
- len = Analog_Input_Encode_Property_APDU(&apdu[0],
- instance,
- PROP_OBJECT_IDENTIFIER,
- BACNET_ARRAY_ALL, &error_class, &error_code);
- ct_test(pTest, len >= 0);
- len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
- ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
- len = decode_object_id(&apdu[len],
- (int *) &decoded_type, &decoded_instance);
- ct_test(pTest, decoded_type == OBJECT_ANALOG_INPUT);
- ct_test(pTest, decoded_instance == instance);
-
- return;
-}
-
-#ifdef TEST_ANALOG_INPUT
-int main(void)
-{
- Test *pTest;
- bool rc;
-
- pTest = ct_create("BACnet Analog Input", NULL);
- /* individual tests */
- rc = ct_addTestFunction(pTest, testAnalogInput);
- assert(rc);
-
- ct_setStream(pTest, stdout);
- ct_run(pTest);
- (void) ct_report(pTest);
- ct_destroy(pTest);
-
- return 0;
-}
-#endif /* TEST_ANALOG_INPUT */
-#endif /* TEST */
+/**************************************************************************
+*
+* Copyright (C) 2005 Steve Karg
+*
+* 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.
+*
+*********************************************************************/
+
+/* Analog Input Objects customize for your use */
+
+#include
+#include
+#include
+#include "bacdef.h"
+#include "bacdcode.h"
+#include "bacenum.h"
+#include "config.h"
+
+/* Analog Input = Photocell */
+#define MAX_ANALOG_INPUTS 2
+
+static uint8_t Present_Value[MAX_ANALOG_INPUTS];
+
+/* we simply have 0-n object instances. Yours might be */
+/* more complex, and then you need validate that the */
+/* given instance exists */
+bool Analog_Input_Valid_Instance(uint32_t object_instance)
+{
+ if (object_instance < MAX_ANALOG_INPUTS)
+ return true;
+
+ return false;
+}
+
+/* we simply have 0-n object instances. */
+unsigned Analog_Input_Count(void)
+{
+ return MAX_ANALOG_INPUTS;
+}
+
+/* we simply have 0-n object instances. */
+uint32_t Analog_Input_Index_To_Instance(unsigned index)
+{
+ return index;
+}
+
+char *Analog_Input_Name(uint32_t object_instance)
+{
+ static char text_string[16] = ""; /* okay for single thread */
+
+ if (object_instance < MAX_ANALOG_INPUTS) {
+ sprintf(text_string, "AI-%lu", object_instance);
+ return text_string;
+ }
+
+ return NULL;
+}
+
+static float Analog_Input_Present_Value(uint32_t object_instance)
+{
+ float value = 0.0;
+
+ if (object_instance < MAX_ANALOG_INPUTS)
+ value = Present_Value[object_instance];
+
+ return value;
+}
+
+/* return apdu length, or -1 on error */
+/* assumption - object has already exists */
+int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
+ uint32_t object_instance,
+ BACNET_PROPERTY_ID property,
+ int32_t array_index,
+ BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
+{
+ int apdu_len = 0; /* return value */
+ BACNET_BIT_STRING bit_string;
+ BACNET_CHARACTER_STRING char_string;
+
+ (void) array_index;
+ switch (property) {
+ case PROP_OBJECT_IDENTIFIER:
+ apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
+ object_instance);
+ break;
+ /* note: Name and Description don't have to be the same.
+ You could make Description writable and different */
+ case PROP_OBJECT_NAME:
+ case PROP_DESCRIPTION:
+ characterstring_init_ansi(&char_string,
+ Analog_Input_Name(object_instance));
+ apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
+ break;
+ case PROP_OBJECT_TYPE:
+ apdu_len = encode_tagged_enumerated(&apdu[0],
+ OBJECT_ANALOG_INPUT);
+ break;
+ case PROP_PRESENT_VALUE:
+ apdu_len = encode_tagged_real(&apdu[0],
+ Analog_Input_Present_Value(object_instance));
+ break;
+ case PROP_STATUS_FLAGS:
+ bitstring_init(&bit_string);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
+ apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
+ break;
+ case PROP_EVENT_STATE:
+ apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
+ break;
+ case PROP_OUT_OF_SERVICE:
+ apdu_len = encode_tagged_boolean(&apdu[0], false);
+ break;
+ case PROP_UNITS:
+ apdu_len = encode_tagged_enumerated(&apdu[0], UNITS_PERCENT);
+ break;
+ default:
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_UNKNOWN_PROPERTY;
+ apdu_len = -1;
+ break;
+ }
+
+ return apdu_len;
+}
+
+#ifdef TEST
+#include
+#include
+#include "ctest.h"
+
+void testAnalogInput(Test * pTest)
+{
+ uint8_t apdu[MAX_APDU] = { 0 };
+ int len = 0;
+ uint32_t len_value = 0;
+ uint8_t tag_number = 0;
+ BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
+ uint32_t decoded_instance = 0;
+ uint32_t instance = 123;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
+
+
+ /* FIXME: we should do a lot more testing here... */
+ len = Analog_Input_Encode_Property_APDU(&apdu[0],
+ instance,
+ PROP_OBJECT_IDENTIFIER,
+ BACNET_ARRAY_ALL, &error_class, &error_code);
+ ct_test(pTest, len >= 0);
+ len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
+ ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
+ len = decode_object_id(&apdu[len],
+ (int *) &decoded_type, &decoded_instance);
+ ct_test(pTest, decoded_type == OBJECT_ANALOG_INPUT);
+ ct_test(pTest, decoded_instance == instance);
+
+ return;
+}
+
+#ifdef TEST_ANALOG_INPUT
+int main(void)
+{
+ Test *pTest;
+ bool rc;
+
+ pTest = ct_create("BACnet Analog Input", NULL);
+ /* individual tests */
+ rc = ct_addTestFunction(pTest, testAnalogInput);
+ assert(rc);
+
+ ct_setStream(pTest, stdout);
+ ct_run(pTest);
+ (void) ct_report(pTest);
+ ct_destroy(pTest);
+
+ return 0;
+}
+#endif /* TEST_ANALOG_INPUT */
+#endif /* TEST */
diff --git a/bacnet-stack/ports/pic18f6720/av.c b/bacnet-stack/ports/pic18f6720/av.c
index 36ff384f..dd6511c8 100644
--- a/bacnet-stack/ports/pic18f6720/av.c
+++ b/bacnet-stack/ports/pic18f6720/av.c
@@ -186,16 +186,16 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
-#if 0
+#if 0
object_index = Analog_Value_Instance_To_Index(object_instance);
- state = Analog_Value_Out_Of_Service[object_index];
+ state = Analog_Value_Out_Of_Service[object_index];
#endif
apdu_len = encode_tagged_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_tagged_enumerated(&apdu[0], UNITS_PERCENT);
break;
-#if 0
+#if 0
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
@@ -247,7 +247,7 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_tagged_real(&apdu[0], real_value);
break;
-#endif
+#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
@@ -312,7 +312,7 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
-#if 0
+#if 0
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
@@ -332,13 +332,13 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
-#endif
+#endif
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
-#if 0
+#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
@@ -350,7 +350,7 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
-#endif
+#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
diff --git a/bacnet-stack/ports/pic18f6720/bi.c b/bacnet-stack/ports/pic18f6720/bi.c
index e3f5fe33..f01eee35 100644
--- a/bacnet-stack/ports/pic18f6720/bi.c
+++ b/bacnet-stack/ports/pic18f6720/bi.c
@@ -1,232 +1,232 @@
-/**************************************************************************
-*
-* Copyright (C) 2006 Steve Karg
-*
-* 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.
-*
-*********************************************************************/
-
-/* Binary Input Objects customize for your use */
-
-#include
-#include
-#include
-#include "bacdef.h"
-#include "bacdcode.h"
-#include "bacenum.h"
-#include "config.h"
-
-#define MAX_BINARY_INPUTS 8
-
-static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
-
-static void Binary_Input_Initialize(void)
-{
- static bool initialized = false;
- unsigned i;
-
- if (!initialized) {
- initialized = true;
- for (i = 0; i < MAX_BINARY_INPUTS; i++) {
- Present_Value[i] = BINARY_INACTIVE;
- }
- }
+/**************************************************************************
+*
+* Copyright (C) 2006 Steve Karg
+*
+* 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.
+*
+*********************************************************************/
+
+/* Binary Input Objects customize for your use */
+
+#include
+#include
+#include
+#include "bacdef.h"
+#include "bacdcode.h"
+#include "bacenum.h"
+#include "config.h"
+
+#define MAX_BINARY_INPUTS 8
+
+static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
+
+static void Binary_Input_Initialize(void)
+{
+ static bool initialized = false;
+ unsigned i;
+
+ if (!initialized) {
+ initialized = true;
+ for (i = 0; i < MAX_BINARY_INPUTS; i++) {
+ Present_Value[i] = BINARY_INACTIVE;
+ }
+ }
}
-
-/* we simply have 0-n object instances. */
-bool Binary_Input_Valid_Instance(uint32_t object_instance)
-{
- if (object_instance < MAX_BINARY_INPUTS)
- return true;
-
- return false;
-}
-
-/* we simply have 0-n object instances. */
-unsigned Binary_Input_Count(void)
-{
- return MAX_BINARY_INPUTS;
-}
-
-/* we simply have 0-n object instances.*/
-uint32_t Binary_Input_Index_To_Instance(unsigned index)
-{
- return index;
-}
-
-/* we simply have 0-n object instances. Yours might be */
-/* more complex, and then you need to return the index */
-/* that correlates to the correct instance number */
-unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
-{
- unsigned index = MAX_BINARY_INPUTS;
-
- if (object_instance < MAX_BINARY_INPUTS)
- index = object_instance;
-
- return index;
-}
-
-static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
- object_instance)
-{
- BACNET_BINARY_PV value = BINARY_INACTIVE;
- unsigned index = 0;
-
- Binary_Input_Initialize();
- index = Binary_Input_Instance_To_Index(object_instance);
- if (index < MAX_BINARY_INPUTS) {
- value = Present_Value[index];
- }
-
- return value;
-}
-
-char *Binary_Input_Name(uint32_t object_instance)
-{
- static char text_string[16] = ""; /* okay for single thread */
-
- if (object_instance < MAX_BINARY_INPUTS) {
- sprintf(text_string, "BI-%lu", object_instance);
- return text_string;
- }
-
- return NULL;
-}
-
-/* return apdu length, or -1 on error */
-/* assumption - object already exists, and has been bounds checked */
-int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
- uint32_t object_instance,
- BACNET_PROPERTY_ID property,
- int32_t array_index,
- BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
-{
- int apdu_len = 0; /* return value */
- BACNET_BIT_STRING bit_string;
- BACNET_CHARACTER_STRING char_string;
- BACNET_POLARITY polarity = POLARITY_NORMAL;
- BACNET_BINARY_PV value = BINARY_INACTIVE;
-
-
- (void) array_index;
- Binary_Input_Initialize();
- switch (property) {
- case PROP_OBJECT_IDENTIFIER:
- apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_BINARY_INPUT,
- object_instance);
- break;
- case PROP_OBJECT_NAME:
- case PROP_DESCRIPTION:
- /* note: object name must be unique in our device */
- characterstring_init_ansi(&char_string,
- Binary_Input_Name(object_instance));
- apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
- break;
- case PROP_OBJECT_TYPE:
- apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
- break;
- case PROP_PRESENT_VALUE:
- value = Binary_Input_Present_Value(object_instance);
- apdu_len = encode_tagged_enumerated(&apdu[0],value);
- break;
- case PROP_STATUS_FLAGS:
- /* note: see the details in the standard on how to use these */
- bitstring_init(&bit_string);
- bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
- apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
- break;
- case PROP_EVENT_STATE:
- /* note: see the details in the standard on how to use this */
- apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
- break;
- case PROP_OUT_OF_SERVICE:
- apdu_len = encode_tagged_boolean(&apdu[0], false);
- break;
- case PROP_POLARITY:
- apdu_len = encode_tagged_enumerated(&apdu[0], polarity);
- break;
- default:
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_UNKNOWN_PROPERTY;
- apdu_len = -1;
- break;
- }
-
- return apdu_len;
-}
-
-#ifdef TEST
-#include
-#include
-#include "ctest.h"
-
-void testBinaryInput(Test * pTest)
-{
- uint8_t apdu[MAX_APDU] = { 0 };
- int len = 0;
- uint32_t len_value = 0;
- uint8_t tag_number = 0;
- BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_OUTPUT;
- uint32_t decoded_instance = 0;
- uint32_t instance = 123;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
-
-
- /* FIXME: we should do a lot more testing here... */
- len = Binary_Input_Encode_Property_APDU(&apdu[0],
- instance,
- PROP_OBJECT_IDENTIFIER,
- BACNET_ARRAY_ALL, &error_class, &error_code);
- ct_test(pTest, len >= 0);
- len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
- ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
- len = decode_object_id(&apdu[len],
- (int *) &decoded_type, &decoded_instance);
- ct_test(pTest, decoded_type == OBJECT_BINARY_INPUT);
- ct_test(pTest, decoded_instance == instance);
-
- return;
-}
-
-#ifdef TEST_BINARY_INPUT
-int main(void)
-{
- Test *pTest;
- bool rc;
-
- pTest = ct_create("BACnet Binary Input", NULL);
- /* individual tests */
- rc = ct_addTestFunction(pTest, testBinaryInput);
- assert(rc);
-
- ct_setStream(pTest, stdout);
- ct_run(pTest);
- (void) ct_report(pTest);
- ct_destroy(pTest);
-
- return 0;
-}
-#endif /* TEST_BINARY_INPUT */
-#endif /* TEST */
+
+/* we simply have 0-n object instances. */
+bool Binary_Input_Valid_Instance(uint32_t object_instance)
+{
+ if (object_instance < MAX_BINARY_INPUTS)
+ return true;
+
+ return false;
+}
+
+/* we simply have 0-n object instances. */
+unsigned Binary_Input_Count(void)
+{
+ return MAX_BINARY_INPUTS;
+}
+
+/* we simply have 0-n object instances.*/
+uint32_t Binary_Input_Index_To_Instance(unsigned index)
+{
+ return index;
+}
+
+/* we simply have 0-n object instances. Yours might be */
+/* more complex, and then you need to return the index */
+/* that correlates to the correct instance number */
+unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
+{
+ unsigned index = MAX_BINARY_INPUTS;
+
+ if (object_instance < MAX_BINARY_INPUTS)
+ index = object_instance;
+
+ return index;
+}
+
+static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
+ object_instance)
+{
+ BACNET_BINARY_PV value = BINARY_INACTIVE;
+ unsigned index = 0;
+
+ Binary_Input_Initialize();
+ index = Binary_Input_Instance_To_Index(object_instance);
+ if (index < MAX_BINARY_INPUTS) {
+ value = Present_Value[index];
+ }
+
+ return value;
+}
+
+char *Binary_Input_Name(uint32_t object_instance)
+{
+ static char text_string[16] = ""; /* okay for single thread */
+
+ if (object_instance < MAX_BINARY_INPUTS) {
+ sprintf(text_string, "BI-%lu", object_instance);
+ return text_string;
+ }
+
+ return NULL;
+}
+
+/* return apdu length, or -1 on error */
+/* assumption - object already exists, and has been bounds checked */
+int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
+ uint32_t object_instance,
+ BACNET_PROPERTY_ID property,
+ int32_t array_index,
+ BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
+{
+ int apdu_len = 0; /* return value */
+ BACNET_BIT_STRING bit_string;
+ BACNET_CHARACTER_STRING char_string;
+ BACNET_POLARITY polarity = POLARITY_NORMAL;
+ BACNET_BINARY_PV value = BINARY_INACTIVE;
+
+
+ (void) array_index;
+ Binary_Input_Initialize();
+ switch (property) {
+ case PROP_OBJECT_IDENTIFIER:
+ apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_BINARY_INPUT,
+ object_instance);
+ break;
+ case PROP_OBJECT_NAME:
+ case PROP_DESCRIPTION:
+ /* note: object name must be unique in our device */
+ characterstring_init_ansi(&char_string,
+ Binary_Input_Name(object_instance));
+ apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
+ break;
+ case PROP_OBJECT_TYPE:
+ apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
+ break;
+ case PROP_PRESENT_VALUE:
+ value = Binary_Input_Present_Value(object_instance);
+ apdu_len = encode_tagged_enumerated(&apdu[0],value);
+ break;
+ case PROP_STATUS_FLAGS:
+ /* note: see the details in the standard on how to use these */
+ bitstring_init(&bit_string);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
+ apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
+ break;
+ case PROP_EVENT_STATE:
+ /* note: see the details in the standard on how to use this */
+ apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
+ break;
+ case PROP_OUT_OF_SERVICE:
+ apdu_len = encode_tagged_boolean(&apdu[0], false);
+ break;
+ case PROP_POLARITY:
+ apdu_len = encode_tagged_enumerated(&apdu[0], polarity);
+ break;
+ default:
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_UNKNOWN_PROPERTY;
+ apdu_len = -1;
+ break;
+ }
+
+ return apdu_len;
+}
+
+#ifdef TEST
+#include
+#include
+#include "ctest.h"
+
+void testBinaryInput(Test * pTest)
+{
+ uint8_t apdu[MAX_APDU] = { 0 };
+ int len = 0;
+ uint32_t len_value = 0;
+ uint8_t tag_number = 0;
+ BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_OUTPUT;
+ uint32_t decoded_instance = 0;
+ uint32_t instance = 123;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
+
+
+ /* FIXME: we should do a lot more testing here... */
+ len = Binary_Input_Encode_Property_APDU(&apdu[0],
+ instance,
+ PROP_OBJECT_IDENTIFIER,
+ BACNET_ARRAY_ALL, &error_class, &error_code);
+ ct_test(pTest, len >= 0);
+ len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
+ ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
+ len = decode_object_id(&apdu[len],
+ (int *) &decoded_type, &decoded_instance);
+ ct_test(pTest, decoded_type == OBJECT_BINARY_INPUT);
+ ct_test(pTest, decoded_instance == instance);
+
+ return;
+}
+
+#ifdef TEST_BINARY_INPUT
+int main(void)
+{
+ Test *pTest;
+ bool rc;
+
+ pTest = ct_create("BACnet Binary Input", NULL);
+ /* individual tests */
+ rc = ct_addTestFunction(pTest, testBinaryInput);
+ assert(rc);
+
+ ct_setStream(pTest, stdout);
+ ct_run(pTest);
+ (void) ct_report(pTest);
+ ct_destroy(pTest);
+
+ return 0;
+}
+#endif /* TEST_BINARY_INPUT */
+#endif /* TEST */
diff --git a/bacnet-stack/ports/pic18f6720/bv.c b/bacnet-stack/ports/pic18f6720/bv.c
index c56158ab..2ff66ddb 100644
--- a/bacnet-stack/ports/pic18f6720/bv.c
+++ b/bacnet-stack/ports/pic18f6720/bv.c
@@ -1,338 +1,338 @@
-/**************************************************************************
-*
-* Copyright (C) 2006 Steve Karg
-*
-* 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.
-*
-*********************************************************************/
-
-/* Binary Value Objects - customize for your use */
-
-#include
-#include
-#include
-#include "bacdef.h"
-#include "bacdcode.h"
-#include "bacenum.h"
-#include "config.h" /* the custom stuff */
-#include "wp.h"
-
-#define MAX_BINARY_VALUES 8
-
+/**************************************************************************
+*
+* Copyright (C) 2006 Steve Karg
+*
+* 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.
+*
+*********************************************************************/
+
+/* Binary Value Objects - customize for your use */
+
+#include
+#include
+#include
+#include "bacdef.h"
+#include "bacdcode.h"
+#include "bacenum.h"
+#include "config.h" /* the custom stuff */
+#include "wp.h"
+
+#define MAX_BINARY_VALUES 8
+
static BACNET_BINARY_PV Present_Value[MAX_BINARY_VALUES];
-
-static void Binary_Value_Initialize(void)
-{
- static bool initialized = false;
- unsigned i;
-
- if (!initialized) {
- initialized = true;
- for (i = 0; i < MAX_BINARY_VALUES; i++) {
- Present_Value[i] = BINARY_INACTIVE;
- }
- }
+
+static void Binary_Value_Initialize(void)
+{
+ static bool initialized = false;
+ unsigned i;
+
+ if (!initialized) {
+ initialized = true;
+ for (i = 0; i < MAX_BINARY_VALUES; i++) {
+ Present_Value[i] = BINARY_INACTIVE;
+ }
+ }
}
-
-/* we simply have 0-n object instances. */
-bool Binary_Value_Valid_Instance(uint32_t object_instance)
-{
- if (object_instance < MAX_BINARY_VALUES)
- return true;
-
- return false;
-}
-
-/* we simply have 0-n object instances. */
-unsigned Binary_Value_Count(void)
-{
- return MAX_BINARY_VALUES;
-}
-
-/* we simply have 0-n object instances. */
-uint32_t Binary_Value_Index_To_Instance(unsigned index)
-{
- return index;
-}
-
-/* we simply have 0-n object instances. */
-unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
-{
- unsigned index = MAX_BINARY_VALUES;
-
- if (object_instance < MAX_BINARY_VALUES)
- index = object_instance;
-
- return index;
-}
-
-static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
- object_instance)
-{
- BACNET_BINARY_PV value = BINARY_INACTIVE;
-
- Binary_Value_Initialize();
- if (object_instance < MAX_BINARY_VALUES) {
- value = Present_Value[object_instance];
- }
-
- return value;
-}
-
-/* note: the object name must be unique within this device */
-char *Binary_Value_Name(uint32_t object_instance)
-{
- static char text_string[16] = ""; /* okay for single thread */
-
- if (object_instance < MAX_BINARY_VALUES) {
- sprintf(text_string, "BV-%lu", object_instance);
- return text_string;
- }
-
- return NULL;
-}
-
-/* return apdu len, or -1 on error */
-int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
- uint32_t object_instance,
- BACNET_PROPERTY_ID property,
- int32_t array_index,
- BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
-{
- int len = 0;
- int apdu_len = 0; /* return value */
- BACNET_BIT_STRING bit_string;
- BACNET_CHARACTER_STRING char_string;
- BACNET_BINARY_PV present_value = BINARY_INACTIVE;
- BACNET_POLARITY polarity = POLARITY_NORMAL;
- unsigned object_index = 0;
- unsigned i = 0;
- bool state = false;
-
- Binary_Value_Initialize();
- switch (property) {
- case PROP_OBJECT_IDENTIFIER:
- apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_BINARY_VALUE,
- object_instance);
- break;
- /* note: Name and Description don't have to be the same.
- You could make Description writable and different */
- case PROP_OBJECT_NAME:
- case PROP_DESCRIPTION:
- characterstring_init_ansi(&char_string,
- Binary_Value_Name(object_instance));
- apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
- break;
- case PROP_OBJECT_TYPE:
- apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
- break;
- case PROP_PRESENT_VALUE:
- present_value = Binary_Value_Present_Value(object_instance);
- apdu_len = encode_tagged_enumerated(&apdu[0], present_value);
- break;
- case PROP_STATUS_FLAGS:
- /* note: see the details in the standard on how to use these */
- bitstring_init(&bit_string);
- bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
- bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
- apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
- break;
- case PROP_EVENT_STATE:
- /* note: see the details in the standard on how to use this */
- apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
- break;
- case PROP_OUT_OF_SERVICE:
- apdu_len = encode_tagged_boolean(&apdu[0], false);
- break;
- case PROP_POLARITY:
- /* FIXME: figure out the polarity */
- apdu_len = encode_tagged_enumerated(&apdu[0], polarity);
- break;
- default:
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_UNKNOWN_PROPERTY;
- apdu_len = -1;
- break;
- }
-
- return apdu_len;
-}
-
-/* returns true if successful */
-bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
- BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
-{
- bool status = false; /* return value */
- unsigned int object_index = 0;
- unsigned int priority = 0;
- BACNET_BINARY_PV level = BINARY_NULL;
+
+/* we simply have 0-n object instances. */
+bool Binary_Value_Valid_Instance(uint32_t object_instance)
+{
+ if (object_instance < MAX_BINARY_VALUES)
+ return true;
+
+ return false;
+}
+
+/* we simply have 0-n object instances. */
+unsigned Binary_Value_Count(void)
+{
+ return MAX_BINARY_VALUES;
+}
+
+/* we simply have 0-n object instances. */
+uint32_t Binary_Value_Index_To_Instance(unsigned index)
+{
+ return index;
+}
+
+/* we simply have 0-n object instances. */
+unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
+{
+ unsigned index = MAX_BINARY_VALUES;
+
+ if (object_instance < MAX_BINARY_VALUES)
+ index = object_instance;
+
+ return index;
+}
+
+static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
+ object_instance)
+{
+ BACNET_BINARY_PV value = BINARY_INACTIVE;
+
+ Binary_Value_Initialize();
+ if (object_instance < MAX_BINARY_VALUES) {
+ value = Present_Value[object_instance];
+ }
+
+ return value;
+}
+
+/* note: the object name must be unique within this device */
+char *Binary_Value_Name(uint32_t object_instance)
+{
+ static char text_string[16] = ""; /* okay for single thread */
+
+ if (object_instance < MAX_BINARY_VALUES) {
+ sprintf(text_string, "BV-%lu", object_instance);
+ return text_string;
+ }
+
+ return NULL;
+}
+
+/* return apdu len, or -1 on error */
+int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
+ uint32_t object_instance,
+ BACNET_PROPERTY_ID property,
+ int32_t array_index,
+ BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
+{
+ int len = 0;
+ int apdu_len = 0; /* return value */
+ BACNET_BIT_STRING bit_string;
+ BACNET_CHARACTER_STRING char_string;
+ BACNET_BINARY_PV present_value = BINARY_INACTIVE;
+ BACNET_POLARITY polarity = POLARITY_NORMAL;
+ unsigned object_index = 0;
+ unsigned i = 0;
+ bool state = false;
+
+ Binary_Value_Initialize();
+ switch (property) {
+ case PROP_OBJECT_IDENTIFIER:
+ apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_BINARY_VALUE,
+ object_instance);
+ break;
+ /* note: Name and Description don't have to be the same.
+ You could make Description writable and different */
+ case PROP_OBJECT_NAME:
+ case PROP_DESCRIPTION:
+ characterstring_init_ansi(&char_string,
+ Binary_Value_Name(object_instance));
+ apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
+ break;
+ case PROP_OBJECT_TYPE:
+ apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
+ break;
+ case PROP_PRESENT_VALUE:
+ present_value = Binary_Value_Present_Value(object_instance);
+ apdu_len = encode_tagged_enumerated(&apdu[0], present_value);
+ break;
+ case PROP_STATUS_FLAGS:
+ /* note: see the details in the standard on how to use these */
+ bitstring_init(&bit_string);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
+ apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
+ break;
+ case PROP_EVENT_STATE:
+ /* note: see the details in the standard on how to use this */
+ apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
+ break;
+ case PROP_OUT_OF_SERVICE:
+ apdu_len = encode_tagged_boolean(&apdu[0], false);
+ break;
+ case PROP_POLARITY:
+ /* FIXME: figure out the polarity */
+ apdu_len = encode_tagged_enumerated(&apdu[0], polarity);
+ break;
+ default:
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_UNKNOWN_PROPERTY;
+ apdu_len = -1;
+ break;
+ }
+
+ return apdu_len;
+}
+
+/* returns true if successful */
+bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
+ BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
+{
+ bool status = false; /* return value */
+ unsigned int object_index = 0;
+ unsigned int priority = 0;
+ BACNET_BINARY_PV level = BINARY_NULL;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
-
- if (!Binary_Value_Valid_Instance(wp_data->object_instance)) {
- *error_class = ERROR_CLASS_OBJECT;
- *error_code = ERROR_CODE_UNKNOWN_OBJECT;
- return false;
- }
- /* decode the some of the request */
+
+ if (!Binary_Value_Valid_Instance(wp_data->object_instance)) {
+ *error_class = ERROR_CLASS_OBJECT;
+ *error_code = ERROR_CODE_UNKNOWN_OBJECT;
+ return false;
+ }
+ /* decode the some of the request */
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
- switch (wp_data->object_property) {
- case PROP_PRESENT_VALUE:
+ switch (wp_data->object_property) {
+ case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
- priority = wp_data->priority;
- /* Command priority 6 is reserved for use by Minimum On/Off
- algorithm and may not be used for other purposes in any
- object. */
- if (priority && (priority <= BACNET_MAX_PRIORITY) &&
- (priority != 6 /* reserved */ ) &&
+ priority = wp_data->priority;
+ /* Command priority 6 is reserved for use by Minimum On/Off
+ algorithm and may not be used for other purposes in any
+ object. */
+ if (priority && (priority <= BACNET_MAX_PRIORITY) &&
+ (priority != 6 /* reserved */ ) &&
(value.type.Enumerated >= MIN_BINARY_PV) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = value.type.Enumerated;
- object_index =
- Binary_Value_Instance_To_Index(wp_data->
- object_instance);
- priority--;
+ object_index =
+ Binary_Value_Instance_To_Index(wp_data->
+ object_instance);
+ priority--;
/* NOTE: this Binary value has no priority array */
- Present_Value[object_index] = level;
+ Present_Value[object_index] = level;
/* Note: you could set the physical output here if we
- are the highest priority.
- However, if Out of Service is TRUE, then don't set the
- physical output. */
- status = true;
- } else if (priority == 6) {
- /* Command priority 6 is reserved for use by Minimum On/Off
- algorithm and may not be used for other purposes in any
- object. */
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
- } else {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
- }
+ are the highest priority.
+ However, if Out of Service is TRUE, then don't set the
+ physical output. */
+ status = true;
+ } else if (priority == 6) {
+ /* Command priority 6 is reserved for use by Minimum On/Off
+ algorithm and may not be used for other purposes in any
+ object. */
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
-#if 0
- /* NOTE: this Binary Value has no priority array */
- level = BINARY_NULL;
- object_index =
- Binary_Value_Instance_To_Index(wp_data->object_instance);
- priority = wp_data->priority;
- if (priority && (priority <= BACNET_MAX_PRIORITY)) {
- priority--;
- Binary_Value_Level[object_index][priority] = level;
- /* Note: you could set the physical output here to the next
- highest priority, or to the relinquish default if no
- priorities are set.
- However, if Out of Service is TRUE, then don't set the
- physical output. This comment may apply to the
- main loop (i.e. check out of service before changing output) */
- status = true;
- } else {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
- }
-#else
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_INVALID_DATA_TYPE;
-#endif
+#if 0
+ /* NOTE: this Binary Value has no priority array */
+ level = BINARY_NULL;
+ object_index =
+ Binary_Value_Instance_To_Index(wp_data->object_instance);
+ priority = wp_data->priority;
+ if (priority && (priority <= BACNET_MAX_PRIORITY)) {
+ priority--;
+ Binary_Value_Level[object_index][priority] = level;
+ /* Note: you could set the physical output here to the next
+ highest priority, or to the relinquish default if no
+ priorities are set.
+ However, if Out of Service is TRUE, then don't set the
+ physical output. This comment may apply to the
+ main loop (i.e. check out of service before changing output) */
+ status = true;
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+#else
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_INVALID_DATA_TYPE;
+#endif
} else {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_INVALID_DATA_TYPE;
- }
- break;
-#if 0
- case PROP_OUT_OF_SERVICE:
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+#if 0
+ case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
- object_index =
- Binary_Value_Instance_To_Index(wp_data->object_instance);
+ object_index =
+ Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
- status = true;
- } else {
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_INVALID_DATA_TYPE;
- }
- break;
-#endif
- default:
- *error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
- break;
- }
-
- return status;
-}
-
-#ifdef TEST
-#include
-#include
-#include "ctest.h"
-
-void testBinary_Value(Test * pTest)
-{
- uint8_t apdu[MAX_APDU] = { 0 };
- int len = 0;
- uint32_t len_value = 0;
- uint8_t tag_number = 0;
- BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_VALUE;
- uint32_t decoded_instance = 0;
- uint32_t instance = 123;
- BACNET_ERROR_CLASS error_class;
- BACNET_ERROR_CODE error_code;
-
-
- len = Binary_Value_Encode_Property_APDU(&apdu[0],
- instance,
- PROP_OBJECT_IDENTIFIER,
- BACNET_ARRAY_ALL, &error_class, &error_code);
- ct_test(pTest, len != 0);
- len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
- ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
- len = decode_object_id(&apdu[len],
- (int *) &decoded_type, &decoded_instance);
- ct_test(pTest, decoded_type == OBJECT_BINARY_VALUE);
- ct_test(pTest, decoded_instance == instance);
-
- return;
-}
-
-#ifdef TEST_BINARY_VALUE
-int main(void)
-{
- Test *pTest;
- bool rc;
-
- pTest = ct_create("BACnet Binary_Value", NULL);
- /* individual tests */
- rc = ct_addTestFunction(pTest, testBinary_Value);
- assert(rc);
-
- ct_setStream(pTest, stdout);
- ct_run(pTest);
- (void) ct_report(pTest);
- ct_destroy(pTest);
-
- return 0;
-}
-#endif /* TEST_BINARY_VALUE */
-#endif /* TEST */
+ status = true;
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+#endif
+ default:
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
+ break;
+ }
+
+ return status;
+}
+
+#ifdef TEST
+#include
+#include
+#include "ctest.h"
+
+void testBinary_Value(Test * pTest)
+{
+ uint8_t apdu[MAX_APDU] = { 0 };
+ int len = 0;
+ uint32_t len_value = 0;
+ uint8_t tag_number = 0;
+ BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_VALUE;
+ uint32_t decoded_instance = 0;
+ uint32_t instance = 123;
+ BACNET_ERROR_CLASS error_class;
+ BACNET_ERROR_CODE error_code;
+
+
+ len = Binary_Value_Encode_Property_APDU(&apdu[0],
+ instance,
+ PROP_OBJECT_IDENTIFIER,
+ BACNET_ARRAY_ALL, &error_class, &error_code);
+ ct_test(pTest, len != 0);
+ len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
+ ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
+ len = decode_object_id(&apdu[len],
+ (int *) &decoded_type, &decoded_instance);
+ ct_test(pTest, decoded_type == OBJECT_BINARY_VALUE);
+ ct_test(pTest, decoded_instance == instance);
+
+ return;
+}
+
+#ifdef TEST_BINARY_VALUE
+int main(void)
+{
+ Test *pTest;
+ bool rc;
+
+ pTest = ct_create("BACnet Binary_Value", NULL);
+ /* individual tests */
+ rc = ct_addTestFunction(pTest, testBinary_Value);
+ assert(rc);
+
+ ct_setStream(pTest, stdout);
+ ct_run(pTest);
+ (void) ct_report(pTest);
+ ct_destroy(pTest);
+
+ return 0;
+}
+#endif /* TEST_BINARY_VALUE */
+#endif /* TEST */
diff --git a/bacnet-stack/ports/pic18f6720/device.c b/bacnet-stack/ports/pic18f6720/device.c
index 7fb4a622..d0274b08 100644
--- a/bacnet-stack/ports/pic18f6720/device.c
+++ b/bacnet-stack/ports/pic18f6720/device.c
@@ -186,7 +186,7 @@ bool Device_Object_List_Identifier(unsigned array_index,
/* normalize the index since
we know it is not the previous objects */
/* array index starts at 1 */
- object_index = array_index - 1;
+ object_index = array_index - 1;
/* 1 for the device object */
object_count = 1;
/* FIXME: add objects as needed */
@@ -538,10 +538,10 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
- characterstring_value(&value.type.Character_String)); */
- /* FIXME: All the object names in a device must be unique.
- Disallow setting the Device Object Name to any objects in
- the device. */
+ characterstring_value(&value.type.Character_String)); */
+ /* FIXME: All the object names in a device must be unique.
+ Disallow setting the Device Object Name to any objects in
+ the device. */
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
diff --git a/bacnet-stack/ports/pic18f6720/h_rp.c b/bacnet-stack/ports/pic18f6720/h_rp.c
index 01df2e86..f3998e53 100644
--- a/bacnet-stack/ports/pic18f6720/h_rp.c
+++ b/bacnet-stack/ports/pic18f6720/h_rp.c
@@ -98,78 +98,78 @@ void handler_read_property(uint8_t * service_request,
}
}
break;
- case OBJECT_ANALOG_INPUT:
- if (Analog_Input_Valid_Instance(data.object_instance)) {
- len = Analog_Input_Encode_Property_APDU(&Temp_Buf[0],
- data.object_instance,
- data.object_property,
- data.array_index, &error_class, &error_code);
- if (len >= 0) {
- /* encode the APDU portion of the packet */
- data.application_data = &Temp_Buf[0];
- data.application_data_len = len;
- /* FIXME: probably need a length limitation sent with encode */
- len =
- rp_ack_encode_apdu(&Handler_Transmit_Buffer
- [pdu_len], service_data->invoke_id, &data);
- error = false;
- }
- }
- break;
- case OBJECT_BINARY_INPUT:
- if (Binary_Input_Valid_Instance(data.object_instance)) {
- len = Binary_Input_Encode_Property_APDU(&Temp_Buf[0],
- data.object_instance,
- data.object_property,
- data.array_index, &error_class, &error_code);
- if (len >= 0) {
- /* encode the APDU portion of the packet */
- data.application_data = &Temp_Buf[0];
- data.application_data_len = len;
- /* FIXME: probably need a length limitation sent with encode */
- len =
- rp_ack_encode_apdu(&Handler_Transmit_Buffer
- [pdu_len], service_data->invoke_id, &data);
- error = false;
- }
- }
- break;
- case OBJECT_BINARY_VALUE:
- if (Binary_Value_Valid_Instance(data.object_instance)) {
- len = Binary_Value_Encode_Property_APDU(&Temp_Buf[0],
- data.object_instance,
- data.object_property,
- data.array_index, &error_class, &error_code);
- if (len >= 0) {
- /* encode the APDU portion of the packet */
- data.application_data = &Temp_Buf[0];
- data.application_data_len = len;
- /* FIXME: probably need a length limitation sent with encode */
- len =
- rp_ack_encode_apdu(&Handler_Transmit_Buffer
- [pdu_len], service_data->invoke_id, &data);
- error = false;
- }
- }
- break;
- case OBJECT_ANALOG_VALUE:
- if (Analog_Value_Valid_Instance(data.object_instance)) {
- len = Analog_Value_Encode_Property_APDU(&Temp_Buf[0],
- data.object_instance,
- data.object_property,
- data.array_index, &error_class, &error_code);
- if (len >= 0) {
- /* encode the APDU portion of the packet */
- data.application_data = &Temp_Buf[0];
- data.application_data_len = len;
- /* FIXME: probably need a length limitation sent with encode */
- len =
- rp_ack_encode_apdu(&Handler_Transmit_Buffer
- [pdu_len], service_data->invoke_id, &data);
- error = false;
- }
- }
- break;
+ case OBJECT_ANALOG_INPUT:
+ if (Analog_Input_Valid_Instance(data.object_instance)) {
+ len = Analog_Input_Encode_Property_APDU(&Temp_Buf[0],
+ data.object_instance,
+ data.object_property,
+ data.array_index, &error_class, &error_code);
+ if (len >= 0) {
+ /* encode the APDU portion of the packet */
+ data.application_data = &Temp_Buf[0];
+ data.application_data_len = len;
+ /* FIXME: probably need a length limitation sent with encode */
+ len =
+ rp_ack_encode_apdu(&Handler_Transmit_Buffer
+ [pdu_len], service_data->invoke_id, &data);
+ error = false;
+ }
+ }
+ break;
+ case OBJECT_BINARY_INPUT:
+ if (Binary_Input_Valid_Instance(data.object_instance)) {
+ len = Binary_Input_Encode_Property_APDU(&Temp_Buf[0],
+ data.object_instance,
+ data.object_property,
+ data.array_index, &error_class, &error_code);
+ if (len >= 0) {
+ /* encode the APDU portion of the packet */
+ data.application_data = &Temp_Buf[0];
+ data.application_data_len = len;
+ /* FIXME: probably need a length limitation sent with encode */
+ len =
+ rp_ack_encode_apdu(&Handler_Transmit_Buffer
+ [pdu_len], service_data->invoke_id, &data);
+ error = false;
+ }
+ }
+ break;
+ case OBJECT_BINARY_VALUE:
+ if (Binary_Value_Valid_Instance(data.object_instance)) {
+ len = Binary_Value_Encode_Property_APDU(&Temp_Buf[0],
+ data.object_instance,
+ data.object_property,
+ data.array_index, &error_class, &error_code);
+ if (len >= 0) {
+ /* encode the APDU portion of the packet */
+ data.application_data = &Temp_Buf[0];
+ data.application_data_len = len;
+ /* FIXME: probably need a length limitation sent with encode */
+ len =
+ rp_ack_encode_apdu(&Handler_Transmit_Buffer
+ [pdu_len], service_data->invoke_id, &data);
+ error = false;
+ }
+ }
+ break;
+ case OBJECT_ANALOG_VALUE:
+ if (Analog_Value_Valid_Instance(data.object_instance)) {
+ len = Analog_Value_Encode_Property_APDU(&Temp_Buf[0],
+ data.object_instance,
+ data.object_property,
+ data.array_index, &error_class, &error_code);
+ if (len >= 0) {
+ /* encode the APDU portion of the packet */
+ data.application_data = &Temp_Buf[0];
+ data.application_data_len = len;
+ /* FIXME: probably need a length limitation sent with encode */
+ len =
+ rp_ack_encode_apdu(&Handler_Transmit_Buffer
+ [pdu_len], service_data->invoke_id, &data);
+ error = false;
+ }
+ }
+ break;
default:
break;
}
diff --git a/bacnet-stack/ports/pic18f6720/mstp.c b/bacnet-stack/ports/pic18f6720/mstp.c
index e586c210..47a3d6bd 100644
--- a/bacnet-stack/ports/pic18f6720/mstp.c
+++ b/bacnet-stack/ports/pic18f6720/mstp.c
@@ -770,7 +770,7 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port)
mstp_port->DataLength);
break;
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
- /*mstp_port->ReplyPostponedTimer = 0;
*/
+ /*mstp_port->ReplyPostponedTimer = 0; */
/* indicate successful reception to the higher layers */
dlmstp_put_receive(mstp_port->SourceAddress,
(uint8_t *) & mstp_port->InputBuffer[0],
@@ -1217,12 +1217,12 @@ void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port)
mstp_port->ReceivedValidFrame = false;
mstp_port->RetryCount = 0;
mstp_port->SilenceTimer = 0;
-/* mstp_port->ReplyPostponedTimer = 0;
*/
+/* mstp_port->ReplyPostponedTimer = 0; */
mstp_port->SoleMaster = false;
mstp_port->SourceAddress = 0;
mstp_port->TokenCount = 0;
#if 0
- /* these are adjustable, so should already be set
*/
+ /* these are adjustable, so should already be set */
mstp_port->Nmax_info_frames = DEFAULT_MAX_INFO_FRAMES;
mstp_port->Nmax_master = DEFAULT_MAX_MASTER;
#endif
diff --git a/bacnet-stack/ports/pic18f6720/mstp.h b/bacnet-stack/ports/pic18f6720/mstp.h
index 3a658cdd..7ff3e79e 100644
--- a/bacnet-stack/ports/pic18f6720/mstp.h
+++ b/bacnet-stack/ports/pic18f6720/mstp.h
@@ -162,7 +162,7 @@ struct mstp_port_struct_t {
/* Machine when a Data Expecting Reply Answer activity is completed. */
/* note: we always send a reply postponed since a message other than
the reply may be in the transmit queue */
-/* uint16_t ReplyPostponedTimer;
*/
+/* uint16_t ReplyPostponedTimer; */
/* Used to store the Source Address of a received frame. */
uint8_t SourceAddress;
diff --git a/bacnet-stack/ports/pic18f6720/pic18f6720.tpi b/bacnet-stack/ports/pic18f6720/pic18f6720.tpi
index 5370f652..acc13425 100644
--- a/bacnet-stack/ports/pic18f6720/pic18f6720.tpi
+++ b/bacnet-stack/ports/pic18f6720/pic18f6720.tpi
@@ -1,408 +1,408 @@
-PICS 0
-BACnet Protocol Implementation Conformance Statement
-
---
---
--- BACnet Stack Demo
--- bacnet.sourceforge.net
--- Author: Steve Karg
---
---
-Vendor Name: "ASHRAE"
-Product Name: "PIC18F6720 Device"
-Product Model Number: "GNU Demo"
-Product Description: "BACnet Demo"
-
-BIBBs Supported:
-{
--- The BIBBs may be any of:
--- DS-RP-A
- DS-RP-B
--- DS-RPM-A DS-RPM-B
--- DS-RPC-A DS-RPC-B
--- DS-WP-A
- DS-WP-B
--- DS-WPM-A DS-WPM-B
--- DS-COV-A DS-COV-B
--- DS-COVP-A DS-COVP-B
--- DS-COVU-A DS-COVU-B
--- AE-N-A AE-N-I-B AE-N-E-B
--- AE-ACK-A AE-ACK-B
--- AE-ASUM-A AE-ASUM-B
--- AE-ESUM-A AE-ESUM-B
--- AE-INFO-A AE-INFO-B
--- AE-LS-A AE-LS-B
--- SCHED-A SCHED-I-B SCHED-E-B
--- T-VMT-A T-VMT-I-B T-VMT-E-B
--- T-ATR-A T-ATR-B
--- DM-DDB-A
- DM-DDB-B
--- DM-DOB-A
--- DM-DOB-B
--- DM-DCC-A
- DM-DCC-B
--- DM-PT-A DM-PT-B
--- DM-TM-A DM-TM-B
--- DM-TS-A
--- DM-TS-B
--- DM-UTC-A
--- DM-UTC-B
--- DM-RD-A
- DM-RD-B
--- DM-BR-A DM-BR-B
--- DM-R-A DM-R-B
--- DM-LM-A DM-LM-B
--- DM-OCD-A DM-OCD-B
--- DM-VT-A DM-VT-B
--- NM-CE-A NM-CE-B
--- NM-RC-A NM-RC-B
-}
-
-BACnet Standard Application Services Supported:
-{
--- AcknowledgeAlarm Initiate Execute
--- ConfirmedCOVNotification Initiate Execute
--- UnconfirmedCOVNotification Initiate
--- ConfirmedEventNotification Initiate Execute
--- UnconfirmedEventNotification Initiate Execute
--- GetAlarmSummary Initiate Execute
--- GetEnrollmentSummary Initiate Execute
--- AtomicReadFile Initiate Execute
--- AtomicWriteFile Initiate Execute
--- AddListElement Initiate Execute
--- RemoveListElement Initiate Execute
--- CreateObject Initiate Execute
--- DeleteObject Initiate Execute
- ReadProperty Execute
--- ReadpropertyConditional Initiate Execute
--- ReadPropertyMultiple Initiate Execute
--- SubscribeCOV Initiate Execute
- WriteProperty Execute
--- WritePropertyMultiple Initiate Execute
- DeviceCommunicationControl Execute
--- ConfirmedPrivateTransfer Initiate Execute
--- UnconfirmedPrivateTransfer Initiate Execute
--- TimeSynchronization Initiate Execute
--- Who-Has Execute
--- I-Have Initiate
- Who-Is Execute
- I-Am Initiate
--- VT-Open Initiate Execute
--- VT-Close Initiate Execute
--- VT-Data Initiate Execute
--- ConfirmedTextMessage Initiate Execute
--- UnconfirmedTextMessage Initiate Execute
- ReinitializeDevice Execute
--- RequestKey Initiate Execute
--- Authenticate Initiate Execute
--- UTCTimeSynchronization Initiate Execute
--- ReadRange Initiate Execute
--- GetEventInformation Initiate Execute
--- LifeSafetyOperation Initiate Execute
--- SubscribeCOVProperty Initiate Execute
--- RequestKey Initiate Execute
--- Authenticate Initiate Execute
-}
-
-Standard Object-Types Supported:
-{
- Analog Input
--- Analog Output
- Analog Value
--- Averaging Createable Deleteable
- Binary Input
--- Binary Output
- Binary Value
--- Calendar Createable Deleteable
--- Command Createable Deleteable
- Device
--- Event Enrollment Createable Deleteable
--- File
--- Group Createable Deleteable
--- Loop Createable Deleteable
--- Multi-state Input Createable Deleteable
--- Multi-state Output
--- Multi-state Value Createable Deleteable
--- Notification Class Createable Deleteable
--- Program Createable Deleteable
--- Schedule Createable Deleteable
--- Life Safety Point
--- Life Safety Zone Createable Deleteable
--- Trend Log Createable Deleteable
--- Load Control
-}
-
-Data Link Layer Option:
-{
--- ISO 8802-3, 10BASE5
--- ISO 8802-3, 10BASE2
--- ISO 8802-3, 10BASET
--- ISO 8802-3, Fiber
--- ARCNET, coax star
--- ARCNET, coax bus
--- ARCNET, twisted pair star
--- ARCNET, twisted pair bus
--- ARCNET, fiber star
-MS/TP master. Baud rate(s): 9600, 19200, 38400, 76800
--- MS/TP slave. Baud rate(s): 9600
--- Point-To-Point. Modem, Baud rate(s): 14.4k
--- Point-To-Point. Modem, Autobaud range: 9600 to 28.8k
--- BACnet/IP, 'DIX' Ethernet
--- BACnet/IP, PPP
--- Other
-}
-
-Character Sets Supported:
-{
- ANSI X3.4
--- Other Character Sets not supported
--- IBM/Microsoft DBCS
--- JIS C 6226
--- ISO 10646 (ICS-4)
--- ISO 10646 (UCS2)
-}
-
-Special Functionality:
-{
- Maximum APDU size in octets: 50
--- Maximum APDU size in octets: 480
--- Segmented Requests Supported, window size: 1
--- Segmented Responses Supported, window size: 1
--- Router
-}
-
-List of Objects in test device:
-{
- {
- object-identifier: (device,12345)
- object-name: "PIC18F6720 Device"
- object-type: device
- system-status: operational
- vendor-name: "ASHRAE"
- vendor-identifier: 0
- model-name: "GNU Demo"
- firmware-revision: "1.00"
- application-software-version: "1.00"
- location: "USA"
- description: "BACnet Demo"
- protocol-version: 1
- protocol-conformance-class: 1
- protocol-services-supported: (T,F,F,F,F,F,F,F,F,F,F,F,T,F,F,T,F,T,F,F,T,F,F,
-F,F,F,F,F,F,F,F,F,F,F,T,F,F,F,F,F)
- protocol-object-types-supported: (T,F,T,T,F,T,F,F,T,F,F,F,F,F,F,F,F,F,F,F,F,
-F,F,F,F,F,F,F,F,F,F,F)
- max-apdu-length-accepted: 50
- segmentation-supported: no-segmentation
- local-time: ?
- local-date: ?
- utc-offset: ?
- daylight-savings-status: ?
- database-revision: ?
- apdu-timeout: 60000
- number-of-apdu-retries: 0
- max-master: 127
- max-info-frames: 1
- device-address-binding: ?
- object-list: {
- (device,12345),(binary-value,0),(binary-value,1),
- (binary-value,2),(binary-value,3),(binary-value,4),
- (binary-value,5),(binary-value,6),(binary-value,7),
- (analog-value,0),(analog-value,1),(analog-value,2),
- (analog-value,3),(analog-input,0),(analog-input,1),
- (binary-input,0),(binary-input,1),(binary-input,2),
- (binary-input,3)
- }
- },
- {
- object-identifier: (binary-value,0)
- object-name: "BV-0"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BV-0"
- },
- {
- object-identifier: (binary-value,1)
- object-name: "BV-1"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BV-1"
- },
- {
- object-identifier: (binary-value,2)
- object-name: "BV-2"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BV-2"
- },
- {
- object-identifier: (binary-value,3)
- object-name: "BV-3"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BV-3"
- },
- {
- object-identifier: (binary-value,4)
- object-name: "BV-4"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BV-4"
- },
- {
- object-identifier: (binary-value,5)
- object-name: "BV-5"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BV-5"
- },
- {
- object-identifier: (binary-value,6)
- object-name: "BV-6"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BV-6"
- },
- {
- object-identifier: (binary-value,7)
- object-name: "BV-7"
- object-type: binary-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- description: "BV-7"
- },
- {
- object-identifier: (analog-value,0)
- object-name: "AV-0"
- object-type: analog-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "AV-0"
- },
- {
- object-identifier: (analog-value,1)
- object-name: "AV-1"
- object-type: analog-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "AV-1"
- },
- {
- object-identifier: (analog-value,2)
- object-name: "AV-2"
- object-type: analog-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "AV-2"
- },
- {
- object-identifier: (analog-value,3)
- object-name: "AV-3"
- object-type: analog-value
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "AV-3"
- },
- {
- object-identifier: (analog-input,0)
- object-name: "AI-0"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "AI-0"
- },
- {
- object-identifier: (analog-input,1)
- object-name: "AI-1"
- object-type: analog-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- units: percent
- description: "AI-1"
- },
- {
- object-identifier: (binary-input,0)
- object-name: "BI-0"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BI-0"
- },
- {
- object-identifier: (binary-input,1)
- object-name: "BI-1"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BI-1"
- },
- {
- object-identifier: (binary-input,2)
- object-name: "BI-2"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BI-2"
- },
- {
- object-identifier: (binary-input,3)
- object-name: "BI-3"
- object-type: binary-input
- present-value: ?
- status-flags: (F,F,F,F)
- event-state: normal
- out-of-service: F
- polarity: normal
- description: "BI-3"
- }
-}
-
-End of BACnet Protocol Implementation Conformance Statement
+PICS 0
+BACnet Protocol Implementation Conformance Statement
+
+--
+--
+-- BACnet Stack Demo
+-- bacnet.sourceforge.net
+-- Author: Steve Karg
+--
+--
+Vendor Name: "ASHRAE"
+Product Name: "PIC18F6720 Device"
+Product Model Number: "GNU Demo"
+Product Description: "BACnet Demo"
+
+BIBBs Supported:
+{
+-- The BIBBs may be any of:
+-- DS-RP-A
+ DS-RP-B
+-- DS-RPM-A DS-RPM-B
+-- DS-RPC-A DS-RPC-B
+-- DS-WP-A
+ DS-WP-B
+-- DS-WPM-A DS-WPM-B
+-- DS-COV-A DS-COV-B
+-- DS-COVP-A DS-COVP-B
+-- DS-COVU-A DS-COVU-B
+-- AE-N-A AE-N-I-B AE-N-E-B
+-- AE-ACK-A AE-ACK-B
+-- AE-ASUM-A AE-ASUM-B
+-- AE-ESUM-A AE-ESUM-B
+-- AE-INFO-A AE-INFO-B
+-- AE-LS-A AE-LS-B
+-- SCHED-A SCHED-I-B SCHED-E-B
+-- T-VMT-A T-VMT-I-B T-VMT-E-B
+-- T-ATR-A T-ATR-B
+-- DM-DDB-A
+ DM-DDB-B
+-- DM-DOB-A
+-- DM-DOB-B
+-- DM-DCC-A
+ DM-DCC-B
+-- DM-PT-A DM-PT-B
+-- DM-TM-A DM-TM-B
+-- DM-TS-A
+-- DM-TS-B
+-- DM-UTC-A
+-- DM-UTC-B
+-- DM-RD-A
+ DM-RD-B
+-- DM-BR-A DM-BR-B
+-- DM-R-A DM-R-B
+-- DM-LM-A DM-LM-B
+-- DM-OCD-A DM-OCD-B
+-- DM-VT-A DM-VT-B
+-- NM-CE-A NM-CE-B
+-- NM-RC-A NM-RC-B
+}
+
+BACnet Standard Application Services Supported:
+{
+-- AcknowledgeAlarm Initiate Execute
+-- ConfirmedCOVNotification Initiate Execute
+-- UnconfirmedCOVNotification Initiate
+-- ConfirmedEventNotification Initiate Execute
+-- UnconfirmedEventNotification Initiate Execute
+-- GetAlarmSummary Initiate Execute
+-- GetEnrollmentSummary Initiate Execute
+-- AtomicReadFile Initiate Execute
+-- AtomicWriteFile Initiate Execute
+-- AddListElement Initiate Execute
+-- RemoveListElement Initiate Execute
+-- CreateObject Initiate Execute
+-- DeleteObject Initiate Execute
+ ReadProperty Execute
+-- ReadpropertyConditional Initiate Execute
+-- ReadPropertyMultiple Initiate Execute
+-- SubscribeCOV Initiate Execute
+ WriteProperty Execute
+-- WritePropertyMultiple Initiate Execute
+ DeviceCommunicationControl Execute
+-- ConfirmedPrivateTransfer Initiate Execute
+-- UnconfirmedPrivateTransfer Initiate Execute
+-- TimeSynchronization Initiate Execute
+-- Who-Has Execute
+-- I-Have Initiate
+ Who-Is Execute
+ I-Am Initiate
+-- VT-Open Initiate Execute
+-- VT-Close Initiate Execute
+-- VT-Data Initiate Execute
+-- ConfirmedTextMessage Initiate Execute
+-- UnconfirmedTextMessage Initiate Execute
+ ReinitializeDevice Execute
+-- RequestKey Initiate Execute
+-- Authenticate Initiate Execute
+-- UTCTimeSynchronization Initiate Execute
+-- ReadRange Initiate Execute
+-- GetEventInformation Initiate Execute
+-- LifeSafetyOperation Initiate Execute
+-- SubscribeCOVProperty Initiate Execute
+-- RequestKey Initiate Execute
+-- Authenticate Initiate Execute
+}
+
+Standard Object-Types Supported:
+{
+ Analog Input
+-- Analog Output
+ Analog Value
+-- Averaging Createable Deleteable
+ Binary Input
+-- Binary Output
+ Binary Value
+-- Calendar Createable Deleteable
+-- Command Createable Deleteable
+ Device
+-- Event Enrollment Createable Deleteable
+-- File
+-- Group Createable Deleteable
+-- Loop Createable Deleteable
+-- Multi-state Input Createable Deleteable
+-- Multi-state Output
+-- Multi-state Value Createable Deleteable
+-- Notification Class Createable Deleteable
+-- Program Createable Deleteable
+-- Schedule Createable Deleteable
+-- Life Safety Point
+-- Life Safety Zone Createable Deleteable
+-- Trend Log Createable Deleteable
+-- Load Control
+}
+
+Data Link Layer Option:
+{
+-- ISO 8802-3, 10BASE5
+-- ISO 8802-3, 10BASE2
+-- ISO 8802-3, 10BASET
+-- ISO 8802-3, Fiber
+-- ARCNET, coax star
+-- ARCNET, coax bus
+-- ARCNET, twisted pair star
+-- ARCNET, twisted pair bus
+-- ARCNET, fiber star
+MS/TP master. Baud rate(s): 9600, 19200, 38400, 76800
+-- MS/TP slave. Baud rate(s): 9600
+-- Point-To-Point. Modem, Baud rate(s): 14.4k
+-- Point-To-Point. Modem, Autobaud range: 9600 to 28.8k
+-- BACnet/IP, 'DIX' Ethernet
+-- BACnet/IP, PPP
+-- Other
+}
+
+Character Sets Supported:
+{
+ ANSI X3.4
+-- Other Character Sets not supported
+-- IBM/Microsoft DBCS
+-- JIS C 6226
+-- ISO 10646 (ICS-4)
+-- ISO 10646 (UCS2)
+}
+
+Special Functionality:
+{
+ Maximum APDU size in octets: 50
+-- Maximum APDU size in octets: 480
+-- Segmented Requests Supported, window size: 1
+-- Segmented Responses Supported, window size: 1
+-- Router
+}
+
+List of Objects in test device:
+{
+ {
+ object-identifier: (device,12345)
+ object-name: "PIC18F6720 Device"
+ object-type: device
+ system-status: operational
+ vendor-name: "ASHRAE"
+ vendor-identifier: 0
+ model-name: "GNU Demo"
+ firmware-revision: "1.00"
+ application-software-version: "1.00"
+ location: "USA"
+ description: "BACnet Demo"
+ protocol-version: 1
+ protocol-conformance-class: 1
+ protocol-services-supported: (T,F,F,F,F,F,F,F,F,F,F,F,T,F,F,T,F,T,F,F,T,F,F,
+F,F,F,F,F,F,F,F,F,F,F,T,F,F,F,F,F)
+ protocol-object-types-supported: (T,F,T,T,F,T,F,F,T,F,F,F,F,F,F,F,F,F,F,F,F,
+F,F,F,F,F,F,F,F,F,F,F)
+ max-apdu-length-accepted: 50
+ segmentation-supported: no-segmentation
+ local-time: ?
+ local-date: ?
+ utc-offset: ?
+ daylight-savings-status: ?
+ database-revision: ?
+ apdu-timeout: 60000
+ number-of-apdu-retries: 0
+ max-master: 127
+ max-info-frames: 1
+ device-address-binding: ?
+ object-list: {
+ (device,12345),(binary-value,0),(binary-value,1),
+ (binary-value,2),(binary-value,3),(binary-value,4),
+ (binary-value,5),(binary-value,6),(binary-value,7),
+ (analog-value,0),(analog-value,1),(analog-value,2),
+ (analog-value,3),(analog-input,0),(analog-input,1),
+ (binary-input,0),(binary-input,1),(binary-input,2),
+ (binary-input,3)
+ }
+ },
+ {
+ object-identifier: (binary-value,0)
+ object-name: "BV-0"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BV-0"
+ },
+ {
+ object-identifier: (binary-value,1)
+ object-name: "BV-1"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BV-1"
+ },
+ {
+ object-identifier: (binary-value,2)
+ object-name: "BV-2"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BV-2"
+ },
+ {
+ object-identifier: (binary-value,3)
+ object-name: "BV-3"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BV-3"
+ },
+ {
+ object-identifier: (binary-value,4)
+ object-name: "BV-4"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BV-4"
+ },
+ {
+ object-identifier: (binary-value,5)
+ object-name: "BV-5"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BV-5"
+ },
+ {
+ object-identifier: (binary-value,6)
+ object-name: "BV-6"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BV-6"
+ },
+ {
+ object-identifier: (binary-value,7)
+ object-name: "BV-7"
+ object-type: binary-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ description: "BV-7"
+ },
+ {
+ object-identifier: (analog-value,0)
+ object-name: "AV-0"
+ object-type: analog-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "AV-0"
+ },
+ {
+ object-identifier: (analog-value,1)
+ object-name: "AV-1"
+ object-type: analog-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "AV-1"
+ },
+ {
+ object-identifier: (analog-value,2)
+ object-name: "AV-2"
+ object-type: analog-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "AV-2"
+ },
+ {
+ object-identifier: (analog-value,3)
+ object-name: "AV-3"
+ object-type: analog-value
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "AV-3"
+ },
+ {
+ object-identifier: (analog-input,0)
+ object-name: "AI-0"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "AI-0"
+ },
+ {
+ object-identifier: (analog-input,1)
+ object-name: "AI-1"
+ object-type: analog-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ units: percent
+ description: "AI-1"
+ },
+ {
+ object-identifier: (binary-input,0)
+ object-name: "BI-0"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BI-0"
+ },
+ {
+ object-identifier: (binary-input,1)
+ object-name: "BI-1"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BI-1"
+ },
+ {
+ object-identifier: (binary-input,2)
+ object-name: "BI-2"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BI-2"
+ },
+ {
+ object-identifier: (binary-input,3)
+ object-name: "BI-3"
+ object-type: binary-input
+ present-value: ?
+ status-flags: (F,F,F,F)
+ event-state: normal
+ out-of-service: F
+ polarity: normal
+ description: "BI-3"
+ }
+}
+
+End of BACnet Protocol Implementation Conformance Statement
diff --git a/bacnet-stack/ports/pic18f6720/readme.txt b/bacnet-stack/ports/pic18f6720/readme.txt
index 8692000e..c5095c69 100644
--- a/bacnet-stack/ports/pic18f6720/readme.txt
+++ b/bacnet-stack/ports/pic18f6720/readme.txt
@@ -1,44 +1,44 @@
-BACnet Stack - SourceForge.net
-Build for MPLAB IDE
-
-These are some settings that are important when building
-the BACnet Stack using MPLAB IDE and MCC18 Compiler,
-
-1. Add the files to the project that you need:
-abort.c, apdu.c, bacapp.c, bacdcode.c, bacerror.c,
-bacstr.c, crc.c, datetime.c, dcc.c, iam.c,
-npdu.c, rd.c, reject.c, rp.c, whois.c, wp.c
-
-From ports/picxx: isr.c, main.c, rs485.c, mstp.c, dlmstp.c
-
-From demo/object/: device.c or dev_tiny.c
-objects as needed: ai.c, ao.c, etc.
-
-From demo/handler/: txbuf.c, h_dcc.c, h_rd.c, h_rp.c or h_rp_tiny.c
-Additional handlers as needed: h_wp.c
-
-2. Project->Options->Project
-
-General Tab: Include Path:
-C:\code\bacnet-stack\;C:\code\bacnet-stack\demo\handler\;C:\code\bacnet-stack\demo\object\;C:\code\bacnet-stack\ports\pic18f6720\
-
-MPLAB C18 Tab: Memory Model:
-Code: Large Code Model
-Data: Large Data Model
-Stack: Multi-bank Model
-
-MPLAB C18 Tab: General: Macro Definitions:
-PRINT_ENABLED=0
-BACDL_MSTP=1
-TSM_ENABLED=0
-BIG_ENDIAN=0
-
-3. The linker script must reserve some extra stack space.
-
-//DATABANK NAME=gpr12 START=0xC00 END=0xCFF
-//DATABANK NAME=gpr13 START=0xD00 END=0xDFF
-DATABANK NAME=stackreg START=0xC00 END=0xDFF PROTECTED
-
-//STACK SIZE=0x100 RAM=gpr13
-STACK SIZE=0x200 RAM=stackreg
-
+BACnet Stack - SourceForge.net
+Build for MPLAB IDE
+
+These are some settings that are important when building
+the BACnet Stack using MPLAB IDE and MCC18 Compiler,
+
+1. Add the files to the project that you need:
+abort.c, apdu.c, bacapp.c, bacdcode.c, bacerror.c,
+bacstr.c, crc.c, datetime.c, dcc.c, iam.c,
+npdu.c, rd.c, reject.c, rp.c, whois.c, wp.c
+
+From ports/picxx: isr.c, main.c, rs485.c, mstp.c, dlmstp.c
+
+From demo/object/: device.c or dev_tiny.c
+objects as needed: ai.c, ao.c, etc.
+
+From demo/handler/: txbuf.c, h_dcc.c, h_rd.c, h_rp.c or h_rp_tiny.c
+Additional handlers as needed: h_wp.c
+
+2. Project->Options->Project
+
+General Tab: Include Path:
+C:\code\bacnet-stack\;C:\code\bacnet-stack\demo\handler\;C:\code\bacnet-stack\demo\object\;C:\code\bacnet-stack\ports\pic18f6720\
+
+MPLAB C18 Tab: Memory Model:
+Code: Large Code Model
+Data: Large Data Model
+Stack: Multi-bank Model
+
+MPLAB C18 Tab: General: Macro Definitions:
+PRINT_ENABLED=0
+BACDL_MSTP=1
+TSM_ENABLED=0
+BIG_ENDIAN=0
+
+3. The linker script must reserve some extra stack space.
+
+//DATABANK NAME=gpr12 START=0xC00 END=0xCFF
+//DATABANK NAME=gpr13 START=0xD00 END=0xDFF
+DATABANK NAME=stackreg START=0xC00 END=0xDFF PROTECTED
+
+//STACK SIZE=0x100 RAM=gpr13
+STACK SIZE=0x200 RAM=stackreg
+
diff --git a/bacnet-stack/ports/rtos32/dlmstp.c b/bacnet-stack/ports/rtos32/dlmstp.c
index 8775972e..7dcec4a1 100644
--- a/bacnet-stack/ports/rtos32/dlmstp.c
+++ b/bacnet-stack/ports/rtos32/dlmstp.c
@@ -43,7 +43,7 @@ static uint8_t PDU_Buffer[MAX_MPDU];
static volatile struct mstp_port_struct_t MSTP_Port;
void dlmstp_init(char *ifname)
-{
+{
(void)ifname;
/* initialize buffer */
Receive_Buffer.ready = false;
diff --git a/bacnet-stack/ports/win32/MAKEFILE.MAK b/bacnet-stack/ports/win32/MAKEFILE.MAK
index 06287917..cd82b241 100644
--- a/bacnet-stack/ports/win32/MAKEFILE.MAK
+++ b/bacnet-stack/ports/win32/MAKEFILE.MAK
@@ -1,151 +1,151 @@
-#
-# Simple makefile to build an RTB executable for RTOS-32
-#
-# This makefile assumes Borland bcc32 development environment
-# on Windows NT/9x/2000/XP
-#
-
-!ifndef BORLAND_DIR
-BORLAND_DIR_Not_Defined:
- @echo .
- @echo You must define environment variable BORLAND_DIR to compile.
-!endif
-
-PRODUCT = bacnet
-PRODUCT_EXE = $(PRODUCT).exe
-
-# Choose the Data Link Layer to Enable
-DEFINES = -DBACDL_BIP=1;TSM_ENABLED=1;BIG_ENDIAN=0
-
-SRCS = main.c bip-init.c \
- ..\..\bip.c \
- ..\..\demo\handler\h_iam.c \
- ..\..\demo\handler\h_whois.c \
- ..\..\demo\handler\h_wp.c \
- ..\..\demo\handler\h_rp.c \
- ..\..\demo\handler\h_rp_a.c \
- ..\..\demo\handler\noserv.c \
- ..\..\demo\handler\txbuf.c \
- ..\..\demo\handler\s_rp.c \
- ..\..\demo\handler\s_whois.c \
- ..\..\bacdcode.c \
- ..\..\bacapp.c \
- ..\..\bacstr.c \
- ..\..\bactext.c \
- ..\..\indtext.c \
- ..\..\bigend.c \
- ..\..\whois.c \
- ..\..\iam.c \
- ..\..\dcc.c \
- ..\..\rp.c \
- ..\..\wp.c \
- ..\..\arf.c \
- ..\..\awf.c \
- ..\..\demo\object\bacfile.c \
- ..\..\demo\object\device.c \
- ..\..\demo\object\ai.c \
- ..\..\demo\object\ao.c \
- ..\..\demo\object\av.c \
- ..\..\demo\object\bi.c \
- ..\..\demo\object\bo.c \
- ..\..\demo\object\bv.c \
- ..\..\demo\object\lsp.c \
- ..\..\demo\object\mso.c \
- ..\..\datalink.c \
- ..\..\tsm.c \
- ..\..\address.c \
- ..\..\abort.c \
- ..\..\reject.c \
- ..\..\bacerror.c \
- ..\..\apdu.c \
- ..\..\npdu.c
-
-OBJS = $(SRCS:.c=.obj)
-
-# Compiler definitions
-#
-BCC_CFG = bcc32.cfg
-CC = $(BORLAND_DIR)\bin\bcc32 +$(BCC_CFG)
-#LINK = $(BORLAND_DIR)\bin\tlink32
-LINK = $(BORLAND_DIR)\bin\ilink32
-TLIB = $(BORLAND_DIR)\bin\tlib
-
-#
-# Include directories
-#
-CC_DIR = $(BORLAND_DIR)\BIN
-INCL_DIRS = -I$(BORLAND_DIR)\include;..\..\;..\..\demo\handler\;..\..\demo\object\;.
-
-CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
-
-# Libraries
-#
-C_LIB_DIR = $(BORLAND_DIR)\lib
-
-LIBS = $(C_LIB_DIR)\IMPORT32.lib \
-$(C_LIB_DIR)\CW32MT.lib
-
-#
-# Main target
-#
-# This should be the first one in the makefile
-
-all : $(BCC_CFG) $(PRODUCT_EXE)
-
-# Linker specific: the link below is for BCC linker/compiler. If you link
-# with a different linker - please change accordingly.
-#
-
-# need a temp response file (@&&) because command line is too long
-$(PRODUCT_EXE) : $(OBJS)
- @echo Running Linker for $(PRODUCT_EXE)
- $(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with |
- $(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
- $<
- $*.map
- $(LIBS)
-| # end of temp response file
-
-#
-# Utilities
-
-clean :
- @echo Deleting obj files, $(PRODUCT_EXE) and map files.
- del *.obj
- del ..\..\*.obj
- del ..\..\demo\handler\*.obj
- del ..\..\demo\object\*.obj
- del $(PRODUCT_EXE)
- del *.map
- del $(BCC_CFG)
-
-#
-# Generic rules
-#
-.SUFFIXES: .cpp .c .sbr .obj
-
-#
-# cc generic rule
-#
-.c.obj:
- $(CC) -o$@ $<
-
-# Compiler configuration file
-$(BCC_CFG) :
- Copy &&|
-$(CFLAGS)
--c
--y #include line numbers in OBJ's
--v #include debug info
--w+ #turn on all warnings
--Od #disable all optimizations
-#-a4 #32 bit data alignment
-#-M # generate link map
-#-ls # linker options
-#-WM- #not multithread
--WM #multithread
--w-aus # ignore warning assigned a value that is never used
--w-sig # ignore warning conversion may lose sig digits
-| $@
-
-# EOF: makefile
+#
+# Simple makefile to build an RTB executable for RTOS-32
+#
+# This makefile assumes Borland bcc32 development environment
+# on Windows NT/9x/2000/XP
+#
+
+!ifndef BORLAND_DIR
+BORLAND_DIR_Not_Defined:
+ @echo .
+ @echo You must define environment variable BORLAND_DIR to compile.
+!endif
+
+PRODUCT = bacnet
+PRODUCT_EXE = $(PRODUCT).exe
+
+# Choose the Data Link Layer to Enable
+DEFINES = -DBACDL_BIP=1;TSM_ENABLED=1;BIG_ENDIAN=0
+
+SRCS = main.c bip-init.c \
+ ..\..\bip.c \
+ ..\..\demo\handler\h_iam.c \
+ ..\..\demo\handler\h_whois.c \
+ ..\..\demo\handler\h_wp.c \
+ ..\..\demo\handler\h_rp.c \
+ ..\..\demo\handler\h_rp_a.c \
+ ..\..\demo\handler\noserv.c \
+ ..\..\demo\handler\txbuf.c \
+ ..\..\demo\handler\s_rp.c \
+ ..\..\demo\handler\s_whois.c \
+ ..\..\bacdcode.c \
+ ..\..\bacapp.c \
+ ..\..\bacstr.c \
+ ..\..\bactext.c \
+ ..\..\indtext.c \
+ ..\..\bigend.c \
+ ..\..\whois.c \
+ ..\..\iam.c \
+ ..\..\dcc.c \
+ ..\..\rp.c \
+ ..\..\wp.c \
+ ..\..\arf.c \
+ ..\..\awf.c \
+ ..\..\demo\object\bacfile.c \
+ ..\..\demo\object\device.c \
+ ..\..\demo\object\ai.c \
+ ..\..\demo\object\ao.c \
+ ..\..\demo\object\av.c \
+ ..\..\demo\object\bi.c \
+ ..\..\demo\object\bo.c \
+ ..\..\demo\object\bv.c \
+ ..\..\demo\object\lsp.c \
+ ..\..\demo\object\mso.c \
+ ..\..\datalink.c \
+ ..\..\tsm.c \
+ ..\..\address.c \
+ ..\..\abort.c \
+ ..\..\reject.c \
+ ..\..\bacerror.c \
+ ..\..\apdu.c \
+ ..\..\npdu.c
+
+OBJS = $(SRCS:.c=.obj)
+
+# Compiler definitions
+#
+BCC_CFG = bcc32.cfg
+CC = $(BORLAND_DIR)\bin\bcc32 +$(BCC_CFG)
+#LINK = $(BORLAND_DIR)\bin\tlink32
+LINK = $(BORLAND_DIR)\bin\ilink32
+TLIB = $(BORLAND_DIR)\bin\tlib
+
+#
+# Include directories
+#
+CC_DIR = $(BORLAND_DIR)\BIN
+INCL_DIRS = -I$(BORLAND_DIR)\include;..\..\;..\..\demo\handler\;..\..\demo\object\;.
+
+CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
+
+# Libraries
+#
+C_LIB_DIR = $(BORLAND_DIR)\lib
+
+LIBS = $(C_LIB_DIR)\IMPORT32.lib \
+$(C_LIB_DIR)\CW32MT.lib
+
+#
+# Main target
+#
+# This should be the first one in the makefile
+
+all : $(BCC_CFG) $(PRODUCT_EXE)
+
+# Linker specific: the link below is for BCC linker/compiler. If you link
+# with a different linker - please change accordingly.
+#
+
+# need a temp response file (@&&) because command line is too long
+$(PRODUCT_EXE) : $(OBJS)
+ @echo Running Linker for $(PRODUCT_EXE)
+ $(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with |
+ $(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
+ $<
+ $*.map
+ $(LIBS)
+| # end of temp response file
+
+#
+# Utilities
+
+clean :
+ @echo Deleting obj files, $(PRODUCT_EXE) and map files.
+ del *.obj
+ del ..\..\*.obj
+ del ..\..\demo\handler\*.obj
+ del ..\..\demo\object\*.obj
+ del $(PRODUCT_EXE)
+ del *.map
+ del $(BCC_CFG)
+
+#
+# Generic rules
+#
+.SUFFIXES: .cpp .c .sbr .obj
+
+#
+# cc generic rule
+#
+.c.obj:
+ $(CC) -o$@ $<
+
+# Compiler configuration file
+$(BCC_CFG) :
+ Copy &&|
+$(CFLAGS)
+-c
+-y #include line numbers in OBJ's
+-v #include debug info
+-w+ #turn on all warnings
+-Od #disable all optimizations
+#-a4 #32 bit data alignment
+#-M # generate link map
+#-ls # linker options
+#-WM- #not multithread
+-WM #multithread
+-w-aus # ignore warning assigned a value that is never used
+-w-sig # ignore warning conversion may lose sig digits
+| $@
+
+# EOF: makefile
diff --git a/bacnet-stack/ports/win32/bacnet/bacnet.plg b/bacnet-stack/ports/win32/bacnet/bacnet.plg
index 15a85f48..378e0134 100644
--- a/bacnet-stack/ports/win32/bacnet/bacnet.plg
+++ b/bacnet-stack/ports/win32/bacnet/bacnet.plg
@@ -1,232 +1,232 @@
-
-
-
-Build Log
-
---------------------Configuration: bacnet - Win32 Debug--------------------
-
-Command Lines
-Creating temporary file "C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP632.tmp" with contents
-[
-/nologo /MLd /W3 /Gm /GX /ZI /Od /I "..\..\.." /I ".." /I "..\..\..\demo\object\\" /I "..\..\..\demo\handler\\" /D "_DEBUG" /D BACDL_BIP=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D TSM_ENABLED=1 /D PRINT_ENABLED=1 /D BIG_ENDIAN=0 /D USE_INADDR=0 /FR"Debug/" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
-"C:\code\bacnet-stack\abort.c"
-"C:\code\bacnet-stack\address.c"
-"C:\code\bacnet-stack\demo\object\ai.c"
-"C:\code\bacnet-stack\demo\object\ao.c"
-"C:\code\bacnet-stack\apdu.c"
-"C:\code\bacnet-stack\arf.c"
-"C:\code\bacnet-stack\demo\object\av.c"
-"C:\code\bacnet-stack\bacapp.c"
-"C:\code\bacnet-stack\bacdcode.c"
-"C:\code\bacnet-stack\bacerror.c"
-"C:\code\bacnet-stack\demo\object\bacfile.c"
-"C:\code\bacnet-stack\bacstr.c"
-"C:\code\bacnet-stack\bactext.c"
-"C:\code\bacnet-stack\demo\object\bi.c"
-"C:\code\bacnet-stack\bigend.c"
-"C:\code\bacnet-stack\ports\win32\bip-init.c"
-"C:\code\bacnet-stack\bip.c"
-"C:\code\bacnet-stack\demo\object\bo.c"
-"C:\code\bacnet-stack\demo\object\bv.c"
-"C:\code\bacnet-stack\crc.c"
-"C:\code\bacnet-stack\datetime.c"
-"C:\code\bacnet-stack\dcc.c"
-"C:\code\bacnet-stack\demo\object\device.c"
-"C:\code\bacnet-stack\demo\handler\h_arf.c"
-"C:\code\bacnet-stack\demo\handler\h_arf_a.c"
-"C:\code\bacnet-stack\demo\handler\h_iam.c"
-"C:\code\bacnet-stack\demo\handler\h_rp.c"
-"C:\code\bacnet-stack\demo\handler\h_rp_a.c"
-"C:\code\bacnet-stack\demo\handler\h_whois.c"
-"C:\code\bacnet-stack\demo\handler\h_wp.c"
-"C:\code\bacnet-stack\iam.c"
-"C:\code\bacnet-stack\indtext.c"
-"C:\code\bacnet-stack\demo\object\lc.c"
-"C:\code\bacnet-stack\demo\object\lsp.c"
-"C:\code\bacnet-stack\ports\win32\main.c"
-"C:\code\bacnet-stack\demo\object\mso.c"
-"C:\code\bacnet-stack\demo\handler\noserv.c"
-"C:\code\bacnet-stack\npdu.c"
-"C:\code\bacnet-stack\reject.c"
-"C:\code\bacnet-stack\ringbuf.c"
-"C:\code\bacnet-stack\rp.c"
-"C:\code\bacnet-stack\demo\handler\s_rp.c"
-"C:\code\bacnet-stack\demo\handler\s_whois.c"
-"C:\code\bacnet-stack\demo\handler\s_wp.c"
-"C:\code\bacnet-stack\tsm.c"
-"C:\code\bacnet-stack\demo\handler\txbuf.c"
-"C:\code\bacnet-stack\whois.c"
-"C:\code\bacnet-stack\wp.c"
-]
-Creating command line "cl.exe @C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP632.tmp"
-Creating temporary file "C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP633.tmp" with contents
-[
-kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/bacnet.pdb" /debug /machine:I386 /out:"Debug/bacnet.exe" /pdbtype:sept
-".\Debug\abort.obj"
-".\Debug\address.obj"
-".\Debug\ai.obj"
-".\Debug\ao.obj"
-".\Debug\apdu.obj"
-".\Debug\arf.obj"
-".\Debug\av.obj"
-".\Debug\bacapp.obj"
-".\Debug\bacdcode.obj"
-".\Debug\bacerror.obj"
-".\Debug\bacfile.obj"
-".\Debug\bacstr.obj"
-".\Debug\bactext.obj"
-".\Debug\bi.obj"
-".\Debug\bigend.obj"
-".\Debug\bip-init.obj"
-".\Debug\bip.obj"
-".\Debug\bo.obj"
-".\Debug\bv.obj"
-".\Debug\crc.obj"
-".\Debug\datetime.obj"
-".\Debug\dcc.obj"
-".\Debug\device.obj"
-".\Debug\h_arf.obj"
-".\Debug\h_arf_a.obj"
-".\Debug\h_iam.obj"
-".\Debug\h_rp.obj"
-".\Debug\h_rp_a.obj"
-".\Debug\h_whois.obj"
-".\Debug\h_wp.obj"
-".\Debug\iam.obj"
-".\Debug\indtext.obj"
-".\Debug\lc.obj"
-".\Debug\lsp.obj"
-".\Debug\main.obj"
-".\Debug\mso.obj"
-".\Debug\noserv.obj"
-".\Debug\npdu.obj"
-".\Debug\reject.obj"
-".\Debug\ringbuf.obj"
-".\Debug\rp.obj"
-".\Debug\s_rp.obj"
-".\Debug\s_whois.obj"
-".\Debug\s_wp.obj"
-".\Debug\tsm.obj"
-".\Debug\txbuf.obj"
-".\Debug\whois.obj"
-".\Debug\wp.obj"
-]
-Creating command line "link.exe @C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP633.tmp"
-Output Window
-Compiling...
-abort.c
-address.c
-ai.c
-ao.c
-apdu.c
-arf.c
-av.c
-bacapp.c
-bacdcode.c
-bacerror.c
-bacfile.c
-bacstr.c
-bactext.c
-bi.c
-bigend.c
-bip-init.c
-bip.c
-bo.c
-bv.c
-crc.c
-Generating Code...
-Compiling...
-datetime.c
-dcc.c
-device.c
-h_arf.c
-h_arf_a.c
-h_iam.c
-h_rp.c
-h_rp_a.c
-h_whois.c
-h_wp.c
-iam.c
-indtext.c
-lc.c
-lsp.c
-main.c
-mso.c
-noserv.c
-npdu.c
-reject.c
-ringbuf.c
-Generating Code...
-Compiling...
-rp.c
-s_rp.c
-s_whois.c
-s_wp.c
-tsm.c
-txbuf.c
-whois.c
-wp.c
-Generating Code...
-Linking...
-Creating temporary file "C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP635.tmp" with contents
-[
-/nologo /o"Debug/bacnet.bsc"
-".\Debug\abort.sbr"
-".\Debug\address.sbr"
-".\Debug\ai.sbr"
-".\Debug\ao.sbr"
-".\Debug\apdu.sbr"
-".\Debug\arf.sbr"
-".\Debug\av.sbr"
-".\Debug\bacapp.sbr"
-".\Debug\bacdcode.sbr"
-".\Debug\bacerror.sbr"
-".\Debug\bacfile.sbr"
-".\Debug\bacstr.sbr"
-".\Debug\bactext.sbr"
-".\Debug\bi.sbr"
-".\Debug\bigend.sbr"
-".\Debug\bip-init.sbr"
-".\Debug\bip.sbr"
-".\Debug\bo.sbr"
-".\Debug\bv.sbr"
-".\Debug\crc.sbr"
-".\Debug\datetime.sbr"
-".\Debug\dcc.sbr"
-".\Debug\device.sbr"
-".\Debug\h_arf.sbr"
-".\Debug\h_arf_a.sbr"
-".\Debug\h_iam.sbr"
-".\Debug\h_rp.sbr"
-".\Debug\h_rp_a.sbr"
-".\Debug\h_whois.sbr"
-".\Debug\h_wp.sbr"
-".\Debug\iam.sbr"
-".\Debug\indtext.sbr"
-".\Debug\lc.sbr"
-".\Debug\lsp.sbr"
-".\Debug\main.sbr"
-".\Debug\mso.sbr"
-".\Debug\noserv.sbr"
-".\Debug\npdu.sbr"
-".\Debug\reject.sbr"
-".\Debug\ringbuf.sbr"
-".\Debug\rp.sbr"
-".\Debug\s_rp.sbr"
-".\Debug\s_whois.sbr"
-".\Debug\s_wp.sbr"
-".\Debug\tsm.sbr"
-".\Debug\txbuf.sbr"
-".\Debug\whois.sbr"
-".\Debug\wp.sbr"]
-Creating command line "bscmake.exe @C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP635.tmp"
-Creating browse info file...
-Output Window
-
-
-
-Results
-bacnet.exe - 0 error(s), 0 warning(s)
-
-
-
+
+
+
+Build Log
+
+--------------------Configuration: bacnet - Win32 Debug--------------------
+
+Command Lines
+Creating temporary file "C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP632.tmp" with contents
+[
+/nologo /MLd /W3 /Gm /GX /ZI /Od /I "..\..\.." /I ".." /I "..\..\..\demo\object\\" /I "..\..\..\demo\handler\\" /D "_DEBUG" /D BACDL_BIP=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D TSM_ENABLED=1 /D PRINT_ENABLED=1 /D BIG_ENDIAN=0 /D USE_INADDR=0 /FR"Debug/" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
+"C:\code\bacnet-stack\abort.c"
+"C:\code\bacnet-stack\address.c"
+"C:\code\bacnet-stack\demo\object\ai.c"
+"C:\code\bacnet-stack\demo\object\ao.c"
+"C:\code\bacnet-stack\apdu.c"
+"C:\code\bacnet-stack\arf.c"
+"C:\code\bacnet-stack\demo\object\av.c"
+"C:\code\bacnet-stack\bacapp.c"
+"C:\code\bacnet-stack\bacdcode.c"
+"C:\code\bacnet-stack\bacerror.c"
+"C:\code\bacnet-stack\demo\object\bacfile.c"
+"C:\code\bacnet-stack\bacstr.c"
+"C:\code\bacnet-stack\bactext.c"
+"C:\code\bacnet-stack\demo\object\bi.c"
+"C:\code\bacnet-stack\bigend.c"
+"C:\code\bacnet-stack\ports\win32\bip-init.c"
+"C:\code\bacnet-stack\bip.c"
+"C:\code\bacnet-stack\demo\object\bo.c"
+"C:\code\bacnet-stack\demo\object\bv.c"
+"C:\code\bacnet-stack\crc.c"
+"C:\code\bacnet-stack\datetime.c"
+"C:\code\bacnet-stack\dcc.c"
+"C:\code\bacnet-stack\demo\object\device.c"
+"C:\code\bacnet-stack\demo\handler\h_arf.c"
+"C:\code\bacnet-stack\demo\handler\h_arf_a.c"
+"C:\code\bacnet-stack\demo\handler\h_iam.c"
+"C:\code\bacnet-stack\demo\handler\h_rp.c"
+"C:\code\bacnet-stack\demo\handler\h_rp_a.c"
+"C:\code\bacnet-stack\demo\handler\h_whois.c"
+"C:\code\bacnet-stack\demo\handler\h_wp.c"
+"C:\code\bacnet-stack\iam.c"
+"C:\code\bacnet-stack\indtext.c"
+"C:\code\bacnet-stack\demo\object\lc.c"
+"C:\code\bacnet-stack\demo\object\lsp.c"
+"C:\code\bacnet-stack\ports\win32\main.c"
+"C:\code\bacnet-stack\demo\object\mso.c"
+"C:\code\bacnet-stack\demo\handler\noserv.c"
+"C:\code\bacnet-stack\npdu.c"
+"C:\code\bacnet-stack\reject.c"
+"C:\code\bacnet-stack\ringbuf.c"
+"C:\code\bacnet-stack\rp.c"
+"C:\code\bacnet-stack\demo\handler\s_rp.c"
+"C:\code\bacnet-stack\demo\handler\s_whois.c"
+"C:\code\bacnet-stack\demo\handler\s_wp.c"
+"C:\code\bacnet-stack\tsm.c"
+"C:\code\bacnet-stack\demo\handler\txbuf.c"
+"C:\code\bacnet-stack\whois.c"
+"C:\code\bacnet-stack\wp.c"
+]
+Creating command line "cl.exe @C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP632.tmp"
+Creating temporary file "C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP633.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/bacnet.pdb" /debug /machine:I386 /out:"Debug/bacnet.exe" /pdbtype:sept
+".\Debug\abort.obj"
+".\Debug\address.obj"
+".\Debug\ai.obj"
+".\Debug\ao.obj"
+".\Debug\apdu.obj"
+".\Debug\arf.obj"
+".\Debug\av.obj"
+".\Debug\bacapp.obj"
+".\Debug\bacdcode.obj"
+".\Debug\bacerror.obj"
+".\Debug\bacfile.obj"
+".\Debug\bacstr.obj"
+".\Debug\bactext.obj"
+".\Debug\bi.obj"
+".\Debug\bigend.obj"
+".\Debug\bip-init.obj"
+".\Debug\bip.obj"
+".\Debug\bo.obj"
+".\Debug\bv.obj"
+".\Debug\crc.obj"
+".\Debug\datetime.obj"
+".\Debug\dcc.obj"
+".\Debug\device.obj"
+".\Debug\h_arf.obj"
+".\Debug\h_arf_a.obj"
+".\Debug\h_iam.obj"
+".\Debug\h_rp.obj"
+".\Debug\h_rp_a.obj"
+".\Debug\h_whois.obj"
+".\Debug\h_wp.obj"
+".\Debug\iam.obj"
+".\Debug\indtext.obj"
+".\Debug\lc.obj"
+".\Debug\lsp.obj"
+".\Debug\main.obj"
+".\Debug\mso.obj"
+".\Debug\noserv.obj"
+".\Debug\npdu.obj"
+".\Debug\reject.obj"
+".\Debug\ringbuf.obj"
+".\Debug\rp.obj"
+".\Debug\s_rp.obj"
+".\Debug\s_whois.obj"
+".\Debug\s_wp.obj"
+".\Debug\tsm.obj"
+".\Debug\txbuf.obj"
+".\Debug\whois.obj"
+".\Debug\wp.obj"
+]
+Creating command line "link.exe @C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP633.tmp"
+Output Window
+Compiling...
+abort.c
+address.c
+ai.c
+ao.c
+apdu.c
+arf.c
+av.c
+bacapp.c
+bacdcode.c
+bacerror.c
+bacfile.c
+bacstr.c
+bactext.c
+bi.c
+bigend.c
+bip-init.c
+bip.c
+bo.c
+bv.c
+crc.c
+Generating Code...
+Compiling...
+datetime.c
+dcc.c
+device.c
+h_arf.c
+h_arf_a.c
+h_iam.c
+h_rp.c
+h_rp_a.c
+h_whois.c
+h_wp.c
+iam.c
+indtext.c
+lc.c
+lsp.c
+main.c
+mso.c
+noserv.c
+npdu.c
+reject.c
+ringbuf.c
+Generating Code...
+Compiling...
+rp.c
+s_rp.c
+s_whois.c
+s_wp.c
+tsm.c
+txbuf.c
+whois.c
+wp.c
+Generating Code...
+Linking...
+Creating temporary file "C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP635.tmp" with contents
+[
+/nologo /o"Debug/bacnet.bsc"
+".\Debug\abort.sbr"
+".\Debug\address.sbr"
+".\Debug\ai.sbr"
+".\Debug\ao.sbr"
+".\Debug\apdu.sbr"
+".\Debug\arf.sbr"
+".\Debug\av.sbr"
+".\Debug\bacapp.sbr"
+".\Debug\bacdcode.sbr"
+".\Debug\bacerror.sbr"
+".\Debug\bacfile.sbr"
+".\Debug\bacstr.sbr"
+".\Debug\bactext.sbr"
+".\Debug\bi.sbr"
+".\Debug\bigend.sbr"
+".\Debug\bip-init.sbr"
+".\Debug\bip.sbr"
+".\Debug\bo.sbr"
+".\Debug\bv.sbr"
+".\Debug\crc.sbr"
+".\Debug\datetime.sbr"
+".\Debug\dcc.sbr"
+".\Debug\device.sbr"
+".\Debug\h_arf.sbr"
+".\Debug\h_arf_a.sbr"
+".\Debug\h_iam.sbr"
+".\Debug\h_rp.sbr"
+".\Debug\h_rp_a.sbr"
+".\Debug\h_whois.sbr"
+".\Debug\h_wp.sbr"
+".\Debug\iam.sbr"
+".\Debug\indtext.sbr"
+".\Debug\lc.sbr"
+".\Debug\lsp.sbr"
+".\Debug\main.sbr"
+".\Debug\mso.sbr"
+".\Debug\noserv.sbr"
+".\Debug\npdu.sbr"
+".\Debug\reject.sbr"
+".\Debug\ringbuf.sbr"
+".\Debug\rp.sbr"
+".\Debug\s_rp.sbr"
+".\Debug\s_whois.sbr"
+".\Debug\s_wp.sbr"
+".\Debug\tsm.sbr"
+".\Debug\txbuf.sbr"
+".\Debug\whois.sbr"
+".\Debug\wp.sbr"]
+Creating command line "bscmake.exe @C:\DOCUME~1\stk01\LOCALS~1\Temp\RSP635.tmp"
+Creating browse info file...
+Output Window
+
+
+
+Results
+bacnet.exe - 0 error(s), 0 warning(s)
+
+
+
diff --git a/bacnet-stack/ports/win32/bacnet/readme.txt b/bacnet-stack/ports/win32/bacnet/readme.txt
index ef74afff..0f4c86dc 100644
--- a/bacnet-stack/ports/win32/bacnet/readme.txt
+++ b/bacnet-stack/ports/win32/bacnet/readme.txt
@@ -1,113 +1,113 @@
-BACnet Stack - SourceForge.net
-Build for Visual C++ 6.0
-
-When building the BACnet stack using Visual C++ compiler,
-there are some settings that are important.
-
-Q. Are there some global configuration options for this BACnet stack?
-
-A. The BACnet stack uses some preprocessor defines to configure
-a number of subtle personalities.
-PRINT_ENABLED=1 - enables printing to stdio
-BIG_ENDIAN=0 - chooses the BACnet encoding and decoding order
-BACDL_BIP=1 - chooses BACnet/IP for the datalink layer
-BACDL_ETHERNET=0 - chooses BACnet Ethernet for the datalink layer
-BACDL_ARCNET=0 - chooses BACnet ARCNET for the datalink layer
-BACDL_MSTP=0 - chooses BACnet MS/TP for the datalink layer
-USE_INADDR=1 - uses INADDR_BROADCAST for broadcast rather than CLASSx
-TSM_ENABLED=1 - enables the Transaction State Machine for clients
-BIP_DEBUG=1 - enables print statements for debugging
-In Visual C++, add a Preprocessor Definition by:
-1. Select "Project" menu
-2. Select "Settings..."
-3. Select the "C/C++" tab (3rd Tab)
-4. Select the Category: General
-5. You can see the "Preprocessor Definitions:" box
-6. Type OPTION_NAME=1 or OPTION_NAME=0 in that edit box
- using a comma to separate multiple options.
-7. Press OK
-8. Compile the entire project again...
-
-Q. MSVC refuses to open bacnet.dsw and bacnet.dsp.
-
-A. bacnet.dsw and bacnet.dsp are text files that were retrieved
-from CVS on a unix client and are now in unix text file format since
-they end with a "\r\n" rather than "\n". Use the unix2dos commandline
-tool to convert them back to dos:
-unix2dos bacnet.dsw
-unix2dos bacnet.dsp
-
-Q. error LNK2001: unresolved external symbol _WinMain@16
-
-A. The demo ports/win32/main.c was designed as a Win32 Console
-Application. If you want to change it to a Windows GUI application,
-you will have to add all the Windows GUI code, including WinMain().
-I recommend that you use a framework, such as WxWidgets/WxWindows,
-but this has not been done yet.
-
-Q. error C1083: Cannot open include file: 'stdint.h': No such file
-
-A. The BACnet stack uses some header files, and Visual C++ needs to know
-where they are:
-1. Select "Project" menu
-2. Select "Settings..."
-3. Select the "C/C++" tab (3rd Tab)
-4. Select the Category: Preprocessor
-5. You can see the "Additional include directories:" box
-6. Type the path to stdint.h in that edit box (using a comma if necessary)
-7. Type the path to bacdcode.h in that edit box (using a comma if necessary)
-In my system, the paths look like:
-c:\code\bacnet-stack\,c:\code\bacnet-stack\ports\win32\,
-c:\code\bacnet-stack\demo\handler\,c:\code\bacnet-stack\demo\object\
-8. Press OK
-9. Compile the project again...
-
-Q. error C2065: 'MAX_MPDU' : undeclared identifier
-
-A. The BACnet stack uses a preprocessor define to configure
-its datalink layer. In Visual C++, add a Preprocessor Definition by:
-1. Select "Project" menu
-2. Select "Settings..."
-3. Select the "C/C++" tab (3rd Tab)
-4. Select the Category: General
-5. You can see the "Preprocessor Definitions:" box
-6. Type BACDL_BIP=1 in that edit box (using a comma if necessary)
-7. Press OK
-8. Compile the entire project again...
-
-Q. error LNK2001: unresolved external symbol _bacapp_print
-
-A. The BACnet stack uses a preprocessor define to configure
-printing to stdio. In Visual C++, add a Preprocessor Definition by:
-1. Select "Project" menu
-2. Select "Settings..."
-3. Select the "C/C++" tab (3rd Tab)
-4. Select the Category: General
-5. You can see the "Preprocessor Definitions:" box
-6. Type PRINT_ENABLED=1 in that edit box (using a comma if necessary)
-7. Press OK
-8. Compile the entire project again...
-
-Q. error LNK2001: unresolved external symbol __imp__closesocket@4
-
-A. Visual C++ needs to have the Winsock library to be happy:
-1. Select "Project" menu
-2. Select "Settings..."
-3. Select the "Link" tab (4th Tab)
-4. You can see "Object/library modules:" edit box
-5. Type Wsock32.LIB in that edit box
-6. Press OK
-7. Compile the entire project again...
-
-Q. error C2061: in file tsm.c
-A. The BACnet stack uses a preprocessor define to configure
-client functionality in the Transaction State Machine (TSM).
-In Visual C++, add a Preprocessor Definition by:
-1. Select "Project" menu
-2. Select "Settings..."
-3. Select the "C/C++" tab (3rd Tab)
-4. Select the Category: General
-5. You can see the "Preprocessor Definitions:" box
-6. Type TSM_ENABLED=1 in that edit box (using a comma if necessary)
-7. Press OK
-8. Compile the entire project again...
+BACnet Stack - SourceForge.net
+Build for Visual C++ 6.0
+
+When building the BACnet stack using Visual C++ compiler,
+there are some settings that are important.
+
+Q. Are there some global configuration options for this BACnet stack?
+
+A. The BACnet stack uses some preprocessor defines to configure
+a number of subtle personalities.
+PRINT_ENABLED=1 - enables printing to stdio
+BIG_ENDIAN=0 - chooses the BACnet encoding and decoding order
+BACDL_BIP=1 - chooses BACnet/IP for the datalink layer
+BACDL_ETHERNET=0 - chooses BACnet Ethernet for the datalink layer
+BACDL_ARCNET=0 - chooses BACnet ARCNET for the datalink layer
+BACDL_MSTP=0 - chooses BACnet MS/TP for the datalink layer
+USE_INADDR=1 - uses INADDR_BROADCAST for broadcast rather than CLASSx
+TSM_ENABLED=1 - enables the Transaction State Machine for clients
+BIP_DEBUG=1 - enables print statements for debugging
+In Visual C++, add a Preprocessor Definition by:
+1. Select "Project" menu
+2. Select "Settings..."
+3. Select the "C/C++" tab (3rd Tab)
+4. Select the Category: General
+5. You can see the "Preprocessor Definitions:" box
+6. Type OPTION_NAME=1 or OPTION_NAME=0 in that edit box
+ using a comma to separate multiple options.
+7. Press OK
+8. Compile the entire project again...
+
+Q. MSVC refuses to open bacnet.dsw and bacnet.dsp.
+
+A. bacnet.dsw and bacnet.dsp are text files that were retrieved
+from CVS on a unix client and are now in unix text file format since
+they end with a "\r\n" rather than "\n". Use the unix2dos commandline
+tool to convert them back to dos:
+unix2dos bacnet.dsw
+unix2dos bacnet.dsp
+
+Q. error LNK2001: unresolved external symbol _WinMain@16
+
+A. The demo ports/win32/main.c was designed as a Win32 Console
+Application. If you want to change it to a Windows GUI application,
+you will have to add all the Windows GUI code, including WinMain().
+I recommend that you use a framework, such as WxWidgets/WxWindows,
+but this has not been done yet.
+
+Q. error C1083: Cannot open include file: 'stdint.h': No such file
+
+A. The BACnet stack uses some header files, and Visual C++ needs to know
+where they are:
+1. Select "Project" menu
+2. Select "Settings..."
+3. Select the "C/C++" tab (3rd Tab)
+4. Select the Category: Preprocessor
+5. You can see the "Additional include directories:" box
+6. Type the path to stdint.h in that edit box (using a comma if necessary)
+7. Type the path to bacdcode.h in that edit box (using a comma if necessary)
+In my system, the paths look like:
+c:\code\bacnet-stack\,c:\code\bacnet-stack\ports\win32\,
+c:\code\bacnet-stack\demo\handler\,c:\code\bacnet-stack\demo\object\
+8. Press OK
+9. Compile the project again...
+
+Q. error C2065: 'MAX_MPDU' : undeclared identifier
+
+A. The BACnet stack uses a preprocessor define to configure
+its datalink layer. In Visual C++, add a Preprocessor Definition by:
+1. Select "Project" menu
+2. Select "Settings..."
+3. Select the "C/C++" tab (3rd Tab)
+4. Select the Category: General
+5. You can see the "Preprocessor Definitions:" box
+6. Type BACDL_BIP=1 in that edit box (using a comma if necessary)
+7. Press OK
+8. Compile the entire project again...
+
+Q. error LNK2001: unresolved external symbol _bacapp_print
+
+A. The BACnet stack uses a preprocessor define to configure
+printing to stdio. In Visual C++, add a Preprocessor Definition by:
+1. Select "Project" menu
+2. Select "Settings..."
+3. Select the "C/C++" tab (3rd Tab)
+4. Select the Category: General
+5. You can see the "Preprocessor Definitions:" box
+6. Type PRINT_ENABLED=1 in that edit box (using a comma if necessary)
+7. Press OK
+8. Compile the entire project again...
+
+Q. error LNK2001: unresolved external symbol __imp__closesocket@4
+
+A. Visual C++ needs to have the Winsock library to be happy:
+1. Select "Project" menu
+2. Select "Settings..."
+3. Select the "Link" tab (4th Tab)
+4. You can see "Object/library modules:" edit box
+5. Type Wsock32.LIB in that edit box
+6. Press OK
+7. Compile the entire project again...
+
+Q. error C2061: in file tsm.c
+A. The BACnet stack uses a preprocessor define to configure
+client functionality in the Transaction State Machine (TSM).
+In Visual C++, add a Preprocessor Definition by:
+1. Select "Project" menu
+2. Select "Settings..."
+3. Select the "C/C++" tab (3rd Tab)
+4. Select the Category: General
+5. You can see the "Preprocessor Definitions:" box
+6. Type TSM_ENABLED=1 in that edit box (using a comma if necessary)
+7. Press OK
+8. Compile the entire project again...
diff --git a/bacnet-stack/ports/win32/bip-init.c b/bacnet-stack/ports/win32/bip-init.c
index 972f9f25..3f4fc18a 100644
--- a/bacnet-stack/ports/win32/bip-init.c
+++ b/bacnet-stack/ports/win32/bip-init.c
@@ -1,358 +1,358 @@
-/*####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####*/
-
-#define WIN32_LEAN_AND_MEAN
-#define STRICT 1
-
-#include
-#include
-#include /* for standard integer types uint8_t etc. */
-#include /* for the standard bool type. */
-#include "bacdcode.h"
-#include "bip.h"
-#include "net.h"
-
-/* To fill a need, we invent the gethostaddr() function. */
-static long gethostaddr(void)
-{
- struct hostent *host_ent;
- char host_name[255];
-
- if (gethostname(host_name, sizeof(host_name)) != 0)
- return -1;
-
- if ((host_ent = gethostbyname(host_name)) == NULL)
- return -1;
-#ifdef BIP_DEBUG
- printf("host: %s at %u.%u.%u.%u\n", host_name,
- ((uint8_t*)host_ent->h_addr)[0],
- ((uint8_t*)host_ent->h_addr)[1],
- ((uint8_t*)host_ent->h_addr)[2],
- ((uint8_t*)host_ent->h_addr)[3]);
-#endif
- /* note: network byte order */
- return *(long *) host_ent->h_addr;
-}
-
-static void set_broadcast_address(uint32_t net_address)
-{
-#if USE_INADDR
- /* Note: sometimes INADDR_BROADCAST does not let me get
- any unicast messages. Not sure why... */
- (void) net_address;
- bip_set_broadcast_addr(INADDR_BROADCAST);
-#else
- long broadcast_address = 0;
- long mask = 0;
-
- if (IN_CLASSA(ntohl(net_address)))
- broadcast_address =
- (ntohl(net_address) & ~IN_CLASSA_HOST) | IN_CLASSA_HOST;
- else if (IN_CLASSB(ntohl(net_address)))
- broadcast_address =
- (ntohl(net_address) & ~IN_CLASSB_HOST) | IN_CLASSB_HOST;
- else if (IN_CLASSC(ntohl(net_address)))
- broadcast_address =
- (ntohl(net_address) & ~IN_CLASSC_HOST) | IN_CLASSC_HOST;
- else if (IN_CLASSD(ntohl(net_address)))
- broadcast_address =
- (ntohl(net_address) & ~IN_CLASSD_HOST) | IN_CLASSD_HOST;
- else
- broadcast_address = INADDR_BROADCAST;
- bip_set_broadcast_addr(htonl(broadcast_address));
-#endif
-}
-
-static void cleanup(void)
-{
- WSACleanup();
-}
-
-
-/* on Windows, ifname is the dotted ip address of the interface */
-void bip_set_interface(char *ifname)
-{
- struct in_addr address;
-
- /* setup local address */
- if (bip_get_addr() == 0) {
- bip_set_addr(inet_addr(ifname));
- }
-#ifdef BIP_DEBUG
- address.s_addr = htonl(bip_get_addr());
- fprintf(stderr, "Interface: %s\n", ifname);
-#endif
- /* setup local broadcast address */
- if (bip_get_broadcast_addr() == 0) {
- address.s_addr = htonl(bip_get_addr());
- set_broadcast_address(address.s_addr);
- }
-}
-
-static char *winsock_error_code_text(int code)
-{
- switch (code) {
- case WSAEACCES:
- return "Permission denied.";
- case WSAEINTR:
- return "Interrupted system call.";
- case WSAEBADF:
- return "Bad file number.";
- case WSAEFAULT:
- return "Bad address.";
- case WSAEINVAL:
- return "Invalid argument.";
- case WSAEMFILE:
- return "Too many open files.";
- case WSAEWOULDBLOCK:
- return "Operation would block.";
- case WSAEINPROGRESS:
- return "Operation now in progress. This error is returned if any Windows Sockets API function is called while a blocking function is in progress.";
- case WSAENOTSOCK:
- return "Socket operation on nonsocket.";
- case WSAEDESTADDRREQ:
- return "Destination address required.";
- case WSAEMSGSIZE:
- return "Message too long.";
- case WSAEPROTOTYPE:
- return "Protocol wrong type for socket.";
- case WSAENOPROTOOPT:
- return "Protocol not available.";
- case WSAEPROTONOSUPPORT:
- return "Protocol not supported.";
- case WSAESOCKTNOSUPPORT:
- return "Socket type not supported.";
- case WSAEOPNOTSUPP:
- return "Operation not supported on socket.";
- case WSAEPFNOSUPPORT:
- return "Protocol family not supported.";
- case WSAEAFNOSUPPORT:
- return "Address family not supported by protocol family.";
- case WSAEADDRINUSE:
- return "Address already in use.";
- case WSAEADDRNOTAVAIL:
- return "Cannot assign requested address.";
- case WSAENETDOWN:
- return "Network is down. This error may be reported at any time if the Windows Sockets implementation detects an underlying failure.";
- case WSAENETUNREACH:
- return "Network is unreachable.";
- case WSAENETRESET:
- return "Network dropped connection on reset.";
- case WSAECONNABORTED:
- return "Software caused connection abort.";
- case WSAECONNRESET:
- return "Connection reset by peer.";
- case WSAENOBUFS:
- return "No buffer space available.";
- case WSAEISCONN:
- return "Socket is already connected.";
- case WSAENOTCONN:
- return "Socket is not connected.";
- case WSAESHUTDOWN:
- return "Cannot send after socket shutdown.";
- case WSAETOOMANYREFS:
- return "Too many references: cannot splice.";
- case WSAETIMEDOUT:
- return "Connection timed out.";
- case WSAECONNREFUSED:
- return "Connection refused.";
- case WSAELOOP:
- return "Too many levels of symbolic links.";
- case WSAENAMETOOLONG:
- return "File name too long.";
- case WSAEHOSTDOWN:
- return "Host is down.";
- case WSAEHOSTUNREACH:
- return "No route to host.";
- case WSASYSNOTREADY:
- return "Returned by WSAStartup(), "
- "indicating that the network subsystem is unusable.";
- case WSAVERNOTSUPPORTED:
- return "Returned by WSAStartup(), "
- "indicating that the Windows Sockets DLL cannot support "
- "this application.";
- case WSANOTINITIALISED:
- return "Winsock not initialized. "
- "This message is returned by any function except WSAStartup(), "
- "indicating that a successful WSAStartup() has not yet "
- "been performed.";
- case WSAEDISCON:
- return "Disconnect.";
- case WSAHOST_NOT_FOUND:
- return "Host not found. "
- "This message indicates that the key "
- "(name, address, and so on) was not found.";
- case WSATRY_AGAIN:
- return "Nonauthoritative host not found. "
- "This error may suggest that the name service itself "
- "is not functioning.";
- case WSANO_RECOVERY:
- return "Nonrecoverable error. "
- "This error may suggest that the name service itself "
- "is not functioning.";
- case WSANO_DATA:
- return "Valid name, no data record of requested type. "
- "This error indicates that the key "
- "(name, address, and so on) was not found.";
- default: return "unknown";
- }
-}
-
-bool bip_init(char *ifname)
-{
- int rv = 0; /* return from socket lib calls */
- struct sockaddr_in sin = { -1 };
- int value = 1;
- int sock_fd = -1;
- int Result;
- int Code;
- WSADATA wd;
- struct in_addr address;
- struct in_addr broadcast_address;
-
- Result = WSAStartup((1 << 8) | 1, &wd);
- /*Result = WSAStartup(MAKEWORD(2,2), &wd); */
- if (Result != 0) {
- Code = WSAGetLastError();
- printf("TCP/IP stack initialization failed\n"
- " error code: %i %s\n",
- Code, winsock_error_code_text(Code));
- exit(1);
- }
- atexit(cleanup);
-
- if (ifname)
- bip_set_interface(ifname);
- /* has address been set? */
- address.s_addr = htonl(bip_get_addr());
- if (address.s_addr == 0) {
- address.s_addr = gethostaddr();
- if (address.s_addr == (unsigned) -1) {
- Code = WSAGetLastError();
- printf("Get host address failed\n"
- " error code: %i %s\n",
- Code, winsock_error_code_text(Code));
- exit(1);
- }
- bip_set_addr(address.s_addr);
- }
-#ifdef BIP_DEBUG
- fprintf(stderr, "IP Address: %s\n", inet_ntoa(address));
-#endif
- /* has broadcast address been set? */
- if (bip_get_broadcast_addr() == 0) {
- set_broadcast_address(address.s_addr);
- }
-#ifdef BIP_DEBUG
- broadcast_address.s_addr = htonl(bip_get_broadcast_addr());
- fprintf(stderr, "IP Broadcast Address: %s\n",
- inet_ntoa(broadcast_address));
- fprintf(stderr, "UDP Port: 0x%04X [%hu]\n",
- bip_get_port(),
- bip_get_port());
-#endif
- /* assumes that the driver has already been initialized */
- sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- bip_set_socket(sock_fd);
- if (sock_fd < 0) {
- fprintf(stderr, "bip: failed to allocate a socket.\n");
- return false;
- }
- /* Allow us to use the same socket for sending and receiving */
- /* This makes sure that the src port is correct when sending */
- rv = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
- (char *) &value, sizeof(value));
- if (rv < 0) {
- fprintf(stderr, "bip: failed to set REUSEADDR socket option.\n");
- close(sock_fd);
- bip_set_socket(-1);
- return false;
- }
- /* allow us to send a broadcast */
- rv = setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST,
- (char *) &value, sizeof(value));
- if (rv < 0) {
- fprintf(stderr, "bip: failed to set BROADCAST socket option.\n");
- close(sock_fd);
- bip_set_socket(-1);
- return false;
- }
-#if 0
- /* probably only for Apple... */
- /* rebind a port that is already in use.
- Note: all users of the port must specify this flag */
- rv = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEPORT,
- (char *) &value, sizeof(value));
- if (rv < 0) {
- fprintf(stderr, "bip: failed to set REUSEPORT socket option.\n");
- close(sock_fd);
- bip_set_socket(-1);
- return false;
- }
-#endif
- /* bind the socket to the local port number and IP address */
- sin.sin_family = AF_INET;
-#if USE_INADDR
- /* by setting sin.sin_addr.s_addr to INADDR_ANY,
- I am telling the IP stack to automatically fill
- in the IP address of the machine the process
- is running on.
-
- Some server computers have multiple IP addresses.
- A socket bound to one of these will not accept
- connections to another address. Frequently you prefer
- to allow any one of the computer's IP addresses
- to be used for connections. Use INADDR_ANY (0L) to
- allow clients to connect using any one of the host's
- IP addresses. */
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
-#else
- /* or we could use the specific adapter address
- note: already in network byte order */
- sin.sin_addr.s_addr = address.s_addr;
-#endif
- sin.sin_port = htons(bip_get_port());
- memset(&(sin.sin_zero), '\0', sizeof(sin.sin_zero));
- rv = bind(sock_fd,
- (const struct sockaddr *) &sin, sizeof(struct sockaddr));
- if (rv < 0) {
- fprintf(stderr, "bip: failed to bind to %s port %hd\n",
- inet_ntoa(sin.sin_addr), bip_get_port());
- close(sock_fd);
- bip_set_socket(-1);
- return false;
- }
-
- return true;
-}
+/*####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####*/
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT 1
+
+#include
+#include
+#include /* for standard integer types uint8_t etc. */
+#include /* for the standard bool type. */
+#include "bacdcode.h"
+#include "bip.h"
+#include "net.h"
+
+/* To fill a need, we invent the gethostaddr() function. */
+static long gethostaddr(void)
+{
+ struct hostent *host_ent;
+ char host_name[255];
+
+ if (gethostname(host_name, sizeof(host_name)) != 0)
+ return -1;
+
+ if ((host_ent = gethostbyname(host_name)) == NULL)
+ return -1;
+#ifdef BIP_DEBUG
+ printf("host: %s at %u.%u.%u.%u\n", host_name,
+ ((uint8_t*)host_ent->h_addr)[0],
+ ((uint8_t*)host_ent->h_addr)[1],
+ ((uint8_t*)host_ent->h_addr)[2],
+ ((uint8_t*)host_ent->h_addr)[3]);
+#endif
+ /* note: network byte order */
+ return *(long *) host_ent->h_addr;
+}
+
+static void set_broadcast_address(uint32_t net_address)
+{
+#if USE_INADDR
+ /* Note: sometimes INADDR_BROADCAST does not let me get
+ any unicast messages. Not sure why... */
+ (void) net_address;
+ bip_set_broadcast_addr(INADDR_BROADCAST);
+#else
+ long broadcast_address = 0;
+ long mask = 0;
+
+ if (IN_CLASSA(ntohl(net_address)))
+ broadcast_address =
+ (ntohl(net_address) & ~IN_CLASSA_HOST) | IN_CLASSA_HOST;
+ else if (IN_CLASSB(ntohl(net_address)))
+ broadcast_address =
+ (ntohl(net_address) & ~IN_CLASSB_HOST) | IN_CLASSB_HOST;
+ else if (IN_CLASSC(ntohl(net_address)))
+ broadcast_address =
+ (ntohl(net_address) & ~IN_CLASSC_HOST) | IN_CLASSC_HOST;
+ else if (IN_CLASSD(ntohl(net_address)))
+ broadcast_address =
+ (ntohl(net_address) & ~IN_CLASSD_HOST) | IN_CLASSD_HOST;
+ else
+ broadcast_address = INADDR_BROADCAST;
+ bip_set_broadcast_addr(htonl(broadcast_address));
+#endif
+}
+
+static void cleanup(void)
+{
+ WSACleanup();
+}
+
+
+/* on Windows, ifname is the dotted ip address of the interface */
+void bip_set_interface(char *ifname)
+{
+ struct in_addr address;
+
+ /* setup local address */
+ if (bip_get_addr() == 0) {
+ bip_set_addr(inet_addr(ifname));
+ }
+#ifdef BIP_DEBUG
+ address.s_addr = htonl(bip_get_addr());
+ fprintf(stderr, "Interface: %s\n", ifname);
+#endif
+ /* setup local broadcast address */
+ if (bip_get_broadcast_addr() == 0) {
+ address.s_addr = htonl(bip_get_addr());
+ set_broadcast_address(address.s_addr);
+ }
+}
+
+static char *winsock_error_code_text(int code)
+{
+ switch (code) {
+ case WSAEACCES:
+ return "Permission denied.";
+ case WSAEINTR:
+ return "Interrupted system call.";
+ case WSAEBADF:
+ return "Bad file number.";
+ case WSAEFAULT:
+ return "Bad address.";
+ case WSAEINVAL:
+ return "Invalid argument.";
+ case WSAEMFILE:
+ return "Too many open files.";
+ case WSAEWOULDBLOCK:
+ return "Operation would block.";
+ case WSAEINPROGRESS:
+ return "Operation now in progress. This error is returned if any Windows Sockets API function is called while a blocking function is in progress.";
+ case WSAENOTSOCK:
+ return "Socket operation on nonsocket.";
+ case WSAEDESTADDRREQ:
+ return "Destination address required.";
+ case WSAEMSGSIZE:
+ return "Message too long.";
+ case WSAEPROTOTYPE:
+ return "Protocol wrong type for socket.";
+ case WSAENOPROTOOPT:
+ return "Protocol not available.";
+ case WSAEPROTONOSUPPORT:
+ return "Protocol not supported.";
+ case WSAESOCKTNOSUPPORT:
+ return "Socket type not supported.";
+ case WSAEOPNOTSUPP:
+ return "Operation not supported on socket.";
+ case WSAEPFNOSUPPORT:
+ return "Protocol family not supported.";
+ case WSAEAFNOSUPPORT:
+ return "Address family not supported by protocol family.";
+ case WSAEADDRINUSE:
+ return "Address already in use.";
+ case WSAEADDRNOTAVAIL:
+ return "Cannot assign requested address.";
+ case WSAENETDOWN:
+ return "Network is down. This error may be reported at any time if the Windows Sockets implementation detects an underlying failure.";
+ case WSAENETUNREACH:
+ return "Network is unreachable.";
+ case WSAENETRESET:
+ return "Network dropped connection on reset.";
+ case WSAECONNABORTED:
+ return "Software caused connection abort.";
+ case WSAECONNRESET:
+ return "Connection reset by peer.";
+ case WSAENOBUFS:
+ return "No buffer space available.";
+ case WSAEISCONN:
+ return "Socket is already connected.";
+ case WSAENOTCONN:
+ return "Socket is not connected.";
+ case WSAESHUTDOWN:
+ return "Cannot send after socket shutdown.";
+ case WSAETOOMANYREFS:
+ return "Too many references: cannot splice.";
+ case WSAETIMEDOUT:
+ return "Connection timed out.";
+ case WSAECONNREFUSED:
+ return "Connection refused.";
+ case WSAELOOP:
+ return "Too many levels of symbolic links.";
+ case WSAENAMETOOLONG:
+ return "File name too long.";
+ case WSAEHOSTDOWN:
+ return "Host is down.";
+ case WSAEHOSTUNREACH:
+ return "No route to host.";
+ case WSASYSNOTREADY:
+ return "Returned by WSAStartup(), "
+ "indicating that the network subsystem is unusable.";
+ case WSAVERNOTSUPPORTED:
+ return "Returned by WSAStartup(), "
+ "indicating that the Windows Sockets DLL cannot support "
+ "this application.";
+ case WSANOTINITIALISED:
+ return "Winsock not initialized. "
+ "This message is returned by any function except WSAStartup(), "
+ "indicating that a successful WSAStartup() has not yet "
+ "been performed.";
+ case WSAEDISCON:
+ return "Disconnect.";
+ case WSAHOST_NOT_FOUND:
+ return "Host not found. "
+ "This message indicates that the key "
+ "(name, address, and so on) was not found.";
+ case WSATRY_AGAIN:
+ return "Nonauthoritative host not found. "
+ "This error may suggest that the name service itself "
+ "is not functioning.";
+ case WSANO_RECOVERY:
+ return "Nonrecoverable error. "
+ "This error may suggest that the name service itself "
+ "is not functioning.";
+ case WSANO_DATA:
+ return "Valid name, no data record of requested type. "
+ "This error indicates that the key "
+ "(name, address, and so on) was not found.";
+ default: return "unknown";
+ }
+}
+
+bool bip_init(char *ifname)
+{
+ int rv = 0; /* return from socket lib calls */
+ struct sockaddr_in sin = { -1 };
+ int value = 1;
+ int sock_fd = -1;
+ int Result;
+ int Code;
+ WSADATA wd;
+ struct in_addr address;
+ struct in_addr broadcast_address;
+
+ Result = WSAStartup((1 << 8) | 1, &wd);
+ /*Result = WSAStartup(MAKEWORD(2,2), &wd); */
+ if (Result != 0) {
+ Code = WSAGetLastError();
+ printf("TCP/IP stack initialization failed\n"
+ " error code: %i %s\n",
+ Code, winsock_error_code_text(Code));
+ exit(1);
+ }
+ atexit(cleanup);
+
+ if (ifname)
+ bip_set_interface(ifname);
+ /* has address been set? */
+ address.s_addr = htonl(bip_get_addr());
+ if (address.s_addr == 0) {
+ address.s_addr = gethostaddr();
+ if (address.s_addr == (unsigned) -1) {
+ Code = WSAGetLastError();
+ printf("Get host address failed\n"
+ " error code: %i %s\n",
+ Code, winsock_error_code_text(Code));
+ exit(1);
+ }
+ bip_set_addr(address.s_addr);
+ }
+#ifdef BIP_DEBUG
+ fprintf(stderr, "IP Address: %s\n", inet_ntoa(address));
+#endif
+ /* has broadcast address been set? */
+ if (bip_get_broadcast_addr() == 0) {
+ set_broadcast_address(address.s_addr);
+ }
+#ifdef BIP_DEBUG
+ broadcast_address.s_addr = htonl(bip_get_broadcast_addr());
+ fprintf(stderr, "IP Broadcast Address: %s\n",
+ inet_ntoa(broadcast_address));
+ fprintf(stderr, "UDP Port: 0x%04X [%hu]\n",
+ bip_get_port(),
+ bip_get_port());
+#endif
+ /* assumes that the driver has already been initialized */
+ sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ bip_set_socket(sock_fd);
+ if (sock_fd < 0) {
+ fprintf(stderr, "bip: failed to allocate a socket.\n");
+ return false;
+ }
+ /* Allow us to use the same socket for sending and receiving */
+ /* This makes sure that the src port is correct when sending */
+ rv = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &value, sizeof(value));
+ if (rv < 0) {
+ fprintf(stderr, "bip: failed to set REUSEADDR socket option.\n");
+ close(sock_fd);
+ bip_set_socket(-1);
+ return false;
+ }
+ /* allow us to send a broadcast */
+ rv = setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST,
+ (char *) &value, sizeof(value));
+ if (rv < 0) {
+ fprintf(stderr, "bip: failed to set BROADCAST socket option.\n");
+ close(sock_fd);
+ bip_set_socket(-1);
+ return false;
+ }
+#if 0
+ /* probably only for Apple... */
+ /* rebind a port that is already in use.
+ Note: all users of the port must specify this flag */
+ rv = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEPORT,
+ (char *) &value, sizeof(value));
+ if (rv < 0) {
+ fprintf(stderr, "bip: failed to set REUSEPORT socket option.\n");
+ close(sock_fd);
+ bip_set_socket(-1);
+ return false;
+ }
+#endif
+ /* bind the socket to the local port number and IP address */
+ sin.sin_family = AF_INET;
+#if USE_INADDR
+ /* by setting sin.sin_addr.s_addr to INADDR_ANY,
+ I am telling the IP stack to automatically fill
+ in the IP address of the machine the process
+ is running on.
+
+ Some server computers have multiple IP addresses.
+ A socket bound to one of these will not accept
+ connections to another address. Frequently you prefer
+ to allow any one of the computer's IP addresses
+ to be used for connections. Use INADDR_ANY (0L) to
+ allow clients to connect using any one of the host's
+ IP addresses. */
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+#else
+ /* or we could use the specific adapter address
+ note: already in network byte order */
+ sin.sin_addr.s_addr = address.s_addr;
+#endif
+ sin.sin_port = htons(bip_get_port());
+ memset(&(sin.sin_zero), '\0', sizeof(sin.sin_zero));
+ rv = bind(sock_fd,
+ (const struct sockaddr *) &sin, sizeof(struct sockaddr));
+ if (rv < 0) {
+ fprintf(stderr, "bip: failed to bind to %s port %hd\n",
+ inet_ntoa(sin.sin_addr), bip_get_port());
+ close(sock_fd);
+ bip_set_socket(-1);
+ return false;
+ }
+
+ return true;
+}
diff --git a/bacnet-stack/ports/win32/ethernet.c b/bacnet-stack/ports/win32/ethernet.c
index 972b30b3..aee013da 100644
--- a/bacnet-stack/ports/win32/ethernet.c
+++ b/bacnet-stack/ports/win32/ethernet.c
@@ -1,455 +1,455 @@
-/*####COPYRIGHTBEGIN####
- -------------------------------------------
- Copyright (C) 2005 Steve Karg, modified by Kevin Liao
-
- 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 /* for standard integer types uint8_t etc. */
-#include /* for the standard bool type. */
-#include
-#include
-#include
-
-#include "bacdef.h"
-#include "ethernet.h"
-#include "bacdcode.h"
-
-
-/* Uses WinPCap to access raw ethernet */
-/* Notes: */
-/* To make ethernet.c work under win32, you have to: */
-/* 1. install winpcap 3.1 development pack; */
-/* 2. install Microsoft Platform SDK Feb 2003. */
-/* 3. remove or modify functions used for log such as */
-/* "LogError()", "LogInfo()", which were implemented */
-/* as a wrapper of Log4cpp. */
-/* -- Kevin Liao */
-
-/* includes for accessing ethernet by using winpcap */
-#include "pcap.h"
-#include "packet32.h"
-#include "ntddndis.h"
-#include "remote-ext.h"
-
-
-/* commonly used comparison address for ethernet */
-uint8_t Ethernet_Broadcast[MAX_MAC_LEN] =
- { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-/* commonly used empty address for ethernet quick compare */
-uint8_t Ethernet_Empty_MAC[MAX_MAC_LEN] = { 0, 0, 0, 0, 0, 0 };
-
-/* my local device data - MAC address */
-uint8_t Ethernet_MAC_Address[MAX_MAC_LEN] = { 0 };
-
-/* couple of var for using winpcap */
-static char pcap_errbuf[PCAP_ERRBUF_SIZE + 1];
-static pcap_t *pcap_eth802_fp = NULL; /* 802.2 file handle, from winpcap */
-static unsigned eth_timeout = 100;
-
-
-/* couple of external func for runtime error logging, you can simply */
-/* replace them with standard "printf(...)" */
-/* Logging extern functions: Info level */
-extern void LogInfo(const char *msg);
-/* Logging extern functions: Error level*/
-extern void LogError(const char *msg);
-/* Logging extern functions: Debug level*/
-extern void LogDebug(const char *msg);
-
-
-bool ethernet_valid(void)
-{
- return (pcap_eth802_fp != NULL);
-}
-
-void ethernet_cleanup(void)
-{
- if (pcap_eth802_fp) {
- pcap_close(pcap_eth802_fp);
- pcap_eth802_fp = NULL;
- }
- LogInfo("ethernet.c: ethernet_cleanup() ok.\n");
-}
-
-void ethernet_set_timeout(unsigned timeout)
-{
- eth_timeout = timeout;
-}
-
-/*----------------------------------------------------------------------
- Portable function to set a socket into nonblocking mode.
- Calling this on a socket causes all future read() and write() calls on
- that socket to do only as much as they can immediately, and return
- without waiting.
- If no data can be read or written, they return -1 and set errno
- to EAGAIN (or EWOULDBLOCK).
- Thanks to Bjorn Reese for this code.
-----------------------------------------------------------------------*/
-/**
- * We don't need to use this function since WinPCap has provided one
- * named "pcap_setnonblock()".
- * Kevin, 2006.08.15
- */
-/*
-int setNonblocking(int fd)
-{
- int flags;
-
- if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
- flags = 0;
- return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-}
-*/
-
-bool ethernet_init(char *if_name)
-{
- PPACKET_OID_DATA pOidData;
- LPADAPTER lpAdapter;
- pcap_if_t *pcap_all_if;
- pcap_if_t *dev;
- BOOLEAN result;
- CHAR str[sizeof(PACKET_OID_DATA) + 128];
- int i;
- char msgBuf[200];
-
- if (ethernet_valid())
- ethernet_cleanup();
-
- /**
- * Find the interface user specified
- */
- /* Retrieve the device list */
- if (pcap_findalldevs(&pcap_all_if, pcap_errbuf) == -1) {
- sprintf(msgBuf,
- "ethernet.c: error in pcap_findalldevs: %s\n", pcap_errbuf);
- LogError(msgBuf);
- return false;
- }
- /* Scan the list printing every entry */
- for (dev = pcap_all_if; dev; dev = dev->next) {
- if (strcmp(if_name, dev->name) == 0)
- break;
- }
- pcap_freealldevs(pcap_all_if); /* we don't need it anymore */
- if (dev == NULL) {
- sprintf(msgBuf,
- "ethernet.c: specified interface not found: %s\n", if_name);
- LogError(msgBuf);
- return false;
- }
-
- /**
- * Get local MAC address
- */
- ZeroMemory(str, sizeof(PACKET_OID_DATA) + 128);
- lpAdapter = PacketOpenAdapter(if_name);
- if (lpAdapter == NULL) {
- ethernet_cleanup();
- sprintf(msgBuf,
- "ethernet.c: error in PacketOpenAdapter(\"%s\")\n", if_name);
- LogError(msgBuf);
- return false;
- }
- pOidData = (PPACKET_OID_DATA) str;
- pOidData->Oid = OID_802_3_CURRENT_ADDRESS;
- pOidData->Length = 6;
- result = PacketRequest(lpAdapter, FALSE, pOidData);
- if (!result) {
- PacketCloseAdapter(lpAdapter);
- ethernet_cleanup();
- LogError("ethernet.c: error in PacketRequest()\n");
- return false;
- }
- for (i = 0; i < 6; ++i)
- Ethernet_MAC_Address[i] = pOidData->Data[i];
- PacketCloseAdapter(lpAdapter);
-
- /**
- * Open interface for subsequent sending and receiving
- */
- /* Open the output device */
- pcap_eth802_fp = pcap_open(if_name, /* name of the device */
- MAX_MPDU, /* portion of the packet to capture */
- PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
- eth_timeout, /* read timeout */
- NULL, /* authentication on the remote machine */
- pcap_errbuf /* error buffer */
- );
- if (pcap_eth802_fp == NULL) {
- PacketCloseAdapter(lpAdapter);
- ethernet_cleanup();
- sprintf(msgBuf,
- "ethernet.c: unable to open the adapter. %s is not supported by WinPcap\n",
- if_name);
- LogError(msgBuf);
- return false;
- }
-
- LogInfo("ethernet.c: ethernet_init() ok.\n");
-
- atexit(ethernet_cleanup);
-
- return ethernet_valid();
-}
-
-/* function to send a packet out the 802.2 socket */
-/* returns bytes sent success, negative on failure */
-int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
- BACNET_ADDRESS * src, /* source address */
- uint8_t * pdu, /* any data to be sent - may be null */
- unsigned pdu_len /* number of bytes of data */
- )
-{
- int bytes = 0;
- uint8_t mtu[MAX_MPDU] = { 0 };
- int mtu_len = 0;
- int i = 0;
-
- /* don't waste time if the socket is not valid */
- if (!ethernet_valid()) {
- LogError
- ("ethernet.c: invalid 802.2 ethernet interface descriptor!\n");
- return -1;
- }
- /* load destination ethernet MAC address */
- if (dest->mac_len == 6) {
- for (i = 0; i < 6; i++) {
- mtu[mtu_len] = dest->mac[i];
- mtu_len++;
- }
- } else {
- LogError("ethernet.c: invalid destination MAC address!\n");
- return -2;
- }
-
- /* load source ethernet MAC address */
- if (src->mac_len == 6) {
- for (i = 0; i < 6; i++) {
- mtu[mtu_len] = src->mac[i];
- mtu_len++;
- }
- } else {
- LogError("ethernet.c: invalid source MAC address!\n");
- return -3;
- }
- if ((14 + 3 + pdu_len) > MAX_MPDU) {
- LogError("ethernet.c: PDU is too big to send!\n");
- return -4;
- }
- /* packet length */
- mtu_len +=
- encode_unsigned16(&mtu[12], 3 /*DSAP,SSAP,LLC */ + pdu_len);
- /* Logical PDU portion */
- mtu[mtu_len++] = 0x82; /* DSAP for BACnet */
- mtu[mtu_len++] = 0x82; /* SSAP for BACnet */
- mtu[mtu_len++] = 0x03; /* Control byte in header */
- memcpy(&mtu[mtu_len], pdu, pdu_len);
- mtu_len += pdu_len;
-
- /* Send the packet */
- if (pcap_sendpacket(pcap_eth802_fp, mtu, mtu_len) != 0) {
- /* did it get sent? */
- char msgBuf[200];
- sprintf(msgBuf,
- "ethernet.c: error sending packet: %s\n",
- pcap_geterr(pcap_eth802_fp));
- LogError(msgBuf);
- return -5;
- }
-
- return mtu_len;
-}
-
-/* function to send a packet out the 802.2 socket */
-/* returns number of bytes sent on success, negative on failure */
-int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
- uint8_t * pdu, /* any data to be sent - may be null */
- unsigned pdu_len /* number of bytes of data */
- )
-{
- int i = 0; /* counter */
- BACNET_ADDRESS src = { 0 }; /* source address */
-
- for (i = 0; i < 6; i++) {
- src.mac[i] = Ethernet_MAC_Address[i];
- src.mac_len++;
- }
- /* function to send a packet out the 802.2 socket */
- /* returns 1 on success, 0 on failure */
- return ethernet_send(dest, /* destination address */
- &src, /* source address */
- pdu, /* any data to be sent - may be null */
- pdu_len /* number of bytes of data */
- );
-}
-
-/* receives an 802.2 framed packet */
-/* returns the number of octets in the PDU, or zero on failure */
-uint16_t ethernet_receive(BACNET_ADDRESS * src, /* source address */
- uint8_t * pdu, /* PDU data */
- uint16_t max_pdu, /* amount of space available in the PDU */
- unsigned timeout /* number of milliseconds to wait for a packet. we ommit it due to winpcap API. */
- )
-{
- struct pcap_pkthdr *header;
- int res;
- u_char *pkt_data;
- uint16_t pdu_len = 0; /* return value */
-
- /* Make sure the socket is open */
- if (!ethernet_valid()) {
- LogError
- ("ethernet.c: invalid 802.2 ethernet interface descriptor!\n");
- return 0;
- }
-
- /* Capture a packet */
- res = pcap_next_ex(pcap_eth802_fp, &header, &pkt_data);
- if (res < 0) {
- char msgBuf[200];
- sprintf(msgBuf,
- "ethernet.c: error in receiving packet: %s\n",
- pcap_geterr(pcap_eth802_fp));
- return 0;
- } else if (res == 0)
- return 0;
-
- if (header->len == 0 || header->caplen == 0)
- return 0;
-
- /* the signature of an 802.2 BACnet packet */
- if ((pkt_data[14] != 0x82) && (pkt_data[15] != 0x82)) {
- /*eth_log_error("ethernet.c: Non-BACnet packet\n"); */
- return 0;
- }
- /* copy the source address */
- src->mac_len = 6;
- memmove(src->mac, &pkt_data[6], 6);
-
- /* check destination address for when */
- /* the Ethernet card is in promiscious mode */
- if ((memcmp(&pkt_data[0], Ethernet_MAC_Address, 6) != 0)
- && (memcmp(&pkt_data[0], Ethernet_Broadcast, 6) != 0)) {
- /*eth_log_error( "ethernet.c: This packet isn't for us\n"); */
- return 0;
- }
-
- (void) decode_unsigned16(&pkt_data[12], &pdu_len);
- pdu_len -= 3 /* DSAP, SSAP, LLC Control */ ;
- /* copy the buffer into the PDU */
- if (pdu_len < max_pdu)
- memmove(&pdu[0], &pkt_data[17], pdu_len);
- /* ignore packets that are too large */
- else
- pdu_len = 0;
-
- return pdu_len;
-}
-
-void ethernet_set_my_address(BACNET_ADDRESS * my_address)
-{
- int i = 0;
-
- for (i = 0; i < 6; i++) {
- Ethernet_MAC_Address[i] = my_address->mac[i];
- }
-
- return;
-}
-
-void ethernet_get_my_address(BACNET_ADDRESS * my_address)
-{
- int i = 0;
-
- my_address->mac_len = 0;
- for (i = 0; i < 6; i++) {
- my_address->mac[i] = Ethernet_MAC_Address[i];
- my_address->mac_len++;
- }
- my_address->net = 0; /* local only, no routing */
- my_address->len = 0;
- for (i = 0; i < MAX_MAC_LEN; i++) {
- my_address->adr[i] = 0;
- }
-
- return;
-}
-
-void ethernet_get_broadcast_address(BACNET_ADDRESS * dest)
-{ /* destination address */
- int i = 0; /* counter */
-
- if (dest) {
- for (i = 0; i < 6; i++) {
- dest->mac[i] = Ethernet_Broadcast[i];
- }
- dest->mac_len = 6;
- dest->net = BACNET_BROADCAST_NETWORK;
- dest->len = 0; /* denotes broadcast address */
- for (i = 0; i < MAX_MAC_LEN; i++) {
- dest->adr[i] = 0;
- }
- }
-
- return;
-}
-
-void ethernet_debug_address(const char *info, BACNET_ADDRESS * dest)
-{
- int i = 0; /* counter */
- char msgBuf[200];
-
- if (info) {
- sprintf(msgBuf, "%s", info);
- LogError(msgBuf);
- }
- /* if */
- if (dest) {
- sprintf(msgBuf,
- "Address:\n MAC Length=%d\n MAC Address=", dest->mac_len);
- LogInfo(msgBuf);
- for (i = 0; i < MAX_MAC_LEN; i++) {
- sprintf(msgBuf, "%02X ", (unsigned) dest->mac[i]);
- LogInfo(msgBuf);
- } /* for */
- LogInfo("\n");
- sprintf(msgBuf,
- " Net=%hu\n Len=%d\n Adr=", dest->net, dest->len);
- LogInfo(msgBuf);
- for (i = 0; i < MAX_MAC_LEN; i++) {
- sprintf(msgBuf, "%02X ", (unsigned) dest->adr[i]);
- LogInfo(msgBuf);
- } /* for */
- LogInfo("\n");
- }
- /* if ( dest ) */
- return;
-}
+/*####COPYRIGHTBEGIN####
+ -------------------------------------------
+ Copyright (C) 2005 Steve Karg, modified by Kevin Liao
+
+ 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 /* for standard integer types uint8_t etc. */
+#include /* for the standard bool type. */
+#include
+#include
+#include
+
+#include "bacdef.h"
+#include "ethernet.h"
+#include "bacdcode.h"
+
+
+/* Uses WinPCap to access raw ethernet */
+/* Notes: */
+/* To make ethernet.c work under win32, you have to: */
+/* 1. install winpcap 3.1 development pack; */
+/* 2. install Microsoft Platform SDK Feb 2003. */
+/* 3. remove or modify functions used for log such as */
+/* "LogError()", "LogInfo()", which were implemented */
+/* as a wrapper of Log4cpp. */
+/* -- Kevin Liao */
+
+/* includes for accessing ethernet by using winpcap */
+#include "pcap.h"
+#include "packet32.h"
+#include "ntddndis.h"
+#include "remote-ext.h"
+
+
+/* commonly used comparison address for ethernet */
+uint8_t Ethernet_Broadcast[MAX_MAC_LEN] =
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+/* commonly used empty address for ethernet quick compare */
+uint8_t Ethernet_Empty_MAC[MAX_MAC_LEN] = { 0, 0, 0, 0, 0, 0 };
+
+/* my local device data - MAC address */
+uint8_t Ethernet_MAC_Address[MAX_MAC_LEN] = { 0 };
+
+/* couple of var for using winpcap */
+static char pcap_errbuf[PCAP_ERRBUF_SIZE + 1];
+static pcap_t *pcap_eth802_fp = NULL; /* 802.2 file handle, from winpcap */
+static unsigned eth_timeout = 100;
+
+
+/* couple of external func for runtime error logging, you can simply */
+/* replace them with standard "printf(...)" */
+/* Logging extern functions: Info level */
+extern void LogInfo(const char *msg);
+/* Logging extern functions: Error level*/
+extern void LogError(const char *msg);
+/* Logging extern functions: Debug level*/
+extern void LogDebug(const char *msg);
+
+
+bool ethernet_valid(void)
+{
+ return (pcap_eth802_fp != NULL);
+}
+
+void ethernet_cleanup(void)
+{
+ if (pcap_eth802_fp) {
+ pcap_close(pcap_eth802_fp);
+ pcap_eth802_fp = NULL;
+ }
+ LogInfo("ethernet.c: ethernet_cleanup() ok.\n");
+}
+
+void ethernet_set_timeout(unsigned timeout)
+{
+ eth_timeout = timeout;
+}
+
+/*----------------------------------------------------------------------
+ Portable function to set a socket into nonblocking mode.
+ Calling this on a socket causes all future read() and write() calls on
+ that socket to do only as much as they can immediately, and return
+ without waiting.
+ If no data can be read or written, they return -1 and set errno
+ to EAGAIN (or EWOULDBLOCK).
+ Thanks to Bjorn Reese for this code.
+----------------------------------------------------------------------*/
+/**
+ * We don't need to use this function since WinPCap has provided one
+ * named "pcap_setnonblock()".
+ * Kevin, 2006.08.15
+ */
+/*
+int setNonblocking(int fd)
+{
+ int flags;
+
+ if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
+ flags = 0;
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+}
+*/
+
+bool ethernet_init(char *if_name)
+{
+ PPACKET_OID_DATA pOidData;
+ LPADAPTER lpAdapter;
+ pcap_if_t *pcap_all_if;
+ pcap_if_t *dev;
+ BOOLEAN result;
+ CHAR str[sizeof(PACKET_OID_DATA) + 128];
+ int i;
+ char msgBuf[200];
+
+ if (ethernet_valid())
+ ethernet_cleanup();
+
+ /**
+ * Find the interface user specified
+ */
+ /* Retrieve the device list */
+ if (pcap_findalldevs(&pcap_all_if, pcap_errbuf) == -1) {
+ sprintf(msgBuf,
+ "ethernet.c: error in pcap_findalldevs: %s\n", pcap_errbuf);
+ LogError(msgBuf);
+ return false;
+ }
+ /* Scan the list printing every entry */
+ for (dev = pcap_all_if; dev; dev = dev->next) {
+ if (strcmp(if_name, dev->name) == 0)
+ break;
+ }
+ pcap_freealldevs(pcap_all_if); /* we don't need it anymore */
+ if (dev == NULL) {
+ sprintf(msgBuf,
+ "ethernet.c: specified interface not found: %s\n", if_name);
+ LogError(msgBuf);
+ return false;
+ }
+
+ /**
+ * Get local MAC address
+ */
+ ZeroMemory(str, sizeof(PACKET_OID_DATA) + 128);
+ lpAdapter = PacketOpenAdapter(if_name);
+ if (lpAdapter == NULL) {
+ ethernet_cleanup();
+ sprintf(msgBuf,
+ "ethernet.c: error in PacketOpenAdapter(\"%s\")\n", if_name);
+ LogError(msgBuf);
+ return false;
+ }
+ pOidData = (PPACKET_OID_DATA) str;
+ pOidData->Oid = OID_802_3_CURRENT_ADDRESS;
+ pOidData->Length = 6;
+ result = PacketRequest(lpAdapter, FALSE, pOidData);
+ if (!result) {
+ PacketCloseAdapter(lpAdapter);
+ ethernet_cleanup();
+ LogError("ethernet.c: error in PacketRequest()\n");
+ return false;
+ }
+ for (i = 0; i < 6; ++i)
+ Ethernet_MAC_Address[i] = pOidData->Data[i];
+ PacketCloseAdapter(lpAdapter);
+
+ /**
+ * Open interface for subsequent sending and receiving
+ */
+ /* Open the output device */
+ pcap_eth802_fp = pcap_open(if_name, /* name of the device */
+ MAX_MPDU, /* portion of the packet to capture */
+ PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
+ eth_timeout, /* read timeout */
+ NULL, /* authentication on the remote machine */
+ pcap_errbuf /* error buffer */
+ );
+ if (pcap_eth802_fp == NULL) {
+ PacketCloseAdapter(lpAdapter);
+ ethernet_cleanup();
+ sprintf(msgBuf,
+ "ethernet.c: unable to open the adapter. %s is not supported by WinPcap\n",
+ if_name);
+ LogError(msgBuf);
+ return false;
+ }
+
+ LogInfo("ethernet.c: ethernet_init() ok.\n");
+
+ atexit(ethernet_cleanup);
+
+ return ethernet_valid();
+}
+
+/* function to send a packet out the 802.2 socket */
+/* returns bytes sent success, negative on failure */
+int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
+ BACNET_ADDRESS * src, /* source address */
+ uint8_t * pdu, /* any data to be sent - may be null */
+ unsigned pdu_len /* number of bytes of data */
+ )
+{
+ int bytes = 0;
+ uint8_t mtu[MAX_MPDU] = { 0 };
+ int mtu_len = 0;
+ int i = 0;
+
+ /* don't waste time if the socket is not valid */
+ if (!ethernet_valid()) {
+ LogError
+ ("ethernet.c: invalid 802.2 ethernet interface descriptor!\n");
+ return -1;
+ }
+ /* load destination ethernet MAC address */
+ if (dest->mac_len == 6) {
+ for (i = 0; i < 6; i++) {
+ mtu[mtu_len] = dest->mac[i];
+ mtu_len++;
+ }
+ } else {
+ LogError("ethernet.c: invalid destination MAC address!\n");
+ return -2;
+ }
+
+ /* load source ethernet MAC address */
+ if (src->mac_len == 6) {
+ for (i = 0; i < 6; i++) {
+ mtu[mtu_len] = src->mac[i];
+ mtu_len++;
+ }
+ } else {
+ LogError("ethernet.c: invalid source MAC address!\n");
+ return -3;
+ }
+ if ((14 + 3 + pdu_len) > MAX_MPDU) {
+ LogError("ethernet.c: PDU is too big to send!\n");
+ return -4;
+ }
+ /* packet length */
+ mtu_len +=
+ encode_unsigned16(&mtu[12], 3 /*DSAP,SSAP,LLC */ + pdu_len);
+ /* Logical PDU portion */
+ mtu[mtu_len++] = 0x82; /* DSAP for BACnet */
+ mtu[mtu_len++] = 0x82; /* SSAP for BACnet */
+ mtu[mtu_len++] = 0x03; /* Control byte in header */
+ memcpy(&mtu[mtu_len], pdu, pdu_len);
+ mtu_len += pdu_len;
+
+ /* Send the packet */
+ if (pcap_sendpacket(pcap_eth802_fp, mtu, mtu_len) != 0) {
+ /* did it get sent? */
+ char msgBuf[200];
+ sprintf(msgBuf,
+ "ethernet.c: error sending packet: %s\n",
+ pcap_geterr(pcap_eth802_fp));
+ LogError(msgBuf);
+ return -5;
+ }
+
+ return mtu_len;
+}
+
+/* function to send a packet out the 802.2 socket */
+/* returns number of bytes sent on success, negative on failure */
+int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
+ uint8_t * pdu, /* any data to be sent - may be null */
+ unsigned pdu_len /* number of bytes of data */
+ )
+{
+ int i = 0; /* counter */
+ BACNET_ADDRESS src = { 0 }; /* source address */
+
+ for (i = 0; i < 6; i++) {
+ src.mac[i] = Ethernet_MAC_Address[i];
+ src.mac_len++;
+ }
+ /* function to send a packet out the 802.2 socket */
+ /* returns 1 on success, 0 on failure */
+ return ethernet_send(dest, /* destination address */
+ &src, /* source address */
+ pdu, /* any data to be sent - may be null */
+ pdu_len /* number of bytes of data */
+ );
+}
+
+/* receives an 802.2 framed packet */
+/* returns the number of octets in the PDU, or zero on failure */
+uint16_t ethernet_receive(BACNET_ADDRESS * src, /* source address */
+ uint8_t * pdu, /* PDU data */
+ uint16_t max_pdu, /* amount of space available in the PDU */
+ unsigned timeout /* number of milliseconds to wait for a packet. we ommit it due to winpcap API. */
+ )
+{
+ struct pcap_pkthdr *header;
+ int res;
+ u_char *pkt_data;
+ uint16_t pdu_len = 0; /* return value */
+
+ /* Make sure the socket is open */
+ if (!ethernet_valid()) {
+ LogError
+ ("ethernet.c: invalid 802.2 ethernet interface descriptor!\n");
+ return 0;
+ }
+
+ /* Capture a packet */
+ res = pcap_next_ex(pcap_eth802_fp, &header, &pkt_data);
+ if (res < 0) {
+ char msgBuf[200];
+ sprintf(msgBuf,
+ "ethernet.c: error in receiving packet: %s\n",
+ pcap_geterr(pcap_eth802_fp));
+ return 0;
+ } else if (res == 0)
+ return 0;
+
+ if (header->len == 0 || header->caplen == 0)
+ return 0;
+
+ /* the signature of an 802.2 BACnet packet */
+ if ((pkt_data[14] != 0x82) && (pkt_data[15] != 0x82)) {
+ /*eth_log_error("ethernet.c: Non-BACnet packet\n"); */
+ return 0;
+ }
+ /* copy the source address */
+ src->mac_len = 6;
+ memmove(src->mac, &pkt_data[6], 6);
+
+ /* check destination address for when */
+ /* the Ethernet card is in promiscious mode */
+ if ((memcmp(&pkt_data[0], Ethernet_MAC_Address, 6) != 0)
+ && (memcmp(&pkt_data[0], Ethernet_Broadcast, 6) != 0)) {
+ /*eth_log_error( "ethernet.c: This packet isn't for us\n"); */
+ return 0;
+ }
+
+ (void) decode_unsigned16(&pkt_data[12], &pdu_len);
+ pdu_len -= 3 /* DSAP, SSAP, LLC Control */ ;
+ /* copy the buffer into the PDU */
+ if (pdu_len < max_pdu)
+ memmove(&pdu[0], &pkt_data[17], pdu_len);
+ /* ignore packets that are too large */
+ else
+ pdu_len = 0;
+
+ return pdu_len;
+}
+
+void ethernet_set_my_address(BACNET_ADDRESS * my_address)
+{
+ int i = 0;
+
+ for (i = 0; i < 6; i++) {
+ Ethernet_MAC_Address[i] = my_address->mac[i];
+ }
+
+ return;
+}
+
+void ethernet_get_my_address(BACNET_ADDRESS * my_address)
+{
+ int i = 0;
+
+ my_address->mac_len = 0;
+ for (i = 0; i < 6; i++) {
+ my_address->mac[i] = Ethernet_MAC_Address[i];
+ my_address->mac_len++;
+ }
+ my_address->net = 0; /* local only, no routing */
+ my_address->len = 0;
+ for (i = 0; i < MAX_MAC_LEN; i++) {
+ my_address->adr[i] = 0;
+ }
+
+ return;
+}
+
+void ethernet_get_broadcast_address(BACNET_ADDRESS * dest)
+{ /* destination address */
+ int i = 0; /* counter */
+
+ if (dest) {
+ for (i = 0; i < 6; i++) {
+ dest->mac[i] = Ethernet_Broadcast[i];
+ }
+ dest->mac_len = 6;
+ dest->net = BACNET_BROADCAST_NETWORK;
+ dest->len = 0; /* denotes broadcast address */
+ for (i = 0; i < MAX_MAC_LEN; i++) {
+ dest->adr[i] = 0;
+ }
+ }
+
+ return;
+}
+
+void ethernet_debug_address(const char *info, BACNET_ADDRESS * dest)
+{
+ int i = 0; /* counter */
+ char msgBuf[200];
+
+ if (info) {
+ sprintf(msgBuf, "%s", info);
+ LogError(msgBuf);
+ }
+ /* if */
+ if (dest) {
+ sprintf(msgBuf,
+ "Address:\n MAC Length=%d\n MAC Address=", dest->mac_len);
+ LogInfo(msgBuf);
+ for (i = 0; i < MAX_MAC_LEN; i++) {
+ sprintf(msgBuf, "%02X ", (unsigned) dest->mac[i]);
+ LogInfo(msgBuf);
+ } /* for */
+ LogInfo("\n");
+ sprintf(msgBuf,
+ " Net=%hu\n Len=%d\n Adr=", dest->net, dest->len);
+ LogInfo(msgBuf);
+ for (i = 0; i < MAX_MAC_LEN; i++) {
+ sprintf(msgBuf, "%02X ", (unsigned) dest->adr[i]);
+ LogInfo(msgBuf);
+ } /* for */
+ LogInfo("\n");
+ }
+ /* if ( dest ) */
+ return;
+}
diff --git a/bacnet-stack/ports/win32/main.c b/bacnet-stack/ports/win32/main.c
index 7d0d76f8..ee8a84e5 100644
--- a/bacnet-stack/ports/win32/main.c
+++ b/bacnet-stack/ports/win32/main.c
@@ -1,257 +1,257 @@
-/**************************************************************************
-*
-* Copyright (C) 2005 Steve Karg
-*
-* 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.
-*
-*********************************************************************/
-
-/* This is one way to use the embedded BACnet stack under Win32 */
-/* compiled with Borland C++ 5.02 or Visual C++ 6.0 */
-#include
-#include
-#include
-#include
-#include /* for kbhit and getch */
-#include "iam.h"
-#include "address.h"
-#include "config.h"
-#include "bacdef.h"
-#include "npdu.h"
-#include "apdu.h"
-#include "device.h"
-#include "handlers.h"
-#include "client.h"
-#include "datalink.h"
-#include "txbuf.h"
-
-/* buffer used for receive */
-static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
-
-/* send a whois to see who is on the network */
-static bool Who_Is_Request = true;
-bool I_Am_Request = true;
-
-static void Read_Properties(void)
-{
- uint32_t device_id = 0;
- bool status = false;
- unsigned max_apdu = 0;
- BACNET_ADDRESS src;
- bool next_device = false;
- static unsigned index = 0;
- static unsigned property = 0;
- /* list of required (and some optional) properties in the
- Device Object
- note: you could just loop through
- all the properties in all the objects. */
- const int object_props[] = {
- PROP_OBJECT_IDENTIFIER,
- PROP_OBJECT_NAME,
- PROP_OBJECT_TYPE,
- PROP_SYSTEM_STATUS,
- PROP_VENDOR_NAME,
- PROP_VENDOR_IDENTIFIER,
- PROP_MODEL_NAME,
- PROP_FIRMWARE_REVISION,
- PROP_APPLICATION_SOFTWARE_VERSION,
- PROP_PROTOCOL_VERSION,
- PROP_PROTOCOL_CONFORMANCE_CLASS,
- PROP_PROTOCOL_SERVICES_SUPPORTED,
- PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
- PROP_MAX_APDU_LENGTH_ACCEPTED,
- PROP_SEGMENTATION_SUPPORTED,
- PROP_LOCAL_TIME,
- PROP_LOCAL_DATE,
- PROP_UTC_OFFSET,
- PROP_DAYLIGHT_SAVINGS_STATUS,
- PROP_APDU_SEGMENT_TIMEOUT,
- PROP_APDU_TIMEOUT,
- PROP_NUMBER_OF_APDU_RETRIES,
- PROP_TIME_SYNCHRONIZATION_RECIPIENTS,
- PROP_MAX_MASTER,
- PROP_MAX_INFO_FRAMES,
- PROP_DEVICE_ADDRESS_BINDING,
- /* note: PROP_OBJECT_LIST is missing cause
- we need to get it with an index method since
- the list could be very large */
- /* some proprietary properties */
- 514, 515,
- /* end of list */
- -1
- };
-
- if (address_count()) {
- if (address_get_by_index(index, &device_id, &max_apdu, &src)) {
- if (object_props[property] < 0)
- next_device = true;
- else {
- status = Send_Read_Property_Request(device_id, /* destination device */
- OBJECT_DEVICE,
- device_id, object_props[property], BACNET_ARRAY_ALL);
- if (status)
- property++;
- }
- } else
- next_device = true;
- if (next_device) {
- next_device = false;
- index++;
- if (index >= MAX_ADDRESS_CACHE)
- index = 0;
- property = 0;
- }
- }
-
- return;
-}
-
-static void LocalIAmHandler(uint8_t * service_request,
- uint16_t service_len, BACNET_ADDRESS * src)
-{
- int len = 0;
- uint32_t device_id = 0;
- unsigned max_apdu = 0;
- int segmentation = 0;
- uint16_t vendor_id = 0;
-
- (void) src;
- (void) service_len;
- len = iam_decode_service_request(service_request,
- &device_id, &max_apdu, &segmentation, &vendor_id);
- fprintf(stderr, "Received I-Am Request");
- if (len != -1) {
- fprintf(stderr, " from %u!\n", device_id);
- address_add(device_id, max_apdu, src);
- } else
- fprintf(stderr, "!\n");
-
- return;
-}
-
-static void Init_Service_Handlers(void)
-{
- /* we need to handle who-is to support dynamic device binding */
- apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
- handler_who_is);
- apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
- LocalIAmHandler);
-
- /* set the handler for all the services we don't implement */
- /* It is required to send the proper reject message... */
- apdu_set_unrecognized_service_handler_handler
- (handler_unrecognized_service);
- /* we must implement read property - it's required! */
- apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
- handler_read_property);
- apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
- handler_write_property);
- /* handle the data coming back from confirmed requests */
- apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
- handler_read_property_ack);
-}
-
-static void print_address(char *name, BACNET_ADDRESS * dest)
-{ /* destination address */
- int i = 0; /* counter */
-
- if (dest) {
- printf("%s: ", name);
- for (i = 0; i < dest->mac_len; i++) {
- printf("%02X", dest->mac[i]);
- }
- printf("\n");
- }
-}
-
-static void print_address_cache(void)
-{
- int i, j;
- BACNET_ADDRESS address;
- uint32_t device_id = 0;
- unsigned max_apdu = 0;
-
- fprintf(stderr, "Device\tMAC\tMaxAPDU\tNet\n");
- for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
- if (address_get_by_index(i, &device_id, &max_apdu, &address)) {
- fprintf(stderr, "%u\t", device_id);
- for (j = 0; j < address.mac_len; j++) {
- fprintf(stderr, "%02X", address.mac[j]);
- }
- fprintf(stderr, "\t");
- fprintf(stderr, "%hu\t", max_apdu);
- fprintf(stderr, "%hu\n", address.net);
- }
- }
-}
-
-int main(int argc, char *argv[])
-{
- BACNET_ADDRESS src = { 0 }; /* address where message came from */
- uint16_t pdu_len = 0;
- unsigned timeout = 100; /* milliseconds */
- BACNET_ADDRESS my_address, broadcast_address;
-
- (void) argc;
- (void) argv;
- Device_Set_Object_Instance_Number(124);
- Init_Service_Handlers();
- /* init the data link layer */
- if (!datalink_init(NULL))
- return 1;
- datalink_get_broadcast_address(&broadcast_address);
- print_address("Broadcast", &broadcast_address);
- datalink_get_my_address(&my_address);
- print_address("Address", &my_address);
-
- printf("BACnet stack running...\n");
- /* loop forever */
- for (;;) {
- /* input */
-
- /* returns 0 bytes on timeout */
- pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
- /* process */
- if (pdu_len) {
- npdu_handler(&src, &Rx_Buf[0], pdu_len);
- }
- if (I_Am_Request) {
- I_Am_Request = false;
- iam_send(&Handler_Transmit_Buffer[0]);
- } else if (Who_Is_Request) {
- Who_Is_Request = false;
- Send_WhoIs(-1, -1);
- } else {
- Read_Properties();
- }
-
- /* output */
-
- /* blink LEDs, Turn on or off outputs, etc */
-
- /* wait for ESC from keyboard before quitting */
- if (kbhit() && (getch() == 0x1B))
- break;
- }
-
- print_address_cache();
-
- return 0;
-}
+/**************************************************************************
+*
+* Copyright (C) 2005 Steve Karg
+*
+* 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.
+*
+*********************************************************************/
+
+/* This is one way to use the embedded BACnet stack under Win32 */
+/* compiled with Borland C++ 5.02 or Visual C++ 6.0 */
+#include
+#include
+#include
+#include
+#include /* for kbhit and getch */
+#include "iam.h"
+#include "address.h"
+#include "config.h"
+#include "bacdef.h"
+#include "npdu.h"
+#include "apdu.h"
+#include "device.h"
+#include "handlers.h"
+#include "client.h"
+#include "datalink.h"
+#include "txbuf.h"
+
+/* buffer used for receive */
+static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
+
+/* send a whois to see who is on the network */
+static bool Who_Is_Request = true;
+bool I_Am_Request = true;
+
+static void Read_Properties(void)
+{
+ uint32_t device_id = 0;
+ bool status = false;
+ unsigned max_apdu = 0;
+ BACNET_ADDRESS src;
+ bool next_device = false;
+ static unsigned index = 0;
+ static unsigned property = 0;
+ /* list of required (and some optional) properties in the
+ Device Object
+ note: you could just loop through
+ all the properties in all the objects. */
+ const int object_props[] = {
+ PROP_OBJECT_IDENTIFIER,
+ PROP_OBJECT_NAME,
+ PROP_OBJECT_TYPE,
+ PROP_SYSTEM_STATUS,
+ PROP_VENDOR_NAME,
+ PROP_VENDOR_IDENTIFIER,
+ PROP_MODEL_NAME,
+ PROP_FIRMWARE_REVISION,
+ PROP_APPLICATION_SOFTWARE_VERSION,
+ PROP_PROTOCOL_VERSION,
+ PROP_PROTOCOL_CONFORMANCE_CLASS,
+ PROP_PROTOCOL_SERVICES_SUPPORTED,
+ PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
+ PROP_MAX_APDU_LENGTH_ACCEPTED,
+ PROP_SEGMENTATION_SUPPORTED,
+ PROP_LOCAL_TIME,
+ PROP_LOCAL_DATE,
+ PROP_UTC_OFFSET,
+ PROP_DAYLIGHT_SAVINGS_STATUS,
+ PROP_APDU_SEGMENT_TIMEOUT,
+ PROP_APDU_TIMEOUT,
+ PROP_NUMBER_OF_APDU_RETRIES,
+ PROP_TIME_SYNCHRONIZATION_RECIPIENTS,
+ PROP_MAX_MASTER,
+ PROP_MAX_INFO_FRAMES,
+ PROP_DEVICE_ADDRESS_BINDING,
+ /* note: PROP_OBJECT_LIST is missing cause
+ we need to get it with an index method since
+ the list could be very large */
+ /* some proprietary properties */
+ 514, 515,
+ /* end of list */
+ -1
+ };
+
+ if (address_count()) {
+ if (address_get_by_index(index, &device_id, &max_apdu, &src)) {
+ if (object_props[property] < 0)
+ next_device = true;
+ else {
+ status = Send_Read_Property_Request(device_id, /* destination device */
+ OBJECT_DEVICE,
+ device_id, object_props[property], BACNET_ARRAY_ALL);
+ if (status)
+ property++;
+ }
+ } else
+ next_device = true;
+ if (next_device) {
+ next_device = false;
+ index++;
+ if (index >= MAX_ADDRESS_CACHE)
+ index = 0;
+ property = 0;
+ }
+ }
+
+ return;
+}
+
+static void LocalIAmHandler(uint8_t * service_request,
+ uint16_t service_len, BACNET_ADDRESS * src)
+{
+ int len = 0;
+ uint32_t device_id = 0;
+ unsigned max_apdu = 0;
+ int segmentation = 0;
+ uint16_t vendor_id = 0;
+
+ (void) src;
+ (void) service_len;
+ len = iam_decode_service_request(service_request,
+ &device_id, &max_apdu, &segmentation, &vendor_id);
+ fprintf(stderr, "Received I-Am Request");
+ if (len != -1) {
+ fprintf(stderr, " from %u!\n", device_id);
+ address_add(device_id, max_apdu, src);
+ } else
+ fprintf(stderr, "!\n");
+
+ return;
+}
+
+static void Init_Service_Handlers(void)
+{
+ /* we need to handle who-is to support dynamic device binding */
+ apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
+ handler_who_is);
+ apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
+ LocalIAmHandler);
+
+ /* set the handler for all the services we don't implement */
+ /* It is required to send the proper reject message... */
+ apdu_set_unrecognized_service_handler_handler
+ (handler_unrecognized_service);
+ /* we must implement read property - it's required! */
+ apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
+ handler_read_property);
+ apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
+ handler_write_property);
+ /* handle the data coming back from confirmed requests */
+ apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
+ handler_read_property_ack);
+}
+
+static void print_address(char *name, BACNET_ADDRESS * dest)
+{ /* destination address */
+ int i = 0; /* counter */
+
+ if (dest) {
+ printf("%s: ", name);
+ for (i = 0; i < dest->mac_len; i++) {
+ printf("%02X", dest->mac[i]);
+ }
+ printf("\n");
+ }
+}
+
+static void print_address_cache(void)
+{
+ int i, j;
+ BACNET_ADDRESS address;
+ uint32_t device_id = 0;
+ unsigned max_apdu = 0;
+
+ fprintf(stderr, "Device\tMAC\tMaxAPDU\tNet\n");
+ for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
+ if (address_get_by_index(i, &device_id, &max_apdu, &address)) {
+ fprintf(stderr, "%u\t", device_id);
+ for (j = 0; j < address.mac_len; j++) {
+ fprintf(stderr, "%02X", address.mac[j]);
+ }
+ fprintf(stderr, "\t");
+ fprintf(stderr, "%hu\t", max_apdu);
+ fprintf(stderr, "%hu\n", address.net);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ BACNET_ADDRESS src = { 0 }; /* address where message came from */
+ uint16_t pdu_len = 0;
+ unsigned timeout = 100; /* milliseconds */
+ BACNET_ADDRESS my_address, broadcast_address;
+
+ (void) argc;
+ (void) argv;
+ Device_Set_Object_Instance_Number(124);
+ Init_Service_Handlers();
+ /* init the data link layer */
+ if (!datalink_init(NULL))
+ return 1;
+ datalink_get_broadcast_address(&broadcast_address);
+ print_address("Broadcast", &broadcast_address);
+ datalink_get_my_address(&my_address);
+ print_address("Address", &my_address);
+
+ printf("BACnet stack running...\n");
+ /* loop forever */
+ for (;;) {
+ /* input */
+
+ /* returns 0 bytes on timeout */
+ pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
+ /* process */
+ if (pdu_len) {
+ npdu_handler(&src, &Rx_Buf[0], pdu_len);
+ }
+ if (I_Am_Request) {
+ I_Am_Request = false;
+ iam_send(&Handler_Transmit_Buffer[0]);
+ } else if (Who_Is_Request) {
+ Who_Is_Request = false;
+ Send_WhoIs(-1, -1);
+ } else {
+ Read_Properties();
+ }
+
+ /* output */
+
+ /* blink LEDs, Turn on or off outputs, etc */
+
+ /* wait for ESC from keyboard before quitting */
+ if (kbhit() && (getch() == 0x1B))
+ break;
+ }
+
+ print_address_cache();
+
+ return 0;
+}
diff --git a/bacnet-stack/ports/win32/net.h b/bacnet-stack/ports/win32/net.h
index a717cf7b..58145a9b 100644
--- a/bacnet-stack/ports/win32/net.h
+++ b/bacnet-stack/ports/win32/net.h
@@ -1,38 +1,38 @@
-/**************************************************************************
-*
-* Copyright (C) 2005 Steve Karg
-*
-* 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 NET_H
-#define NET_H
-
-#define WIN32_LEAN_AND_MEAN
-#define STRICT 1
-
-#include
-
-#define close closesocket
-
-typedef int socklen_t;
-
-#endif
+/**************************************************************************
+*
+* Copyright (C) 2005 Steve Karg
+*
+* 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 NET_H
+#define NET_H
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT 1
+
+#include
+
+#define close closesocket
+
+typedef int socklen_t;
+
+#endif
diff --git a/bacnet-stack/ports/win32/readme.txt b/bacnet-stack/ports/win32/readme.txt
index a5bd7030..90b110f0 100644
--- a/bacnet-stack/ports/win32/readme.txt
+++ b/bacnet-stack/ports/win32/readme.txt
@@ -1,15 +1,15 @@
-BACnet Stack - Win32
-
-This directory contains a demo program that compiles with a Win32 compiler.
-It was tested with the freely downloadable Borland C++ 5.5, as well as
-Borland C++ 5 and Visual C++ 6.0.
-
-The makefile.mak file is used with the Borland command line tools.
-Run setvars.bat to configure the environment for the Borland tools.
-Edit it if necessary to set the correct location of your tools.
-
-The bacnet.ide file is used with the Borland IDE.
-
-The bacnet directory is used with Visual C++ 6 tools, and there is a
-workspace file bacnet.dsw that is used to compile the demo program.
-
+BACnet Stack - Win32
+
+This directory contains a demo program that compiles with a Win32 compiler.
+It was tested with the freely downloadable Borland C++ 5.5, as well as
+Borland C++ 5 and Visual C++ 6.0.
+
+The makefile.mak file is used with the Borland command line tools.
+Run setvars.bat to configure the environment for the Borland tools.
+Edit it if necessary to set the correct location of your tools.
+
+The bacnet.ide file is used with the Borland IDE.
+
+The bacnet directory is used with Visual C++ 6 tools, and there is a
+workspace file bacnet.dsw that is used to compile the demo program.
+
diff --git a/bacnet-stack/ports/win32/setvars.bat b/bacnet-stack/ports/win32/setvars.bat
index 6a804123..fb8fe9cc 100644
--- a/bacnet-stack/ports/win32/setvars.bat
+++ b/bacnet-stack/ports/win32/setvars.bat
@@ -1,2 +1,2 @@
-set BORLAND_DIR=\bcc55
-
+set BORLAND_DIR=\bcc55
+
diff --git a/bacnet-stack/ports/win32/stdbool.h b/bacnet-stack/ports/win32/stdbool.h
index 2b7511a6..4c05de20 100644
--- a/bacnet-stack/ports/win32/stdbool.h
+++ b/bacnet-stack/ports/win32/stdbool.h
@@ -1,28 +1,28 @@
-#ifndef STDBOOL_H
-#define STDBOOL_H
-
-/* C99 Boolean types for compilers without C99 support */
-
-#ifndef __cplusplus
-typedef int _Bool;
-#ifndef bool
-#define bool _Bool
-#endif
-#ifndef true
-#define true 1
-#endif
-#ifndef false
-#define false 0
-#endif
-#define __bool_true_false_are_defined 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#endif
+#ifndef STDBOOL_H
+#define STDBOOL_H
+
+/* C99 Boolean types for compilers without C99 support */
+
+#ifndef __cplusplus
+typedef int _Bool;
+#ifndef bool
+#define bool _Bool
+#endif
+#ifndef true
+#define true 1
+#endif
+#ifndef false
+#define false 0
+#endif
+#define __bool_true_false_are_defined 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#endif
diff --git a/bacnet-stack/ports/win32/stdint.h b/bacnet-stack/ports/win32/stdint.h
index 9c003d0a..3bd54ae8 100644
--- a/bacnet-stack/ports/win32/stdint.h
+++ b/bacnet-stack/ports/win32/stdint.h
@@ -1,19 +1,19 @@
-/* Defines the standard integer types that are used in code */
-/* for the x86 processor and Borland Compiler */
-
-#ifndef STDINT_H
-#define STDINT_H
-
-#include
-
-typedef unsigned char uint8_t; /* 1 byte 0 to 255 */
-typedef signed char int8_t; /* 1 byte -127 to 127 */
-typedef unsigned short uint16_t; /* 2 bytes 0 to 65535 */
-typedef signed short int16_t; /* 2 bytes -32767 to 32767 */
-/*typedef unsigned short long uint24_t; // 3 bytes 0 to 16777215 */
-typedef unsigned long uint32_t; /* 4 bytes 0 to 4294967295 */
-typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
-/* typedef signed long long int64_t; */
-/* typedef unsigned long long uint64_t; */
-
-#endif /* STDINT_H */
+/* Defines the standard integer types that are used in code */
+/* for the x86 processor and Borland Compiler */
+
+#ifndef STDINT_H
+#define STDINT_H
+
+#include
+
+typedef unsigned char uint8_t; /* 1 byte 0 to 255 */
+typedef signed char int8_t; /* 1 byte -127 to 127 */
+typedef unsigned short uint16_t; /* 2 bytes 0 to 65535 */
+typedef signed short int16_t; /* 2 bytes -32767 to 32767 */
+/*typedef unsigned short long uint24_t; // 3 bytes 0 to 16777215 */
+typedef unsigned long uint32_t; /* 4 bytes 0 to 4294967295 */
+typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
+/* typedef signed long long int64_t; */
+/* typedef unsigned long long uint64_t; */
+
+#endif /* STDINT_H */