diff --git a/CMakeLists.txt b/CMakeLists.txt
index cf31fc89..7cd47231 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -369,6 +369,8 @@ add_library(${PROJECT_NAME}
src/bacnet/get_alarm_sum.h
src/bacnet/getevent.c
src/bacnet/getevent.h
+ src/bacnet/hostnport.c
+ src/bacnet/hostnport.h
src/bacnet/iam.c
src/bacnet/iam.h
src/bacnet/ihave.c
diff --git a/Makefile b/Makefile
index 3c0ee5e9..f43fad61 100644
--- a/Makefile
+++ b/Makefile
@@ -212,6 +212,11 @@ pretty-ports:
find ./ports -maxdepth 2 -type f -iname *.h -o -iname *.c -exec \
clang-format -i -style=file -fallback-style=none {} \;
+.PHONY: pretty-test
+pretty-test:
+ find ./test/bacnet -maxdepth 2 -type f -iname *.h -o -iname *.c -exec \
+ clang-format -i -style=file -fallback-style=none {} \;
+
CLANG_TIDY_OPTIONS = -fix-errors -checks="readability-braces-around-statements"
CLANG_TIDY_OPTIONS += -- -Isrc -Iports/linux
.PHONY: tidy
diff --git a/ports/at91sam7s/Makefile b/ports/at91sam7s/Makefile
index c207e07d..9db9fb54 100644
--- a/ports/at91sam7s/Makefile
+++ b/ports/at91sam7s/Makefile
@@ -81,6 +81,7 @@ CORESRC = $(BACNET_CORE)/abort.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/bacapp.c \
$(BACNET_CORE)/bacdcode.c \
+ $(BACNET_CORE)/bacdevobjpropref.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
@@ -90,6 +91,7 @@ CORESRC = $(BACNET_CORE)/abort.c \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/ihave.c \
+ $(BACNET_CORE)/hostnport.c \
$(BACNET_CORE)/lighting.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/npdu.c \
diff --git a/ports/at91sam7s/bacnet.ewp b/ports/at91sam7s/bacnet.ewp
index 1ff4a2a6..bd4ee565 100644
--- a/ports/at91sam7s/bacnet.ewp
+++ b/ports/at91sam7s/bacnet.ewp
@@ -1,1134 +1,1233 @@
-
-
+
- 2
-
- Debug
-
- ARM
-
- 1
-
- General
- 3
-
- 24
- 1
+ 3
+
+ Debug
+
+ ARM
+
1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ICCARM
- 2
-
- 31
- 1
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AARM
- 2
-
- 9
- 1
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OBJCOPY
- 0
-
- 1
- 1
- 1
-
-
-
-
-
-
-
-
- CUSTOM
- 3
-
-
-
- 0
-
-
-
- BICOMP
- 0
-
-
-
- BUILDACTION
- 1
-
-
-
-
-
-
- ILINK
- 0
-
- 17
- 1
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- IARCHIVE
- 0
-
- 0
- 1
- 1
-
-
-
-
-
-
- BILINK
- 0
-
-
-
-
- BACnet-Basic
+
+ General
+ 3
+
+ 31
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ICCARM
+ 2
+
+ 36
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AARM
+ 2
+
+ 10
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ OBJCOPY
+ 0
+
+ 1
+ 1
+ 1
+
+
+
+
+
+
+
+
+ CUSTOM
+ 3
+
+
+
+ 0
+
+
+
+ BICOMP
+ 0
+
+
+
+ BUILDACTION
+ 1
+
+
+
+
+
+
+ ILINK
+ 0
+
+ 23
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IARCHIVE
+ 0
+
+ 0
+ 1
+ 1
+
+
+
+
+
+
+ BILINK
+ 0
+
+
+
+
+ BACnet-Basic
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\sys\bigend.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_apdu.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_dcc.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_noserv.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\npdu\h_npdu.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_rd.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_rp.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_rpm.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_whohas.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_whois.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\h_wp.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\sys\ringbuf.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\s_iam.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\service\s_ihave.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\basic\tsm\tsm.c
+
+
+
+ BACnet-Core
+
+ $PROJ_DIR$\..\..\src\bacnet\abort.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\bacaddr.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\bacapp.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\bacdcode.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\bacdevobjpropref.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\bacerror.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\bacint.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\bacreal.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\bacstr.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\datalink\crc.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\datetime.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\dcc.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\hostnport.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\iam.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\ihave.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\lighting.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\memcopy.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\npdu.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\proplist.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\rd.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\reject.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\rp.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\rpm.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\whohas.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\whois.c
+
+
+ $PROJ_DIR$\..\..\src\bacnet\wp.c
+
+
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_apdu.c
+ $PROJ_DIR$\ai.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_dcc.c
+ $PROJ_DIR$\av.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_noserv.c
+ $PROJ_DIR$\bi.c
- $PROJ_DIR$\..\..\src\bacnet\basic\npdu\h_npdu.c
+ $PROJ_DIR$\blinker.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_rd.c
+ $PROJ_DIR$\bv.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_rp.c
+ $PROJ_DIR$\device.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_rpm.c
+ $PROJ_DIR$\dlmstp.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_whohas.c
+ $PROJ_DIR$\init.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_whois.c
+ $PROJ_DIR$\isr.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\h_wp.c
+ $PROJ_DIR$\main.c
- $PROJ_DIR$\..\..\src\bacnet\basic\sys\ringbuf.c
+ $PROJ_DIR$\netport.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\s_iam.c
+ $PROJ_DIR$\rs485.c
- $PROJ_DIR$\..\..\src\bacnet\basic\service\s_ihave.c
+ $PROJ_DIR$\timer.c
-
- $PROJ_DIR$\..\..\src\bacnet\basic\tsm\tsm.c
-
-
-
- BACnet-Core
-
- $PROJ_DIR$\..\..\src\bacnet\abort.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\bacaddr.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\bacapp.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\bacdcode.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\bacdevobjpropref.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\bacerror.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\bacint.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\bacreal.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\bacstr.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\datalink\crc.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\datetime.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\dcc.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\iam.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\ihave.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\lighting.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\memcopy.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\npdu.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\proplist.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\rd.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\reject.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\rp.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\rpm.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\whohas.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\whois.c
-
-
- $PROJ_DIR$\..\..\src\bacnet\wp.c
-
-
-
- $PROJ_DIR$\ai.c
-
-
- $PROJ_DIR$\av.c
-
-
- $PROJ_DIR$\bi.c
-
-
- $PROJ_DIR$\blinker.c
-
-
- $PROJ_DIR$\bv.c
-
-
- $PROJ_DIR$\device.c
-
-
- $PROJ_DIR$\netport.c
-
-
- $PROJ_DIR$\dlmstp.c
-
-
- $PROJ_DIR$\init.c
-
-
- $PROJ_DIR$\isr.c
-
-
- $PROJ_DIR$\main.c
-
-
- $PROJ_DIR$\rs485.c
-
-
- $PROJ_DIR$\timer.c
-
-
-
diff --git a/ports/bdk-atxx4-mstp/bacnet.cproj b/ports/bdk-atxx4-mstp/bacnet.cproj
index 28acd2a6..73f9e8f9 100644
--- a/ports/bdk-atxx4-mstp/bacnet.cproj
+++ b/ports/bdk-atxx4-mstp/bacnet.cproj
@@ -359,6 +359,10 @@
compile
BACnet Core\bacdcode.c
+
+ compile
+ BACnet Core\bacdevobjpropref.c
+
compile
BACnet Core\bacerror.c
@@ -395,6 +399,10 @@
compile
BACnet Core\ihave.c
+
+ compile
+ BACnet Core\hostnport.c
+
compile
BACnet Core\lighting.c
diff --git a/ports/bdk-atxx4-mstp/bacnet.ewp b/ports/bdk-atxx4-mstp/bacnet.ewp
index 19c85171..7500b152 100644
--- a/ports/bdk-atxx4-mstp/bacnet.ewp
+++ b/ports/bdk-atxx4-mstp/bacnet.ewp
@@ -4442,6 +4442,9 @@
$PROJ_DIR$\mstimer-init.c
+
+ $PROJ_DIR$\netport.c
+
$PROJ_DIR$\rs485.c
diff --git a/ports/esp32/readme.txt b/ports/esp32/readme.txt
index 05ba58cb..55191c94 100644
--- a/ports/esp32/readme.txt
+++ b/ports/esp32/readme.txt
@@ -38,6 +38,7 @@ Goto lib/stack and copy the requested files from Steve code :
h_whois.c
h_wp.c
iam.c
+ hostnport.c
lighting.c
memcopy.c
noserv.c
diff --git a/ports/pic18f6720/BACnet-Server.X/nbproject/Makefile-genesis.properties b/ports/pic18f6720/BACnet-Server.X/nbproject/Makefile-genesis.properties
index f3e0aab6..b3bd2089 100644
--- a/ports/pic18f6720/BACnet-Server.X/nbproject/Makefile-genesis.properties
+++ b/ports/pic18f6720/BACnet-Server.X/nbproject/Makefile-genesis.properties
@@ -1,8 +1,6 @@
#
-#Mon May 30 09:47:38 CDT 2016
-default.com-microchip-mplab-nbide-toolchainC18-C18LanguageToolchain.md5=21ae92f54c0f89bc027339aedc19b7f9
-default.languagetoolchain.dir=C\:\\Program Files (x86)\\Microchip\\mplabc18\\v3.40\\bin
-com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=ef199adcc8f049579a105cca20571dcb
-default.languagetoolchain.version=3.40
-host.platform=windows
-conf.ids=default
+#Sun Aug 22 10:50:21 CDT 2021
+configurations-xml=76d5fe9d80d284cbe317219a22001b30
+com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=9db8f8a224aa17d0023ea7f468f871dc
+host.platform=linux
+conf.ids=
diff --git a/ports/pic18f6720/BACnet-Server.X/nbproject/configurations.xml b/ports/pic18f6720/BACnet-Server.X/nbproject/configurations.xml
index 3c186e58..af276e1d 100644
--- a/ports/pic18f6720/BACnet-Server.X/nbproject/configurations.xml
+++ b/ports/pic18f6720/BACnet-Server.X/nbproject/configurations.xml
@@ -1,5 +1,5 @@
-
+
3.40
3
+
+
+
+
+
+
+
false
+ false
+
+
false
diff --git a/ports/pic18f6720/BACnet-Server.X/nbproject/project.xml b/ports/pic18f6720/BACnet-Server.X/nbproject/project.xml
index b7fe3eff..12dadd53 100644
--- a/ports/pic18f6720/BACnet-Server.X/nbproject/project.xml
+++ b/ports/pic18f6720/BACnet-Server.X/nbproject/project.xml
@@ -10,7 +10,20 @@
h
ISO-8859-1
+
+
+ ../
+
+
+
+ default
+ 2
+
+
+
+ false
+
diff --git a/ports/stm32f10x/Makefile b/ports/stm32f10x/Makefile
index c4d12391..b306f72d 100644
--- a/ports/stm32f10x/Makefile
+++ b/ports/stm32f10x/Makefile
@@ -55,6 +55,7 @@ BACNET_SRC = \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/bacapp.c \
$(BACNET_CORE)/bacdcode.c \
+ $(BACNET_CORE)/bacdevobjpropref.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
@@ -63,6 +64,7 @@ BACNET_SRC = \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/ihave.c \
+ $(BACNET_CORE)/hostnport.c \
$(BACNET_CORE)/lighting.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/npdu.c \
diff --git a/ports/stm32f10x/bacnet.ewp b/ports/stm32f10x/bacnet.ewp
index 4160746b..7c7b4416 100644
--- a/ports/stm32f10x/bacnet.ewp
+++ b/ports/stm32f10x/bacnet.ewp
@@ -1057,6 +1057,9 @@
$PROJ_DIR$\..\..\src\bacnet\bacdcode.c
+
+ $PROJ_DIR$\..\..\src\bacnet\bacdevobjpropref.c
+
$PROJ_DIR$\..\..\src\bacnet\bacerror.c
@@ -1078,6 +1081,9 @@
$PROJ_DIR$\..\..\src\bacnet\ihave.c
+
+ $PROJ_DIR$\..\..\src\bacnet\hostnport.c
+
$PROJ_DIR$\..\..\src\bacnet\lighting.c
diff --git a/ports/stm32f4xx/Makefile b/ports/stm32f4xx/Makefile
index 4712d38a..d393319a 100644
--- a/ports/stm32f4xx/Makefile
+++ b/ports/stm32f4xx/Makefile
@@ -53,6 +53,7 @@ BACNET_SRC = \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/bacapp.c \
$(BACNET_CORE)/bacdcode.c \
+ $(BACNET_CORE)/bacdevobjpropref.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
@@ -61,6 +62,7 @@ BACNET_SRC = \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/ihave.c \
+ $(BACNET_CORE)/hostnport.c \
$(BACNET_CORE)/lighting.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/npdu.c \
diff --git a/ports/stm32f4xx/bacnet.ewp b/ports/stm32f4xx/bacnet.ewp
index d49f1e6d..1977e427 100644
--- a/ports/stm32f4xx/bacnet.ewp
+++ b/ports/stm32f4xx/bacnet.ewp
@@ -1090,6 +1090,9 @@
$PROJ_DIR$\..\..\src\bacnet\ihave.c
+
+ $PROJ_DIR$\..\..\src\bacnet\hostnport.c
+
$PROJ_DIR$\..\..\src\bacnet\lighting.c
diff --git a/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj b/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj
index 0ec0acf4..e2a343f9 100644
--- a/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj
+++ b/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj
@@ -198,6 +198,7 @@
+
diff --git a/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj.filters b/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj.filters
index 88b31647..c68efa7c 100644
--- a/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj.filters
+++ b/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj.filters
@@ -90,6 +90,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/ports/xplained/bacnet.cproj b/ports/xplained/bacnet.cproj
index 08e7bfb5..1685112c 100644
--- a/ports/xplained/bacnet.cproj
+++ b/ports/xplained/bacnet.cproj
@@ -586,6 +586,10 @@
compile
+
+ compile
+ bacnet-stack\hostnport.c
+
compile
bacnet-stack\lighting.c
@@ -768,6 +772,10 @@
compile
bacnet-stack\bacdcode.c
+
+ compile
+ bacnet-stack\bacdevobjpropref.c
+
compile
bacnet-stack\bacerror.c
diff --git a/ports/xplained/bname.c b/ports/xplained/bname.c
index 45c2c893..4aea5f81 100644
--- a/ports/xplained/bname.c
+++ b/ports/xplained/bname.c
@@ -166,7 +166,7 @@ bool bacnet_name_write_unique(uint16_t offset,
bool status = false;
size_t length = 0;
uint8_t encoding = 0;
- int duplicate_type = 0;
+ BACNET_OBJECT_TYPE duplicate_type = 0;
uint32_t duplicate_instance = 0;
length = characterstring_length(char_string);
diff --git a/src/bacnet/bacapp.c b/src/bacnet/bacapp.c
index 5afdb752..27c47b9c 100644
--- a/src/bacnet/bacapp.c
+++ b/src/bacnet/bacapp.c
@@ -51,120 +51,120 @@
#include "bacnet/datetime.h"
#include "bacnet/bacstr.h"
#include "bacnet/lighting.h"
-#if defined(BACAPP_HOST_N_PORT)
-#include "bacnet/datalink/datalink.h"
-#endif
+#include "bacnet/hostnport.h"
/** @file bacapp.c Utilities for the BACnet_Application_Data_Value */
-/** @brief Encode application data given by a pointer into the APDU.
- * Return the number encoded bytes.
- *
- * @param apdu Pointer to the buffer to encode to.
- * @param value Pointer to the application data.
- *
- * @return Bytes encoded.
+/**
+ * @brief Encode application data given by a pointer into the APDU.
+ * @param apdu - Pointer to the buffer to encode to, or NULL for length
+ * @param value - Pointer to the application data value to encode from
+ * @return number of bytes encoded
*/
int bacapp_encode_application_data(
uint8_t *apdu, BACNET_APPLICATION_DATA_VALUE *value)
{
int apdu_len = 0; /* total length of the apdu, return value */
- if (value && apdu) {
+ if (value) {
switch (value->tag) {
#if defined(BACAPP_NULL)
case BACNET_APPLICATION_TAG_NULL:
- apdu[0] = value->tag;
+ if (apdu) {
+ apdu[0] = value->tag;
+ }
apdu_len++;
break;
#endif
#if defined(BACAPP_BOOLEAN)
case BACNET_APPLICATION_TAG_BOOLEAN:
apdu_len =
- encode_application_boolean(&apdu[0], value->type.Boolean);
+ encode_application_boolean(apdu, value->type.Boolean);
break;
#endif
#if defined(BACAPP_UNSIGNED)
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
apdu_len = encode_application_unsigned(
- &apdu[0], value->type.Unsigned_Int);
+ apdu, value->type.Unsigned_Int);
break;
#endif
#if defined(BACAPP_SIGNED)
case BACNET_APPLICATION_TAG_SIGNED_INT:
apdu_len =
- encode_application_signed(&apdu[0], value->type.Signed_Int);
+ encode_application_signed(apdu, value->type.Signed_Int);
break;
#endif
#if defined(BACAPP_REAL)
case BACNET_APPLICATION_TAG_REAL:
- apdu_len = encode_application_real(&apdu[0], value->type.Real);
+ apdu_len = encode_application_real(apdu, value->type.Real);
break;
#endif
#if defined(BACAPP_DOUBLE)
case BACNET_APPLICATION_TAG_DOUBLE:
apdu_len =
- encode_application_double(&apdu[0], value->type.Double);
+ encode_application_double(apdu, value->type.Double);
break;
#endif
#if defined(BACAPP_OCTET_STRING)
case BACNET_APPLICATION_TAG_OCTET_STRING:
apdu_len = encode_application_octet_string(
- &apdu[0], &value->type.Octet_String);
+ apdu, &value->type.Octet_String);
break;
#endif
#if defined(BACAPP_CHARACTER_STRING)
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
apdu_len = encode_application_character_string(
- &apdu[0], &value->type.Character_String);
+ apdu, &value->type.Character_String);
break;
#endif
#if defined(BACAPP_BIT_STRING)
case BACNET_APPLICATION_TAG_BIT_STRING:
apdu_len = encode_application_bitstring(
- &apdu[0], &value->type.Bit_String);
+ apdu, &value->type.Bit_String);
break;
#endif
#if defined(BACAPP_ENUMERATED)
case BACNET_APPLICATION_TAG_ENUMERATED:
apdu_len = encode_application_enumerated(
- &apdu[0], value->type.Enumerated);
+ apdu, value->type.Enumerated);
break;
#endif
#if defined(BACAPP_DATE)
case BACNET_APPLICATION_TAG_DATE:
- apdu_len = encode_application_date(&apdu[0], &value->type.Date);
+ apdu_len = encode_application_date(apdu, &value->type.Date);
break;
#endif
#if defined(BACAPP_TIME)
case BACNET_APPLICATION_TAG_TIME:
- apdu_len = encode_application_time(&apdu[0], &value->type.Time);
+ apdu_len = encode_application_time(apdu, &value->type.Time);
break;
#endif
#if defined(BACAPP_OBJECT_ID)
case BACNET_APPLICATION_TAG_OBJECT_ID:
- apdu_len = encode_application_object_id(&apdu[0],
+ apdu_len = encode_application_object_id(apdu,
value->type.Object_Id.type, value->type.Object_Id.instance);
break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND)
- case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
- apdu_len = lighting_command_encode(
- &apdu[0], &value->type.Lighting_Command);
+#if defined (BACAPP_TYPES_EXTRA)
+ case BACNET_APPLICATION_TAG_EMPTYLIST:
+ /* Empty data list */
+ apdu_len = 0; /* EMPTY */
break;
-#endif
-#if defined(BACAPP_HOST_N_PORT)
- case BACNET_APPLICATION_TAG_HOST_N_PORT:
- apdu_len = bvlc_foreign_device_bbmd_host_address_encode(
- &apdu[0], MAX_APDU, &value->type.IP_Address);
break;
-#endif
-#if defined(BACAPP_DEVICE_OBJECT_PROP_REF)
+ case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
+ /* BACnetLightingCommand */
+ apdu_len = lighting_command_encode(
+ apdu, &value->type.Lighting_Command);
+ break;
+ case BACNET_APPLICATION_TAG_HOST_N_PORT:
+ apdu_len = host_n_port_encode(apdu,
+ &value->type.Host_Address);
+ break;
case BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE:
/* BACnetDeviceObjectPropertyReference */
apdu_len = bacapp_encode_device_obj_property_ref(
- &apdu[0], &value->type.Device_Object_Property_Reference);
+ apdu, &value->type.Device_Object_Property_Reference);
break;
#endif
default:
@@ -177,8 +177,6 @@ int bacapp_encode_application_data(
/**
* @brief Decode the data and store it into value.
- * Return the number of octets consumed.
- *
* @param apdu Receive buffer
* @param tag_data_type Data type of the given tag
* @param len_value_type Count of bytes of given tag
@@ -194,7 +192,7 @@ int bacapp_decode_data(uint8_t *apdu,
{
int len = 0;
- if (apdu && value) {
+ if (value) {
switch (tag_data_type) {
#if defined(BACAPP_NULL)
case BACNET_APPLICATION_TAG_NULL:
@@ -209,86 +207,88 @@ int bacapp_decode_data(uint8_t *apdu,
#if defined(BACAPP_UNSIGNED)
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
len = decode_unsigned(
- &apdu[0], len_value_type, &value->type.Unsigned_Int);
+ apdu, len_value_type, &value->type.Unsigned_Int);
break;
#endif
#if defined(BACAPP_SIGNED)
case BACNET_APPLICATION_TAG_SIGNED_INT:
len = decode_signed(
- &apdu[0], len_value_type, &value->type.Signed_Int);
+ apdu, len_value_type, &value->type.Signed_Int);
break;
#endif
#if defined(BACAPP_REAL)
case BACNET_APPLICATION_TAG_REAL:
len = decode_real_safe(
- &apdu[0], len_value_type, &(value->type.Real));
+ apdu, len_value_type, &(value->type.Real));
break;
#endif
#if defined(BACAPP_DOUBLE)
case BACNET_APPLICATION_TAG_DOUBLE:
len = decode_double_safe(
- &apdu[0], len_value_type, &(value->type.Double));
+ apdu, len_value_type, &(value->type.Double));
break;
#endif
#if defined(BACAPP_OCTET_STRING)
case BACNET_APPLICATION_TAG_OCTET_STRING:
len = decode_octet_string(
- &apdu[0], len_value_type, &value->type.Octet_String);
+ apdu, len_value_type, &value->type.Octet_String);
break;
#endif
#if defined(BACAPP_CHARACTER_STRING)
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
len = decode_character_string(
- &apdu[0], len_value_type, &value->type.Character_String);
+ apdu, len_value_type, &value->type.Character_String);
break;
#endif
#if defined(BACAPP_BIT_STRING)
case BACNET_APPLICATION_TAG_BIT_STRING:
len = decode_bitstring(
- &apdu[0], len_value_type, &value->type.Bit_String);
+ apdu, len_value_type, &value->type.Bit_String);
break;
#endif
#if defined(BACAPP_ENUMERATED)
case BACNET_APPLICATION_TAG_ENUMERATED:
len = decode_enumerated(
- &apdu[0], len_value_type, &value->type.Enumerated);
+ apdu, len_value_type, &value->type.Enumerated);
break;
#endif
#if defined(BACAPP_DATE)
case BACNET_APPLICATION_TAG_DATE:
len = decode_date_safe(
- &apdu[0], len_value_type, &value->type.Date);
+ apdu, len_value_type, &value->type.Date);
break;
#endif
#if defined(BACAPP_TIME)
case BACNET_APPLICATION_TAG_TIME:
len = decode_bacnet_time_safe(
- &apdu[0], len_value_type, &value->type.Time);
+ apdu, len_value_type, &value->type.Time);
break;
#endif
#if defined(BACAPP_OBJECT_ID)
case BACNET_APPLICATION_TAG_OBJECT_ID: {
BACNET_OBJECT_TYPE object_type = OBJECT_NONE;
uint32_t instance = 0;
- len = bacnet_object_id_decode(
- &apdu[0], len_value_type, &object_type, &instance);
+ len = decode_object_id_safe(
+ apdu, len_value_type, &object_type, &instance);
value->type.Object_Id.type = object_type;
value->type.Object_Id.instance = instance;
} break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined (BACAPP_TYPES_EXTRA)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
len = lighting_command_decode(
- &apdu[0], len_value_type, &value->type.Lighting_Command);
+ apdu, len_value_type, &value->type.Lighting_Command);
+ break;
+ case BACNET_APPLICATION_TAG_HOST_N_PORT:
+ len = host_n_port_decode(
+ apdu, len_value_type, NULL,
+ &value->type.Host_Address);
+ break;
+ case BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE:
+ /* BACnetDeviceObjectPropertyReference */
+ len = bacapp_decode_device_obj_property_ref(
+ apdu, &value->type.Device_Object_Property_Reference);
break;
-#endif
-#if defined(BACAPP_HOST_N_PORT)
- case BACNET_APPLICATION_TAG_HOST_N_PORT: {
- BACNET_ERROR_CODE error_code;
- len = bvlc_foreign_device_bbmd_host_address_decode(
- &apdu[0], len_value_type, &error_code,
- &value->type.IP_Address);
- } break;
#endif
default:
break;
@@ -401,8 +401,7 @@ bool bacapp_decode_application_data_safe(uint8_t *new_apdu,
apdu_len += tag_len;
apdu_len_remaining -= tag_len;
/* The tag is boolean then len_value_type is interpreted as value,
- *not length, so don't bother
- ** checking with apdu_len_remaining */
+ not length, so don't bother checking with apdu_len_remaining */
if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN ||
len_value_type <= apdu_len_remaining) {
value->tag = tag_number;
@@ -420,14 +419,12 @@ bool bacapp_decode_application_data_safe(uint8_t *new_apdu,
return ret;
}
-/** @brief Decode the data and
- * return the number of octets consumed.
- *
+/**
+ * @brief Decode the data to determine the data length
* @param apdu Pointer to the received data.
* @param tag_data_type Data type to be decoded.
* @param len_value_type Length of the data in bytes.
- *
- * @return Count of bytes decoded.
+ * @return Number of bytes decoded.
*/
int bacapp_decode_data_len(
uint8_t *apdu, uint8_t tag_data_type, uint32_t len_value_type)
@@ -451,8 +448,8 @@ int bacapp_decode_data_len(
case BACNET_APPLICATION_TAG_DATE:
case BACNET_APPLICATION_TAG_TIME:
case BACNET_APPLICATION_TAG_OBJECT_ID:
- len = (int) (~0U >> 1);
- if ( len_value_type < (uint32_t) len) {
+ len = (int)(~0U >> 1);
+ if (len_value_type < (uint32_t)len) {
len = (int)len_value_type;
}
break;
@@ -465,10 +462,8 @@ int bacapp_decode_data_len(
/**
* @brief Determine the BACnet Application Data number of APDU bytes consumed
- *
* @param apdu - buffer of data to be decoded
* @param apdu_len_max - number of bytes in the buffer
- *
* @return number of bytes decoded, or zero if errors occur
*/
int bacapp_decode_application_data_len(uint8_t *apdu, unsigned apdu_len_max)
@@ -499,100 +494,100 @@ int bacapp_encode_context_data_value(uint8_t *apdu,
{
int apdu_len = 0; /* total length of the apdu, return value */
- if (value && apdu) {
+ if (value) {
switch (value->tag) {
#if defined(BACAPP_NULL)
case BACNET_APPLICATION_TAG_NULL:
- apdu_len = encode_context_null(&apdu[0], context_tag_number);
+ apdu_len = encode_context_null(apdu, context_tag_number);
break;
#endif
#if defined(BACAPP_BOOLEAN)
case BACNET_APPLICATION_TAG_BOOLEAN:
apdu_len = encode_context_boolean(
- &apdu[0], context_tag_number, value->type.Boolean);
+ apdu, context_tag_number, value->type.Boolean);
break;
#endif
#if defined(BACAPP_UNSIGNED)
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
apdu_len = encode_context_unsigned(
- &apdu[0], context_tag_number, value->type.Unsigned_Int);
+ apdu, context_tag_number, value->type.Unsigned_Int);
break;
#endif
#if defined(BACAPP_SIGNED)
case BACNET_APPLICATION_TAG_SIGNED_INT:
apdu_len = encode_context_signed(
- &apdu[0], context_tag_number, value->type.Signed_Int);
+ apdu, context_tag_number, value->type.Signed_Int);
break;
#endif
#if defined(BACAPP_REAL)
case BACNET_APPLICATION_TAG_REAL:
apdu_len = encode_context_real(
- &apdu[0], context_tag_number, value->type.Real);
+ apdu, context_tag_number, value->type.Real);
break;
#endif
#if defined(BACAPP_DOUBLE)
case BACNET_APPLICATION_TAG_DOUBLE:
apdu_len = encode_context_double(
- &apdu[0], context_tag_number, value->type.Double);
+ apdu, context_tag_number, value->type.Double);
break;
#endif
#if defined(BACAPP_OCTET_STRING)
case BACNET_APPLICATION_TAG_OCTET_STRING:
apdu_len = encode_context_octet_string(
- &apdu[0], context_tag_number, &value->type.Octet_String);
+ apdu, context_tag_number, &value->type.Octet_String);
break;
#endif
#if defined(BACAPP_CHARACTER_STRING)
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
- apdu_len = encode_context_character_string(&apdu[0],
+ apdu_len = encode_context_character_string(apdu,
context_tag_number, &value->type.Character_String);
break;
#endif
#if defined(BACAPP_BIT_STRING)
case BACNET_APPLICATION_TAG_BIT_STRING:
apdu_len = encode_context_bitstring(
- &apdu[0], context_tag_number, &value->type.Bit_String);
+ apdu, context_tag_number, &value->type.Bit_String);
break;
#endif
#if defined(BACAPP_ENUMERATED)
case BACNET_APPLICATION_TAG_ENUMERATED:
apdu_len = encode_context_enumerated(
- &apdu[0], context_tag_number, value->type.Enumerated);
+ apdu, context_tag_number, value->type.Enumerated);
break;
#endif
#if defined(BACAPP_DATE)
case BACNET_APPLICATION_TAG_DATE:
apdu_len = encode_context_date(
- &apdu[0], context_tag_number, &value->type.Date);
+ apdu, context_tag_number, &value->type.Date);
break;
#endif
#if defined(BACAPP_TIME)
case BACNET_APPLICATION_TAG_TIME:
apdu_len = encode_context_time(
- &apdu[0], context_tag_number, &value->type.Time);
+ apdu, context_tag_number, &value->type.Time);
break;
#endif
#if defined(BACAPP_OBJECT_ID)
case BACNET_APPLICATION_TAG_OBJECT_ID:
- apdu_len = encode_context_object_id(&apdu[0],
+ apdu_len = encode_context_object_id(apdu,
context_tag_number, value->type.Object_Id.type,
value->type.Object_Id.instance);
break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined (BACAPP_TYPES_EXTRA)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
- apdu_len = lighting_command_encode_context(&apdu[0],
+ apdu_len = lighting_command_encode_context(apdu,
context_tag_number, &value->type.Lighting_Command);
break;
-#endif
-#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
- apdu_len = encode_opening_tag(&apdu[0], context_tag_number);
- apdu_len += bvlc_foreign_device_bbmd_host_address_encode(
- &apdu[apdu_len], MAX_APDU-apdu_len,
- &value->type.IP_Address);
- apdu_len += encode_closing_tag(&apdu[apdu_len],
- context_tag_number);
+ apdu_len = host_n_port_context_encode(apdu,
+ context_tag_number, &value->type.Host_Address);
+ break;
+ case BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE:
+ /* BACnetDeviceObjectPropertyReference */
+ apdu_len = bacapp_encode_context_device_obj_property_ref(
+ apdu, context_tag_number,
+ &value->type.Device_Object_Property_Reference);
break;
#endif
default:
@@ -610,6 +605,21 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
BACNET_APPLICATION_TAG tag = MAX_BACNET_APPLICATION_TAG;
switch (property) {
+ case PROP_DATE_LIST:
+ switch (tag_number) {
+ case 0: /* single calendar date */
+ tag = BACNET_APPLICATION_TAG_DATE;
+ break;
+ case 1: /* range of dates */
+ tag = BACNET_APPLICATION_TAG_DATERANGE;
+ break;
+ case 2: /* selection of weeks, month, and day of month */
+ tag = BACNET_APPLICATION_TAG_WEEKNDAY;
+ break;
+ default:
+ break;
+ }
+ break;
case PROP_ACTUAL_SHED_LEVEL:
case PROP_REQUESTED_SHED_LEVEL:
case PROP_EXPECTED_SHED_LEVEL:
@@ -673,6 +683,7 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
}
break;
case PROP_LOG_DEVICE_OBJECT_PROPERTY:
+ case PROP_OBJECT_PROPERTY_REFERENCE:
switch (tag_number) {
case 0: /* Object ID */
case 3: /* Device ID */
@@ -707,12 +718,11 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
tag = BACNET_APPLICATION_TAG_OBJECT_ID;
break;
case 1:
- /* 2015.08.22 EKH 135-2012 pg 708
- todo - Context 1 in Recipient list would be a BACnetAddress,
- not coded yet... BACnetRecipient::= CHOICE { device [0]
- BACnetObjectIdentifier, address [1] BACnetAddress
- }
- */
+ /* BACnetRecipient::= CHOICE {
+ device [0] BACnetObjectIdentifier
+ -->address [1] BACnetAddress
+ }
+ */
break;
default:
break;
@@ -722,7 +732,9 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
/* BACnetCOVSubscription */
switch (tag_number) {
case 0: /* BACnetRecipientProcess */
+ break;
case 1: /* BACnetObjectPropertyReference */
+ tag = BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE;
break;
case 2: /* issueConfirmedNotifications */
tag = BACNET_APPLICATION_TAG_BOOLEAN;
@@ -737,6 +749,45 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
break;
}
break;
+ case PROP_SETPOINT_REFERENCE:
+ switch (tag_number) {
+ case 0:
+ tag = BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE;
+ break;
+ default:
+ break;
+ }
+ break;
+ case PROP_FD_BBMD_ADDRESS:
+ case PROP_BACNET_IP_GLOBAL_ADDRESS:
+ switch (tag_number) {
+ case 0:
+ tag = BACNET_APPLICATION_TAG_HOST_N_PORT;
+ break;
+ default:
+ break;
+ }
+ break;
+ case PROP_LIGHTING_COMMAND:
+ switch (tag_number) {
+ case 0:
+ tag = BACNET_APPLICATION_TAG_LIGHTING_COMMAND;
+ break;
+ default:
+ break;
+ }
+ break;
+ case PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES:
+ case PROP_GROUP_MEMBERS:
+ switch (tag_number) {
+ case 0:
+ tag =
+ BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE;
+ break;
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -753,9 +804,9 @@ int bacapp_encode_context_data(uint8_t *apdu,
if (value && apdu) {
tag_data_type = bacapp_context_tag_type(property, value->context_tag);
- if (tag_data_type < MAX_BACNET_APPLICATION_TAG) {
+ if (tag_data_type != MAX_BACNET_APPLICATION_TAG) {
apdu_len = bacapp_encode_context_data_value(
- &apdu[0], value->context_tag, value);
+ &apdu[0], tag_data_type, value);
} else {
/* FIXME: what now? */
apdu_len = 0;
@@ -787,7 +838,7 @@ int bacapp_decode_context_data(uint8_t *apdu,
!decode_is_closing_tag_number(&apdu[0], tag_number)) {
value->context_tag = tag_number;
value->tag = bacapp_context_tag_type(property, tag_number);
- if (value->tag < MAX_BACNET_APPLICATION_TAG) {
+ if (value->tag != MAX_BACNET_APPLICATION_TAG) {
len = bacapp_decode_data(
&apdu[apdu_len], value->tag, len_value_type, value);
apdu_len += len;
@@ -799,14 +850,43 @@ int bacapp_decode_context_data(uint8_t *apdu,
} else {
apdu_len = BACNET_STATUS_ERROR;
}
- } else if (tag_len == 1) { /* and is a Closing tag */
- apdu_len = 0; /* Don't advance over that closing tag. */
+ } else if (tag_len == 1) {
+ /* and is a Closing tag */
+ /* Don't advance over that closing tag. */
+ apdu_len = 0;
}
}
return apdu_len;
}
+#if defined (BACAPP_TYPES_EXTRA)
+/**
+ * @brief Context or Application tagged property value decoding
+ *
+ * @param apdu - buffer of data to be decoded
+ * @param max_apdu_len - number of bytes in the buffer
+ * @param value - stores the decoded property value
+ * @param property - context property identifier
+ * @return number of bytes decoded, or ERROR if errors occur
+ */
+int bacapp_decode_generic_property(
+ uint8_t * apdu,
+ int max_apdu_len,
+ BACNET_APPLICATION_DATA_VALUE * value,
+ BACNET_PROPERTY_ID prop)
+{
+ int len = 0;
+ if (IS_CONTEXT_SPECIFIC(*apdu)) {
+ len = bacapp_decode_context_data(apdu, max_apdu_len, value, prop);
+ } else {
+ len = bacapp_decode_application_data(apdu, max_apdu_len, value);
+ }
+ return len;
+}
+#endif
+
+#if defined (BACAPP_TYPES_EXTRA)
/**
* @brief Determine the BACnet Context Data number of APDU bytes consumed
*
@@ -831,7 +911,7 @@ int bacapp_decode_context_data_len(
if (tag_len) {
apdu_len = tag_len;
tag = bacapp_context_tag_type(property, tag_number);
- if (tag < MAX_BACNET_APPLICATION_TAG) {
+ if (tag != MAX_BACNET_APPLICATION_TAG) {
len = bacapp_decode_data_len(NULL, tag, len_value_type);
apdu_len += len;
} else {
@@ -842,17 +922,18 @@ int bacapp_decode_context_data_len(
return apdu_len;
}
+#endif
int bacapp_encode_data(uint8_t *apdu, BACNET_APPLICATION_DATA_VALUE *value)
{
int apdu_len = 0; /* total length of the apdu, return value */
- if (value && apdu) {
+ if (value) {
if (value->context_specific) {
apdu_len = bacapp_encode_context_data_value(
- &apdu[0], value->context_tag, value);
+ apdu, value->context_tag, value);
} else {
- apdu_len = bacapp_encode_application_data(&apdu[0], value);
+ apdu_len = bacapp_encode_application_data(apdu, value);
}
}
@@ -940,22 +1021,22 @@ bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE *dest_value,
src_value->type.Object_Id.instance;
break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined (BACAPP_TYPES_EXTRA)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
status =
lighting_command_copy(&dest_value->type.Lighting_Command,
&src_value->type.Lighting_Command);
break;
-#endif
-#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
status =
- bvlc_address_copy(&dest_value->type.IP_Address,
- &src_value->type.IP_Address);
+ host_n_port_copy(&dest_value->type.Host_Address,
+ &src_value->type.Host_Address);
break;
#endif
default:
- status = false;
+ memcpy(&dest_value->type, &src_value->type,
+ sizeof(src_value->type));
+ status = true;
break;
}
dest_value->next = src_value->next;
@@ -1007,9 +1088,11 @@ int bacapp_data_len(
opening_tag_number_counter--;
}
} else if (IS_CONTEXT_SPECIFIC(apdu[apdu_len])) {
+#if defined (BACAPP_TYPES_EXTRA)
/* context-specific tagged data */
len = bacapp_decode_context_data_len(
&apdu[apdu_len], apdu_len_max - apdu_len, property);
+#endif
} else {
/* application tagged data */
len = bacapp_decode_application_data_len(
@@ -1036,33 +1119,13 @@ int bacapp_data_len(
return total_len;
}
-static bool append_str(char **str, size_t *rem_str_len, const char *add_str)
-{
- bool retval;
- int bytes_written;
-
- bytes_written = snprintf(*str, *rem_str_len, "%s", add_str);
- if ((bytes_written < 0) || (bytes_written >= *rem_str_len)) {
- /* If there was an error or output was truncated, return error */
- retval = false;
- } else {
- /* Successfully wrote the contents to the string. Let's advance the
- * string pointer to the end, and account for the used space */
- *str += bytes_written;
- *rem_str_len -= bytes_written;
- retval = true;
- }
-
- return retval;
-}
-
-/* Extract the value into a string
- * Inputs: str - the buffer to store the extracted value.
- * str_len - the size of the buffer
- * object_value - ptr to BACnet object value from which to extract str
- * Return: number of bytes (excluding terminating NULL byte) that were stored
- * to the output string. If output was truncated due to string size,
- * then the returned value is greater than str_len (a la snprintf() ).
+/**
+ * @brief Extract the value into a text string
+ * @param str - the buffer to store the extracted value, or NULL for length
+ * @param str_len - the size of the buffer
+ * @param object_value - ptr to BACnet object value from which to extract str
+ * @return number of bytes (excluding terminating NULL byte) that were stored
+ * to the output string.
*/
int bacapp_snprintf_value(
char *str, size_t str_len, BACNET_OBJECT_PROPERTY_VALUE *object_value)
@@ -1072,11 +1135,9 @@ int bacapp_snprintf_value(
BACNET_APPLICATION_DATA_VALUE *value;
BACNET_PROPERTY_ID property = PROP_ALL;
BACNET_OBJECT_TYPE object_type = MAX_BACNET_OBJECT_TYPE;
- int ret_val = -1;
- char *p_str = str;
- size_t rem_str_len = str_len;
- char temp_str[32];
-#if defined(BACAPP_OCTET_STRING)
+ int ret_val = BACNET_STATUS_ERROR;
+ int slen = 0;
+#if defined(BACAPP_OCTET_STRING) || defined (BACAPP_TYPES_EXTRA)
uint8_t *octet_str;
#endif
#ifdef __STDC_ISO_10646__
@@ -1131,15 +1192,17 @@ int bacapp_snprintf_value(
len = octetstring_length(&value->type.Octet_String);
octet_str = octetstring_value(&value->type.Octet_String);
for (i = 0; i < len; i++) {
- snprintf(temp_str, sizeof(temp_str), "%02X", *octet_str);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
+ slen = snprintf(str, str_len, "%02X", *octet_str);
octet_str++;
- }
- if (i == len) {
- /* Everything went fine */
- ret_val = str_len - rem_str_len;
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
}
break;
#endif
@@ -1147,9 +1210,16 @@ int bacapp_snprintf_value(
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
len = characterstring_length(&value->type.Character_String);
char_str = characterstring_value(&value->type.Character_String);
- if (!append_str(&p_str, &rem_str_len, "\"")) {
- break;
+ slen = snprintf(str, str_len, "\"");
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
}
+ ret_val += slen;
#ifdef __STDC_ISO_10646__
if (characterstring_encoding(&value->type.Character_String) ==
CHARACTER_UTF8) {
@@ -1168,10 +1238,16 @@ int bacapp_snprintf_value(
}
}
/* For portability, cast wchar_t to wint_t */
- snprintf(temp_str, sizeof(temp_str), "%lc", (wint_t)wc);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
+ slen = snprintf(str, str_len, "%lc", (wint_t)wc);
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
}
+ ret_val += slen;
if (len > wclen) {
len -= wclen;
char_str += wclen;
@@ -1184,49 +1260,67 @@ int bacapp_snprintf_value(
{
for (i = 0; i < len; i++) {
if (isprint(*((unsigned char *)char_str))) {
- snprintf(temp_str, sizeof(temp_str), "%c",
- *char_str);
+ slen = snprintf(str, str_len, "%c", *char_str);
} else {
- snprintf(temp_str, sizeof(temp_str), "%c", '.');
+ slen = snprintf(str, str_len, "%c", '.');
}
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
}
+ ret_val += slen;
char_str++;
}
}
- if ((i == len) && append_str(&p_str, &rem_str_len, "\"")) {
- /* Everything is fine. Indicate how many bytes were */
- /* written */
- ret_val = str_len - rem_str_len;
- }
+ slen = snprintf(str, str_len, "\"");
+ ret_val += slen;
break;
#endif
#if defined(BACAPP_BIT_STRING)
case BACNET_APPLICATION_TAG_BIT_STRING:
len = bitstring_bits_used(&value->type.Bit_String);
- if (!append_str(&p_str, &rem_str_len, "{")) {
- break;
-}
- for (i = 0; i < len; i++) {
- snprintf(temp_str, sizeof(temp_str), "%s",
- bitstring_bit(&value->type.Bit_String, (uint8_t)i)
- ? "true"
- : "false");
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
- if (i < len - 1) {
- if (!append_str(&p_str, &rem_str_len, ",")) {
- break;
-}
+ slen = snprintf(str, str_len, "{");
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
}
}
- if ((i == len) && append_str(&p_str, &rem_str_len, "}")) {
- /* Everything is fine. Indicate how many bytes were */
- /* written */
- ret_val = str_len - rem_str_len;
+ ret_val += slen;
+ for (i = 0; i < len; i++) {
+ bool bit;
+ bit = bitstring_bit(&value->type.Bit_String, (uint8_t)i);
+ slen = snprintf(str, str_len, "%s", bit ? "true" : "false");
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
+ if (i < (len - 1)) {
+ slen = snprintf(str, str_len, ",");
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
+ }
}
+ slen = snprintf(str, str_len, "}");
+ ret_val += slen;
break;
#endif
#if defined(BACAPP_ENUMERATED)
@@ -1310,176 +1404,208 @@ int bacapp_snprintf_value(
#endif
#if defined(BACAPP_DATE)
case BACNET_APPLICATION_TAG_DATE:
- if (!append_str(&p_str, &rem_str_len,
- bactext_day_of_week_name(value->type.Date.wday))) {
- break;
-}
- if (!append_str(&p_str, &rem_str_len, ", ")) {
- break;
-}
-
- if (!append_str(&p_str, &rem_str_len,
- bactext_month_name(value->type.Date.month))) {
- break;
-}
+ slen = snprintf(str, str_len, "%s, %s",
+ bactext_day_of_week_name(value->type.Date.wday),
+ bactext_month_name(value->type.Date.month));
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
if (value->type.Date.day == 255) {
- if (!append_str(&p_str, &rem_str_len, " (unspecified), ")) {
- break;
-}
+ slen = snprintf(str, str_len, " (unspecified), ");
} else {
- snprintf(temp_str, sizeof(temp_str), " %u, ",
+ slen = snprintf(str, str_len, " %u, ",
(unsigned)value->type.Date.day);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
}
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
if (value->type.Date.year == 2155) {
- if (!append_str(&p_str, &rem_str_len, "(unspecified)")) {
- break;
-}
+ slen = snprintf(str, str_len, "(unspecified)");
} else {
- snprintf(temp_str, sizeof(temp_str), "%u",
+ slen = snprintf(str, str_len, "%u",
(unsigned)value->type.Date.year);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
}
- /* If we get here, then everything is OK. Indicate how many */
- /* bytes were written. */
- ret_val = str_len - rem_str_len;
+ ret_val += slen;
break;
#endif
#if defined(BACAPP_TIME)
case BACNET_APPLICATION_TAG_TIME:
if (value->type.Time.hour == 255) {
- if (!append_str(&p_str, &rem_str_len, "**:")) {
- break;
-}
+ slen = snprintf(str, str_len, "**:");
} else {
- snprintf(temp_str, sizeof(temp_str),
- "%02u:", (unsigned)value->type.Time.hour);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
+ slen= snprintf(str, str_len, "%02u:",
+ (unsigned)value->type.Time.hour);
}
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
if (value->type.Time.min == 255) {
- if (!append_str(&p_str, &rem_str_len, "**:")) {
- break;
-}
+ slen = snprintf(str, str_len, "**:");
} else {
- snprintf(temp_str, sizeof(temp_str),
- "%02u:", (unsigned)value->type.Time.min);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
+ slen = snprintf(str, str_len, "%02u:",
+ (unsigned)value->type.Time.min);
}
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
if (value->type.Time.sec == 255) {
- if (!append_str(&p_str, &rem_str_len, "**.")) {
- break;
-}
+ slen = snprintf(str, str_len, "**.");
} else {
- snprintf(temp_str, sizeof(temp_str), "%02u.",
+ slen = snprintf(str, str_len, "%02u.",
(unsigned)value->type.Time.sec);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
}
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
if (value->type.Time.hundredths == 255) {
- if (!append_str(&p_str, &rem_str_len, "**")) {
- break;
-}
+ slen = snprintf(str, str_len, "**");
} else {
- snprintf(temp_str, sizeof(temp_str), "%02u",
+ slen = snprintf(str, str_len, "%02u",
(unsigned)value->type.Time.hundredths);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
}
- /* If we get here, then everything is OK. Indicate how many */
- /* bytes were written. */
- ret_val = str_len - rem_str_len;
+ ret_val += slen;
break;
#endif
#if defined(BACAPP_OBJECT_ID)
case BACNET_APPLICATION_TAG_OBJECT_ID:
- if (!append_str(&p_str, &rem_str_len, "(")) {
- break;
-}
+ slen = snprintf(str, str_len, "(");
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
if (value->type.Object_Id.type < MAX_ASHRAE_OBJECT_TYPE) {
- if (!append_str(&p_str, &rem_str_len,
- bactext_object_type_name(
- value->type.Object_Id.type))) {
- break;
-}
- snprintf(temp_str, sizeof(temp_str), ", %lu",
- (unsigned long)value->type.Object_Id.instance);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
+ slen = snprintf(str, str_len, "%s, ",
+ bactext_object_type_name(value->type.Object_Id.type));
} else if (value->type.Object_Id.type < 128) {
- if (!append_str(&p_str, &rem_str_len, "reserved ")) {
- break;
-}
- snprintf(temp_str, sizeof(temp_str), "%u, ",
+ slen = snprintf(str, str_len, "reserved %u, ",
(unsigned)value->type.Object_Id.type);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
- snprintf(temp_str, sizeof(temp_str), "%lu",
- (unsigned long)value->type.Object_Id.instance);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
} else {
- if (!append_str(&p_str, &rem_str_len, "proprietary ")) {
- break;
-}
- snprintf(temp_str, sizeof(temp_str), "%u, ",
+ slen = snprintf(str, str_len, "proprietary %u, ",
(unsigned)value->type.Object_Id.type);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
- snprintf(temp_str, sizeof(temp_str), "%lu",
- (unsigned long)value->type.Object_Id.instance);
- if (!append_str(&p_str, &rem_str_len, temp_str)) {
- break;
-}
}
- if (!append_str(&p_str, &rem_str_len, ")")) {
- break;
-}
- /* If we get here, then everything is OK. Indicate how many */
- /* bytes were written. */
- ret_val = str_len - rem_str_len;
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
+ slen = snprintf(str, str_len, "%lu",
+ (unsigned long)value->type.Object_Id.instance);
+ ret_val += slen;
break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined (BACAPP_TYPES_EXTRA)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
- if (!append_str(&p_str, &rem_str_len, "(")) {
- break;
-}
- if (!append_str(&p_str, &rem_str_len,
- bactext_lighting_operation_name(
- value->type.Lighting_Command.operation))) {
- break;
+ slen = snprintf(str, str_len, "(");
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
}
+ ret_val += slen;
+ slen = snprintf(str, str_len, "%s",
+ bactext_lighting_operation_name(
+ value->type.Lighting_Command.operation));
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
/* FIXME: add the Lighting Command optional values */
- if (!append_str(&p_str, &rem_str_len, ")")) {
- break;
-}
- /* If we get here, then everything is OK. Indicate how many */
- /* bytes were written. */
- ret_val = str_len - rem_str_len;
+ slen = snprintf(str, str_len, ")");
+ ret_val += slen;
break;
-#endif
-#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
- ret_val = snprintf(str, str_len, "%u.%u.%u.%u:%u",
- (unsigned)value->type.IP_Address.address[0],
- (unsigned)value->type.IP_Address.address[1],
- (unsigned)value->type.IP_Address.address[2],
- (unsigned)value->type.IP_Address.address[3],
- (unsigned)value->type.IP_Address.port);
+ if (value->type.Host_Address.host_ip_address) {
+ octet_str = octetstring_value(
+ &value->type.Host_Address.host.ip_address);
+ slen = snprintf(str, str_len, "%u.%u.%u.%u:%u",
+ (unsigned)octet_str[0],
+ (unsigned)octet_str[1],
+ (unsigned)octet_str[2],
+ (unsigned)octet_str[3],
+ (unsigned)value->type.Host_Address.port);
+ ret_val += slen;
+ } else if (value->type.Host_Address.host_name) {
+ BACNET_CHARACTER_STRING *name;
+ name = &value->type.Host_Address.host.name;
+ len = characterstring_length(name);
+ char_str = characterstring_value(name);
+ slen = snprintf(str, str_len, "\"");
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
+ for (i = 0; i < len; i++) {
+ if (isprint(*((unsigned char *)char_str))) {
+ slen = snprintf(str, str_len, "%c", *char_str);
+ } else {
+ slen = snprintf(str, str_len, "%c", '.');
+ }
+ char_str++;
+ if (str) {
+ str += slen;
+ if (str_len >= slen) {
+ str_len -= slen;
+ } else {
+ str_len = 0;
+ }
+ }
+ ret_val += slen;
+ }
+ slen = snprintf(str, str_len, "\"");
+ ret_val += slen;
+ }
break;
#endif
default:
@@ -1492,42 +1618,45 @@ int bacapp_snprintf_value(
}
#ifdef BACAPP_PRINT_ENABLED
-/* Print the extracted value from the requested BACnet object property to the
+/**
+ * Print the extracted value from the requested BACnet object property to the
* specified stream. If stream is NULL, do not print anything. If extraction
* failed, do not print anything. Return the status of the extraction.
+ *
+ * @param stream - the I/O stream send the printed value.
+ * @param object_value - ptr to BACnet object value from which to extract str
+ *
+ * @return true if the value was sent to the stream
*/
bool bacapp_print_value(
FILE *stream, BACNET_OBJECT_PROPERTY_VALUE *object_value)
{
- char *str;
bool retval = false;
- size_t str_len = 32;
- int status;
+ int str_len = 0;
- while (true) {
- /* Try to allocate memory for the output string. Give up if unable. */
- str = (char *)calloc(sizeof(char), str_len);
- if (!str)
- break;
-
- /* Try to extract the value into allocated memory. If unable, try again
- */
- /* another time with a string that is twice as large. */
- status = bacapp_snprintf_value(str, str_len, object_value);
- if ((status < 0) || ((size_t)status >= str_len)) {
- free(str);
- str_len *= 2;
- } else if (status == 0) {
- free(str);
- break;
- } else {
- if (stream)
- fprintf(stream, "%s", str);
- free(str);
- retval = true;
- break;
+ /* get the string length first */
+ str_len = bacapp_snprintf_value(NULL, 0, object_value);
+ if (str_len > 0) {
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ char str[str_len+1];
+#else
+ char *str;
+ str = calloc(sizeof(char), str_len+1);
+#endif
+ bacapp_snprintf_value(str, str_len+1, object_value);
+ if (stream) {
+ fprintf(stream, "%s", str);
}
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ /* nothing to do with stack based RAM */
+#else
+ if (str) {
+ free(str);
+ }
+#endif
+ retval = true;
}
+
return retval;
}
#endif
@@ -1548,11 +1677,11 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
unsigned long unsigned_long_value = 0;
double double_value = 0.0;
int count = 0;
-#if defined(BACAPP_HOST_N_PORT)
+#if defined(BACAPP_TYPES_EXTRA)
unsigned a[4] = { 0 }, p = 0;
#endif
- if (value && (tag_number < MAX_BACNET_APPLICATION_TAG)) {
+ if (value && (tag_number != MAX_BACNET_APPLICATION_TAG)) {
status = true;
value->tag = tag_number;
switch (tag_number) {
@@ -1664,24 +1793,26 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
}
break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined (BACAPP_TYPES_EXTRA)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
/* FIXME: add parsing for lighting command */
break;
-#endif
-#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
count = sscanf(argv, "%3u.%3u.%3u.%3u:%5u",
&a[0], &a[1], &a[2], &a[3], &p);
if ((count == 4) || (count == 5)) {
- value->type.IP_Address.address[0] = a[0];
- value->type.IP_Address.address[1] = a[1];
- value->type.IP_Address.address[2] = a[2];
- value->type.IP_Address.address[3] = a[3];
+ uint8_t address[4];
+ value->type.Host_Address.host_ip_address = true;
+ value->type.Host_Address.host_name = false;
+ address[0] = (uint8_t)a[0];
+ address[1] = (uint8_t)a[1];
+ address[2] = (uint8_t)a[2];
+ address[3] = (uint8_t)a[3];
+ octetstring_init(&value->type.Host_Address.host.ip_address, address, 4);
if (count == 4) {
- value->type.IP_Address.port = 0xBAC0U;
+ value->type.Host_Address.port = 0xBAC0U;
} else {
- value->type.IP_Address.port = (uint16_t)p;
+ value->type.Host_Address.port = (uint16_t)p;
}
status = true;
} else {
@@ -1763,7 +1894,7 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value,
}
if (test_value->tag == value->tag) {
status = true;
-}
+ }
if (status) {
/* second test for same-ness */
status = false;
@@ -1778,42 +1909,42 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value,
case BACNET_APPLICATION_TAG_BOOLEAN:
if (test_value->type.Boolean == value->type.Boolean) {
status = true;
-}
+ }
break;
#endif
#if defined(BACAPP_UNSIGNED)
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
if (test_value->type.Unsigned_Int == value->type.Unsigned_Int) {
status = true;
-}
+ }
break;
#endif
#if defined(BACAPP_SIGNED)
case BACNET_APPLICATION_TAG_SIGNED_INT:
if (test_value->type.Signed_Int == value->type.Signed_Int) {
status = true;
-}
+ }
break;
#endif
#if defined(BACAPP_REAL)
case BACNET_APPLICATION_TAG_REAL:
if (test_value->type.Real == value->type.Real) {
status = true;
-}
+ }
break;
#endif
#if defined(BACAPP_DOUBLE)
case BACNET_APPLICATION_TAG_DOUBLE:
if (test_value->type.Double == value->type.Double) {
status = true;
-}
+ }
break;
#endif
#if defined(BACAPP_ENUMERATED)
case BACNET_APPLICATION_TAG_ENUMERATED:
if (test_value->type.Enumerated == value->type.Enumerated) {
status = true;
-}
+ }
break;
#endif
#if defined(BACAPP_DATE)
@@ -1821,7 +1952,7 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value,
if (datetime_compare_date(
&test_value->type.Date, &value->type.Date) == 0) {
status = true;
-}
+ }
break;
#endif
#if defined(BACAPP_TIME)
@@ -1829,7 +1960,7 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value,
if (datetime_compare_time(
&test_value->type.Time, &value->type.Time) == 0) {
status = true;
-}
+ }
break;
#endif
#if defined(BACAPP_OBJECT_ID)
@@ -1860,17 +1991,14 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value,
&value->type.Bit_String, &test_value->type.Bit_String);
break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined (BACAPP_TYPES_EXTRA)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
status = lighting_command_same(&value->type.Lighting_Command,
&test_value->type.Lighting_Command);
break;
-#endif
-#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
- status =
- !bvlc_address_different(&value->type.IP_Address,
- &value->type.IP_Address);
+ status = host_n_port_same(&value->type.Host_Address,
+ &value->type.Host_Address);
break;
#endif
default:
@@ -1880,520 +2008,3 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value,
}
return status;
}
-
-#ifdef TEST_BACNET_APPLICATION_DATA
-#include
-#include
-#include "ctest.h"
-
-#include
-
-static void testBACnetApplicationData_Safe(Test *pTest)
-{
- int i;
- uint8_t apdu[MAX_APDU];
- int len = 0;
- int apdu_len;
- BACNET_APPLICATION_DATA_VALUE input_value[13];
- uint32_t len_segment[13];
- uint32_t single_length_segment;
- BACNET_APPLICATION_DATA_VALUE value;
-
- for (i = 0; i < 13; i++) {
- input_value[i].tag = (BACNET_APPLICATION_TAG)i;
- input_value[i].context_specific = 0;
- input_value[i].context_tag = 0;
- input_value[i].next = NULL;
- switch (input_value[i].tag) {
- case BACNET_APPLICATION_TAG_NULL:
- /* NULL: no data */
- break;
-
- case BACNET_APPLICATION_TAG_BOOLEAN:
- input_value[i].type.Boolean = true;
- break;
-
- case BACNET_APPLICATION_TAG_UNSIGNED_INT:
- input_value[i].type.Unsigned_Int = 0xDEADBEEF;
- break;
-
- case BACNET_APPLICATION_TAG_SIGNED_INT:
- input_value[i].type.Signed_Int = 0x00C0FFEE;
- break;
- case BACNET_APPLICATION_TAG_REAL:
- input_value[i].type.Real = 3.141592654f;
- break;
- case BACNET_APPLICATION_TAG_DOUBLE:
- input_value[i].type.Double = 2.32323232323;
- break;
-
- case BACNET_APPLICATION_TAG_OCTET_STRING: {
- uint8_t test_octet[5] = { "Karg" };
- octetstring_init(&input_value[i].type.Octet_String, test_octet,
- sizeof(test_octet));
- } break;
-
- case BACNET_APPLICATION_TAG_CHARACTER_STRING:
- characterstring_init_ansi(
- &input_value[i].type.Character_String, "Hello There!");
- break;
-
- case BACNET_APPLICATION_TAG_BIT_STRING:
- bitstring_init(&input_value[i].type.Bit_String);
- bitstring_set_bit(&input_value[i].type.Bit_String, 0, true);
- bitstring_set_bit(&input_value[i].type.Bit_String, 1, false);
- bitstring_set_bit(&input_value[i].type.Bit_String, 2, false);
- bitstring_set_bit(&input_value[i].type.Bit_String, 3, true);
- bitstring_set_bit(&input_value[i].type.Bit_String, 4, false);
- bitstring_set_bit(&input_value[i].type.Bit_String, 5, true);
- bitstring_set_bit(&input_value[i].type.Bit_String, 6, true);
- break;
-
- case BACNET_APPLICATION_TAG_ENUMERATED:
- input_value[i].type.Enumerated = 0x0BADF00D;
- break;
-
- case BACNET_APPLICATION_TAG_DATE:
- input_value[i].type.Date.day = 10;
- input_value[i].type.Date.month = 9;
- input_value[i].type.Date.wday = 3;
- input_value[i].type.Date.year = 1998;
- break;
-
- case BACNET_APPLICATION_TAG_TIME:
- input_value[i].type.Time.hour = 12;
- input_value[i].type.Time.hundredths = 56;
- input_value[i].type.Time.min = 20;
- input_value[i].type.Time.sec = 41;
- break;
-
- case BACNET_APPLICATION_TAG_OBJECT_ID:
- input_value[i].type.Object_Id.instance = 1234;
- input_value[i].type.Object_Id.type = 12;
- break;
-
- default:
- break;
- }
- single_length_segment = bacapp_encode_data(&apdu[len], &input_value[i]);
- ;
- assert(single_length_segment > 0);
- /* len_segment is accumulated length */
- if (i == 0) {
- len_segment[i] = single_length_segment;
- } else {
- len_segment[i] = single_length_segment + len_segment[i - 1];
- }
- len = len_segment[i];
- }
- /*
- ** Start processing packets at processivly truncated lengths
- */
-
- for (apdu_len = len; apdu_len >= 0; apdu_len--) {
- bool status;
- bool expected_status;
- for (i = 0; i < 14; i++) {
- if (i == 13) {
- expected_status = false;
- } else {
- if (apdu_len < len_segment[i]) {
- expected_status = false;
- } else {
- expected_status = true;
- }
- }
- status = bacapp_decode_application_data_safe(
- i == 0 ? apdu : NULL, apdu_len, &value);
-
- ct_test(pTest, status == expected_status);
- if (status) {
- ct_test(pTest, value.tag == i);
- ct_test(pTest, bacapp_same_value(&input_value[i], &value));
- ct_test(pTest, !value.context_specific);
- ct_test(pTest, value.next == NULL);
- } else {
- break;
- }
- }
- }
-}
-
-void testBACnetApplicationDataLength(Test *pTest)
-{
- int apdu_len = 0; /* total length of the apdu, return value */
- int len = 0; /* total length of the apdu, return value */
- int test_len = 0; /* length of the data */
- uint8_t apdu[480] = { 0 };
- BACNET_TIME local_time;
- BACNET_DATE local_date;
-
- /* create some constructed data */
- /* 1. zero elements */
- test_len = 0;
- apdu_len = 0;
- len = encode_opening_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- len = encode_closing_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- /* verify the length of the data inside the opening/closing tags */
- len = bacapp_data_len(
- &apdu[0], apdu_len, PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES);
- ct_test(pTest, test_len == len);
-
- /* 2. application tagged data, one element */
- test_len = 0;
- apdu_len = 0;
- len = encode_opening_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- len = encode_application_unsigned(&apdu[apdu_len], 4194303);
- test_len += len;
- apdu_len += len;
- len = encode_closing_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- /* verify the length of the data inside the opening/closing tags */
- len = bacapp_data_len(&apdu[0], apdu_len, PROP_OBJECT_IDENTIFIER);
- ct_test(pTest, test_len == len);
-
- /* 3. application tagged data, multiple elements */
- test_len = 0;
- apdu_len = 0;
- len = encode_opening_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_unsigned(&apdu[apdu_len], 1);
- test_len += len;
- apdu_len += len;
- len = encode_application_unsigned(&apdu[apdu_len], 42);
- test_len += len;
- apdu_len += len;
- len = encode_application_unsigned(&apdu[apdu_len], 91);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_application_null(&apdu[apdu_len]);
- test_len += len;
- apdu_len += len;
- len = encode_closing_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- /* verify the length of the data inside the opening/closing tags */
- len = bacapp_data_len(&apdu[0], apdu_len, PROP_PRIORITY_ARRAY);
- ct_test(pTest, test_len == len);
-
- /* 4. complex datatype - one element */
- test_len = 0;
- apdu_len = 0;
- len = encode_opening_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- len = encode_opening_tag(&apdu[apdu_len], 3);
- test_len += len;
- apdu_len += len;
- local_date.year = 2006; /* AD */
- local_date.month = 4; /* 1=Jan */
- local_date.day = 1; /* 1..31 */
- local_date.wday = 6; /* 1=Monday */
- len = encode_application_date(&apdu[apdu_len], &local_date);
- test_len += len;
- apdu_len += len;
- local_time.hour = 7;
- local_time.min = 0;
- local_time.sec = 3;
- local_time.hundredths = 1;
- len = encode_application_time(&apdu[apdu_len], &local_time);
- test_len += len;
- apdu_len += len;
- len = encode_closing_tag(&apdu[apdu_len], 3);
- test_len += len;
- apdu_len += len;
- len = encode_closing_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- /* verify the length of the data inside the opening/closing tags */
- len = bacapp_data_len(&apdu[0], apdu_len, PROP_START_TIME);
- ct_test(pTest, test_len == len);
-
- /* 5. complex datatype - multiple elements */
-
- /* 6. context tagged data, one element */
- test_len = 0;
- apdu_len = 0;
- len = encode_opening_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- len = encode_context_unsigned(&apdu[apdu_len], 1, 91);
- test_len += len;
- apdu_len += len;
- len = encode_closing_tag(&apdu[apdu_len], 3);
- apdu_len += len;
- /* verify the length of the data inside the opening/closing tags */
- len = bacapp_data_len(&apdu[0], apdu_len, PROP_REQUESTED_SHED_LEVEL);
- ct_test(pTest, test_len == len);
-}
-
-static bool testBACnetApplicationDataValue(BACNET_APPLICATION_DATA_VALUE *value)
-{
- uint8_t apdu[480] = { 0 };
- int apdu_len = 0;
- BACNET_APPLICATION_DATA_VALUE test_value;
-
- apdu_len = bacapp_encode_application_data(&apdu[0], value);
- bacapp_decode_application_data(&apdu[0], apdu_len, &test_value);
-
- return bacapp_same_value(value, &test_value);
-}
-
-void testBACnetApplicationData(Test *pTest)
-{
- BACNET_APPLICATION_DATA_VALUE value;
- bool status = false;
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_NULL, NULL, &value);
- ct_test(pTest, status == true);
- status = testBACnetApplicationDataValue(&value);
- ct_test(pTest, status == true);
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_BOOLEAN, "1", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Boolean == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_BOOLEAN, "0", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Boolean == false);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_UNSIGNED_INT, "0", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Unsigned_Int == 0);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_UNSIGNED_INT, "0xFFFF", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Unsigned_Int == 0xFFFF);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_UNSIGNED_INT, "0xFFFFFFFF", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Unsigned_Int == 0xFFFFFFFF);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_SIGNED_INT, "0", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Signed_Int == 0);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_SIGNED_INT, "-1", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Signed_Int == -1);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_SIGNED_INT, "32768", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Signed_Int == 32768);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_SIGNED_INT, "-32768", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Signed_Int == -32768);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_REAL, "0.0", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_REAL, "-1.0", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_REAL, "1.0", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_REAL, "3.14159", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_REAL, "-3.14159", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_ENUMERATED, "0", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Enumerated == 0);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_ENUMERATED, "0xFFFF", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Enumerated == 0xFFFF);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_ENUMERATED, "0xFFFFFFFF", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Enumerated == 0xFFFFFFFF);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_DATE, "2005/5/22:1", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Date.year == 2005);
- ct_test(pTest, value.type.Date.month == 5);
- ct_test(pTest, value.type.Date.day == 22);
- ct_test(pTest, value.type.Date.wday == 1);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- /* Happy Valentines Day! */
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_DATE, "2007/2/14", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Date.year == 2007);
- ct_test(pTest, value.type.Date.month == 2);
- ct_test(pTest, value.type.Date.day == 14);
- ct_test(pTest, value.type.Date.wday == BACNET_WEEKDAY_WEDNESDAY);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- /* Wildcard Values */
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_DATE, "2155/255/255:255", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Date.year == 2155);
- ct_test(pTest, value.type.Date.month == 255);
- ct_test(pTest, value.type.Date.day == 255);
- ct_test(pTest, value.type.Date.wday == 255);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_TIME, "23:59:59.12", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Time.hour == 23);
- ct_test(pTest, value.type.Time.min == 59);
- ct_test(pTest, value.type.Time.sec == 59);
- ct_test(pTest, value.type.Time.hundredths == 12);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_TIME, "23:59:59", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Time.hour == 23);
- ct_test(pTest, value.type.Time.min == 59);
- ct_test(pTest, value.type.Time.sec == 59);
- ct_test(pTest, value.type.Time.hundredths == 0);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_TIME, "23:59", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Time.hour == 23);
- ct_test(pTest, value.type.Time.min == 59);
- ct_test(pTest, value.type.Time.sec == 0);
- ct_test(pTest, value.type.Time.hundredths == 0);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- /* Wildcard Values */
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_TIME, "255:255:255.255", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Time.hour == 255);
- ct_test(pTest, value.type.Time.min == 255);
- ct_test(pTest, value.type.Time.sec == 255);
- ct_test(pTest, value.type.Time.hundredths == 255);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OBJECT_ID, "0:100", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, value.type.Object_Id.type == 0);
- ct_test(pTest, value.type.Object_Id.instance == 100);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_CHARACTER_STRING, "Karg!", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- /* test empty string */
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_CHARACTER_STRING, "", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OCTET_STRING, "1234567890ABCDEF", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OCTET_STRING, "12-34-56-78-90-AB-CD-EF", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OCTET_STRING, "12 34 56 78 90 AB CD EF", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
- /* test empty string */
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OCTET_STRING, "", &value);
- ct_test(pTest, status == true);
- ct_test(pTest, testBACnetApplicationDataValue(&value));
-
- return;
-}
-
-int main(void)
-{
- Test *pTest;
- bool rc;
-
- pTest = ct_create("BACnet Application Data", NULL);
- /* individual tests */
- rc = ct_addTestFunction(pTest, testBACnetApplicationData);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetApplicationDataLength);
- assert(rc);
- rc = ct_addTestFunction(pTest, testBACnetApplicationData_Safe);
- assert(rc);
-
- ct_setStream(pTest, stdout);
- ct_run(pTest);
- (void)ct_report(pTest);
- ct_destroy(pTest);
-
- return 0;
-}
-#endif /* TEST_BACNET_APPLICATION_DATA */
diff --git a/src/bacnet/bacapp.h b/src/bacnet/bacapp.h
index 026b6c12..5c9c3fd3 100644
--- a/src/bacnet/bacapp.h
+++ b/src/bacnet/bacapp.h
@@ -1,26 +1,26 @@
/**************************************************************************
-*
-* Copyright (C) 2012 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.
-*********************************************************************/
+ *
+ * Copyright (C) 2012 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 BACAPP_H
#define BACAPP_H
@@ -32,15 +32,9 @@
#include "bacnet/bacint.h"
#include "bacnet/bacstr.h"
#include "bacnet/datetime.h"
-#if defined (BACAPP_LIGHTING_COMMAND)
#include "bacnet/lighting.h"
-#endif
-#if defined (BACAPP_DEVICE_OBJECT_PROP_REF)
#include "bacnet/bacdevobjpropref.h"
-#endif
-#if defined(BACAPP_HOST_N_PORT)
-#include "bacnet/datalink/datalink.h"
-#endif
+#include "bacnet/hostnport.h"
struct BACnet_Application_Data_Value;
typedef struct BACnet_Application_Data_Value {
@@ -85,13 +79,9 @@ typedef struct BACnet_Application_Data_Value {
#if defined (BACAPP_OBJECT_ID)
BACNET_OBJECT_ID Object_Id;
#endif
-#if defined (BACAPP_LIGHTING_COMMAND)
+#if defined (BACAPP_TYPES_EXTRA)
BACNET_LIGHTING_COMMAND Lighting_Command;
-#endif
-#if defined(BACAPP_HOST_N_PORT)
- BACNET_IP_ADDRESS IP_Address;
-#endif
-#if defined (BACAPP_DEVICE_OBJECT_PROP_REF)
+ BACNET_HOST_N_PORT Host_Address;
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE
Device_Object_Property_Reference;
#endif
@@ -204,6 +194,13 @@ extern "C" {
BACNET_PROPERTY_ID property,
uint8_t tag_number);
+ BACNET_STACK_EXPORT
+ int bacapp_decode_generic_property(
+ uint8_t * apdu,
+ int max_apdu_len,
+ BACNET_APPLICATION_DATA_VALUE * value,
+ BACNET_PROPERTY_ID prop);
+
BACNET_STACK_EXPORT
bool bacapp_copy(
BACNET_APPLICATION_DATA_VALUE * dest_value,
@@ -238,7 +235,6 @@ extern "C" {
#define BACAPP_PRINT_ENABLED
#endif
#endif
-
BACNET_STACK_EXPORT
int bacapp_snprintf_value(
char *str,
diff --git a/src/bacnet/bacdcode.c b/src/bacnet/bacdcode.c
index a1476780..67796d65 100644
--- a/src/bacnet/bacdcode.c
+++ b/src/bacnet/bacdcode.c
@@ -227,7 +227,7 @@ int decode_max_apdu(uint8_t octet)
* Encode a BACnet tag and returns the number of bytes consumed.
* (From clause 20.2.1 General Rules for Encoding BACnet Tags)
*
- * @param apdu Pointer to the encode buffer.
+ * @param apdu Pointer to the encode buffer, or NULL for length
* @param tag_number Number of the tag to encode,
* see BACNET_APPLICATION_TAG_X macros.
* @param context_specific Indicates to encode in the given context.
@@ -241,36 +241,64 @@ int encode_tag(uint8_t *apdu,
uint32_t len_value_type)
{
int len = 1; /* return value */
+ uint8_t *apdu_offset = NULL;
- apdu[0] = 0;
+ if (apdu) {
+ apdu[0] = 0;
+ }
if (context_specific) {
- apdu[0] = BIT(3);
+ if (apdu) {
+ apdu[0] = BIT(3);
+ }
}
/* additional tag byte after this byte */
/* for extended tag byte */
if (tag_number <= 14) {
- apdu[0] |= (tag_number << 4);
+ if (apdu) {
+ apdu[0] |= (tag_number << 4);
+ }
} else {
- apdu[0] |= 0xF0;
- apdu[1] = tag_number;
+ if (apdu) {
+ apdu[0] |= 0xF0;
+ apdu[1] = tag_number;
+ }
len++;
}
/* NOTE: additional len byte(s) after extended tag byte */
/* if larger than 4 */
if (len_value_type <= 4) {
- apdu[0] |= len_value_type;
+ if (apdu) {
+ apdu[0] |= len_value_type;
+ }
} else {
- apdu[0] |= 5;
+ if (apdu) {
+ apdu[0] |= 5;
+ }
if (len_value_type <= 253) {
- apdu[len++] = (uint8_t)len_value_type;
+ if (apdu) {
+ apdu[len] = (uint8_t)len_value_type;
+ }
+ len++;
} else if (len_value_type <= 65535) {
- apdu[len++] = 254;
- len += encode_unsigned16(&apdu[len], (uint16_t)len_value_type);
+ if (apdu) {
+ apdu[len] = 254;
+ }
+ len++;
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_unsigned16(apdu_offset, (uint16_t)len_value_type);
} else {
- apdu[len++] = 255;
- len += encode_unsigned32(&apdu[len], len_value_type);
+ if (apdu) {
+ apdu[len] = 255;
+ }
+ len++;
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_unsigned32(apdu_offset, len_value_type);
}
}
@@ -282,7 +310,7 @@ int encode_tag(uint8_t *apdu,
* of bytes consumed.
* (From clause 20.2.1.3.2 Constructed Data.)
*
- * @param apdu Pointer to the encode buffer.
+ * @param apdu Pointer to the encode buffer, or NULL for length
* @param tag_number Number of the tag to encode,
* see BACNET_APPLICATION_TAG_X macros.
*
@@ -292,18 +320,26 @@ int encode_opening_tag(uint8_t *apdu, uint8_t tag_number)
{
int len = 1;
- /* set class field to context specific */
- apdu[0] = BIT(3);
+ if (apdu) {
+ /* set class field to context specific */
+ apdu[0] = BIT(3);
+ }
/* additional tag byte after this byte for extended tag byte */
if (tag_number <= 14) {
- apdu[0] |= (tag_number << 4);
+ if (apdu) {
+ apdu[0] |= (tag_number << 4);
+ }
} else {
- apdu[0] |= 0xF0;
- apdu[1] = tag_number;
+ if (apdu) {
+ apdu[0] |= 0xF0;
+ apdu[1] = tag_number;
+ }
len++;
}
- /* set type field to opening tag */
- apdu[0] |= 6;
+ if (apdu) {
+ /* set type field to opening tag */
+ apdu[0] |= 6;
+ }
return len;
}
@@ -313,7 +349,7 @@ int encode_opening_tag(uint8_t *apdu, uint8_t tag_number)
* of bytes consumed.
* (From clause 20.2.1.3.2 Constructed Data.)
*
- * @param apdu Pointer to the encode buffer.
+ * @param apdu Pointer to the encode buffer, or NULL for length
* @param tag_number Number of the tag to encode,
* see BACNET_APPLICATION_TAG_X macros.
*
@@ -324,21 +360,38 @@ int encode_closing_tag(uint8_t *apdu, uint8_t tag_number)
int len = 1;
/* set class field to context specific */
- apdu[0] = BIT(3);
+ if (apdu) {
+ apdu[0] = BIT(3);
+ }
/* additional tag byte after this byte for extended tag byte */
if (tag_number <= 14) {
- apdu[0] |= (tag_number << 4);
+ if (apdu) {
+ apdu[0] |= (tag_number << 4);
+ }
} else {
- apdu[0] |= 0xF0;
- apdu[1] = tag_number;
+ if (apdu) {
+ apdu[0] |= 0xF0;
+ apdu[1] = tag_number;
+ }
len++;
}
- /* set type field to closing tag */
- apdu[0] |= 7;
+ if (apdu) {
+ /* set type field to closing tag */
+ apdu[0] |= 7;
+ }
return len;
}
+/**
+ * Decode a BACnet tag and returns the number of bytes consumed.
+ *
+ * @param apdu Pointer to the encode buffer
+ * @param tag_number Place holder for number of the tag decoded
+ * see BACNET_APPLICATION_TAG_X macros.
+ *
+ * @return Returns the number of apdu bytes consumed.
+ */
int decode_tag_number(uint8_t *apdu, uint8_t *tag_number)
{
int len = 1; /* return value */
@@ -638,9 +691,8 @@ int encode_application_boolean(uint8_t *apdu, bool boolean_value)
} else {
len_value = 0;
}
-
len =
- encode_tag(&apdu[0], BACNET_APPLICATION_TAG_BOOLEAN, false, len_value);
+ encode_tag(apdu, BACNET_APPLICATION_TAG_BOOLEAN, false, len_value);
return len;
}
@@ -662,8 +714,10 @@ int encode_context_boolean(
{
int len; /* return value */
- len = encode_tag(&apdu[0], (uint8_t)tag_number, true, 1);
- apdu[len] = (bool)(boolean_value ? 1 : 0);
+ len = encode_tag(apdu, (uint8_t)tag_number, true, 1);
+ if (apdu) {
+ apdu[len] = (bool)(boolean_value ? 1 : 0);
+ }
len++;
return len;
@@ -748,7 +802,7 @@ bool decode_boolean(uint32_t len_value)
*/
int encode_application_null(uint8_t *apdu)
{
- return encode_tag(&apdu[0], BACNET_APPLICATION_TAG_NULL, false, 0);
+ return encode_tag(apdu, BACNET_APPLICATION_TAG_NULL, false, 0);
}
/**
@@ -764,7 +818,7 @@ int encode_application_null(uint8_t *apdu)
*/
int encode_context_null(uint8_t *apdu, uint8_t tag_number)
{
- return encode_tag(&apdu[0], tag_number, true, 0);
+ return encode_tag(apdu, tag_number, true, 0);
}
/**
@@ -818,9 +872,7 @@ static uint8_t byte_reverse_bits(uint8_t in_byte)
* @return Returns the number of apdu bytes consumed.
*/
int decode_bitstring(
- uint8_t * apdu,
- uint32_t len_value,
- BACNET_BIT_STRING * bit_string)
+ uint8_t *apdu, uint32_t len_value, BACNET_BIT_STRING *bit_string)
{
int len = 0; /* Return value */
uint8_t unused_bits;
@@ -837,13 +889,13 @@ int decode_bitstring(
len = 1;
/* Copy the bytes in reversed bit order. */
for (i = 0; i < bytes_used; i++) {
- bitstring_set_octet(bit_string, (uint8_t) i,
- byte_reverse_bits(apdu[len++]));
+ bitstring_set_octet(
+ bit_string, (uint8_t)i, byte_reverse_bits(apdu[len++]));
}
/* Erase the remaining unused bits. */
- unused_bits = (uint8_t) (apdu[0] & 0x07);
- bitstring_set_bits_used(bit_string, (uint8_t) bytes_used,
- unused_bits);
+ unused_bits = (uint8_t)(apdu[0] & 0x07);
+ bitstring_set_bits_used(
+ bit_string, (uint8_t)bytes_used, unused_bits);
}
}
}
@@ -888,15 +940,24 @@ int encode_bitstring(uint8_t *apdu, BACNET_BIT_STRING *bit_string)
/* if the bit string is empty, then the first octet shall be zero */
if (bitstring_bits_used(bit_string) == 0) {
- apdu[len++] = 0;
+ if (apdu) {
+ apdu[len] = 0;
+ }
+ len++;
} else {
used_bytes = bitstring_bytes_used(bit_string);
remaining_used_bits =
(uint8_t)(bitstring_bits_used(bit_string) - ((used_bytes - 1) * 8));
/* number of unused bits in the subsequent final octet */
- apdu[len++] = (uint8_t)(8 - remaining_used_bits);
+ if (apdu) {
+ apdu[len] = (uint8_t)(8 - remaining_used_bits);
+ }
+ len++;
for (i = 0; i < used_bytes; i++) {
- apdu[len++] = byte_reverse_bits(bitstring_octet(bit_string, i));
+ if (apdu) {
+ apdu[len] = byte_reverse_bits(bitstring_octet(bit_string, i));
+ }
+ len++;
}
}
@@ -907,12 +968,16 @@ int encode_application_bitstring(uint8_t *apdu, BACNET_BIT_STRING *bit_string)
{
int len = 0;
uint32_t bit_string_encoded_length = 1; /* 1 for the bits remaining octet */
+ uint8_t *apdu_offset = NULL;
/* bit string may use more than 1 octet for the tag, so find out how many */
bit_string_encoded_length += bitstring_bytes_used(bit_string);
- len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_BIT_STRING, false,
+ len = encode_tag(apdu, BACNET_APPLICATION_TAG_BIT_STRING, false,
bit_string_encoded_length);
- len += encode_bitstring(&apdu[len], bit_string);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bitstring(apdu_offset, bit_string);
return len;
}
@@ -922,41 +987,103 @@ int encode_context_bitstring(
{
int len = 0;
uint32_t bit_string_encoded_length = 1; /* 1 for the bits remaining octet */
+ uint8_t *apdu_offset = NULL;
/* bit string may use more than 1 octet for the tag, so find out how many */
bit_string_encoded_length += bitstring_bytes_used(bit_string);
- len = encode_tag(&apdu[0], tag_number, true, bit_string_encoded_length);
- len += encode_bitstring(&apdu[len], bit_string);
+ len = encode_tag(apdu, tag_number, true, bit_string_encoded_length);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bitstring(apdu_offset, bit_string);
return len;
}
-/* from clause 20.2.14 Encoding of an Object Identifier Value */
-/* returns the number of apdu bytes consumed */
-int decode_object_id(
- uint8_t *apdu, BACNET_OBJECT_TYPE *object_type, uint32_t *instance)
+/**
+ * @brief Decode the BACnet Object Identifier Value
+ * as defined in clause 20.2.14 Encoding of an Object Identifier Value
+ *
+ * @param apdu - buffer of data to be decoded
+ * @param len_value_type - the expected length of the Object Identifier
+ * @param object_type - decoded object type, if decoded
+ * @param object_instance - decoded object instance, if decoded
+ *
+ * @return the number of apdu bytes consumed
+ */
+int decode_object_id_safe(
+ uint8_t *apdu,
+ uint32_t len_value_type,
+ BACNET_OBJECT_TYPE *object_type,
+ uint32_t *instance)
{
uint32_t value = 0;
int len = 0;
len = decode_unsigned32(apdu, &value);
- *object_type = (BACNET_OBJECT_TYPE)(
- ((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT));
- *instance = (value & BACNET_MAX_INSTANCE);
+ if (len_value_type == len) {
+ if (apdu) {
+ /* value is meaningless if apdu was NULL */
+ if (object_type) {
+ *object_type = (BACNET_OBJECT_TYPE)(
+ ((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT));
+ }
+ if (instance) {
+ *instance = (value & BACNET_MAX_INSTANCE);
+ }
+ }
+ }
return len;
}
+/**
+ * @brief Decode the BACnet Object Identifier Value
+ * as defined in clause 20.2.14 Encoding of an Object Identifier Value
+ *
+ * @param apdu - buffer of data to be decoded
+ * @param len_value_type - the expected length of the Object Identifier
+ * @param object_type - decoded object type, if decoded
+ * @param object_instance - decoded object instance, if decoded
+ *
+ * @return the number of apdu bytes consumed
+ */
+int decode_object_id(
+ uint8_t *apdu,
+ BACNET_OBJECT_TYPE *object_type,
+ uint32_t *instance)
+{
+ const uint32_t len_value = 4;
+
+ return decode_object_id_safe(apdu, len_value, object_type, instance);
+}
+
+/**
+ * @brief Decode the BACnet Object Identifier Value
+ * as defined in clause 20.2.14 Encoding of an Object Identifier Value
+ *
+ * @param apdu - buffer of data to be decoded
+ * @param apdu_len_max - number of bytes in the buffer
+ * @param object_type - decoded object type, if decoded
+ * @param object_instance - decoded object instance, if decoded
+ *
+ * @return the number of apdu bytes consumed, or 0 if apdu is too small
+ */
int bacnet_object_id_decode(uint8_t *apdu,
+ uint16_t apdu_len_max,
uint32_t len_value_type,
BACNET_OBJECT_TYPE *object_type,
uint32_t *instance)
{
- if (len_value_type != 4) {
- return 0;
- } else {
- return decode_object_id(apdu, object_type, instance);
+ int len = 0;
+
+ len = decode_object_id_safe(NULL, len_value_type, object_type, instance);
+ if (len <= apdu_len_max) {
+ return decode_object_id_safe(apdu, len_value_type, object_type,
+ instance);
}
+
+ return 0;
}
/**
@@ -986,14 +1113,10 @@ int bacnet_object_id_application_decode(uint8_t *apdu,
if ((len > 0) && (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID)) {
apdu_len = len;
if (apdu_len < apdu_len_max) {
- if ((apdu_len_max - (unsigned)apdu_len) >= len_value_type) {
- len = bacnet_object_id_decode(
- &apdu[len], len_value_type, object_type, object_instance);
- if (len > 0) {
- apdu_len += len;
- } else {
- apdu_len = BACNET_STATUS_ERROR;
- }
+ len = bacnet_object_id_decode(&apdu[len], apdu_len_max - apdu_len,
+ len_value_type, object_type, object_instance);
+ if (len > 0) {
+ apdu_len += len;
} else {
apdu_len = BACNET_STATUS_ERROR;
}
@@ -1039,7 +1162,8 @@ int bacnet_object_id_context_decode(uint8_t *apdu,
apdu_len += len;
if (apdu_len < apdu_len_max) {
len = bacnet_object_id_decode(&apdu[apdu_len],
- len_value_type, object_type, object_instance);
+ apdu_len_max - apdu_len, len_value_type, object_type,
+ object_instance);
if (len > 0) {
apdu_len += len;
} else {
@@ -1073,8 +1197,17 @@ int decode_context_object_id(uint8_t *apdu,
return len;
}
-/* from clause 20.2.14 Encoding of an Object Identifier Value */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode the BACnet Object Identifier Value
+ * as defined in clause 20.2.14 Encoding of an Object Identifier Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param object_type - object type to be encoded
+ * @param object_instance - object instance to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_bacnet_object_id(
uint8_t *apdu, BACNET_OBJECT_TYPE object_type, uint32_t instance)
{
@@ -1089,36 +1222,61 @@ int encode_bacnet_object_id(
return len;
}
-/* from clause 20.2.14 Encoding of an Object Identifier Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode the BACnet Object Identifier Value as Context Tagged
+ * as defined in clause 20.2.14 Encoding of an Object Identifier Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param tag_number - context tag number to be encoded
+ * @param object_type - object type to be encoded
+ * @param object_instance - object instance to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_context_object_id(uint8_t *apdu,
uint8_t tag_number,
BACNET_OBJECT_TYPE object_type,
uint32_t instance)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
/* length of object id is 4 octets, as per 20.2.14 */
-
- len = encode_tag(&apdu[0], tag_number, true, 4);
- len += encode_bacnet_object_id(&apdu[len], object_type, instance);
+ len = encode_tag(apdu, tag_number, true, 4);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_object_id(apdu_offset, object_type, instance);
return len;
}
-/* from clause 20.2.14 Encoding of an Object Identifier Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode the BACnet Object Identifier Value as Application Tagged
+ * as defined in clause 20.2.14 Encoding of an Object Identifier Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param object_type - object type to be encoded
+ * @param object_instance - object instance to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_application_object_id(
uint8_t *apdu, BACNET_OBJECT_TYPE object_type, uint32_t instance)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
- /* assumes that the tag only consumes 1 octet */
- len = encode_bacnet_object_id(&apdu[1], object_type, instance);
- len += encode_tag(
- &apdu[0], BACNET_APPLICATION_TAG_OBJECT_ID, false, (uint32_t)len);
+ /* get the length by using NULL APDU */
+ len = encode_bacnet_object_id(NULL, object_type, instance);
+ len = encode_tag(
+ apdu, BACNET_APPLICATION_TAG_OBJECT_ID, false, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_object_id(apdu_offset, object_type, instance);
return len;
}
@@ -1138,7 +1296,7 @@ int encode_octet_string(uint8_t *apdu, BACNET_OCTET_STRING *octet_string)
to bounds check since it might not be the only data chunk */
len = (int)octetstring_length(octet_string);
value = octetstring_value(octet_string);
- if (value) {
+ if (value && apdu) {
for (i = 0; i < len; i++) {
apdu[i] = value[i];
}
@@ -1154,21 +1312,19 @@ int encode_octet_string(uint8_t *apdu, BACNET_OCTET_STRING *octet_string)
int encode_application_octet_string(
uint8_t *apdu, BACNET_OCTET_STRING *octet_string)
{
- int apdu_len = 0;
+ int len = 0;
+ uint8_t *apdu_offset = NULL;
if (octet_string) {
- apdu_len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_OCTET_STRING,
+ len = encode_tag(apdu, BACNET_APPLICATION_TAG_OCTET_STRING,
false, octetstring_length(octet_string));
- /* FIXME: probably need to pass in the length of the APDU
- to bounds check since it might not be the only data chunk */
- if ((apdu_len + octetstring_length(octet_string)) < MAX_APDU) {
- apdu_len += encode_octet_string(&apdu[apdu_len], octet_string);
- } else {
- apdu_len = 0;
+ if (apdu) {
+ apdu_offset = &apdu[len];
}
+ len += encode_octet_string(apdu_offset, octet_string);
}
- return apdu_len;
+ return len;
}
/* from clause 20.2.8 Encoding of an Octet String Value */
@@ -1177,19 +1333,19 @@ int encode_application_octet_string(
int encode_context_octet_string(
uint8_t *apdu, uint8_t tag_number, BACNET_OCTET_STRING *octet_string)
{
- int apdu_len = 0;
+ int len = 0;
+ uint8_t *apdu_offset = NULL;
- if (apdu && octet_string) {
- apdu_len = encode_tag(
- &apdu[0], tag_number, true, octetstring_length(octet_string));
- if ((apdu_len + octetstring_length(octet_string)) < MAX_APDU) {
- apdu_len += encode_octet_string(&apdu[apdu_len], octet_string);
- } else {
- apdu_len = 0;
+ if (octet_string) {
+ len = encode_tag(
+ apdu, tag_number, true, octetstring_length(octet_string));
+ if (apdu) {
+ apdu_offset = &apdu[len];
}
+ len += encode_octet_string(apdu_offset, octet_string);
}
- return apdu_len;
+ return len;
}
/**
@@ -1248,7 +1404,6 @@ int decode_context_octet_string(
if (decode_is_context_tag(&apdu[len], tag_number) &&
!decode_is_closing_tag(&apdu[len])) {
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
-
if (len_value > 0) {
status = octetstring_init(octet_string, &apdu[len], len_value);
} else {
@@ -1317,10 +1472,12 @@ uint32_t encode_bacnet_character_string_safe(uint8_t *apdu,
uint32_t i;
apdu_len += length;
- if (apdu && (apdu_len <= max_apdu)) {
- apdu[0] = encoding;
- for (i = 0; i < length; i++) {
- apdu[1 + i] = (uint8_t)pString[i];
+ if (apdu_len <= max_apdu) {
+ if (apdu) {
+ apdu[0] = encoding;
+ for (i = 0; i < length; i++) {
+ apdu[1 + i] = (uint8_t)pString[i];
+ }
}
} else {
apdu_len = 0;
@@ -1345,35 +1502,34 @@ int encode_application_character_string(
uint8_t *apdu, BACNET_CHARACTER_STRING *char_string)
{
int len = 0;
- int string_len = 0;
+ uint8_t *apdu_offset = NULL;
- string_len =
- (int)characterstring_length(char_string) + 1 /* for encoding */;
- len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_CHARACTER_STRING, false,
- (uint32_t)string_len);
- if ((len + string_len) < MAX_APDU) {
- len += encode_bacnet_character_string(&apdu[len], char_string);
- } else {
- len = 0;
+ len = encode_bacnet_character_string(NULL, char_string);
+ len = encode_tag(apdu, BACNET_APPLICATION_TAG_CHARACTER_STRING,
+ false, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
}
+ len += encode_bacnet_character_string(apdu_offset, char_string);
return len;
}
+/* from clause 20.2.9 Encoding of a Character String Value */
+/* and 20.2.1 General Rules for Encoding BACnet Tags */
+/* returns the number of apdu bytes consumed */
int encode_context_character_string(
uint8_t *apdu, uint8_t tag_number, BACNET_CHARACTER_STRING *char_string)
{
int len = 0;
- int string_len = 0;
+ uint8_t *apdu_offset = NULL;
- string_len =
- (int)characterstring_length(char_string) + 1 /* for encoding */;
- len += encode_tag(&apdu[0], tag_number, true, (uint32_t)string_len);
- if ((len + string_len) < MAX_APDU) {
- len += encode_bacnet_character_string(&apdu[len], char_string);
- } else {
- len = 0;
+ len = encode_bacnet_character_string(NULL, char_string);
+ len = encode_tag(apdu, tag_number, true, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
}
+ len += encode_bacnet_character_string(apdu_offset, char_string);
return len;
}
@@ -1420,7 +1576,6 @@ int bacnet_character_string_decode(uint8_t *apdu,
* and 20.2.1 General Rules for Encoding BACnet Tags
*
* @param apdu - buffer to hold the bytes
- * @param apdu_len_max - number of bytes in the buffer to decode
* @param len_value - number of bytes in the unsigned value encoding
* @param value - the character string value decoded
*
@@ -1729,68 +1884,100 @@ int decode_context_unsigned(
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 */
+/**
+ * @brief Encode the BACnet Unsigned value
+ * as defined in clause 20.2.4 Encoding of an Unsigned Integer Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param value - value to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_bacnet_unsigned(uint8_t *apdu, BACNET_UNSIGNED_INTEGER value)
{
int len = 0; /* return value */
len = bacnet_unsigned_length(value);
- if (len == 1) {
- apdu[0] = (uint8_t)value;
- } else if (len == 2) {
- (void)encode_unsigned16(&apdu[0], (uint16_t)value);
- } else if (len == 3) {
- (void)encode_unsigned24(&apdu[0], (uint32_t)value);
- } else {
-#ifdef UINT64_MAX
- if (len == 4) {
- (void)encode_unsigned32(&apdu[0], (uint32_t)value);
- } else if (len == 5) {
- (void)encode_unsigned40(&apdu[0], value);
- } else if (len == 6) {
- (void)encode_unsigned48(&apdu[0], value);
- } else if (len == 7) {
- (void)encode_unsigned56(&apdu[0], value);
+ if (apdu) {
+ if (len == 1) {
+ apdu[0] = (uint8_t)value;
+ } else if (len == 2) {
+ (void)encode_unsigned16(&apdu[0], (uint16_t)value);
+ } else if (len == 3) {
+ (void)encode_unsigned24(&apdu[0], (uint32_t)value);
} else {
- len = encode_unsigned64(&apdu[0], value);
- }
+#ifdef UINT64_MAX
+ if (len == 4) {
+ (void)encode_unsigned32(&apdu[0], (uint32_t)value);
+ } else if (len == 5) {
+ (void)encode_unsigned40(&apdu[0], value);
+ } else if (len == 6) {
+ (void)encode_unsigned48(&apdu[0], value);
+ } else if (len == 7) {
+ (void)encode_unsigned56(&apdu[0], value);
+ } else {
+ len = encode_unsigned64(&apdu[0], value);
+ }
#else
- len = encode_unsigned32(&apdu[0], value);
+ len = encode_unsigned32(&apdu[0], value);
#endif
+ }
}
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 */
+/**
+ * @brief Encode the BACnet Unsigned value as Context Tagged
+ * as defined in clause 20.2.4 Encoding of an Unsigned Integer Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param tag_number - context tag number to be encoded
+ * @param value - value to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_context_unsigned(
uint8_t *apdu, uint8_t tag_number, BACNET_UNSIGNED_INTEGER value)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
/* length of unsigned is variable, as per 20.2.4 */
len = bacnet_unsigned_length(value);
- len = encode_tag(&apdu[0], tag_number, true, (uint32_t)len);
- len += encode_bacnet_unsigned(&apdu[len], value);
+ len = encode_tag(apdu, tag_number, true, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_unsigned(apdu_offset, 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 */
+/**
+ * @brief Encode the BACnet Unsigned value as Application Tagged
+ * as defined in clause 20.2.4 Encoding of an Unsigned Integer Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param value - value to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_application_unsigned(uint8_t *apdu, BACNET_UNSIGNED_INTEGER value)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
len = bacnet_unsigned_length(value);
len = encode_tag(
- &apdu[0], BACNET_APPLICATION_TAG_UNSIGNED_INT, false, (uint32_t)len);
- len += encode_bacnet_unsigned(&apdu[len], value);
+ apdu, BACNET_APPLICATION_TAG_UNSIGNED_INT, false, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_unsigned(apdu_offset, value);
return len;
}
@@ -1914,49 +2101,69 @@ int decode_context_enumerated(uint8_t *apdu, uint8_t tag_value, uint32_t *value)
return len;
}
-/* from clause 20.2.11 Encoding of an Enumerated Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode the BACnet Enumerated Value
+ * as defined in clause 20.2.11 Encoding of an Enumerated Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param value - value to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_bacnet_enumerated(uint8_t *apdu, uint32_t value)
{
return encode_bacnet_unsigned(apdu, value);
}
-/* from clause 20.2.11 Encoding of an Enumerated Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode the BACnet Enumerated Value as Application Tagged
+ * as defined in clause 20.2.11 Encoding of an Enumerated Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param value - value to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_application_enumerated(uint8_t *apdu, uint32_t value)
{
int len = 0; /* return value */
+ uint8_t *apdu_offset = NULL;
- /* assumes that the tag only consumes 1 octet */
- len = encode_bacnet_enumerated(&apdu[1], value);
- len += encode_tag(
- &apdu[0], BACNET_APPLICATION_TAG_ENUMERATED, false, (uint32_t)len);
+ len = bacnet_unsigned_length(value);
+ len = encode_tag(
+ apdu, BACNET_APPLICATION_TAG_ENUMERATED, false, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_enumerated(apdu_offset, value);
return len;
}
-/* from clause 20.2.11 Encoding of an Enumerated Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode the BACnet Enumerated Value as Context Tagged
+ * as defined in clause 20.2.11 Encoding of an Enumerated Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param tag_number - context tag number to be encoded
+ * @param value - value to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_context_enumerated(uint8_t *apdu, uint8_t tag_number, uint32_t value)
{
int len = 0; /* return value */
+ uint8_t *apdu_offset = NULL;
- /* length of enumerated is variable, as per 20.2.11 */
- if (value < 0x100) {
- len = 1;
- } else if (value < 0x10000) {
- len = 2;
- } else if (value < 0x1000000) {
- len = 3;
- } else {
- len = 4;
+ len = bacnet_unsigned_length(value);
+ len = encode_tag(apdu, tag_number, true, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
}
-
- len = encode_tag(&apdu[0], tag_number, true, (uint32_t)len);
- len += encode_bacnet_enumerated(&apdu[len], value);
+ len += encode_bacnet_enumerated(apdu_offset, value);
return len;
}
@@ -1970,7 +2177,7 @@ int encode_context_enumerated(uint8_t *apdu, uint8_t tag_number, uint32_t value)
* @param apdu - buffer to hold the bytes
* @param apdu_len_max - number of bytes in the buffer to decode
* @param len_value - number of bytes in the unsigned value encoding
- * @param value - the unsigned value decoded
+ * @param value - the signed value decoded
*
* @return number of bytes decoded, or zero if errors occur
*/
@@ -2003,14 +2210,14 @@ int bacnet_signed_decode(
}
/**
- * @brief Decodes from bytes into a BACnet Signed value
+ * @brief Decodes from bytes into a BACnet Signed Integer
* as defined in clause 20.2.5 Encoding of a Signed Integer Value
* and 20.2.1 General Rules for Encoding BACnet Tags
*
* @param apdu - buffer to hold the bytes
* @param apdu_len_max - number of bytes in the buffer to decode
* @param tag_value - context tag number expected
- * @param value - the unsigned value decoded
+ * @param value - the signed value decoded
*
* @return number of bytes decoded, zero if wrong tag number,
* or error (-1) if malformed
@@ -2090,13 +2297,13 @@ int bacnet_signed_application_decode(
}
/**
- * @brief Decodes from bytes into a BACnet Unsigned value
- * from clause 20.2.4 Encoding of an Unsigned Integer Value
+ * @brief Decodes from bytes into a BACnet Signed Integer
+ * from clause 20.2.5 Encoding of an Signed Integer Value
* and 20.2.1 General Rules for Encoding BACnet Tags
*
* @param apdu - buffer holding the bytes
* @param len_value - number of bytes in the unsigned value encoding
- * @param value - the unsigned value decoded
+ * @param value - the signed value decoded
*
* @return number of bytes decoded, #BACNET_STATUS_ERROR (-1) if
* wrong tag number, or error (-1) if malformed
@@ -2109,13 +2316,13 @@ int decode_signed(uint8_t *apdu, uint32_t len_value, int32_t *value)
}
/**
- * @brief Decodes from bytes into a BACnet Unsigned value
- * from clause 20.2.4 Encoding of an Unsigned Integer Value
+ * @brief Decodes from bytes into a BACnet Signed Integer
+ * from clause 20.2.5 Encoding of an Signed Integer Value
* and 20.2.1 General Rules for Encoding BACnet Tags
*
* @param apdu - buffer holding the bytes
* @param tag_value - context tag number expected
- * @param value - the unsigned value decoded
+ * @param value - the signed value decoded
*
* @return number of bytes decoded, #BACNET_STATUS_ERROR (-1) if
* wrong tag number, or error (-1) if malformed
@@ -2133,66 +2340,85 @@ int decode_context_signed(uint8_t *apdu, uint8_t tag_value, int32_t *value)
return len;
}
-/* from clause 20.2.5 Encoding of a Signed Integer Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Decodes from bytes into a BACnet Signed Integer
+ * from clause 20.2.5 Encoding of an Signed Integer Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer holding the bytes, or NULL for length
+ * @param value - the signed value decoded
+ *
+ * @return number of bytes encoded
+ */
+/* */
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);
+ len = bacnet_signed_length(value);
+ if (apdu) {
+ if (len == 1) {
+ (void)encode_signed8(&apdu[0], (int8_t)value);
+ } else if (len == 2) {
+ (void)encode_signed16(&apdu[0], (int16_t)value);
+ } else if (len == 3) {
+ (void)encode_signed24(&apdu[0], value);
+ } else {
+ (void)encode_signed32(&apdu[0], value);
+ }
}
return len;
}
-/* from clause 20.2.5 Encoding of a Signed Integer Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode the BACnet Signed Integer as Application Tagged
+ * as defined in clause 20.2.5 Encoding of a Signed Integer Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param value - value to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_application_signed(uint8_t *apdu, int32_t value)
{
int len = 0; /* return value */
+ uint8_t *apdu_offset = NULL;
- /* assumes that the tag only consumes 1 octet */
- len = encode_bacnet_signed(&apdu[1], value);
- len += encode_tag(
- &apdu[0], BACNET_APPLICATION_TAG_SIGNED_INT, false, (uint32_t)len);
+ len = bacnet_signed_length(value);
+ len = encode_tag(
+ apdu, BACNET_APPLICATION_TAG_SIGNED_INT, false, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_signed(apdu_offset, value);
return len;
}
-/* from clause 20.2.5 Encoding of a Signed Integer Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode the BACnet Signed Integer as Context Tagged
+ * as defined in clause 20.2.5 Encoding of a Signed Integer Value
+ * and 20.2.1 General Rules for Encoding BACnet Tags
+ *
+ * @param apdu - buffer of data to be encoded, or NULL for length
+ * @param tag_number - context tag number to be encoded
+ * @param value - value to be encoded
+ *
+ * @return the number of apdu bytes encoded
+ */
int encode_context_signed(uint8_t *apdu, uint8_t tag_number, int32_t value)
{
int len = 0; /* return value */
+ uint8_t *apdu_offset = NULL;
- /* length of signed int is variable, as per 20.2.11 */
- if ((value >= -128) && (value < 128)) {
- len = 1;
- } else if ((value >= -32768) && (value < 32768)) {
- len = 2;
- } else if ((value > -8388608) && (value < 8388608)) {
- len = 3;
- } else {
- len = 4;
+ len = bacnet_signed_length(value);
+ len = encode_tag(apdu, tag_number, true, (uint32_t)len);
+ if (apdu) {
+ apdu_offset = &apdu[len];
}
-
- len = encode_tag(&apdu[0], tag_number, true, (uint32_t)len);
- len += encode_bacnet_signed(&apdu[len], value);
+ len += encode_bacnet_signed(apdu_offset, value);
return len;
}
@@ -2202,19 +2428,22 @@ int encode_context_signed(uint8_t *apdu, uint8_t tag_number, int32_t value)
* @brief Encode a real floating value. From clause 20.2.6 Encoding of a
* Real Number Value and 20.2.1 General Rules for Encoding BACnet Tags.
*
- * @param apdu Transmit buffer
+ * @param apdu buffer to be encoded, or NULL for length
* @param value The float value to be encoded.
*
- * @return Returns the number of apdu bytes consumed.
+ * @return the number of apdu bytes consumed.
*/
int encode_application_real(uint8_t *apdu, float value)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
- /* assumes that the tag only consumes 1 octet */
- len = encode_bacnet_real(value, &apdu[1]);
- len +=
- encode_tag(&apdu[0], BACNET_APPLICATION_TAG_REAL, false, (uint32_t)len);
+ /* length of REAL is 4 octets, as per 20.2.6 */
+ len = encode_tag(apdu, BACNET_APPLICATION_TAG_REAL, false, 4);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_real(value, apdu_offset);
return len;
}
@@ -2233,10 +2462,15 @@ int encode_application_real(uint8_t *apdu, float value)
int encode_context_real(uint8_t *apdu, uint8_t tag_number, float value)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
+
+ /* length of REAL is 4 octets, as per 20.2.6 */
+ len = encode_tag(apdu, tag_number, true, 4);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_real(value, apdu_offset);
- /* length of double is 4 octets, as per 20.2.6 */
- len = encode_tag(&apdu[0], tag_number, true, 4);
- len += encode_bacnet_real(value, &apdu[len]);
return len;
}
@@ -2255,32 +2489,57 @@ int decode_context_real(uint8_t *apdu, uint8_t tag_number, float *real_value)
}
#if BACNET_USE_DOUBLE
-/* from clause 20.2.7 Encoding of a Double Precision Real Number Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode a Double Precision Real Number Value as Application Tagged
+ * From clause 20.2.7 Encoding of a Double Precision Real Number Value
+ * and clause 20.2.1 General Rules for Encoding BACnet Tags.
+ *
+ * @param apdu buffer to be encoded, or NULL for length
+ * @param value The value to be encoded.
+ *
+ * @return the number of apdu bytes consumed.
+ */
int encode_application_double(uint8_t *apdu, double value)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
- /* assumes that the tag only consumes 2 octet */
- len = encode_bacnet_double(value, &apdu[2]);
-
- len += encode_tag(
- &apdu[0], BACNET_APPLICATION_TAG_DOUBLE, false, (uint32_t)len);
+ /* length of DOUBLE is 8 octets, as per 20.2.7 */
+ len = encode_tag(apdu, BACNET_APPLICATION_TAG_DOUBLE, false, 8);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_double(value, apdu_offset);
return len;
}
+/**
+ * @brief Encode a Double Precision Real Number Value as Context Tagged
+ * From clause 20.2.7 Encoding of a Double Precision Real Number Value
+ * and clause 20.2.1 General Rules for Encoding BACnet Tags.
+ *
+ * @param apdu buffer to be encoded, or NULL for length
+ * @param tag_number Tag number to be used
+ * @param value The value to be encoded.
+ *
+ * @return the number of apdu bytes consumed.
+ */
int encode_context_double(uint8_t *apdu, uint8_t tag_number, double value)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
/* length of double is 8 octets, as per 20.2.7 */
- len = encode_tag(&apdu[0], tag_number, true, 8);
- len += encode_bacnet_double(value, &apdu[len]);
+ len = encode_tag(apdu, tag_number, true, 8);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_double(value, apdu_offset);
return len;
}
+
int decode_context_double(
uint8_t *apdu, uint8_t tag_number, double *double_value)
{
@@ -2297,41 +2556,75 @@ int decode_context_double(
}
#endif
-/* from clause 20.2.13 Encoding of a Time Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode a Time Value
+ * From clause 20.2.13 Encoding of a Time Value
+ * and clause 20.2.1 General Rules for Encoding BACnet Tags.
+ *
+ * @param apdu buffer to be encoded, or NULL for length
+ * @param value The value to be encoded.
+ *
+ * @return the number of apdu bytes consumed.
+ */
int encode_bacnet_time(uint8_t *apdu, BACNET_TIME *btime)
{
- apdu[0] = btime->hour;
- apdu[1] = btime->min;
- apdu[2] = btime->sec;
- apdu[3] = btime->hundredths;
+ if (apdu) {
+ apdu[0] = btime->hour;
+ apdu[1] = btime->min;
+ apdu[2] = btime->sec;
+ apdu[3] = btime->hundredths;
+ }
return 4;
}
-/* from clause 20.2.13 Encoding of a Time Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode a Time Value as Application Tagged
+ * From clause 20.2.13 Encoding of a Time Value
+ * and clause 20.2.1 General Rules for Encoding BACnet Tags.
+ *
+ * @param apdu buffer to be encoded, or NULL for length
+ * @param btime The value to be encoded.
+ *
+ * @return the number of apdu bytes consumed.
+ */
int encode_application_time(uint8_t *apdu, BACNET_TIME *btime)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
- /* assumes that the tag only consumes 1 octet */
- len = encode_bacnet_time(&apdu[1], btime);
- len +=
- encode_tag(&apdu[0], BACNET_APPLICATION_TAG_TIME, false, (uint32_t)len);
+ /* length of Time value is 4 octets, as per 20.2.13 */
+ len = encode_tag(apdu, BACNET_APPLICATION_TAG_TIME, false, 4);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_time(apdu_offset, btime);
return len;
}
+/**
+ * @brief Encode a Time Value as Context Tagged
+ * From clause 20.2.13 Encoding of a Time Value
+ * and clause 20.2.1 General Rules for Encoding BACnet Tags.
+ *
+ * @param apdu buffer to be encoded, or NULL for length
+ * @param tag_number Tag number to be used
+ * @param btime The value to be encoded.
+ *
+ * @return the number of apdu bytes consumed.
+ */
int encode_context_time(uint8_t *apdu, uint8_t tag_number, BACNET_TIME *btime)
{
int len = 0; /* return value */
+ uint8_t *apdu_offset = NULL;
/* length of time is 4 octets, as per 20.2.13 */
- len = encode_tag(&apdu[0], tag_number, true, 4);
- len += encode_bacnet_time(&apdu[len], btime);
+ len = encode_tag(apdu, tag_number, true, 4);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_time(apdu_offset, btime);
return len;
}
@@ -2509,58 +2802,92 @@ int decode_context_bacnet_time(
return len;
}
-/* BACnet Date */
-/* year = years since 1900, wildcard=1900+255 */
-/* month 1=Jan */
-/* day = day of month */
-/* wday 1=Monday...7=Sunday */
-
-/* from clause 20.2.12 Encoding of a Date Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode a Date Value
+ * From clause 20.2.12 Encoding of a Date Value
+ * and clause 20.2.1 General Rules for Encoding BACnet Tags.
+ *
+ * BACnet Date
+ * year = years since 1900, wildcard=1900+255
+ * month 1=Jan
+ * day = day of month
+ * wday 1=Monday...7=Sunday
+ *
+ * @param apdu buffer to be encoded, or NULL for length
+ * @param value The value to be encoded.
+ *
+ * @return the number of apdu bytes consumed.
+ */
int encode_bacnet_date(uint8_t *apdu, BACNET_DATE *bdate)
{
- if (bdate->year >= 1900) {
- /* normal encoding, including wildcard */
- apdu[0] = (uint8_t)(bdate->year - 1900);
- } else if (bdate->year < 0x100) {
- /* allow 2 digit years */
- apdu[0] = (uint8_t)bdate->year;
- } else {
- /*
- ** Don't try and guess what the user meant here. Just fail
- */
- return BACNET_STATUS_ERROR;
+ if (apdu) {
+ if (bdate->year >= 1900) {
+ /* normal encoding, including wildcard */
+ apdu[0] = (uint8_t)(bdate->year - 1900);
+ } else if (bdate->year < 0x100) {
+ /* allow 2 digit years */
+ apdu[0] = (uint8_t)bdate->year;
+ } else {
+ /*
+ ** Don't try and guess what the user meant here. Just fail
+ */
+ return BACNET_STATUS_ERROR;
+ }
+ apdu[1] = bdate->month;
+ apdu[2] = bdate->day;
+ apdu[3] = bdate->wday;
}
- apdu[1] = bdate->month;
- apdu[2] = bdate->day;
- apdu[3] = bdate->wday;
return 4;
}
-/* from clause 20.2.12 Encoding of a Date Value */
-/* and 20.2.1 General Rules for Encoding BACnet Tags */
-/* returns the number of apdu bytes consumed */
+/**
+ * @brief Encode a Date Value as Application Tagged
+ * From clause 20.2.12 Encoding of a Date Value
+ * and clause 20.2.1 General Rules for Encoding BACnet Tags.
+ *
+ * @param apdu buffer to be encoded, or NULL for length
+ * @param bdate The value to be encoded.
+ *
+ * @return the number of apdu bytes consumed.
+ */
int encode_application_date(uint8_t *apdu, BACNET_DATE *bdate)
{
int len = 0;
+ uint8_t *apdu_offset = NULL;
- /* assumes that the tag only consumes 1 octet */
- len = encode_bacnet_date(&apdu[1], bdate);
- len +=
- encode_tag(&apdu[0], BACNET_APPLICATION_TAG_DATE, false, (uint32_t)len);
+ /* length of Date value is 4 octets, as per 20.2.12 */
+ len = encode_tag(apdu, BACNET_APPLICATION_TAG_DATE, false, 4);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_date(apdu_offset, bdate);
return len;
}
+/**
+ * @brief Encode a Date Value as Context Tagged
+ * From clause 20.2.12 Encoding of a Date Value
+ * and clause 20.2.1 General Rules for Encoding BACnet Tags.
+ *
+ * @param apdu buffer to be encoded, or NULL for length
+ * @param tag_number Tag number to be used
+ * @param bdate The value to be encoded.
+ *
+ * @return the number of apdu bytes consumed.
+ */
int encode_context_date(uint8_t *apdu, uint8_t tag_number, BACNET_DATE *bdate)
{
int len = 0; /* return value */
+ uint8_t *apdu_offset = NULL;
/* length of date is 4 octets, as per 20.2.12 */
- len = encode_tag(&apdu[0], tag_number, true, 4);
- len += encode_bacnet_date(&apdu[len], bdate);
+ len = encode_tag(apdu, tag_number, true, 4);
+ if (apdu) {
+ apdu_offset = &apdu[len];
+ }
+ len += encode_bacnet_date(apdu_offset, bdate);
return len;
}
diff --git a/src/bacnet/bacdcode.h b/src/bacnet/bacdcode.h
index 0149897f..7b3122b0 100644
--- a/src/bacnet/bacdcode.h
+++ b/src/bacnet/bacdcode.h
@@ -1,26 +1,26 @@
/**************************************************************************
-*
-* Copyright (C) 2012 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.
-*********************************************************************/
+ *
+ * Copyright (C) 2012 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 BACDCODE_H
#define BACDCODE_H
@@ -215,10 +215,16 @@ extern "C" {
uint8_t * apdu,
BACNET_OBJECT_TYPE * object_type,
uint32_t * object_instance);
+ int decode_object_id_safe(
+ uint8_t * apdu,
+ uint32_t len_value,
+ BACNET_OBJECT_TYPE * object_type,
+ uint32_t * object_instance);
BACNET_STACK_EXPORT
int bacnet_object_id_decode(
uint8_t * apdu,
+ uint16_t apdu_len_max,
uint32_t len_value,
BACNET_OBJECT_TYPE * object_type,
uint32_t * instance);
diff --git a/src/bacnet/bacint.c b/src/bacnet/bacint.c
index 0efae52c..e3856426 100644
--- a/src/bacnet/bacint.c
+++ b/src/bacnet/bacint.c
@@ -43,15 +43,17 @@
int encode_unsigned16(uint8_t *apdu, uint16_t value)
{
- apdu[0] = (uint8_t)((value & 0xff00) >> 8);
- apdu[1] = (uint8_t)(value & 0x00ff);
+ if (apdu) {
+ apdu[0] = (uint8_t)((value & 0xff00) >> 8);
+ apdu[1] = (uint8_t)(value & 0x00ff);
+ }
return 2;
}
int decode_unsigned16(uint8_t *apdu, uint16_t *value)
{
- if (value) {
+ if (apdu && value) {
*value = (uint16_t)((((uint16_t)apdu[0]) << 8) & 0xff00);
*value |= ((uint16_t)(((uint16_t)apdu[1]) & 0x00ff));
}
@@ -61,16 +63,18 @@ int decode_unsigned16(uint8_t *apdu, uint16_t *value)
int encode_unsigned24(uint8_t *apdu, uint32_t value)
{
- apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
- apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
- apdu[2] = (uint8_t)(value & 0x0000ff);
+ if (apdu) {
+ apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
+ apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
+ apdu[2] = (uint8_t)(value & 0x0000ff);
+ }
return 3;
}
int decode_unsigned24(uint8_t *apdu, uint32_t *value)
{
- if (value) {
+ if (apdu && value) {
*value = ((uint32_t)((((uint32_t)apdu[0]) << 16) & 0x00ff0000));
*value |= (uint32_t)((((uint32_t)apdu[1]) << 8) & 0x0000ff00);
*value |= ((uint32_t)(((uint32_t)apdu[2]) & 0x000000ff));
@@ -81,17 +85,19 @@ int decode_unsigned24(uint8_t *apdu, uint32_t *value)
int encode_unsigned32(uint8_t *apdu, uint32_t value)
{
- apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
- apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
- apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
- apdu[3] = (uint8_t)(value & 0x000000ff);
+ if (apdu) {
+ apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
+ apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
+ apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
+ apdu[3] = (uint8_t)(value & 0x000000ff);
+ }
return 4;
}
int decode_unsigned32(uint8_t *apdu, uint32_t *value)
{
- if (value) {
+ if (apdu && value) {
*value = ((uint32_t)((((uint32_t)apdu[0]) << 24) & 0xff000000));
*value |= ((uint32_t)((((uint32_t)apdu[1]) << 16) & 0x00ff0000));
*value |= ((uint32_t)((((uint32_t)apdu[2]) << 8) & 0x0000ff00));
@@ -110,11 +116,13 @@ int decode_unsigned32(uint8_t *apdu, uint32_t *value)
*/
int encode_unsigned40(uint8_t *buffer, uint64_t value)
{
- buffer[0] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
- buffer[1] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
- buffer[2] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
- buffer[3] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
- buffer[4] = (uint8_t)(value & 0x00000000000000ffULL);
+ if (buffer) {
+ buffer[0] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
+ buffer[1] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
+ buffer[2] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
+ buffer[3] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
+ buffer[4] = (uint8_t)(value & 0x00000000000000ffULL);
+ }
return 5;
}
@@ -127,7 +135,7 @@ int encode_unsigned40(uint8_t *buffer, uint64_t value)
*/
int decode_unsigned40(uint8_t *buffer, uint64_t *value)
{
- if (value) {
+ if (buffer && value) {
*value =
((uint64_t)((((uint64_t)buffer[0]) << 32) & 0x000000ff00000000ULL));
*value |=
@@ -150,12 +158,14 @@ int decode_unsigned40(uint8_t *buffer, uint64_t *value)
*/
int encode_unsigned48(uint8_t *buffer, uint64_t value)
{
- buffer[0] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
- buffer[1] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
- buffer[2] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
- buffer[3] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
- buffer[4] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
- buffer[5] = (uint8_t)(value & 0x00000000000000ffULL);
+ if (buffer) {
+ buffer[0] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
+ buffer[1] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
+ buffer[2] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
+ buffer[3] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
+ buffer[4] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
+ buffer[5] = (uint8_t)(value & 0x00000000000000ffULL);
+ }
return 6;
}
@@ -168,7 +178,7 @@ int encode_unsigned48(uint8_t *buffer, uint64_t value)
*/
int decode_unsigned48(uint8_t *buffer, uint64_t *value)
{
- if (value) {
+ if (buffer && value) {
*value =
((uint64_t)((((uint64_t)buffer[0]) << 40) & 0x0000ff0000000000ULL));
*value |=
@@ -193,13 +203,15 @@ int decode_unsigned48(uint8_t *buffer, uint64_t *value)
*/
int encode_unsigned56(uint8_t *buffer, uint64_t value)
{
- buffer[0] = (uint8_t)((value & 0x00ff000000000000ULL) >> 48);
- buffer[1] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
- buffer[2] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
- buffer[3] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
- buffer[4] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
- buffer[5] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
- buffer[6] = (uint8_t)(value & 0x00000000000000ffULL);
+ if (buffer) {
+ buffer[0] = (uint8_t)((value & 0x00ff000000000000ULL) >> 48);
+ buffer[1] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
+ buffer[2] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
+ buffer[3] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
+ buffer[4] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
+ buffer[5] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
+ buffer[6] = (uint8_t)(value & 0x00000000000000ffULL);
+ }
return 7;
}
@@ -212,7 +224,7 @@ int encode_unsigned56(uint8_t *buffer, uint64_t value)
*/
int decode_unsigned56(uint8_t *buffer, uint64_t *value)
{
- if (value) {
+ if (buffer && value) {
*value =
((uint64_t)((((uint64_t)buffer[0]) << 48) & 0x00ff000000000000ULL));
*value |=
@@ -239,14 +251,16 @@ int decode_unsigned56(uint8_t *buffer, uint64_t *value)
*/
int encode_unsigned64(uint8_t *buffer, uint64_t value)
{
- buffer[0] = (uint8_t)((value & 0xff00000000000000ULL) >> 56);
- buffer[1] = (uint8_t)((value & 0x00ff000000000000ULL) >> 48);
- buffer[2] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
- buffer[3] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
- buffer[4] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
- buffer[5] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
- buffer[6] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
- buffer[7] = (uint8_t)(value & 0x00000000000000ffULL);
+ if (buffer) {
+ buffer[0] = (uint8_t)((value & 0xff00000000000000ULL) >> 56);
+ buffer[1] = (uint8_t)((value & 0x00ff000000000000ULL) >> 48);
+ buffer[2] = (uint8_t)((value & 0x0000ff0000000000ULL) >> 40);
+ buffer[3] = (uint8_t)((value & 0x000000ff00000000ULL) >> 32);
+ buffer[4] = (uint8_t)((value & 0x00000000ff000000ULL) >> 24);
+ buffer[5] = (uint8_t)((value & 0x0000000000ff0000ULL) >> 16);
+ buffer[6] = (uint8_t)((value & 0x000000000000ff00ULL) >> 8);
+ buffer[7] = (uint8_t)(value & 0x00000000000000ffULL);
+ }
return 8;
}
@@ -259,7 +273,7 @@ int encode_unsigned64(uint8_t *buffer, uint64_t value)
*/
int decode_unsigned64(uint8_t *buffer, uint64_t *value)
{
- if (value) {
+ if (buffer && value) {
*value =
((uint64_t)((((uint64_t)buffer[0]) << 56) & 0xff00000000000000ULL));
*value |=
@@ -320,14 +334,16 @@ int bacnet_unsigned_length(BACNET_UNSIGNED_INTEGER value)
#if BACNET_USE_SIGNED
int encode_signed8(uint8_t *apdu, int8_t value)
{
- apdu[0] = (uint8_t)value;
+ if (apdu) {
+ apdu[0] = (uint8_t)value;
+ }
return 1;
}
int decode_signed8(uint8_t *apdu, int32_t *value)
{
- if (value) {
+ if (apdu && value) {
/* negative - bit 7 is set */
if (apdu[0] & 0x80) {
*value = 0xFFFFFF00;
@@ -342,15 +358,17 @@ int decode_signed8(uint8_t *apdu, int32_t *value)
int encode_signed16(uint8_t *apdu, int16_t value)
{
- apdu[0] = (uint8_t)((value & 0xff00) >> 8);
- apdu[1] = (uint8_t)(value & 0x00ff);
+ if (apdu) {
+ apdu[0] = (uint8_t)((value & 0xff00) >> 8);
+ apdu[1] = (uint8_t)(value & 0x00ff);
+ }
return 2;
}
int decode_signed16(uint8_t *apdu, int32_t *value)
{
- if (value) {
+ if (apdu && value) {
/* negative - bit 7 is set */
if (apdu[0] & 0x80) {
*value = 0xFFFF0000;
@@ -366,16 +384,18 @@ int decode_signed16(uint8_t *apdu, int32_t *value)
int encode_signed24(uint8_t *apdu, int32_t value)
{
- apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
- apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
- apdu[2] = (uint8_t)(value & 0x0000ff);
+ if (apdu) {
+ apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
+ apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
+ apdu[2] = (uint8_t)(value & 0x0000ff);
+ }
return 3;
}
int decode_signed24(uint8_t *apdu, int32_t *value)
{
- if (value) {
+ if (apdu && value) {
/* negative - bit 7 is set */
if (apdu[0] & 0x80) {
*value = 0xFF000000;
@@ -392,10 +412,12 @@ int decode_signed24(uint8_t *apdu, int32_t *value)
int encode_signed32(uint8_t *apdu, int32_t value)
{
- apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
- apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
- apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
- apdu[3] = (uint8_t)(value & 0x000000ff);
+ if (apdu) {
+ apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
+ apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
+ apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
+ apdu[3] = (uint8_t)(value & 0x000000ff);
+ }
return 4;
}
@@ -411,4 +433,27 @@ int decode_signed32(uint8_t *apdu, int32_t *value)
return 4;
}
+
+/**
+ * @brief Determines the number of bytes used by a BACnet Signed Integer
+ * from clause 20.2.5 Encoding of an Signed Integer Value
+ * @param value - signed value
+ * @return number of bytes used by a BACnet Signed Integer
+ */
+int bacnet_signed_length(int32_t value)
+{
+ int len;
+
+ if ((value >= -128) && (value < 128)) {
+ len = 1;
+ } else if ((value >= -32768) && (value < 32768)) {
+ len = 2;
+ } else if ((value > -8388608) && (value < 8388608)) {
+ len = 3;
+ } else {
+ len = 4;
+ }
+
+ return len;
+}
#endif
diff --git a/src/bacnet/bacint.h b/src/bacnet/bacint.h
index 95e4df9e..89d9ba66 100644
--- a/src/bacnet/bacint.h
+++ b/src/bacnet/bacint.h
@@ -100,9 +100,14 @@ extern "C" {
uint8_t * buffer,
uint64_t * value);
#endif
+
BACNET_STACK_EXPORT
int bacnet_unsigned_length(
BACNET_UNSIGNED_INTEGER value);
+ BACNET_STACK_EXPORT
+ int bacnet_signed_length(
+ int32_t value);
+
/* signed value encoding and decoding */
BACNET_STACK_EXPORT
int encode_signed8(
diff --git a/src/bacnet/bacreal.c b/src/bacnet/bacreal.c
index 7515b406..f50c29d6 100644
--- a/src/bacnet/bacreal.c
+++ b/src/bacnet/bacreal.c
@@ -56,20 +56,24 @@ int decode_real(uint8_t *apdu, float *real_value)
float real_value;
} my_data;
- /* NOTE: assumes the compiler stores float as IEEE-754 float */
- if (big_endian()) {
- my_data.byte[0] = apdu[0];
- my_data.byte[1] = apdu[1];
- my_data.byte[2] = apdu[2];
- my_data.byte[3] = apdu[3];
- } else {
- my_data.byte[0] = apdu[3];
- my_data.byte[1] = apdu[2];
- my_data.byte[2] = apdu[1];
- my_data.byte[3] = apdu[0];
+ if (apdu) {
+ /* NOTE: assumes the compiler stores float as IEEE-754 float */
+ if (big_endian()) {
+ my_data.byte[0] = apdu[0];
+ my_data.byte[1] = apdu[1];
+ my_data.byte[2] = apdu[2];
+ my_data.byte[3] = apdu[3];
+ } else {
+ my_data.byte[0] = apdu[3];
+ my_data.byte[1] = apdu[2];
+ my_data.byte[2] = apdu[1];
+ my_data.byte[3] = apdu[0];
+ }
+ if (real_value) {
+ *real_value = my_data.real_value;
+ }
}
- *real_value = my_data.real_value;
return 4;
}
@@ -77,7 +81,9 @@ int decode_real(uint8_t *apdu, float *real_value)
int decode_real_safe(uint8_t *apdu, uint32_t len_value, float *real_value)
{
if (len_value != 4) {
- *real_value = 0.0f;
+ if (real_value) {
+ *real_value = 0.0f;
+ }
return (int)len_value;
} else {
return decode_real(apdu, real_value);
@@ -95,16 +101,18 @@ int encode_bacnet_real(float value, uint8_t *apdu)
/* NOTE: assumes the compiler stores float as IEEE-754 float */
my_data.real_value = value;
- if (big_endian()) {
- apdu[0] = my_data.byte[0];
- apdu[1] = my_data.byte[1];
- apdu[2] = my_data.byte[2];
- apdu[3] = my_data.byte[3];
- } else {
- apdu[0] = my_data.byte[3];
- apdu[1] = my_data.byte[2];
- apdu[2] = my_data.byte[1];
- apdu[3] = my_data.byte[0];
+ if (apdu) {
+ if (big_endian()) {
+ apdu[0] = my_data.byte[0];
+ apdu[1] = my_data.byte[1];
+ apdu[2] = my_data.byte[2];
+ apdu[3] = my_data.byte[3];
+ } else {
+ apdu[0] = my_data.byte[3];
+ apdu[1] = my_data.byte[2];
+ apdu[2] = my_data.byte[1];
+ apdu[3] = my_data.byte[0];
+ }
}
return 4;
@@ -121,27 +129,31 @@ int decode_double(uint8_t *apdu, double *double_value)
double double_value;
} my_data;
- /* NOTE: assumes the compiler stores float as IEEE-754 float */
- if (big_endian()) {
- my_data.byte[0] = apdu[0];
- my_data.byte[1] = apdu[1];
- my_data.byte[2] = apdu[2];
- my_data.byte[3] = apdu[3];
- my_data.byte[4] = apdu[4];
- my_data.byte[5] = apdu[5];
- my_data.byte[6] = apdu[6];
- my_data.byte[7] = apdu[7];
- } else {
- my_data.byte[0] = apdu[7];
- my_data.byte[1] = apdu[6];
- my_data.byte[2] = apdu[5];
- my_data.byte[3] = apdu[4];
- my_data.byte[4] = apdu[3];
- my_data.byte[5] = apdu[2];
- my_data.byte[6] = apdu[1];
- my_data.byte[7] = apdu[0];
+ if (apdu) {
+ /* NOTE: assumes the compiler stores float as IEEE-754 float */
+ if (big_endian()) {
+ my_data.byte[0] = apdu[0];
+ my_data.byte[1] = apdu[1];
+ my_data.byte[2] = apdu[2];
+ my_data.byte[3] = apdu[3];
+ my_data.byte[4] = apdu[4];
+ my_data.byte[5] = apdu[5];
+ my_data.byte[6] = apdu[6];
+ my_data.byte[7] = apdu[7];
+ } else {
+ my_data.byte[0] = apdu[7];
+ my_data.byte[1] = apdu[6];
+ my_data.byte[2] = apdu[5];
+ my_data.byte[3] = apdu[4];
+ my_data.byte[4] = apdu[3];
+ my_data.byte[5] = apdu[2];
+ my_data.byte[6] = apdu[1];
+ my_data.byte[7] = apdu[0];
+ }
+ if (double_value) {
+ *double_value = my_data.double_value;
+ }
}
- *double_value = my_data.double_value;
return 8;
}
@@ -149,7 +161,9 @@ int decode_double(uint8_t *apdu, double *double_value)
int decode_double_safe(uint8_t *apdu, uint32_t len_value, double *double_value)
{
if (len_value != 8) {
- *double_value = 0.0;
+ if (double_value) {
+ *double_value = 0.0;
+ }
return (int)len_value;
} else {
return decode_double(apdu, double_value);
@@ -167,24 +181,26 @@ int encode_bacnet_double(double value, uint8_t *apdu)
/* NOTE: assumes the compiler stores float as IEEE-754 float */
my_data.double_value = value;
- if (big_endian()) {
- apdu[0] = my_data.byte[0];
- apdu[1] = my_data.byte[1];
- apdu[2] = my_data.byte[2];
- apdu[3] = my_data.byte[3];
- apdu[4] = my_data.byte[4];
- apdu[5] = my_data.byte[5];
- apdu[6] = my_data.byte[6];
- apdu[7] = my_data.byte[7];
- } else {
- apdu[0] = my_data.byte[7];
- apdu[1] = my_data.byte[6];
- apdu[2] = my_data.byte[5];
- apdu[3] = my_data.byte[4];
- apdu[4] = my_data.byte[3];
- apdu[5] = my_data.byte[2];
- apdu[6] = my_data.byte[1];
- apdu[7] = my_data.byte[0];
+ if (apdu) {
+ if (big_endian()) {
+ apdu[0] = my_data.byte[0];
+ apdu[1] = my_data.byte[1];
+ apdu[2] = my_data.byte[2];
+ apdu[3] = my_data.byte[3];
+ apdu[4] = my_data.byte[4];
+ apdu[5] = my_data.byte[5];
+ apdu[6] = my_data.byte[6];
+ apdu[7] = my_data.byte[7];
+ } else {
+ apdu[0] = my_data.byte[7];
+ apdu[1] = my_data.byte[6];
+ apdu[2] = my_data.byte[5];
+ apdu[3] = my_data.byte[4];
+ apdu[4] = my_data.byte[3];
+ apdu[5] = my_data.byte[2];
+ apdu[6] = my_data.byte[1];
+ apdu[7] = my_data.byte[0];
+ }
}
return 8;
diff --git a/src/bacnet/bactext.c b/src/bacnet/bactext.c
index af35931d..b669fcdd 100644
--- a/src/bacnet/bactext.c
+++ b/src/bacnet/bactext.c
@@ -129,8 +129,8 @@ const char *bactext_unconfirmed_service_name(unsigned index)
bacnet_unconfirmed_service_names, index, ASHRAE_Reserved_String);
}
-INDTEXT_DATA bacnet_application_tag_names[] = { { BACNET_APPLICATION_TAG_NULL,
- "Null" },
+INDTEXT_DATA bacnet_application_tag_names[] = {
+ { BACNET_APPLICATION_TAG_NULL, "Null" },
{ BACNET_APPLICATION_TAG_BOOLEAN, "Boolean" },
{ BACNET_APPLICATION_TAG_UNSIGNED_INT, "Unsigned Int" },
{ BACNET_APPLICATION_TAG_SIGNED_INT, "Signed Int" },
@@ -145,7 +145,29 @@ INDTEXT_DATA bacnet_application_tag_names[] = { { BACNET_APPLICATION_TAG_NULL,
{ BACNET_APPLICATION_TAG_OBJECT_ID, "Object ID" },
{ BACNET_APPLICATION_TAG_RESERVE1, "Reserved 1" },
{ BACNET_APPLICATION_TAG_RESERVE2, "Reserved 2" },
- { BACNET_APPLICATION_TAG_RESERVE3, "Reserved 3" }, { 0, NULL } };
+ { BACNET_APPLICATION_TAG_RESERVE3, "Reserved 3" },
+ /* complex data types */
+ { BACNET_APPLICATION_TAG_EMPTYLIST, "Empty List" },
+ { BACNET_APPLICATION_TAG_WEEKNDAY, "BACnetWeeknday" },
+ { BACNET_APPLICATION_TAG_DATERANGE, "BACnetDateRange" },
+ { BACNET_APPLICATION_TAG_DATETIME, "BACnetDateTime" },
+ { BACNET_APPLICATION_TAG_TIMESTAMP, "BACnetTimeStamp" },
+ { BACNET_APPLICATION_TAG_ERROR, "Error" },
+ { BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE,
+ "BACnetDeviceObjectPropertyReference" },
+ { BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE,
+ "BACnetDeviceObjectReference" },
+ { BACNET_APPLICATION_TAG_DESTINATION, "BACnetDestination" },
+ { BACNET_APPLICATION_TAG_RECIPIENT, "BACnetRecipient" },
+ { BACNET_APPLICATION_TAG_COV_SUBSCRIPTION, "BACnetCOVSubscription" },
+ { BACNET_APPLICATION_TAG_CALENDAR_ENTRY, "BACnetCalendarEntry" },
+ { BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE, "BACnetWeeklySchedule" },
+ { BACNET_APPLICATION_TAG_SPECIAL_EVENT, "BACnetSpecialEvent" },
+ { BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION,
+ "BACnetReadAccessSpecification" },
+ { BACNET_APPLICATION_TAG_LIGHTING_COMMAND, "BACnetLightingCommand" },
+ { BACNET_APPLICATION_TAG_HOST_N_PORT, "BACnetHostNPort" },
+ { 0, NULL } };
const char *bactext_application_tag_name(unsigned index)
{
diff --git a/src/bacnet/basic/object/channel.c b/src/bacnet/basic/object/channel.c
index fa87acf2..608b9b76 100644
--- a/src/bacnet/basic/object/channel.c
+++ b/src/bacnet/basic/object/channel.c
@@ -45,7 +45,7 @@
#include "bacnet/proplist.h"
#include "bacnet/lighting.h"
#include "bacnet/basic/object/device.h"
-#if defined(CHANNEL_LIGHTING_COMMAND) || defined(BACAPP_LIGHTING_COMMAND)
+#if defined(CHANNEL_LIGHTING_COMMAND)
#include "bacnet/basic/object/lo.h"
#endif
/* me! */
@@ -628,7 +628,7 @@ bool Channel_Value_Copy(
status = true;
break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND) && defined(CHANNEL_LIGHTING_COMMAND)
+#if defined(BACAPP_TYPES_EXTRA) && defined(CHANNEL_LIGHTING_COMMAND)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
cvalue->tag = value->tag;
lighting_command_copy(
@@ -1045,7 +1045,7 @@ int Channel_Coerce_Data_Encode(uint8_t *apdu,
}
break;
#endif
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined(BACAPP_TYPES_EXTRA)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
if (tag == BACNET_APPLICATION_TAG_LIGHTING_COMMAND) {
apdu_len = lighting_command_encode(
diff --git a/src/bacnet/basic/object/command.c b/src/bacnet/basic/object/command.c
index b0dbbd28..928f7cc7 100644
--- a/src/bacnet/basic/object/command.c
+++ b/src/bacnet/basic/object/command.c
@@ -279,7 +279,7 @@ int cl_decode_apdu(uint8_t *apdu,
&bcl->Value.type.Object_Id.type,
&bcl->Value.type.Object_Id.instance);
break;
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined(BACAPP_TYPES_EXTRA)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
len = lighting_command_decode(&apdu[dec_len], apdu_len - dec_len,
&bcl->Value.type.Lighting_Command);
diff --git a/src/bacnet/basic/object/device.c b/src/bacnet/basic/object/device.c
index 810d4d21..8d878a07 100644
--- a/src/bacnet/basic/object/device.c
+++ b/src/bacnet/basic/object/device.c
@@ -210,7 +210,7 @@ static object_functions_t My_Object_Table[] = {
Trend_Log_Write_Property, Trend_Log_Property_Lists, TrendLogGetRRInfo,
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */ },
-#if (BACNET_PROTOCOL_REVISION >= 14) && defined(BACAPP_LIGHTING_COMMAND)
+#if (BACNET_PROTOCOL_REVISION >= 14)
{ OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count,
Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance,
Lighting_Output_Object_Name, Lighting_Output_Read_Property,
diff --git a/src/bacnet/config.h b/src/bacnet/config.h
index ce3dba69..d2ada166 100644
--- a/src/bacnet/config.h
+++ b/src/bacnet/config.h
@@ -143,9 +143,8 @@
defined(BACAPP_ENUMERATED) || \
defined(BACAPP_DATE) || \
defined(BACAPP_TIME) || \
- defined(BACAPP_LIGHTING_COMMAND) || \
- defined(BACAPP_DEVICE_OBJECT_PROP_REF) || \
- defined(BACAPP_OBJECT_ID))
+ defined(BACAPP_OBJECT_ID) || \
+ defined(BACAPP_TYPES_EXTRA))
#define BACAPP_ALL
#endif
@@ -163,8 +162,7 @@
#define BACAPP_DATE
#define BACAPP_TIME
#define BACAPP_OBJECT_ID
-#define BACAPP_DEVICE_OBJECT_PROP_REF
-#define BACAPP_LIGHTING_COMMAND
+#define BACAPP_TYPES_EXTRA
#elif defined (BACAPP_MINIMAL)
#define BACAPP_NULL
#define BACAPP_BOOLEAN
diff --git a/src/bacnet/datalink/bvlc.c b/src/bacnet/datalink/bvlc.c
index a31f2ee5..461b1cdc 100644
--- a/src/bacnet/datalink/bvlc.c
+++ b/src/bacnet/datalink/bvlc.c
@@ -39,6 +39,7 @@
#include "bacnet/bacdcode.h"
#include "bacnet/bacint.h"
#include "bacnet/bacdef.h"
+#include "bacnet/hostnport.h"
#include "bacnet/datalink/bvlc.h"
/**
@@ -2623,15 +2624,6 @@ const char *bvlc_result_code_name(uint16_t result_code)
/**
* @brief Encode a BBMD Address for Network Port object
- *
- * BACnetHostNPort ::= SEQUENCE {
- * host [0] BACnetHostAddress,
- * BACnetHostAddress ::= CHOICE {
- * ip-address [1] OCTET STRING, -- 4 octets for B/IP
- * }
- * port [1] Unsigned16
- * }
- *
* @param apdu - the APDU buffer
* @param apdu_size - the APDU buffer size
* @param ip_address - IP address and port number
@@ -2641,27 +2633,17 @@ int bvlc_foreign_device_bbmd_host_address_encode(uint8_t *apdu,
uint16_t apdu_size,
BACNET_IP_ADDRESS *ip_address)
{
- int len = 0;
+ BACNET_HOST_N_PORT address = { 0 };
int apdu_len = 0;
- BACNET_OCTET_STRING octet_string;
- if (apdu && (apdu_size >= 9) && ip_address) {
- /* host [0] BACnetHostAddress - opening */
- len = encode_opening_tag(&apdu[apdu_len], 0);
- apdu_len += len;
- /* CHOICE - ip-address [1] OCTET STRING */
- octetstring_init(&octet_string,
- &ip_address->address[0], IP_ADDRESS_MAX);
- len = encode_context_octet_string(&apdu[apdu_len], 1,
- &octet_string);
- apdu_len += len;
- /* host [0] BACnetHostAddress - closing */
- len = encode_closing_tag(&apdu[apdu_len], 0);
- apdu_len += len;
- /* port [1] Unsigned16 */
- len = encode_context_unsigned(
- &apdu[apdu_len], 1, ip_address->port);
- apdu_len += len;
+ address.host_ip_address = true;
+ address.host_name = false;
+ octetstring_init(&address.host.ip_address, &ip_address->address[0],
+ IP_ADDRESS_MAX);
+ address.port = ip_address->port;
+ apdu_len = host_n_port_encode(NULL, &address);
+ if (apdu_len <= apdu_size) {
+ apdu_len = host_n_port_encode(apdu, &address);
}
return apdu_len;
@@ -2669,15 +2651,6 @@ int bvlc_foreign_device_bbmd_host_address_encode(uint8_t *apdu,
/**
* @brief Decode the Broadcast-Distribution-Table for Network Port object
- *
- * BACnetHostNPort ::= SEQUENCE {
- * host [0] BACnetHostAddress,
- * BACnetHostAddress ::= CHOICE {
- * ip-address [1] OCTET STRING, -- 4 octets for B/IP
- * }
- * port [1] Unsigned16
- * }
- *
* @param apdu - the APDU buffer
* @param apdu_len - the APDU buffer length
* @param ip_address - IP address and port number
@@ -2688,77 +2661,24 @@ int bvlc_foreign_device_bbmd_host_address_decode(uint8_t *apdu,
BACNET_ERROR_CODE *error_code,
BACNET_IP_ADDRESS *ip_address)
{
+ BACNET_HOST_N_PORT address = { 0 };
int len = 0;
- BACNET_OCTET_STRING octet_string = { 0 };
- uint8_t tag_number = 0;
- uint32_t len_value_type = 0;
- BACNET_UNSIGNED_INTEGER unsigned_value = 0;
- /* default reject code */
- if (error_code) {
- *error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
- }
- /* check for value pointers */
- if ((apdu_len == 0) || (!apdu)) {
- return BACNET_STATUS_REJECT;
- }
- /* host [0] BACnetHostAddress - opening */
- if (!decode_is_opening_tag_number(&apdu[len++], 0)) {
- if (error_code) {
- *error_code = ERROR_CODE_REJECT_INVALID_TAG;
+ len = host_n_port_decode(apdu, apdu_len, error_code, &address);
+ if (len > 0) {
+ if (address.host_ip_address) {
+ ip_address->port = address.port;
+ (void)octetstring_copy_value(
+ &ip_address->address[0],
+ IP_ADDRESS_MAX,
+ &address.host.ip_address);
+ } else {
+ len = BACNET_STATUS_REJECT;
+ if (error_code) {
+ *error_code = ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE;
+ }
}
- return BACNET_STATUS_REJECT;
- }
- if (len > apdu_len) {
- return BACNET_STATUS_REJECT;
- }
- /* CHOICE - ip-address [1] OCTET STRING */
- len += decode_tag_number_and_value(
- &apdu[len], &tag_number, &len_value_type);
- if (tag_number != 1) {
- if (error_code) {
- *error_code = ERROR_CODE_REJECT_INVALID_TAG;
- }
- return BACNET_STATUS_REJECT;
- }
- len += decode_octet_string(&apdu[len], len_value_type,
- &octet_string);
- if (len > apdu_len) {
- return BACNET_STATUS_REJECT;
- }
- (void)octetstring_copy_value(&ip_address->address[0],
- IP_ADDRESS_MAX, &octet_string);
- /* host [0] BACnetHostAddress - closing */
- if (!decode_is_closing_tag_number(&apdu[len++], 0)) {
- if (error_code) {
- *error_code = ERROR_CODE_REJECT_INVALID_TAG;
- }
- return BACNET_STATUS_REJECT;
- }
- if (len > apdu_len) {
- return BACNET_STATUS_REJECT;
- }
- /* port [1] Unsigned16 */
- len += decode_tag_number_and_value(
- &apdu[len], &tag_number, &len_value_type);
- if (tag_number != 1) {
- if (error_code) {
- *error_code = ERROR_CODE_REJECT_INVALID_TAG;
- }
- return BACNET_STATUS_REJECT;
- }
- len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
- if (len > apdu_len) {
- return BACNET_STATUS_REJECT;
- }
- if (unsigned_value <= UINT16_MAX) {
- ip_address->port = unsigned_value;
- } else {
- if (error_code) {
- *error_code = ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE;
- }
- return BACNET_STATUS_REJECT;
}
- return apdu_len;
+ return len;
}
diff --git a/src/bacnet/datalink/dlmstp.h b/src/bacnet/datalink/dlmstp.h
index 8785dfe3..14948272 100644
--- a/src/bacnet/datalink/dlmstp.h
+++ b/src/bacnet/datalink/dlmstp.h
@@ -55,7 +55,7 @@ typedef struct dlmstp_statistics {
} DLMSTP_STATISTICS;
/* callback to signify the receipt of a preamble */
-typedef void (*dlmstp_hook_frame_rx_start_cb)();
+typedef void (*dlmstp_hook_frame_rx_start_cb)(void);
/* callback on for receiving every valid frame */
typedef void (*dlmstp_hook_frame_rx_complete_cb)(
diff --git a/src/bacnet/hostnport.c b/src/bacnet/hostnport.c
new file mode 100644
index 00000000..4be24c08
--- /dev/null
+++ b/src/bacnet/hostnport.c
@@ -0,0 +1,308 @@
+/**
+ * @file
+ * @brief BACnetHostNPort complex data type encode and decode
+ * @author Steve Karg
+ * @date May 2022
+ * @section LICENSE
+ *
+ * Copyright (C) 2022 Steve Karg
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bacnet/hostnport.h"
+#include "bacnet/bacdcode.h"
+
+/**
+ * @brief Encode a BACnetHostNPort complex data type
+ *
+ * BACnetHostNPort ::= SEQUENCE {
+ * host [0] BACnetHostAddress,
+ * BACnetHostAddress ::= CHOICE {
+ * none [0] NULL,
+ * ip-address [1] OCTET STRING,
+ * -- 4 octets for B/IP or 16 octets for B/IPv6
+ * name [2] CharacterString
+ * -- Internet host name (see RFC 1123)
+ * }
+ * port [1] Unsigned16
+ * }
+ *
+ * @param apdu - the APDU buffer, or NULL for length
+ * @param address - IP address and port number
+ * @return length of the encoded APDU buffer
+ */
+int host_n_port_encode(uint8_t *apdu,
+ BACNET_HOST_N_PORT *address)
+{
+ int len = 0;
+ int apdu_len = 0;
+ uint8_t *apdu_offset = NULL;
+
+ if (address) {
+ /* host [0] BACnetHostAddress - opening */
+ len = encode_opening_tag(apdu, 0);
+ apdu_len += len;
+ if (address->host_ip_address) {
+ /* CHOICE - ip-address [1] OCTET STRING */
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ len = encode_context_octet_string(apdu_offset, 1, &address->host.ip_address);
+ apdu_len += len;
+ } else if (address->host_name) {
+ /* CHOICE - name [2] CharacterString */
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ len = encode_context_character_string(apdu_offset, 1,
+ &address->host.name);
+ apdu_len += len;
+ } else {
+ /* none */
+ }
+ /* host [0] BACnetHostAddress - closing */
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ len = encode_closing_tag(apdu_offset, 0);
+ apdu_len += len;
+ /* port [1] Unsigned16 */
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ len = encode_context_unsigned(
+ apdu_offset, 1, address->port);
+ apdu_len += len;
+ }
+
+ return apdu_len;
+}
+
+/**
+ * @brief Encode a BACnetHostNPort complex data type
+ * @param apdu - the APDU buffer
+ * @param tag_number - the APDU buffer size
+ * @param address - IP address and port number
+ * @return length of the APDU buffer, or 0 if not able to encode
+ */
+int host_n_port_context_encode(
+ uint8_t * apdu,
+ uint8_t tag_number,
+ BACNET_HOST_N_PORT *address)
+{
+ int len = 0;
+ int apdu_len = 0;
+ uint8_t *apdu_offset = NULL;
+
+ if (address) {
+ apdu_offset = apdu;
+ len = encode_opening_tag(apdu_offset, tag_number);
+ apdu_len += len;
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ len = host_n_port_encode(apdu_offset, address);
+ apdu_len += len;
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ len = encode_closing_tag(apdu_offset, tag_number);
+ apdu_len += len;
+ }
+
+ return apdu_len;
+}
+
+/**
+ * @brief Decode the BACnetHostNPort complex data
+ *
+ * BACnetHostNPort ::= SEQUENCE {
+ * host [0] BACnetHostAddress,
+ * BACnetHostAddress ::= CHOICE {
+ * BACnetHostAddress ::= CHOICE {
+ * none [0] NULL,
+ * ip-address [1] OCTET STRING,
+ * -- 4 octets for B/IP or 16 octets for B/IPv6
+ * name [2] CharacterString
+ * -- Internet host name (see RFC 1123)
+ * }
+ * port [1] Unsigned16
+ * }
+ *
+ * @param apdu - the APDU buffer
+ * @param apdu_len - the APDU buffer length
+ * @param ip_address - IP address and port number
+ * @return length of the APDU buffer decoded, or ERROR, REJECT, or ABORT
+ */
+int host_n_port_decode(uint8_t *apdu,
+ uint16_t apdu_len,
+ BACNET_ERROR_CODE *error_code,
+ BACNET_HOST_N_PORT *address)
+{
+ int len = 0;
+ BACNET_OCTET_STRING octet_string = { 0 };
+ BACNET_CHARACTER_STRING char_string = { 0 };
+ uint8_t tag_number = 0;
+ uint32_t len_value_type = 0;
+ BACNET_UNSIGNED_INTEGER unsigned_value = 0;
+
+ /* default reject code */
+ if (error_code) {
+ *error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
+ }
+ /* check for value pointers */
+ if ((apdu_len == 0) || (!apdu)) {
+ return BACNET_STATUS_REJECT;
+ }
+ /* host [0] BACnetHostAddress - opening */
+ if (!decode_is_opening_tag_number(&apdu[len++], 0)) {
+ if (error_code) {
+ *error_code = ERROR_CODE_REJECT_INVALID_TAG;
+ }
+ return BACNET_STATUS_REJECT;
+ }
+ if (len > apdu_len) {
+ return BACNET_STATUS_REJECT;
+ }
+ len += decode_tag_number_and_value(
+ &apdu[len], &tag_number, &len_value_type);
+ if (tag_number == 0) {
+ /* CHOICE - none [0] NULL */
+ address->host_ip_address = false;
+ address->host_name = false;
+ } else if (tag_number == 1) {
+ /* CHOICE - ip-address [1] OCTET STRING */
+ address->host_ip_address = true;
+ address->host_name = false;
+ len += decode_octet_string(&apdu[len], len_value_type,
+ &octet_string);
+ if (len > apdu_len) {
+ return BACNET_STATUS_REJECT;
+ }
+ (void)octetstring_copy(&address->host.ip_address,
+ &octet_string);
+ } else if (tag_number == 2) {
+ address->host_ip_address = false;
+ address->host_name = true;
+ len += decode_character_string(&apdu[len], len_value_type,
+ &char_string);
+ if (len > apdu_len) {
+ return BACNET_STATUS_REJECT;
+ }
+ (void)characterstring_copy(&address->host.name,
+ &char_string);
+ } else {
+ if (error_code) {
+ *error_code = ERROR_CODE_REJECT_INVALID_TAG;
+ }
+ return BACNET_STATUS_REJECT;
+ }
+ /* host [0] BACnetHostAddress - closing */
+ if (!decode_is_closing_tag_number(&apdu[len++], 0)) {
+ if (error_code) {
+ *error_code = ERROR_CODE_REJECT_INVALID_TAG;
+ }
+ return BACNET_STATUS_REJECT;
+ }
+ if (len > apdu_len) {
+ return BACNET_STATUS_REJECT;
+ }
+ /* port [1] Unsigned16 */
+ len += decode_tag_number_and_value(
+ &apdu[len], &tag_number, &len_value_type);
+ if (tag_number != 1) {
+ if (error_code) {
+ *error_code = ERROR_CODE_REJECT_INVALID_TAG;
+ }
+ return BACNET_STATUS_REJECT;
+ }
+ len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
+ if (len > apdu_len) {
+ return BACNET_STATUS_REJECT;
+ }
+ if (unsigned_value <= UINT16_MAX) {
+ address->port = unsigned_value;
+ } else {
+ if (error_code) {
+ *error_code = ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE;
+ }
+ return BACNET_STATUS_REJECT;
+ }
+
+ return apdu_len;
+}
+
+/**
+ * @brief Copy the BACnetHostNPort complex data from src to dst
+ * @param dst - destination structure
+ * @param src - source structure
+ * @return true if successfully copied
+ */
+bool host_n_port_copy(
+ BACNET_HOST_N_PORT * dst,
+ BACNET_HOST_N_PORT * src)
+{
+ bool status = false;
+
+ if (dst && src) {
+ dst->host_ip_address = src->host_ip_address;
+ dst->host_name = src->host_name;
+ if (src->host_ip_address) {
+ status = octetstring_copy(
+ &dst->host.ip_address,
+ &src->host.ip_address);
+ } else if (src->host_name) {
+ status = characterstring_copy(
+ &dst->host.name,
+ &src->host.name);
+ } else {
+ status = true;
+ }
+ dst->port = src->port;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Compare the BACnetHostNPort complex data of src and dst
+ * @param host1 - host 1 structure
+ * @param host2 - host 2 structure
+ * @return true if successfully copied
+ */
+bool host_n_port_same(
+ BACNET_HOST_N_PORT * host1,
+ BACNET_HOST_N_PORT * host2)
+{
+ bool status = false;
+
+ if (host1 && host2) {
+ if ((host1->host_ip_address == host2->host_ip_address) &&
+ (host1->host_name == host2->host_name)) {
+ if (host1->host_ip_address) {
+ status = octetstring_value_same(
+ &host1->host.ip_address,
+ &host2->host.ip_address);
+ } else if (host1->host_name) {
+ status = characterstring_same(
+ &host1->host.name,
+ &host2->host.name);
+ } else {
+ status = true;
+ }
+ if (status) {
+ if (host1->port != host2->port) {
+ status = false;
+ }
+ }
+ }
+ }
+ return status;
+}
diff --git a/src/bacnet/hostnport.h b/src/bacnet/hostnport.h
new file mode 100644
index 00000000..559113ba
--- /dev/null
+++ b/src/bacnet/hostnport.h
@@ -0,0 +1,74 @@
+/**
+ * @file
+ * @brief API for BACnetHostNPort complex data type encode and decode
+ * @author Steve Karg
+ * @date May 2022
+ * @section LICENSE
+ *
+ * Copyright (C) 2022 Steve Karg
+ *
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef BACNET_HOST_N_PORT_H
+#define BACNET_HOST_N_PORT_H
+
+#include
+#include
+#include "bacnet/bacnet_stack_exports.h"
+#include "bacnet/bacenum.h"
+#include "bacnet/bacstr.h"
+#include "bacnet/datalink/bvlc.h"
+
+/**
+ * BACnetHostNPort ::= SEQUENCE {
+ * host [0] BACnetHostAddress,
+ * BACnetHostAddress ::= CHOICE {
+ * none [0] NULL,
+ * ip-address [1] OCTET STRING,
+ * name [2] CharacterString
+ * }
+ * port [1] Unsigned16
+ * }
+ */
+typedef struct BACnetHostNPort {
+ bool host_ip_address:1;
+ bool host_name:1;
+ union BACnetHostAddress {
+ /* none = host_ip_address AND host_name are FALSE */
+ BACNET_OCTET_STRING ip_address;
+ BACNET_CHARACTER_STRING name;
+ } host;
+ uint16_t port;
+} BACNET_HOST_N_PORT;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ BACNET_STACK_EXPORT
+ int host_n_port_encode(
+ uint8_t * apdu,
+ BACNET_HOST_N_PORT *address);
+ BACNET_STACK_EXPORT
+ int host_n_port_context_encode(
+ uint8_t * apdu,
+ uint8_t tag_number,
+ BACNET_HOST_N_PORT *address);
+ BACNET_STACK_EXPORT
+ int host_n_port_decode(uint8_t *apdu,
+ uint16_t apdu_len,
+ BACNET_ERROR_CODE *error_code,
+ BACNET_HOST_N_PORT *address);
+ BACNET_STACK_EXPORT
+ bool host_n_port_copy(
+ BACNET_HOST_N_PORT * dst,
+ BACNET_HOST_N_PORT * src);
+ BACNET_STACK_EXPORT
+ bool host_n_port_same(
+ BACNET_HOST_N_PORT * dst,
+ BACNET_HOST_N_PORT * src);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/src/bacnet/lighting.c b/src/bacnet/lighting.c
index 9cc45dbc..d5443c8c 100644
--- a/src/bacnet/lighting.c
+++ b/src/bacnet/lighting.c
@@ -50,44 +50,58 @@
/**
* Encodes into bytes from the lighting-command structure
*
- * @param apdu - buffer to hold the bytes
+ * @param apdu - buffer to hold the bytes, or null for length
* @param value - lighting command value to encode
*
- * @return number of bytes encoded, or 0 if unable to encode.
+ * @return number of bytes encoded
*/
int lighting_command_encode(uint8_t *apdu, BACNET_LIGHTING_COMMAND *data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* total length of the apdu, return value */
+ uint8_t *apdu_offset = NULL;
- if (apdu) {
- len = encode_context_enumerated(&apdu[apdu_len], 0, data->operation);
+ len = encode_context_enumerated(apdu, 0, data->operation);
+ apdu_len += len;
+ /* optional target-level */
+ if (data->use_target_level) {
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ len = encode_context_real(apdu_offset, 1, data->target_level);
apdu_len += len;
- /* optional target-level */
- if (data->use_target_level) {
- len = encode_context_real(&apdu[apdu_len], 1, data->target_level);
- apdu_len += len;
+ }
+ /* optional ramp-rate */
+ if (data->use_ramp_rate) {
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
}
- /* optional ramp-rate */
- if (data->use_ramp_rate) {
- len = encode_context_real(&apdu[apdu_len], 2, data->ramp_rate);
- apdu_len += len;
+ len = encode_context_real(apdu_offset, 2, data->ramp_rate);
+ apdu_len += len;
+ }
+ /* optional step increment */
+ if (data->use_step_increment) {
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
}
- /* optional step increment */
- if (data->use_step_increment) {
- len = encode_context_real(&apdu[apdu_len], 3, data->step_increment);
- apdu_len += len;
+ len = encode_context_real(apdu_offset, 3, data->step_increment);
+ apdu_len += len;
+ }
+ /* optional fade time */
+ if (data->use_fade_time) {
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
}
- /* optional fade time */
- if (data->use_fade_time) {
- len = encode_context_unsigned(&apdu[apdu_len], 4, data->fade_time);
- apdu_len += len;
- }
- /* optional priority */
- if (data->use_priority) {
- len = encode_context_unsigned(&apdu[apdu_len], 5, data->priority);
- apdu_len += len;
+ len = encode_context_unsigned(apdu_offset, 4, data->fade_time);
+ apdu_len += len;
+ }
+ /* optional priority */
+ if (data->use_priority) {
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
}
+ len = encode_context_unsigned(apdu_offset, 5, data->priority);
+ apdu_len += len;
}
return apdu_len;
@@ -107,10 +121,17 @@ int lighting_command_encode_context(
uint8_t *apdu, uint8_t tag_number, BACNET_LIGHTING_COMMAND *value)
{
int apdu_len = 0;
+ uint8_t *apdu_offset = NULL;
- apdu_len += encode_opening_tag(&apdu[apdu_len], tag_number);
- apdu_len += lighting_command_encode(&apdu[apdu_len], value);
- apdu_len += encode_closing_tag(&apdu[apdu_len], tag_number);
+ apdu_len += encode_opening_tag(apdu, tag_number);
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ apdu_len += lighting_command_encode(apdu_offset, value);
+ if (apdu) {
+ apdu_offset = &apdu[apdu_len];
+ }
+ apdu_len += encode_closing_tag(apdu_offset, tag_number);
return apdu_len;
}
@@ -292,75 +313,3 @@ bool lighting_command_same(
return status;
}
-
-#ifdef TEST_LIGHTING_COMMAND
-#include
-#include
-#include "ctest.h"
-
-static void testBACnetLightingCommand(Test *pTest, BACNET_LIGHTING_COMMAND *data)
-{
- bool status = false;
- BACNET_LIGHTING_COMMAND test_data;
- int len, apdu_len;
- uint8_t apdu[MAX_APDU] = { 0 };
-
- status = lighting_command_copy(&test_data, NULL);
- ct_test(pTest, status == false);
- status = lighting_command_copy(NULL, data);
- ct_test(pTest, status == false);
- status = lighting_command_copy(&test_data, data);
- ct_test(pTest, status == true);
- status = lighting_command_same(&test_data, data);
- ct_test(pTest, status == true);
- len = lighting_command_encode(apdu, data);
- apdu_len = lighting_command_decode(apdu, sizeof(apdu), &test_data);
- ct_test(pTest, len > 0);
- ct_test(pTest, apdu_len > 0);
- status = lighting_command_same(&test_data, data);
-}
-
-static void testBACnetLightingCommandAll(Test *pTest)
-{
- BACNET_LIGHTING_COMMAND data;
-
- data.operation = BACNET_LIGHTS_NONE;
- data.use_target_level = false;
- data.use_ramp_rate = false;
- data.use_step_increment = false;
- data.use_fade_time = false;
- data.use_priority = false;
- data.target_level = 0.0;
- data.ramp_rate = 100.0;
- data.step_increment = 1.0;
- data.fade_time = 100;
- data.priority = 1;
- testBACnetLightingCommand(pTest, &data);
- data.operation = BACNET_LIGHTS_STOP;
- data.use_target_level = true;
- data.use_ramp_rate = true;
- data.use_step_increment = true;
- data.use_fade_time = true;
- data.use_priority = true;
- testBACnetLightingCommand(pTest, &data);
-}
-
-int main(void)
-{
- Test *pTest;
- bool rc;
-
- pTest = ct_create("BACnet Lighting Command", NULL);
- /* individual tests */
- rc = ct_addTestFunction(pTest, testBACnetLightingCommandAll);
- assert(rc);
-
- ct_setStream(pTest, stdout);
- ct_run(pTest);
- (void)ct_report(pTest);
- ct_destroy(pTest);
-
- return 0;
-}
-
-#endif
diff --git a/test/bacnet/bacapp/CMakeLists.txt b/test/bacnet/bacapp/CMakeLists.txt
index 0be45fd1..31e10ea1 100644
--- a/test/bacnet/bacapp/CMakeLists.txt
+++ b/test/bacnet/bacapp/CMakeLists.txt
@@ -24,7 +24,7 @@ add_compile_definitions(
BIG_ENDIAN=0
CONFIG_ZTEST=1
PRINT_ENABLED=1
- BACAPP_HOST_N_PORT=1
+ BACAPP_ALL=1
)
include_directories(
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/datalink/bvlc.c
diff --git a/test/bacnet/bacapp/src/main.c b/test/bacnet/bacapp/src/main.c
index 396f3308..65721a21 100644
--- a/test/bacnet/bacapp/src/main.c
+++ b/test/bacnet/bacapp/src/main.c
@@ -13,6 +13,51 @@
#include
#include
#include
+#include
+
+static const BACNET_APPLICATION_TAG tag_list[] = {
+ BACNET_APPLICATION_TAG_NULL,
+ #if defined(BACAPP_BOOLEAN)
+ BACNET_APPLICATION_TAG_BOOLEAN,
+ #endif
+ #if defined(BACAPP_UNSIGNED)
+ BACNET_APPLICATION_TAG_UNSIGNED_INT,
+ #endif
+ #if defined(BACAPP_SIGNED)
+ BACNET_APPLICATION_TAG_SIGNED_INT,
+ #endif
+ #if defined(BACAPP_REAL)
+ BACNET_APPLICATION_TAG_REAL,
+ #endif
+ #if defined(BACAPP_DOUBLE)
+ BACNET_APPLICATION_TAG_DOUBLE,
+ #endif
+ #if defined(BACAPP_OCTET_STRING)
+ BACNET_APPLICATION_TAG_OCTET_STRING,
+ #endif
+ #if defined(BACAPP_CHARACTER_STRING)
+ BACNET_APPLICATION_TAG_CHARACTER_STRING,
+ #endif
+ #if defined(BACAPP_BIT_STRING)
+ BACNET_APPLICATION_TAG_BIT_STRING,
+ #endif
+ #if defined(BACAPP_ENUMERATED)
+ BACNET_APPLICATION_TAG_ENUMERATED,
+ #endif
+ #if defined(BACAPP_DATE)
+ BACNET_APPLICATION_TAG_DATE,
+ #endif
+ #if defined(BACAPP_TIME)
+ BACNET_APPLICATION_TAG_TIME,
+ #endif
+ #if defined(BACAPP_OBJECT_ID)
+ BACNET_APPLICATION_TAG_OBJECT_ID,
+ #endif
+ #if defined(BACAPP_TYPES_EXTRA)
+ BACNET_APPLICATION_TAG_LIGHTING_COMMAND,
+ BACNET_APPLICATION_TAG_HOST_N_PORT,
+ #endif
+};
/**
* @addtogroup bacnet_tests
@@ -103,57 +148,13 @@ static void test_bacapp_copy(void)
memset(&src_value, 0xAA, sizeof(src_value));
memset(&dest_value, 0, sizeof(dest_value));
- zassert_false(bacapp_copy(&dest_value, &src_value), NULL);
+ zassert_true(bacapp_copy(&dest_value, &src_value), NULL);
zassert_equal(dest_value.tag, src_value.tag, NULL);
zassert_equal(dest_value.next, src_value.next, NULL);
- const BACNET_APPLICATION_TAG tags[] = {
- BACNET_APPLICATION_TAG_NULL,
- #if defined(BACAPP_BOOLEAN)
- BACNET_APPLICATION_TAG_BOOLEAN,
- #endif
- #if defined(BACAPP_UNSIGNED)
- BACNET_APPLICATION_TAG_UNSIGNED_INT,
- #endif
- #if defined(BACAPP_SIGNED)
- BACNET_APPLICATION_TAG_SIGNED_INT,
- #endif
- #if defined(BACAPP_REAL)
- BACNET_APPLICATION_TAG_REAL,
- #endif
- #if defined(BACAPP_DOUBLE)
- BACNET_APPLICATION_TAG_DOUBLE,
- #endif
- #if defined(BACAPP_OCTET_STRING)
- BACNET_APPLICATION_TAG_OCTET_STRING,
- #endif
- #if defined(BACAPP_CHARACTER_STRING)
- BACNET_APPLICATION_TAG_CHARACTER_STRING,
- #endif
- #if defined(BACAPP_BIT_STRING)
- BACNET_APPLICATION_TAG_BIT_STRING,
- #endif
- #if defined(BACAPP_ENUMERATED)
- BACNET_APPLICATION_TAG_ENUMERATED,
- #endif
- #if defined(BACAPP_DATE)
- BACNET_APPLICATION_TAG_DATE,
- #endif
- #if defined(BACAPP_TIME)
- BACNET_APPLICATION_TAG_TIME,
- #endif
- #if defined(BACAPP_OBJECT_ID)
- BACNET_APPLICATION_TAG_OBJECT_ID,
- #endif
- #if defined(BACAPP_LIGHTING_COMMAND)
- BACNET_APPLICATION_TAG_LIGHTING_COMMAND,
- #endif
- #if defined(BACAPP_HOST_N_PORT)
- BACNET_APPLICATION_TAG_HOST_N_PORT,
- #endif
- };
- for (i = 0; i < sizeof(tags)/sizeof(tags[0]); ++i) {
- BACNET_APPLICATION_TAG tag = tags[i];
+ for (i = 0; i < sizeof(tag_list)/sizeof(tag_list[0]); ++i) {
+ BACNET_APPLICATION_TAG tag = tag_list[i];
+ bool result;
bool expected_result = true;
#if ! defined(BACAPP_NULL)
@@ -163,11 +164,18 @@ static void test_bacapp_copy(void)
#endif
memset(&src_value, 0, sizeof(src_value));
+ src_value.next = NULL;
memset(&dest_value, 0xBB, sizeof(dest_value));
+ dest_value.next = NULL;
src_value.tag = tag;
- src_value.next = (struct BACnet_Application_Data_Value *)(((uint32_t)tags[i]) << 8);
- zassert_equal(bacapp_copy(&dest_value, &src_value), expected_result, NULL);
- zassert_true(bacapp_same_value(&dest_value, &src_value), NULL);
+ result = bacapp_copy(&dest_value, &src_value);
+ zassert_equal(result, expected_result, NULL);
+ result = bacapp_same_value(&dest_value, &src_value);
+ if (!result) {
+ printf("bacapp: same-value of tag=%s[%u]\n",
+ bactext_application_tag_name(tag), tag);
+ }
+ zassert_true(result, NULL);
zassert_equal(dest_value.next, src_value.next, NULL);
}
}
@@ -428,7 +436,7 @@ static void test_bacapp_same_value(void)
memset(&test_value, 0, sizeof(test_value));
test_value.tag = BACNET_APPLICATION_TAG_LIGHTING_COMMAND;
value = test_value; /* Struct copy */
-#if defined(BACAPP_LIGHTING_COMMAND)
+#if defined(BACAPP_TYPES_EXTRA)
zassert_true(bacapp_same_value(&value, &test_value), NULL);
#else
zassert_false(bacapp_same_value(&value, &test_value), NULL);
@@ -528,7 +536,6 @@ static void testBACnetApplicationData_Safe(void)
break;
}
single_length_segment = bacapp_encode_data(&apdu[len], &input_value[i]);
- ;
zassert_true(single_length_segment > 0, NULL);
/* len_segment is accumulated length */
if (i == 0) {
@@ -724,10 +731,38 @@ static bool verifyBACnetApplicationDataValue(BACNET_APPLICATION_DATA_VALUE *valu
{
uint8_t apdu[480] = { 0 };
int apdu_len = 0;
- BACNET_APPLICATION_DATA_VALUE test_value;
+ int null_len = 0;
+ BACNET_APPLICATION_DATA_VALUE test_value = { 0 };
apdu_len = bacapp_encode_application_data(&apdu[0], value);
- bacapp_decode_application_data(&apdu[0], apdu_len, &test_value);
+ zassert_true(apdu_len > 0, NULL);
+ null_len = bacapp_encode_application_data(NULL, value);
+ zassert_equal(apdu_len, null_len, NULL);
+ apdu_len = bacapp_decode_application_data(&apdu[0], apdu_len, &test_value);
+ zassert_true(apdu_len != BACNET_STATUS_ERROR, NULL);
+
+ return bacapp_same_value(value, &test_value);
+}
+
+/**
+ * @brief Test
+ */
+static bool verifyBACnetComplexDataValue(
+ BACNET_APPLICATION_DATA_VALUE *value,
+ BACNET_PROPERTY_ID prop)
+{
+ uint8_t apdu[480] = { 0 };
+ int apdu_len = 0;
+ int null_len = 0;
+ BACNET_APPLICATION_DATA_VALUE test_value = { 0 };
+
+ apdu_len = bacapp_encode_application_data(&apdu[0], value);
+ zassert_true(apdu_len > 0, NULL);
+ null_len = bacapp_encode_application_data(NULL, value);
+ zassert_equal(apdu_len, null_len, NULL);
+ apdu_len = bacapp_decode_generic_property(&apdu[0], apdu_len,
+ &test_value, prop);
+ zassert_true(apdu_len != BACNET_STATUS_ERROR, NULL);
return bacapp_same_value(value, &test_value);
}
@@ -737,7 +772,7 @@ static bool verifyBACnetApplicationDataValue(BACNET_APPLICATION_DATA_VALUE *valu
*/
static void testBACnetApplicationData(void)
{
- BACNET_APPLICATION_DATA_VALUE value;
+ BACNET_APPLICATION_DATA_VALUE value = { 0 };
bool status = false;
status = bacapp_parse_application_data(
@@ -816,6 +851,64 @@ static void testBACnetApplicationData(void)
zassert_true(status, NULL);
zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_DOUBLE, "0.0", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_DOUBLE, "-1.0", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_DOUBLE, "1.0", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_DOUBLE, "3.14159", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_DOUBLE, "-3.14159", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_OCTET_STRING, "1234567890ABCDEF", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_OCTET_STRING, "12-34-56-78-90-AB-CD-EF", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_OCTET_STRING, "12 34 56 78 90 AB CD EF", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ /* test empty string */
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_OCTET_STRING, "", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_CHARACTER_STRING, "Karg!", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ /* test empty string */
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_CHARACTER_STRING, "", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_BIT_STRING, "1011010010011111", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_BIT_STRING, "111100001111", &value);
+ zassert_true(status, NULL);
+ zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+
status = bacapp_parse_application_data(
BACNET_APPLICATION_TAG_ENUMERATED, "0", &value);
zassert_true(status, NULL);
@@ -906,35 +999,85 @@ static void testBACnetApplicationData(void)
zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_CHARACTER_STRING, "Karg!", &value);
+ BACNET_APPLICATION_TAG_OBJECT_ID, "8:4194303", &value);
zassert_true(status, NULL);
zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
- /* test empty string */
status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_CHARACTER_STRING, "", &value);
+ BACNET_APPLICATION_TAG_OBJECT_ID, "0:0", &value);
zassert_true(status, NULL);
zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OCTET_STRING, "1234567890ABCDEF", &value);
- zassert_true(status, NULL);
- zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ BACNET_APPLICATION_TAG_HOST_N_PORT, "192", &value);
+ zassert_false(status, NULL);
status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OCTET_STRING, "12-34-56-78-90-AB-CD-EF", &value);
+ BACNET_APPLICATION_TAG_HOST_N_PORT, "192.168.1.1", &value);
zassert_true(status, NULL);
- zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OCTET_STRING, "12 34 56 78 90 AB CD EF", &value);
+ BACNET_APPLICATION_TAG_HOST_N_PORT, "192.168.1.1:47808", &value);
zassert_true(status, NULL);
- zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
- /* test empty string */
- status = bacapp_parse_application_data(
- BACNET_APPLICATION_TAG_OCTET_STRING, "", &value);
- zassert_true(status, NULL);
- zassert_true(verifyBACnetApplicationDataValue(&value), NULL);
+ status = verifyBACnetComplexDataValue(&value, PROP_FD_BBMD_ADDRESS);
+ status = verifyBACnetComplexDataValue(&value,
+ PROP_BACNET_IP_GLOBAL_ADDRESS);
return;
}
+
+/**
+ * @brief Test
+ */
+static void test_bacapp_context_data(void)
+{
+ const uint8_t context_tag_number = 1;
+ uint8_t apdu[480] = { 0 };
+ BACNET_APPLICATION_DATA_VALUE value = { 0 };
+ BACNET_APPLICATION_DATA_VALUE test_value = { 0 };
+ bool status = false;
+ int apdu_len, null_len, test_len;
+ unsigned i = 0;
+
+ for (i = 0; i < sizeof(tag_list)/sizeof(tag_list[0]); i++) {
+ BACNET_APPLICATION_TAG tag = tag_list[i];
+ value.tag = tag;
+ null_len = bacapp_encode_context_data_value(NULL,
+ context_tag_number, &value);
+ apdu_len = bacapp_encode_context_data_value(apdu,
+ context_tag_number, &value);
+ if (apdu_len != null_len) {
+ printf("bacapp: NULL len=%d != APDU len=%d for tag=%s",
+ null_len, apdu_len, bactext_application_tag_name(tag));
+ }
+ zassert_equal(apdu_len, null_len, NULL);
+ }
+}
+
+/**
+ * @brief Test
+ */
+static void test_bacapp_sprintf_data(void)
+{
+ BACNET_APPLICATION_DATA_VALUE value = { 0 };
+ BACNET_OBJECT_PROPERTY_VALUE object_value = { 0 };
+ bool status = false;
+ int str_len = 0;
+
+ object_value.object_type = OBJECT_DEVICE;
+ object_value.object_instance = 0;
+ object_value.object_property = PROP_DAYLIGHT_SAVINGS_STATUS;
+ object_value.array_index = BACNET_ARRAY_ALL;
+ object_value.value = &value;
+
+ status = bacapp_parse_application_data(
+ BACNET_APPLICATION_TAG_NULL, NULL, &value);
+ zassert_true(status, NULL);
+ str_len = bacapp_snprintf_value(NULL, 0, &object_value);
+ if (str_len > 0) {
+ char str[str_len+1];
+ bacapp_snprintf_value(str, str_len+1, &object_value);
+ zassert_mem_equal(str, "Null", str_len, NULL);
+ }
+}
+
/**
* @}
*/
@@ -951,7 +1094,9 @@ void test_main(void)
ztest_unit_test(test_bacapp_same_value),
ztest_unit_test(testBACnetApplicationData),
ztest_unit_test(testBACnetApplicationDataLength),
- ztest_unit_test(testBACnetApplicationData_Safe)
+ ztest_unit_test(testBACnetApplicationData_Safe),
+ ztest_unit_test(test_bacapp_context_data),
+ ztest_unit_test(test_bacapp_sprintf_data)
);
ztest_run_test_suite(bacapp_tests);
diff --git a/test/bacnet/bacdcode/src/main.c b/test/bacnet/bacdcode/src/main.c
index 138b0d71..d59cdff8 100644
--- a/test/bacnet/bacdcode/src/main.c
+++ b/test/bacnet/bacdcode/src/main.c
@@ -101,6 +101,8 @@ static void testBACDCodeTags(void)
len = encode_opening_tag(&apdu[0], tag_number);
test_len = get_apdu_len(IS_EXTENDED_TAG_NUMBER(apdu[0]), 0);
zassert_equal(len, test_len, NULL);
+ test_len = encode_opening_tag(NULL, tag_number);
+ zassert_equal(len, test_len, NULL);
len = decode_tag_number_and_value(&apdu[0], &test_tag_number, &value);
zassert_equal(value, 0, NULL);
zassert_equal(len, test_len, NULL);
@@ -109,6 +111,8 @@ static void testBACDCodeTags(void)
zassert_false(IS_CLOSING_TAG(apdu[0]), NULL);
len = encode_closing_tag(&apdu[0], tag_number);
zassert_equal(len, test_len, NULL);
+ test_len = encode_closing_tag(NULL, tag_number);
+ zassert_equal(len, test_len, NULL);
len = decode_tag_number_and_value(&apdu[0], &test_tag_number, &value);
zassert_equal(len, test_len, NULL);
zassert_equal(value, 0, NULL);
@@ -145,18 +149,20 @@ static void testBACDCodeEnumerated(void)
uint32_t value = 1;
uint32_t decoded_value = 0;
int i = 0, apdu_len = 0;
- int len = 0;
+ int len = 0, null_len = 0;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t tag_number = 0;
uint32_t len_value = 0;
for (i = 0; i < 31; i++) {
apdu_len = encode_application_enumerated(&array[0], value);
+ null_len = encode_application_enumerated(NULL, value);
len = decode_tag_number_and_value(&array[0], &tag_number, &len_value);
len += decode_enumerated(&array[len], len_value, &decoded_value);
zassert_equal(decoded_value, value, NULL);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_ENUMERATED, NULL);
zassert_equal(len, apdu_len, NULL);
+ zassert_equal(null_len, apdu_len, NULL);
/* encode back the value */
encode_application_enumerated(&encoded_array[0], decoded_value);
zassert_equal(memcmp(&array[0], &encoded_array[0], sizeof(array)), 0, NULL);
@@ -169,10 +175,12 @@ static void testBACDCodeEnumerated(void)
zassert_false(IS_CONTEXT_SPECIFIC(apdu[0]), NULL);
/* context specific encoding */
apdu_len = encode_context_enumerated(&apdu[0], 3, value);
+ null_len = encode_context_enumerated(NULL, 3, value);
zassert_true(IS_CONTEXT_SPECIFIC(apdu[0]), NULL);
len = decode_tag_number_and_value(&apdu[0], &tag_number, NULL);
zassert_equal(len, 1, NULL);
zassert_equal(tag_number, 3, NULL);
+ zassert_equal(null_len, apdu_len, NULL);
/* test the interesting values */
value = value << 1;
}
@@ -187,7 +195,7 @@ static void testBACDCodeReal(void)
float value = 42.123F;
float decoded_value = 0.0F;
uint8_t apdu[MAX_APDU] = { 0 };
- int len = 0, apdu_len = 0;
+ int len = 0, apdu_len = 0, null_len = 0;
uint8_t tag_number = 0;
uint32_t long_value = 0;
@@ -199,7 +207,9 @@ static void testBACDCodeReal(void)
/* a real will take up 4 octects plus a one octet tag */
apdu_len = encode_application_real(&apdu[0], value);
+ null_len = encode_application_real(NULL, value);
zassert_equal(apdu_len, 5, NULL);
+ zassert_equal(apdu_len, null_len, NULL);
/* len tells us how many octets were used for encoding the value */
len = decode_tag_number_and_value(&apdu[0], &tag_number, &long_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_REAL, NULL);
@@ -219,7 +229,7 @@ static void testBACDCodeDouble(void)
double value = 42.123;
double decoded_value = 0.0;
uint8_t apdu[MAX_APDU] = { 0 };
- int len = 0, apdu_len = 0;
+ int len = 0, apdu_len = 0, null_len = 0;
uint8_t tag_number = 0;
uint32_t long_value = 0;
@@ -231,7 +241,9 @@ static void testBACDCodeDouble(void)
/* a real will take up 4 octects plus a one octet tag */
apdu_len = encode_application_double(&apdu[0], value);
+ null_len = encode_application_double(NULL, value);
zassert_equal(apdu_len, 10, NULL);
+ zassert_equal(apdu_len, null_len, NULL);
/* len tells us how many octets were used for encoding the value */
len = decode_tag_number_and_value(&apdu[0], &tag_number, &long_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_DOUBLE, NULL);
@@ -249,7 +261,7 @@ static void verifyBACDCodeUnsignedValue(BACNET_UNSIGNED_INTEGER value)
uint8_t array[5] = { 0 };
uint8_t encoded_array[5] = { 0 };
BACNET_UNSIGNED_INTEGER decoded_value = 0;
- int len;
+ int len = 0, null_len = 0;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t tag_number = 0;
uint32_t len_value = 0;
@@ -267,7 +279,9 @@ static void verifyBACDCodeUnsignedValue(BACNET_UNSIGNED_INTEGER value)
zassert_equal(memcmp(&array[0], &encoded_array[0], sizeof(array)), 0, NULL);
/* an unsigned will take up to 4 octects */
/* plus a one octet for the tag */
- encode_application_unsigned(&apdu[0], value);
+ len = encode_application_unsigned(&apdu[0], value);
+ null_len = encode_application_unsigned(NULL, value);
+ zassert_equal(len, null_len, NULL);
/* apdu_len varies... */
len = decode_tag_number_and_value(&apdu[0], &tag_number, NULL);
zassert_equal(len, 1, NULL);
@@ -298,15 +312,23 @@ static void testBACDCodeUnsigned(void)
static void testBACnetUnsigned(void)
{
uint8_t apdu[32] = { 0 };
- BACNET_UNSIGNED_INTEGER value = 0, test_value = 0;
- int len = 0, test_len = 0;
+ BACNET_UNSIGNED_INTEGER value = 1, test_value = 0;
+ int len = 0, test_len = 0, null_len = 0;
+ unsigned i;
+#ifdef UINT64_MAX
+ const unsigned max_bits = 64;
+#else
+ const unsigned max_bits = 32;
+#endif
- for (value = 0; value == BACNET_UNSIGNED_INTEGER_MAX;
- value = (value << 8) | 0xff) {
+ for (i = 0; i < max_bits; i++) {
len = encode_bacnet_unsigned(&apdu[0], value);
+ null_len = encode_bacnet_unsigned(NULL, value);
test_len = decode_unsigned(&apdu[0], len, &test_value);
+ zassert_equal(len, null_len, NULL);
zassert_equal(len, test_len, NULL);
zassert_equal(value, test_value, NULL);
+ value |= (value << 1);
}
}
@@ -315,13 +337,15 @@ static void testBACDCodeSignedValue(int32_t value)
uint8_t array[5] = { 0 };
uint8_t encoded_array[5] = { 0 };
int32_t decoded_value = 0;
- int len = 0;
+ int len = 0, null_len = 0;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t tag_number = 0;
uint32_t len_value = 0;
int diff = 0;
len = encode_application_signed(&array[0], value);
+ null_len = encode_application_signed(NULL, value);
+ zassert_equal(null_len, len, NULL);
len = decode_tag_number_and_value(&array[0], &tag_number, &len_value);
len = decode_signed(&array[len], len_value, &decoded_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_SIGNED_INT, NULL);
@@ -331,7 +355,9 @@ static void testBACDCodeSignedValue(int32_t value)
"value=%ld decoded_value=%ld\n", (long)value, (long)decoded_value);
print_apdu(&array[0], sizeof(array));
}
- encode_application_signed(&encoded_array[0], decoded_value);
+ len = encode_application_signed(&encoded_array[0], decoded_value);
+ null_len = encode_application_signed(NULL, decoded_value);
+ zassert_equal(null_len, len, NULL);
diff = memcmp(&array[0], &encoded_array[0], sizeof(array));
zassert_equal(diff, 0, NULL);
if (diff) {
@@ -342,7 +368,9 @@ static void testBACDCodeSignedValue(int32_t value)
}
/* a signed int will take up to 4 octects */
/* plus a one octet for the tag */
- encode_application_signed(&apdu[0], value);
+ len = encode_application_signed(&apdu[0], value);
+ null_len = encode_application_signed(NULL, value);
+ zassert_equal(null_len, len, NULL);
len = decode_tag_number_and_value(&apdu[0], &tag_number, NULL);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_SIGNED_INT, NULL);
zassert_false(IS_CONTEXT_SPECIFIC(apdu[0]), NULL);
@@ -378,19 +406,28 @@ static void testBACnetSigned(void)
{
uint8_t apdu[32] = { 0 };
int32_t value = 0, test_value = 0;
- int len = 0, test_len = 0;
+ int len = 0, test_len = 0, null_len = 0;
+ unsigned i = 0;
- for (value = -2147483647; value < 0; value += 127) {
+ value = -2147483647;
+ for (i = 0; i < 32; i++) {
len = encode_bacnet_signed(&apdu[0], value);
+ null_len = encode_bacnet_signed(NULL, value);
test_len = decode_signed(&apdu[0], len, &test_value);
+ zassert_equal(len, null_len, NULL);
zassert_equal(len, test_len, NULL);
zassert_equal(value, test_value, NULL);
+ value /= 2;
}
- for (value = 2147483647; value > 0; value -= 127) {
+ value = 2147483647;
+ for (i = 0; i < 32; i++) {
len = encode_bacnet_signed(&apdu[0], value);
+ null_len = encode_bacnet_signed(NULL, value);
test_len = decode_signed(&apdu[0], len, &test_value);
+ zassert_equal(len, null_len, NULL);
zassert_equal(len, test_len, NULL);
zassert_equal(value, test_value, NULL);
+ value /= 2;
}
}
@@ -402,8 +439,7 @@ static void testBACDCodeOctetString(void)
BACNET_OCTET_STRING test_octet_string;
uint8_t test_value[MAX_APDU] = { "" };
int i; /* for loop counter */
- int apdu_len;
- int len;
+ int apdu_len = 0, len = 0, null_len = 0;
uint8_t tag_number = 0;
uint32_t len_value = 0;
bool status = false;
@@ -412,6 +448,8 @@ static void testBACDCodeOctetString(void)
status = octetstring_init(&octet_string, NULL, 0);
zassert_true(status, NULL);
apdu_len = encode_application_octet_string(&array[0], &octet_string);
+ null_len = encode_application_octet_string(NULL, &octet_string);
+ zassert_equal(apdu_len, null_len, NULL);
len = decode_tag_number_and_value(&array[0], &tag_number, &len_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_OCTET_STRING, NULL);
len += decode_octet_string(&array[len], len_value, &test_octet_string);
@@ -426,6 +464,8 @@ static void testBACDCodeOctetString(void)
zassert_true(status, NULL);
apdu_len =
encode_application_octet_string(&encoded_array[0], &octet_string);
+ null_len = encode_application_octet_string(NULL, &octet_string);
+ zassert_equal(apdu_len, null_len, NULL);
len = decode_tag_number_and_value(
&encoded_array[0], &tag_number, &len_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_OCTET_STRING, NULL);
@@ -454,8 +494,7 @@ static void testBACDCodeCharacterString(void)
BACNET_CHARACTER_STRING test_char_string;
char test_value[MAX_APDU] = { "" };
int i; /* for loop counter */
- int apdu_len;
- int len;
+ int apdu_len = 0, len = 0, null_len = 0;
uint8_t tag_number = 0;
uint32_t len_value = 0;
int diff = 0; /* for comparison */
@@ -464,6 +503,8 @@ static void testBACDCodeCharacterString(void)
status = characterstring_init(&char_string, CHARACTER_ANSI_X34, NULL, 0);
zassert_true(status, NULL);
apdu_len = encode_application_character_string(&array[0], &char_string);
+ null_len = encode_application_character_string(NULL, &char_string);
+ zassert_equal(apdu_len, null_len, NULL);
len = decode_tag_number_and_value(&array[0], &tag_number, &len_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_CHARACTER_STRING, NULL);
len += decode_character_string(&array[len], len_value, &test_char_string);
@@ -478,6 +519,8 @@ static void testBACDCodeCharacterString(void)
zassert_true(status, NULL);
apdu_len = encode_application_character_string(
&encoded_array[0], &char_string);
+ null_len = encode_application_character_string(NULL, &char_string);
+ zassert_equal(apdu_len, null_len, NULL);
len = decode_tag_number_and_value(
&encoded_array[0], &tag_number, &len_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_CHARACTER_STRING, NULL);
@@ -506,10 +549,12 @@ static void testBACDCodeObject(void)
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
uint32_t instance = 123;
uint32_t decoded_instance = 0;
- int len = 0;
+ int apdu_len = 0, len = 0, null_len = 0;
uint8_t tag_number = 0;
- encode_bacnet_object_id(&encoded_array[0], type, instance);
+ apdu_len = encode_bacnet_object_id(&encoded_array[0], type, instance);
+ null_len = encode_bacnet_object_id(NULL, type, instance);
+ zassert_equal(apdu_len, null_len, NULL);
decode_object_id(&encoded_array[0], &decoded_type, &decoded_instance);
zassert_equal(decoded_type, type, NULL);
zassert_equal(decoded_instance, instance, NULL);
@@ -520,6 +565,8 @@ static void testBACDCodeObject(void)
/* test application encoded */
len =
encode_application_object_id(&encoded_array[0], type, instance);
+ null_len = encode_application_object_id(NULL, type, instance);
+ zassert_equal(len, null_len, NULL);
zassert_true(len > 0, NULL);
bacnet_object_id_application_decode(
&encoded_array[0], len, &decoded_type, &decoded_instance);
@@ -549,6 +596,8 @@ static void testBACDCodeObject(void)
len = encode_context_object_id(
&encoded_array[0], tag_number, type, instance);
zassert_true(len > 0, NULL);
+ null_len = encode_context_object_id(NULL, tag_number, type, instance);
+ zassert_equal(len, null_len, NULL);
len = decode_context_object_id(
&encoded_array[0], tag_number, &decoded_type, &decoded_instance);
zassert_true(len > 0, NULL);
@@ -588,7 +637,7 @@ static void testBACDCodeBitString(void)
uint8_t apdu[MAX_APDU] = { 0 };
uint32_t len_value = 0;
uint8_t tag_number = 0;
- int len = 0;
+ int len = 0, null_len = 0;
bitstring_init(&bit_string);
/* verify initialization */
@@ -603,6 +652,8 @@ static void testBACDCodeBitString(void)
zassert_true(bitstring_bit(&bit_string, bit), NULL);
/* encode */
len = encode_application_bitstring(&apdu[0], &bit_string);
+ null_len = encode_application_bitstring(NULL, &bit_string);
+ zassert_equal(len, null_len, NULL);
/* decode */
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_BIT_STRING, NULL);
@@ -618,6 +669,8 @@ static void testBACDCodeBitString(void)
zassert_false(bitstring_bit(&bit_string, bit), NULL);
/* encode */
len = encode_application_bitstring(&apdu[0], &bit_string);
+ null_len = encode_application_bitstring(NULL, &bit_string);
+ zassert_equal(len, null_len, NULL);
/* decode */
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
zassert_equal(tag_number, BACNET_APPLICATION_TAG_BIT_STRING, NULL);
diff --git a/test/bacnet/bacdevobjpropref/CMakeLists.txt b/test/bacnet/bacdevobjpropref/CMakeLists.txt
index d34bb035..a3149264 100644
--- a/test/bacnet/bacdevobjpropref/CMakeLists.txt
+++ b/test/bacnet/bacdevobjpropref/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
# Test and test library files
./src/main.c
diff --git a/test/bacnet/basic/binding/address/CMakeLists.txt b/test/bacnet/basic/binding/address/CMakeLists.txt
index f4fcaedc..42c330e6 100644
--- a/test/bacnet/basic/binding/address/CMakeLists.txt
+++ b/test/bacnet/basic/binding/address/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
# Test and test library files
./src/main.c
diff --git a/test/bacnet/basic/object/acc/CMakeLists.txt b/test/bacnet/basic/object/acc/CMakeLists.txt
index 56a1dadf..01f0d962 100644
--- a/test/bacnet/basic/object/acc/CMakeLists.txt
+++ b/test/bacnet/basic/object/acc/CMakeLists.txt
@@ -44,6 +44,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/basic/sys/days.c
# Test and test library files
diff --git a/test/bacnet/basic/object/access_credential/CMakeLists.txt b/test/bacnet/basic/object/access_credential/CMakeLists.txt
index 82c44fce..d4c30050 100644
--- a/test/bacnet/basic/object/access_credential/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_credential/CMakeLists.txt
@@ -48,6 +48,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/access_door/CMakeLists.txt b/test/bacnet/basic/object/access_door/CMakeLists.txt
index e5583c3c..ca00f7b6 100644
--- a/test/bacnet/basic/object/access_door/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_door/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/access_point/CMakeLists.txt b/test/bacnet/basic/object/access_point/CMakeLists.txt
index b1cf0fce..5a4198be 100644
--- a/test/bacnet/basic/object/access_point/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_point/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/timestamp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/access_rights/CMakeLists.txt b/test/bacnet/basic/object/access_rights/CMakeLists.txt
index 003c43b1..2f64f65b 100644
--- a/test/bacnet/basic/object/access_rights/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_rights/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/access_user/CMakeLists.txt b/test/bacnet/basic/object/access_user/CMakeLists.txt
index 6357dbde..32eb83c4 100644
--- a/test/bacnet/basic/object/access_user/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_user/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/access_zone/CMakeLists.txt b/test/bacnet/basic/object/access_zone/CMakeLists.txt
index 9d51081f..6eade962 100644
--- a/test/bacnet/basic/object/access_zone/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_zone/CMakeLists.txt
@@ -49,6 +49,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/ai/CMakeLists.txt b/test/bacnet/basic/object/ai/CMakeLists.txt
index c364385b..eb87ab95 100644
--- a/test/bacnet/basic/object/ai/CMakeLists.txt
+++ b/test/bacnet/basic/object/ai/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/memcopy.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/ao/CMakeLists.txt b/test/bacnet/basic/object/ao/CMakeLists.txt
index 2fe0378c..20fe06ab 100644
--- a/test/bacnet/basic/object/ao/CMakeLists.txt
+++ b/test/bacnet/basic/object/ao/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/av/CMakeLists.txt b/test/bacnet/basic/object/av/CMakeLists.txt
index 215ebcb5..1b3e0c7b 100644
--- a/test/bacnet/basic/object/av/CMakeLists.txt
+++ b/test/bacnet/basic/object/av/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/memcopy.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/bi/CMakeLists.txt b/test/bacnet/basic/object/bi/CMakeLists.txt
index abbe8e57..6c9d3313 100644
--- a/test/bacnet/basic/object/bi/CMakeLists.txt
+++ b/test/bacnet/basic/object/bi/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/memcopy.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/bo/CMakeLists.txt b/test/bacnet/basic/object/bo/CMakeLists.txt
index 02ffe1f5..b2e5e856 100644
--- a/test/bacnet/basic/object/bo/CMakeLists.txt
+++ b/test/bacnet/basic/object/bo/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/bv/CMakeLists.txt b/test/bacnet/basic/object/bv/CMakeLists.txt
index fffd35b2..d0f4afa7 100644
--- a/test/bacnet/basic/object/bv/CMakeLists.txt
+++ b/test/bacnet/basic/object/bv/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/command/CMakeLists.txt b/test/bacnet/basic/object/command/CMakeLists.txt
index 45b871ac..2c513d51 100644
--- a/test/bacnet/basic/object/command/CMakeLists.txt
+++ b/test/bacnet/basic/object/command/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/credential_data_input/CMakeLists.txt b/test/bacnet/basic/object/credential_data_input/CMakeLists.txt
index e0f4b435..9bafae5b 100644
--- a/test/bacnet/basic/object/credential_data_input/CMakeLists.txt
+++ b/test/bacnet/basic/object/credential_data_input/CMakeLists.txt
@@ -48,6 +48,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/device/CMakeLists.txt b/test/bacnet/basic/object/device/CMakeLists.txt
index ea6c349c..1d9face1 100644
--- a/test/bacnet/basic/object/device/CMakeLists.txt
+++ b/test/bacnet/basic/object/device/CMakeLists.txt
@@ -79,6 +79,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/dcc.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/memcopy.c
${SRC_DIR}/bacnet/npdu.c
diff --git a/test/bacnet/basic/object/lc/CMakeLists.txt b/test/bacnet/basic/object/lc/CMakeLists.txt
index cb4fd269..8c4df833 100644
--- a/test/bacnet/basic/object/lc/CMakeLists.txt
+++ b/test/bacnet/basic/object/lc/CMakeLists.txt
@@ -47,6 +47,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
./stubs.c
diff --git a/test/bacnet/basic/object/lo/CMakeLists.txt b/test/bacnet/basic/object/lo/CMakeLists.txt
index 31dcbdef..db50c050 100644
--- a/test/bacnet/basic/object/lo/CMakeLists.txt
+++ b/test/bacnet/basic/object/lo/CMakeLists.txt
@@ -47,6 +47,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/lsp/CMakeLists.txt b/test/bacnet/basic/object/lsp/CMakeLists.txt
index 0cd9307c..00e5c7fa 100644
--- a/test/bacnet/basic/object/lsp/CMakeLists.txt
+++ b/test/bacnet/basic/object/lsp/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/ms-input/CMakeLists.txt b/test/bacnet/basic/object/ms-input/CMakeLists.txt
index 0ee0150d..4ee07d61 100644
--- a/test/bacnet/basic/object/ms-input/CMakeLists.txt
+++ b/test/bacnet/basic/object/ms-input/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/mso/CMakeLists.txt b/test/bacnet/basic/object/mso/CMakeLists.txt
index 9a61505a..15ea943f 100644
--- a/test/bacnet/basic/object/mso/CMakeLists.txt
+++ b/test/bacnet/basic/object/mso/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/msv/CMakeLists.txt b/test/bacnet/basic/object/msv/CMakeLists.txt
index 5f849dea..1c5f4705 100644
--- a/test/bacnet/basic/object/msv/CMakeLists.txt
+++ b/test/bacnet/basic/object/msv/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/memcopy.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/netport/CMakeLists.txt b/test/bacnet/basic/object/netport/CMakeLists.txt
index dd1c1788..39184f03 100644
--- a/test/bacnet/basic/object/netport/CMakeLists.txt
+++ b/test/bacnet/basic/object/netport/CMakeLists.txt
@@ -47,6 +47,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/osv/CMakeLists.txt b/test/bacnet/basic/object/osv/CMakeLists.txt
index f3e34069..7e20eae9 100644
--- a/test/bacnet/basic/object/osv/CMakeLists.txt
+++ b/test/bacnet/basic/object/osv/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/piv/CMakeLists.txt b/test/bacnet/basic/object/piv/CMakeLists.txt
index fee6de14..c70781c6 100644
--- a/test/bacnet/basic/object/piv/CMakeLists.txt
+++ b/test/bacnet/basic/object/piv/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/basic/object/schedule/CMakeLists.txt b/test/bacnet/basic/object/schedule/CMakeLists.txt
index 133b53cc..42fdb29c 100644
--- a/test/bacnet/basic/object/schedule/CMakeLists.txt
+++ b/test/bacnet/basic/object/schedule/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/wp.c
# Test and test library files
diff --git a/test/bacnet/cov/CMakeLists.txt b/test/bacnet/cov/CMakeLists.txt
index 03c9a59d..8ff10e79 100644
--- a/test/bacnet/cov/CMakeLists.txt
+++ b/test/bacnet/cov/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/memcopy.c
# Test and test library files
diff --git a/test/bacnet/datalink/bvlc/CMakeLists.txt b/test/bacnet/datalink/bvlc/CMakeLists.txt
index ee70e162..00dd7a7e 100644
--- a/test/bacnet/datalink/bvlc/CMakeLists.txt
+++ b/test/bacnet/datalink/bvlc/CMakeLists.txt
@@ -38,8 +38,11 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/bacint.c
${SRC_DIR}/bacnet/bacreal.c
${SRC_DIR}/bacnet/bacstr.c
+ ${SRC_DIR}/bacnet/bactext.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/basic/sys/days.c
+ ${SRC_DIR}/bacnet/hostnport.c
+ ${SRC_DIR}/bacnet/indtext.c
# Test and test library files
./src/main.c
${ZTST_DIR}/ztest_mock.c
diff --git a/test/bacnet/datalink/bvlc/src/main.c b/test/bacnet/datalink/bvlc/src/main.c
index 9547de84..915c0945 100644
--- a/test/bacnet/datalink/bvlc/src/main.c
+++ b/test/bacnet/datalink/bvlc/src/main.c
@@ -819,12 +819,11 @@ static void test_BVLC_Address_Get_Set(void)
static void test_BVLC_BBMD_Address(void)
{
uint8_t apdu[480] = { 0 };
- uint16_t apdu_len = 0;
- int16_t test_apdu_len = 0;
- uint16_t i = 0;
+ int apdu_len = 0;
+ int test_apdu_len = 0;
BACNET_IP_ADDRESS bbmd_address;
BACNET_IP_ADDRESS test_bbmd_address;
- BACNET_ERROR_CODE error_code = 0;
+ BACNET_ERROR_CODE error_code = ERROR_CODE_SUCCESS;
bool status = false;
status = bvlc_address_port_from_ascii(
@@ -835,6 +834,9 @@ static void test_BVLC_BBMD_Address(void)
zassert_not_equal(apdu_len, 0, NULL);
test_apdu_len = bvlc_foreign_device_bbmd_host_address_decode(apdu,
apdu_len, &error_code, &test_bbmd_address);
+ if (test_apdu_len < 0) {
+ printf("BVLC: error-code=%s\n", bactext_error_code_name(error_code));
+ }
zassert_not_equal(test_apdu_len, 0, NULL);
zassert_not_equal(test_apdu_len, BACNET_STATUS_ERROR, NULL);
zassert_not_equal(test_apdu_len, BACNET_STATUS_ABORT, NULL);
diff --git a/test/bacnet/getalarm/CMakeLists.txt b/test/bacnet/getalarm/CMakeLists.txt
index 12f7f2cc..f6da266b 100644
--- a/test/bacnet/getalarm/CMakeLists.txt
+++ b/test/bacnet/getalarm/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/timestamp.c
diff --git a/test/bacnet/getevent/CMakeLists.txt b/test/bacnet/getevent/CMakeLists.txt
index e03f9b07..5d99dd74 100644
--- a/test/bacnet/getevent/CMakeLists.txt
+++ b/test/bacnet/getevent/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/timestamp.c
diff --git a/test/bacnet/lso/CMakeLists.txt b/test/bacnet/lso/CMakeLists.txt
index 2e9f23f7..ce8d6d18 100644
--- a/test/bacnet/lso/CMakeLists.txt
+++ b/test/bacnet/lso/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/memcopy.c
# Test and test library files
diff --git a/test/bacnet/ptransfer/CMakeLists.txt b/test/bacnet/ptransfer/CMakeLists.txt
index 10c5c57e..0300ed6c 100644
--- a/test/bacnet/ptransfer/CMakeLists.txt
+++ b/test/bacnet/ptransfer/CMakeLists.txt
@@ -46,6 +46,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
# Test and test library files
./src/main.c
diff --git a/test/bacnet/rpm/CMakeLists.txt b/test/bacnet/rpm/CMakeLists.txt
index ece3f7b7..0a52c488 100644
--- a/test/bacnet/rpm/CMakeLists.txt
+++ b/test/bacnet/rpm/CMakeLists.txt
@@ -47,6 +47,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/memcopy.c
# Test and test library files
diff --git a/test/bacnet/timesync/CMakeLists.txt b/test/bacnet/timesync/CMakeLists.txt
index 3092837d..2f46f68b 100644
--- a/test/bacnet/timesync/CMakeLists.txt
+++ b/test/bacnet/timesync/CMakeLists.txt
@@ -47,6 +47,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
# Test and test library files
./src/main.c
diff --git a/test/bacnet/wp/CMakeLists.txt b/test/bacnet/wp/CMakeLists.txt
index 3a244a07..cb0fe33d 100644
--- a/test/bacnet/wp/CMakeLists.txt
+++ b/test/bacnet/wp/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
+ ${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/indtext.c
# Test and test library files