From f147283293e83f0e1d8d922b9bda58c5e2825893 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Wed, 1 Jun 2022 15:42:50 -0500 Subject: [PATCH] Feature/apdu null length returned (#285) * Add APDU as NULL to get BACnet type lengths. * Fix bacapp copy test to succeed * fix BACnet REAL and DOUBLE decode * Add unit test for NULL APDU encoding for length * Add unit tests for bacapp context * refactor host-n-port to hostnport.c module * fix BVLC decoder * additional unit testing for bacapp * include bacdevobjpropref module in builds * simplify bacapp snprintf to be able to return length * adjust compiler for variable-length arrays * fix bug found by scan-build Authored-by: Steve Karg --- CMakeLists.txt | 2 + Makefile | 5 + ports/at91sam7s/Makefile | 2 + ports/at91sam7s/bacnet.ewp | 2309 +++++++++-------- ports/bdk-atxx4-mstp/bacnet.cproj | 8 + ports/bdk-atxx4-mstp/bacnet.ewp | 3 + ports/esp32/readme.txt | 1 + .../nbproject/Makefile-genesis.properties | 12 +- .../nbproject/configurations.xml | 12 +- .../BACnet-Server.X/nbproject/project.xml | 13 + ports/stm32f10x/Makefile | 2 + ports/stm32f10x/bacnet.ewp | 6 + ports/stm32f4xx/Makefile | 2 + ports/stm32f4xx/bacnet.ewp | 3 + .../BACnet_Stack_Library.vcxproj | 1 + .../BACnet_Stack_Library.vcxproj.filters | 3 + ports/xplained/bacnet.cproj | 8 + ports/xplained/bname.c | 2 +- src/bacnet/bacapp.c | 1385 ++++------ src/bacnet/bacapp.h | 68 +- src/bacnet/bacdcode.c | 921 ++++--- src/bacnet/bacdcode.h | 50 +- src/bacnet/bacint.c | 155 +- src/bacnet/bacint.h | 5 + src/bacnet/bacreal.c | 140 +- src/bacnet/bactext.c | 28 +- src/bacnet/basic/object/channel.c | 6 +- src/bacnet/basic/object/command.c | 2 +- src/bacnet/basic/object/device.c | 2 +- src/bacnet/config.h | 8 +- src/bacnet/datalink/bvlc.c | 130 +- src/bacnet/datalink/dlmstp.h | 2 +- src/bacnet/hostnport.c | 308 +++ src/bacnet/hostnport.h | 74 + src/bacnet/lighting.c | 149 +- test/bacnet/bacapp/CMakeLists.txt | 3 +- test/bacnet/bacapp/src/main.c | 289 ++- test/bacnet/bacdcode/src/main.c | 97 +- test/bacnet/bacdevobjpropref/CMakeLists.txt | 1 + .../basic/binding/address/CMakeLists.txt | 1 + test/bacnet/basic/object/acc/CMakeLists.txt | 1 + .../object/access_credential/CMakeLists.txt | 1 + .../basic/object/access_door/CMakeLists.txt | 1 + .../basic/object/access_point/CMakeLists.txt | 1 + .../basic/object/access_rights/CMakeLists.txt | 1 + .../basic/object/access_user/CMakeLists.txt | 1 + .../basic/object/access_zone/CMakeLists.txt | 1 + test/bacnet/basic/object/ai/CMakeLists.txt | 1 + test/bacnet/basic/object/ao/CMakeLists.txt | 1 + test/bacnet/basic/object/av/CMakeLists.txt | 1 + test/bacnet/basic/object/bi/CMakeLists.txt | 1 + test/bacnet/basic/object/bo/CMakeLists.txt | 1 + test/bacnet/basic/object/bv/CMakeLists.txt | 1 + .../basic/object/command/CMakeLists.txt | 1 + .../credential_data_input/CMakeLists.txt | 1 + .../bacnet/basic/object/device/CMakeLists.txt | 1 + test/bacnet/basic/object/lc/CMakeLists.txt | 1 + test/bacnet/basic/object/lo/CMakeLists.txt | 1 + test/bacnet/basic/object/lsp/CMakeLists.txt | 1 + .../basic/object/ms-input/CMakeLists.txt | 1 + test/bacnet/basic/object/mso/CMakeLists.txt | 1 + test/bacnet/basic/object/msv/CMakeLists.txt | 1 + .../basic/object/netport/CMakeLists.txt | 1 + test/bacnet/basic/object/osv/CMakeLists.txt | 1 + test/bacnet/basic/object/piv/CMakeLists.txt | 1 + .../basic/object/schedule/CMakeLists.txt | 1 + test/bacnet/cov/CMakeLists.txt | 1 + test/bacnet/datalink/bvlc/CMakeLists.txt | 3 + test/bacnet/datalink/bvlc/src/main.c | 10 +- test/bacnet/getalarm/CMakeLists.txt | 1 + test/bacnet/getevent/CMakeLists.txt | 1 + test/bacnet/lso/CMakeLists.txt | 1 + test/bacnet/ptransfer/CMakeLists.txt | 1 + test/bacnet/rpm/CMakeLists.txt | 1 + test/bacnet/timesync/CMakeLists.txt | 1 + test/bacnet/wp/CMakeLists.txt | 1 + 76 files changed, 3474 insertions(+), 2791 deletions(-) create mode 100644 src/bacnet/hostnport.c create mode 100644 src/bacnet/hostnport.h 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