Chore/bacnet-sc-unrelated-cleanup (#620)

* Added required linux Ethernet library for ethernet build

* Added .obj to gitignore

* Fixed BACnet port for APPLE to use BSD in CMake

* Changed format in CMake to enable cleaner SC merge

* Added create-object and delete-object recipes in GCC Makefile

* Added datalink timer to all example OS apps

* Changed most microcontroller ports to use BACAPP_MINIMAL to specify which datatypes can be written.

* Fixed zephyr OS for BACnet/IP warning

* Fixed zephyr OS log to not require log_strdup

* Added writefile API to file object example

* Added API to device-client to make it more robust.

* Added API in network-port object for getting the ASCII object-name

* Added debug print with a timestamp option

* Added debug print with hex dump print

* Added API to network port object for activate and discard

* Added default define for debug with timestamp

* Added prototype in header for disabled debug printf.

* Added fifo peek ahead function to peek at more than one byte.

* Added get-mac value for network port that uses buffer rather than octetstring
This commit is contained in:
Steve Karg
2024-04-19 12:54:56 -05:00
committed by GitHub
parent 600508c357
commit 770be70688
47 changed files with 687 additions and 152 deletions
+7 -6
View File
@@ -62,7 +62,7 @@ jobs:
gcc --version gcc --version
make clean make clean
make LEGACY=true BBMD=client all make LEGACY=true BBMD=client all
gateway: gateway:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -127,7 +127,7 @@ jobs:
run: | run: |
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq libconfig-dev sudo apt-get install -qq libconfig-dev
- name: Build BACnet/IPv6 Demos - name: Build BACnet/IPv6 Demo Apps
run: | run: |
gcc --version gcc --version
make clean make clean
@@ -141,7 +141,7 @@ jobs:
run: | run: |
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq libconfig-dev sudo apt-get install -qq libconfig-dev
- name: Build MSTP Demos - name: Build MSTP Demo Apps
run: | run: |
gcc --version gcc --version
make clean make clean
@@ -155,7 +155,8 @@ jobs:
run: | run: |
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq libconfig-dev sudo apt-get install -qq libconfig-dev
- name: Build Ethernet Demos sudo apt-get install -qq libcap-dev
- name: Build Ethernet Demo Apps
run: | run: |
gcc --version gcc --version
make clean make clean
@@ -195,7 +196,7 @@ jobs:
arm-none-eabi-gcc --version arm-none-eabi-gcc --version
make stm32f4xx-cmake make stm32f4xx-cmake
make at91sam7s-cmake make at91sam7s-cmake
ports-avr: ports-avr:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -234,7 +235,7 @@ jobs:
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq build-essential sudo apt-get install -qq build-essential
sudo apt-get install -qq mingw-w64 sudo apt-get install -qq mingw-w64
- name: Build Win32 Demos - name: Build Win32 Demo Apps
run: | run: |
export CC=i686-w64-mingw32-gcc export CC=i686-w64-mingw32-gcc
export LD=i686-w64-mingw32-ld export LD=i686-w64-mingw32-ld
+1
View File
@@ -1,6 +1,7 @@
*.log *.log
*.a *.a
*.o *.o
*.obj
*.exe *.exe
*.bak *.bak
*~ *~
+3 -1
View File
@@ -597,6 +597,7 @@ elseif(WIN32)
elseif(APPLE) elseif(APPLE)
message(STATUS "BACNET: building for APPLE") message(STATUS "BACNET: building for APPLE")
set(BACNET_PORT_DIRECTORY_PATH ${CMAKE_CURRENT_LIST_DIR}/ports/bsd) set(BACNET_PORT_DIRECTORY_PATH ${CMAKE_CURRENT_LIST_DIR}/ports/bsd)
add_compile_definitions(BACNET_PORT=bsd)
target_sources(${PROJECT_NAME} PRIVATE target_sources(${PROJECT_NAME} PRIVATE
ports/bsd/bacport.h ports/bsd/bacport.h
@@ -617,7 +618,8 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
endif() endif()
target_include_directories(${PROJECT_NAME} PUBLIC target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${BACNET_PORT_DIRECTORY_PATH}>) $<BUILD_INTERFACE:${BACNET_PORT_DIRECTORY_PATH}>
)
# #
# examples # examples
+19
View File
@@ -17,6 +17,17 @@ bsd:
win32: win32:
$(MAKE) BACNET_PORT=win32 -s -C apps all $(MAKE) BACNET_PORT=win32 -s -C apps all
.PHONY: mingw32
mingw32:
i686-w64-mingw32-gcc --version
ORIGINAL_CC=$(CC) ; \
ORIGINAL_LD=$(LD) ; \
export CC=i686-w64-mingw32-gcc ; \
export LD=i686-w64-mingw32-ld ; \
$(MAKE) BACNET_PORT=win32 -s -C apps all ; \
export CC=$(ORIGINAL_CC) ; \
export LD=$(ORIGINAL_LD)
.PHONY: mstpwin32 .PHONY: mstpwin32
mstpwin32: mstpwin32:
$(MAKE) BACDL=mstp BACNET_PORT=win32 -s -C apps all $(MAKE) BACDL=mstp BACNET_PORT=win32 -s -C apps all
@@ -85,10 +96,18 @@ apdu:
blinkt: blinkt:
$(MAKE) -s -C apps $@ $(MAKE) -s -C apps $@
.PHONY: create-object
create-object:
$(MAKE) -s -C apps $@
.PHONY: dcc .PHONY: dcc
dcc: dcc:
$(MAKE) -s -C apps $@ $(MAKE) -s -C apps $@
.PHONY: delete-object
delete-object:
$(MAKE) -s -C apps $@
.PHONY: epics .PHONY: epics
epics: epics:
$(MAKE) -s -C apps $@ $(MAKE) -s -C apps $@
+8
View File
@@ -274,10 +274,18 @@ apdu: $(BACNET_LIB_TARGET)
blinkt: blinkt:
$(MAKE) -C $@ $(MAKE) -C $@
.PHONY: create-object
create-object: $(BACNET_LIB_TARGET)
$(MAKE) -B -C $@
.PHONY: dcc .PHONY: dcc
dcc: $(BACNET_LIB_TARGET) dcc: $(BACNET_LIB_TARGET)
$(MAKE) -B -C $@ $(MAKE) -B -C $@
.PHONY: delete-object
delete-object: $(BACNET_LIB_TARGET)
$(MAKE) -B -C $@
.PHONY: epics .PHONY: epics
epics: $(BACNET_LIB_TARGET) epics: $(BACNET_LIB_TARGET)
$(MAKE) -B -C $@ $(MAKE) -B -C $@
+1
View File
@@ -390,6 +390,7 @@ int main(int argc, char *argv[])
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
(uint16_t)((current_seconds - last_seconds) * 1000)); (uint16_t)((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+2
View File
@@ -464,6 +464,8 @@ int main(int argc, char *argv[])
if (mstimer_expired(&maintenance_timer)) { if (mstimer_expired(&maintenance_timer)) {
mstimer_reset(&maintenance_timer); mstimer_reset(&maintenance_timer);
tsm_timer_milliseconds(mstimer_interval(&maintenance_timer)); tsm_timer_milliseconds(mstimer_interval(&maintenance_timer));
datalink_maintenance_timer(
mstimer_interval(&maintenance_timer)/1000L);
} }
if (mstimer_expired(&apdu_timer)) { if (mstimer_expired(&apdu_timer)) {
printf("\rError: APDU Timeout!\n"); printf("\rError: APDU Timeout!\n");
+2
View File
@@ -370,6 +370,8 @@ int main(int argc, char *argv[])
if (mstimer_expired(&maintenance_timer)) { if (mstimer_expired(&maintenance_timer)) {
mstimer_reset(&maintenance_timer); mstimer_reset(&maintenance_timer);
tsm_timer_milliseconds(mstimer_interval(&maintenance_timer)); tsm_timer_milliseconds(mstimer_interval(&maintenance_timer));
datalink_maintenance_timer(
mstimer_interval(&maintenance_timer)/1000L);
} }
if (mstimer_expired(&apdu_timer)) { if (mstimer_expired(&apdu_timer)) {
MyPrintHandler(Target_Object_Type, Target_Object_Instance, MyPrintHandler(Target_Object_Type, Target_Object_Instance,
+1
View File
@@ -244,6 +244,7 @@ int main(int argc, char *argv[])
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
(uint16_t)((current_seconds - last_seconds) * 1000)); (uint16_t)((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+2
View File
@@ -331,6 +331,8 @@ int main(int argc, char *argv[])
if (mstimer_expired(&maintenance_timer)) { if (mstimer_expired(&maintenance_timer)) {
mstimer_reset(&maintenance_timer); mstimer_reset(&maintenance_timer);
tsm_timer_milliseconds(mstimer_interval(&maintenance_timer)); tsm_timer_milliseconds(mstimer_interval(&maintenance_timer));
datalink_maintenance_timer(
mstimer_interval(&maintenance_timer)/1000L);
} }
if (mstimer_expired(&apdu_timer)) { if (mstimer_expired(&apdu_timer)) {
MyPrintHandler(ERROR_CLASS_COMMUNICATION, MyPrintHandler(ERROR_CLASS_COMMUNICATION,
+1 -1
View File
@@ -1522,8 +1522,8 @@ int main(int argc, char *argv[])
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
(uint16_t)((current_seconds - last_seconds) * 1000)); (uint16_t)((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
/* OK to proceed; see what we are up to now */ /* OK to proceed; see what we are up to now */
switch (myState) { switch (myState) {
case INITIAL_BINDING: case INITIAL_BINDING:
+1 -1
View File
@@ -584,11 +584,11 @@ int main(int argc, char *argv[])
for (;;) { for (;;) {
/* increment timer - exit if timed out */ /* increment timer - exit if timed out */
current_seconds = time(NULL); current_seconds = time(NULL);
/* at least one second has passed */ /* at least one second has passed */
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
(uint16_t)((current_seconds - last_seconds) * 1000)); (uint16_t)((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1 -1
View File
@@ -237,8 +237,8 @@ int main(int argc, char *argv[])
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
(uint16_t)((current_seconds - last_seconds) * 1000)); (uint16_t)((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
} }
+1 -6
View File
@@ -418,29 +418,25 @@ static void Wait_For_Answer_Or_Timeout(unsigned timeout_ms, waitAction action)
while (true) { while (true) {
time_t current_seconds = time(NULL); time_t current_seconds = time(NULL);
/* If error was detected then bail out */ /* If error was detected then bail out */
if (Error_Detected) { if (Error_Detected) {
LogError("Some other error occurred"); LogError("Some other error occurred");
break; break;
} }
if (elapsed_seconds > timeout_seconds) { if (elapsed_seconds > timeout_seconds) {
LogError("APDU Timeout"); LogError("APDU Timeout");
break; break;
} }
/* Process PDU if one comes in */ /* Process PDU if one comes in */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout_ms); pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout_ms);
if (pdu_len) { if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len); npdu_handler(&src, &Rx_Buf[0], pdu_len);
} }
/* at least one second has passed */ /* at least one second has passed */
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000)); tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (action == waitAnswer) { if (action == waitAnswer) {
/* Response was received. Exit. */ /* Response was received. Exit. */
if (tsm_invoke_id_free(Request_Invoke_ID)) { if (tsm_invoke_id_free(Request_Invoke_ID)) {
@@ -459,7 +455,6 @@ static void Wait_For_Answer_Or_Timeout(unsigned timeout_ms, waitAction action)
LogError("Invalid waitAction requested"); LogError("Invalid waitAction requested");
break; break;
} }
/* Keep track of time */ /* Keep track of time */
elapsed_seconds += (current_seconds - last_seconds); elapsed_seconds += (current_seconds - last_seconds);
last_seconds = current_seconds; last_seconds = current_seconds;
+2 -2
View File
@@ -268,7 +268,6 @@ int main(int argc, char *argv[])
/* returns 0 bytes on timeout */ /* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */ /* process */
if (pdu_len) { if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len); npdu_handler(&src, &Rx_Buf[0], pdu_len);
@@ -279,8 +278,8 @@ int main(int argc, char *argv[])
last_seconds = current_seconds; last_seconds = current_seconds;
tsm_timer_milliseconds( tsm_timer_milliseconds(
((current_seconds - last_seconds) * 1000)); ((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (_kbhit()) { if (_kbhit()) {
iKey = toupper(_getch()); iKey = toupper(_getch());
if (iKey == 'Q') { if (iKey == 'Q') {
@@ -313,6 +312,7 @@ int main(int argc, char *argv[])
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
((current_seconds - last_seconds) * 1000)); ((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1
View File
@@ -338,6 +338,7 @@ int main(int argc, char *argv[])
/* at least one second has passed */ /* at least one second has passed */
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000)); tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
/* wait until the device is bound, or timeout and quit */ /* wait until the device is bound, or timeout and quit */
if (!found) { if (!found) {
+3 -2
View File
@@ -194,8 +194,8 @@ static void print_help(char *filename)
"number.\n" "number.\n"
"Valid ranges are from 00 to FF (hex) for MS/TP or ARCNET,\n" "Valid ranges are from 00 to FF (hex) for MS/TP or ARCNET,\n"
"or an IP string with optional port number like 10.1.2.3:47808\n" "or an IP string with optional port number like 10.1.2.3:47808\n"
"or an Ethernet MAC in hex like 00:21:70:7e:32:bb\n" "or an Ethernet MAC in hex like 00:21:70:7e:32:bb\n");
"\n"); printf("\n");
printf("device-instance:\n" printf("device-instance:\n"
"BACnet Device Object Instance number that you are\n" "BACnet Device Object Instance number that you are\n"
"trying to communicate to. This number will be used\n" "trying to communicate to. This number will be used\n"
@@ -417,6 +417,7 @@ int main(int argc, char *argv[])
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
(uint16_t)((current_seconds - last_seconds) * 1000)); (uint16_t)((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1
View File
@@ -535,6 +535,7 @@ int main(int argc, char *argv[])
/* at least one second has passed */ /* at least one second has passed */
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000)); tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1
View File
@@ -368,6 +368,7 @@ int main(int argc, char *argv[])
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
(uint16_t)((current_seconds - last_seconds) * 1000)); (uint16_t)((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1
View File
@@ -204,6 +204,7 @@ int main(int argc, char *argv[])
/* at least one second has passed */ /* at least one second has passed */
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000)); tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1
View File
@@ -360,6 +360,7 @@ int main(int argc, char *argv[])
delta_seconds = current_seconds - last_seconds; delta_seconds = current_seconds - last_seconds;
elapsed_seconds += delta_seconds; elapsed_seconds += delta_seconds;
tsm_timer_milliseconds((delta_seconds * 1000)); tsm_timer_milliseconds((delta_seconds * 1000));
datalink_maintenance_timer(delta_seconds);
/* keep track of time for next check */ /* keep track of time for next check */
last_seconds = current_seconds; last_seconds = current_seconds;
} }
+2 -1
View File
@@ -314,7 +314,8 @@ int main(int argc, char *argv[])
/* increment timer - exit if timed out */ /* increment timer - exit if timed out */
delta_seconds = current_seconds - last_seconds; delta_seconds = current_seconds - last_seconds;
elapsed_seconds += delta_seconds; elapsed_seconds += delta_seconds;
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000)); tsm_timer_milliseconds(delta_seconds * 1000);
datalink_maintenance_timer(delta_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1
View File
@@ -222,6 +222,7 @@ int main(int argc, char *argv[])
/* at least one second has passed */ /* at least one second has passed */
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000)); tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
/* wait until the device is bound, or timeout and quit */ /* wait until the device is bound, or timeout and quit */
if (!found) { if (!found) {
+1
View File
@@ -427,6 +427,7 @@ int main(int argc, char *argv[])
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds( tsm_timer_milliseconds(
(uint16_t)((current_seconds - last_seconds) * 1000)); (uint16_t)((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1
View File
@@ -505,6 +505,7 @@ int main(int argc, char *argv[])
/* at least one second has passed */ /* at least one second has passed */
if (current_seconds != last_seconds) { if (current_seconds != last_seconds) {
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000)); tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
datalink_maintenance_timer(current_seconds - last_seconds);
} }
if (Error_Detected) { if (Error_Detected) {
break; break;
+1
View File
@@ -188,6 +188,7 @@ target_compile_definitions(${EXECUTABLE} PRIVATE
-DPRINT_ENABLED=0 -DPRINT_ENABLED=0
-DMAX_TSM_TRANSACTIONS=0 -DMAX_TSM_TRANSACTIONS=0
-DCRC_USE_TABLE -DCRC_USE_TABLE
-DBACAPP_MINIMAL
) )
# inhibit pedantic warnings # inhibit pedantic warnings
+1 -1
View File
@@ -22,7 +22,7 @@ BACNET_FLAGS += -DMAX_OCTET_STRING_BYTES=64
BACNET_FLAGS += -DPRINT_ENABLED=0 BACNET_FLAGS += -DPRINT_ENABLED=0
BACNET_FLAGS += -DMAX_APDU=480 BACNET_FLAGS += -DMAX_APDU=480
BACNET_FLAGS += -DCRC_USE_TABLE BACNET_FLAGS += -DCRC_USE_TABLE
#BACNET_FLAGS += -DDLMSTP_TEST BACNET_FLAGS += -DBACAPP_MINIMAL
ifeq (${LEGACY},true) ifeq (${LEGACY},true)
# disable deprecated function warnings for legacy builds # disable deprecated function warnings for legacy builds
BACNET_FLAGS += -DBACNET_STACK_DEPRECATED_DISABLE BACNET_FLAGS += -DBACNET_STACK_DEPRECATED_DISABLE
+1
View File
@@ -231,6 +231,7 @@
<state>PRINT_ENABLED=0</state> <state>PRINT_ENABLED=0</state>
<state>MAX_APDU=480</state> <state>MAX_APDU=480</state>
<state>CRC_USE_TABLE</state> <state>CRC_USE_TABLE</state>
<state>BACAPP_MINIMAL</state>
</option> </option>
<option> <option>
<name>CCPreprocFile</name> <name>CCPreprocFile</name>
+1 -1
View File
@@ -141,7 +141,7 @@ OPTIMIZE_FLAGS := -Os -ggdb
OPTIMIZE_FLAGS += -DNDEBUG OPTIMIZE_FLAGS += -DNDEBUG
BACNET_FLAGS = -DBACDL_MSTP=1 BACNET_FLAGS = -DBACDL_MSTP=1
BACNET_FLAGS += -DBACAPP_ALL BACNET_FLAGS += -DBACAPP_MINIMAL
BACNET_FLAGS += -DMAX_APDU=480 BACNET_FLAGS += -DMAX_APDU=480
BACNET_FLAGS += -DBIG_ENDIAN=0 BACNET_FLAGS += -DBIG_ENDIAN=0
BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0 BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0
+1
View File
@@ -229,6 +229,7 @@
<state>BACDL_MSTP</state> <state>BACDL_MSTP</state>
<state>MAX_APDU=480</state> <state>MAX_APDU=480</state>
<state>MAX_TSM_TRANSACTIONS=0</state> <state>MAX_TSM_TRANSACTIONS=0</state>
<state>BACAPP_MINIMAL</state>
</option> </option>
<option> <option>
<name>CCPreprocFile</name> <name>CCPreprocFile</name>
+1
View File
@@ -221,6 +221,7 @@ target_compile_definitions(${EXECUTABLE} PRIVATE
-DMAX_APDU=480 -DMAX_APDU=480
-DBIG_ENDIAN=0 -DBIG_ENDIAN=0
-DMAX_TSM_TRANSACTIONS=1 -DMAX_TSM_TRANSACTIONS=1
-DBACAPP_MINIMAL
) )
# inhibit pedantic warnings # inhibit pedantic warnings
+1 -1
View File
@@ -144,12 +144,12 @@ OPTIMIZE_FLAGS := -Os -ggdb
OPTIMIZE_FLAGS += -DNDEBUG OPTIMIZE_FLAGS += -DNDEBUG
BACNET_FLAGS = -DBACDL_MSTP=1 BACNET_FLAGS = -DBACDL_MSTP=1
BACNET_FLAGS += -DBACAPP_ALL
BACNET_FLAGS += -DMAX_APDU=1476 BACNET_FLAGS += -DMAX_APDU=1476
BACNET_FLAGS += -DBIG_ENDIAN=0 BACNET_FLAGS += -DBIG_ENDIAN=0
BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0 BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0
BACNET_FLAGS += -DMAX_CHARACTER_STRING_BYTES=64 BACNET_FLAGS += -DMAX_CHARACTER_STRING_BYTES=64
BACNET_FLAGS += -DMAX_OCTET_STRING_BYTES=64 BACNET_FLAGS += -DMAX_OCTET_STRING_BYTES=64
BACNET_FLAGS += -DBACAPP_MINIMAL
# if called from root Makefile, PRINT was already defined # if called from root Makefile, PRINT was already defined
BACNET_FLAGS += -UPRINT_ENABLED BACNET_FLAGS += -UPRINT_ENABLED
BACNET_FLAGS += -DPRINT_ENABLED=0 BACNET_FLAGS += -DPRINT_ENABLED=0
+1
View File
@@ -227,6 +227,7 @@
<state>MAX_APDU=1476</state> <state>MAX_APDU=1476</state>
<state>BIG_ENDIAN=0</state> <state>BIG_ENDIAN=0</state>
<state>MAX_TSM_TRANSACTIONS=1</state> <state>MAX_TSM_TRANSACTIONS=1</state>
<state>BACAPP_MINIMAL</state>
</option> </option>
<option> <option>
<name>CCPreprocFile</name> <name>CCPreprocFile</name>
@@ -216,10 +216,8 @@
<ClInclude Include="..\..\..\..\src\bacnet\bacdef.h" /> <ClInclude Include="..\..\..\..\src\bacnet\bacdef.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacdest.h" /> <ClInclude Include="..\..\..\..\src\bacnet\bacdest.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacdevobjpropref.h" /> <ClInclude Include="..\..\..\..\src\bacnet\bacdevobjpropref.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacenum.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacerror.h" /> <ClInclude Include="..\..\..\..\src\bacnet\bacerror.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacint.h" /> <ClInclude Include="..\..\..\..\src\bacnet\bacint.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacnet_stack_exports.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacprop.h" /> <ClInclude Include="..\..\..\..\src\bacnet\bacprop.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacpropstates.h" /> <ClInclude Include="..\..\..\..\src\bacnet\bacpropstates.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bacreal.h" /> <ClInclude Include="..\..\..\..\src\bacnet\bacreal.h" />
@@ -339,9 +337,6 @@
<ClInclude Include="..\..\..\..\src\bacnet\basic\sys\ringbuf.h" /> <ClInclude Include="..\..\..\..\src\bacnet\basic\sys\ringbuf.h" />
<ClInclude Include="..\..\..\..\src\bacnet\basic\sys\sbuf.h" /> <ClInclude Include="..\..\..\..\src\bacnet\basic\sys\sbuf.h" />
<ClInclude Include="..\..\..\..\src\bacnet\basic\tsm\tsm.h" /> <ClInclude Include="..\..\..\..\src\bacnet\basic\tsm\tsm.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bits.h" />
<ClInclude Include="..\..\..\..\src\bacnet\bytes.h" />
<ClInclude Include="..\..\..\..\src\bacnet\config.h" />
<ClInclude Include="..\..\..\..\src\bacnet\cov.h" /> <ClInclude Include="..\..\..\..\src\bacnet\cov.h" />
<ClInclude Include="..\..\..\..\src\bacnet\create_object.h" /> <ClInclude Include="..\..\..\..\src\bacnet\create_object.h" />
<ClInclude Include="..\..\..\..\src\bacnet\credential_authentication_factor.h" /> <ClInclude Include="..\..\..\..\src\bacnet\credential_authentication_factor.h" />
@@ -647,9 +647,6 @@
<ClInclude Include="..\..\..\..\src\bacnet\bacint.h"> <ClInclude Include="..\..\..\..\src\bacnet\bacint.h">
<Filter>Source Files\src\bacnet</Filter> <Filter>Source Files\src\bacnet</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\..\src\bacnet\bacnet_stack_exports.h">
<Filter>Source Files\src\bacnet</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\src\bacnet\bacprop.h"> <ClInclude Include="..\..\..\..\src\bacnet\bacprop.h">
<Filter>Source Files\src\bacnet</Filter> <Filter>Source Files\src\bacnet</Filter>
</ClInclude> </ClInclude>
@@ -668,15 +665,6 @@
<ClInclude Include="..\..\..\..\src\bacnet\bactimevalue.h"> <ClInclude Include="..\..\..\..\src\bacnet\bactimevalue.h">
<Filter>Source Files\src\bacnet</Filter> <Filter>Source Files\src\bacnet</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\..\src\bacnet\bits.h">
<Filter>Source Files\src\bacnet</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\src\bacnet\bytes.h">
<Filter>Source Files\src\bacnet</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\src\bacnet\config.h">
<Filter>Source Files\src\bacnet</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\src\bacnet\cov.h"> <ClInclude Include="..\..\..\..\src\bacnet\cov.h">
<Filter>Source Files\src\bacnet</Filter> <Filter>Source Files\src\bacnet</Filter>
</ClInclude> </ClInclude>
+2 -2
View File
@@ -338,7 +338,7 @@ uint16_t bip_receive(
} }
ZSOCK_FD_ZERO(&read_fds); ZSOCK_FD_ZERO(&read_fds);
ZSOCK_FD_SET(BIP_Socket, &read_fds); ZSOCK_FD_SET(BIP_Socket, &read_fds);
FD_SET(BIP_Broadcast_Socket, &read_fds); ZSOCK_FD_SET(BIP_Broadcast_Socket, &read_fds);
max = BIP_Socket > BIP_Broadcast_Socket ? BIP_Socket : BIP_Broadcast_Socket; max = BIP_Socket > BIP_Broadcast_Socket ? BIP_Socket : BIP_Broadcast_Socket;
@@ -507,7 +507,7 @@ void bip_set_interface(char *ifname)
bip_set_addr(&unicast); bip_set_addr(&unicast);
bip_set_broadcast_addr(&broadcast); bip_set_broadcast_addr(&broadcast);
LOG_INF("BACnet/IP Unicast: %u.%u.%u.%u:%d", unicast.address[0], LOG_INF("BACnet/IP Unicast: %u.%u.%u.%u:%d", unicast.address[0],
unicast.address[1], unicast.address[2], unicast.address[3], unicast.address[1], unicast.address[2], unicast.address[3],
unicast.port); unicast.port);
LOG_INF("BACnet/IP Broadcast: %u.%u.%u.%u", broadcast.address[0], LOG_INF("BACnet/IP Broadcast: %u.%u.%u.%u", broadcast.address[0],
broadcast.address[1], broadcast.address[2], broadcast.address[3]); broadcast.address[1], broadcast.address[2], broadcast.address[3]);
+9 -9
View File
@@ -93,7 +93,7 @@ static char* inet6_ntoa(struct in6_addr *a)
/* Avoid overwhelming the logging system */ /* Avoid overwhelming the logging system */
while(log_buffered_cnt()) while(log_buffered_cnt())
{ {
k_sleep(K_MSEC(1)); k_sleep(K_MSEC(1));
} }
@@ -316,7 +316,7 @@ uint16_t bip6_receive(
/* we could just use a non-blocking socket, but that consumes all /* we could just use a non-blocking socket, but that consumes all
the CPU time. We can use a timeout; it is only supported as the CPU time. We can use a timeout; it is only supported as
a select. */ a select. */
if (timeout >= 1000) { if (timeout >= 1000) {
select_timeout.tv_sec = timeout / 1000; select_timeout.tv_sec = timeout / 1000;
select_timeout.tv_usec = select_timeout.tv_usec =
@@ -334,7 +334,7 @@ uint16_t bip6_receive(
received_bytes = zsock_recvfrom(BIP6_Socket, (char *)&npdu[0], max_npdu, received_bytes = zsock_recvfrom(BIP6_Socket, (char *)&npdu[0], max_npdu,
0, (struct sockaddr *)&sin, &sin_len); 0, (struct sockaddr *)&sin, &sin_len);
} }
else else
{ {
return 0; return 0;
} }
@@ -439,13 +439,13 @@ void bip6_set_interface(char *ifname)
for(x=0; x<NET_IF_MAX_IPV6_ADDR; x++) for(x=0; x<NET_IF_MAX_IPV6_ADDR; x++)
{ {
inet6_ntoa(&interface->config.ip.ipv6->unicast[x].address.in6_addr ); inet6_ntoa(&interface->config.ip.ipv6->unicast[x].address.in6_addr );
LOG_INF(" unicast[%d]: %s", x, log_strdup(ipv6_addr_str)); LOG_INF(" unicast[%d]: %s", x, ipv6_addr_str);
} }
for(x=0; x<NET_IF_MAX_IPV6_MADDR; x++) for(x=0; x<NET_IF_MAX_IPV6_MADDR; x++)
{ {
inet6_ntoa(&interface->config.ip.ipv6->mcast[x].address.in6_addr ); inet6_ntoa(&interface->config.ip.ipv6->mcast[x].address.in6_addr );
LOG_INF(" multicast[%d]: %s", x, log_strdup(ipv6_addr_str)); LOG_INF(" multicast[%d]: %s", x, ipv6_addr_str);
} }
if(CONFIG_BACDL_BIP6_ADDRESS_INDEX >= NET_IF_MAX_IPV6_ADDR) if(CONFIG_BACDL_BIP6_ADDRESS_INDEX >= NET_IF_MAX_IPV6_ADDR)
@@ -459,7 +459,7 @@ void bip6_set_interface(char *ifname)
memcpy(&unicast.address, &interface->config.ip.ipv6->unicast memcpy(&unicast.address, &interface->config.ip.ipv6->unicast
[CONFIG_BACDL_BIP6_ADDRESS_INDEX].address.in6_addr, IP6_ADDRESS_MAX); [CONFIG_BACDL_BIP6_ADDRESS_INDEX].address.in6_addr, IP6_ADDRESS_MAX);
if(net_addr_pton(AF_INET6, CONFIG_BACDL_BIP6_MCAST_ADDRESS, &multicast.address)) if(net_addr_pton(AF_INET6, CONFIG_BACDL_BIP6_MCAST_ADDRESS, &multicast.address))
{ {
LOG_ERR("%s:%d - Failed to parse IPv6 multicast address: %s", THIS_FILE, __LINE__, CONFIG_BACDL_BIP6_MCAST_ADDRESS); LOG_ERR("%s:%d - Failed to parse IPv6 multicast address: %s", THIS_FILE, __LINE__, CONFIG_BACDL_BIP6_MCAST_ADDRESS);
@@ -468,8 +468,8 @@ void bip6_set_interface(char *ifname)
bip6_set_addr(&unicast); bip6_set_addr(&unicast);
bip6_set_broadcast_addr(&multicast); bip6_set_broadcast_addr(&multicast);
LOG_INF(" Unicast: %s", log_strdup(inet6_ntoa((struct in6_addr*)&unicast.address))); LOG_INF(" Unicast: %s", inet6_ntoa((struct in6_addr*)&unicast.address));
LOG_INF(" Multicast: %s", log_strdup(inet6_ntoa((struct in6_addr*)&multicast.address))); LOG_INF(" Multicast: %s", inet6_ntoa((struct in6_addr*)&multicast.address));
} }
else else
{ {
@@ -490,7 +490,7 @@ bool bip6_init(char *ifname)
bip6_set_interface(ifname); bip6_set_interface(ifname);
if (BIP6_Address.s6_addr == 0) { if (BIP6_Address.s6_addr == 0) {
LOG_ERR("%s:%d - Failed to get an IPv6 address on interface: %s\n", THIS_FILE, __LINE__, log_strdup(ifname ? ifname : "[default]")); LOG_ERR("%s:%d - Failed to get an IPv6 address on interface: %s\n", THIS_FILE, __LINE__, ifname ? ifname : "[default]");
return false; return false;
} }
+33 -2
View File
@@ -294,7 +294,7 @@ static long fsize(FILE *pFile)
/** /**
* @brief Read the entire file into a buffer * @brief Read the entire file into a buffer
* @param object_instance - object-instance number of the object * @param object_instance - object-instance number of the object
* @param buffer - pointer to buffer pointer where heap data will be stored * @param buffer - data store from the file
* @param buffer_size - in bytes * @param buffer_size - in bytes
* @return file size in bytes * @return file size in bytes
*/ */
@@ -322,6 +322,35 @@ uint32_t bacfile_read(uint32_t object_instance, uint8_t *buffer,
return (uint32_t)file_size; return (uint32_t)file_size;
} }
/**
* @brief Write the entire file from a buffer
* @param object_instance - object-instance number of the object
* @param buffer - data store for the file
* @param buffer_size - in bytes
* @return file size in bytes
*/
uint32_t bacfile_write(uint32_t object_instance, uint8_t *buffer,
uint32_t buffer_size)
{
const char *pFilename = NULL;
FILE *pFile = NULL;
long file_size = 0;
pFilename = bacfile_pathname(object_instance);
if (pFilename) {
/* open the file as a clean slate when starting at 0 */
pFile = fopen(pFilename, "wb");
if (pFile) {
if (fwrite(buffer, buffer_size, 1, pFile) == 1) {
file_size = buffer_size;
}
fclose(pFile);
}
}
return (uint32_t)file_size;
}
/** /**
* @brief Determines the file size for a given file * @brief Determines the file size for a given file
* @param pFile - file handle * @param pFile - file handle
@@ -1053,5 +1082,7 @@ void bacfile_cleanup(void)
*/ */
void bacfile_init(void) void bacfile_init(void)
{ {
Object_List = Keylist_Create(); if (!Object_List) {
Object_List = Keylist_Create();
}
} }
+5
View File
@@ -173,6 +173,11 @@ extern "C" {
uint32_t object_instance, uint32_t object_instance,
uint8_t *buffer, uint8_t *buffer,
uint32_t buffer_size); uint32_t buffer_size);
BACNET_STACK_EXPORT
uint32_t bacfile_write(
uint32_t object_instance,
uint8_t *buffer,
uint32_t buffer_size);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
uint32_t bacfile_create( uint32_t bacfile_create(
@@ -40,6 +40,7 @@
#include "bacnet/apdu.h" #include "bacnet/apdu.h"
#include "bacnet/proplist.h" #include "bacnet/proplist.h"
#include "bacnet/rp.h" /* ReadProperty handling */ #include "bacnet/rp.h" /* ReadProperty handling */
#include "bacnet/dcc.h" /* DeviceCommunicationControl handling */
#include "bacnet/version.h" #include "bacnet/version.h"
#include "bacnet/basic/services.h" #include "bacnet/basic/services.h"
#include "bacnet/datalink/datalink.h" #include "bacnet/datalink/datalink.h"
@@ -165,6 +166,25 @@ static struct object_functions *Device_Objects_Find_Functions(
return (NULL); return (NULL);
} }
/** Try to find a rr_info_function helper function for the requested object
* type.
* @ingroup ObjIntf
*
* @param object_type [in] The type of BACnet Object the handler wants to
* access.
* @return Pointer to the object helper function that implements the
* ReadRangeInfo function, Object_RR_Info, for this type of Object on
* success, else a NULL pointer if the type of Object isn't supported
* or doesn't have a ReadRangeInfo function.
*/
rr_info_function Device_Objects_RR_Info(BACNET_OBJECT_TYPE object_type)
{
struct object_functions *pObject = NULL;
pObject = Device_Objects_Find_Functions(object_type);
return (pObject != NULL ? pObject->Object_RR_Info : NULL);
}
/** For a given object type, returns the special property list. /** For a given object type, returns the special property list.
* This function is used for ReadPropertyMultiple calls which want * This function is used for ReadPropertyMultiple calls which want
* just Required, just Optional, or All properties. * just Required, just Optional, or All properties.
@@ -250,6 +270,80 @@ void Device_Property_Lists(
return; return;
} }
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static const char *Reinit_Password = "filister";
/** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
/* Note: you could use a mix of state and password to multiple things */
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
/* note: you probably want to restart *after* the
simple ack has been sent from the return handler
so just set a flag from here */
Reinitialize_State = rd_data->state;
status = true;
break;
case BACNET_REINIT_WARMSTART:
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
/* note: restart *after* the simple ack has been sent */
Reinitialize_State = rd_data->state;
status = true;
break;
case BACNET_REINIT_STARTBACKUP:
case BACNET_REINIT_ENDBACKUP:
case BACNET_REINIT_STARTRESTORE:
case BACNET_REINIT_ENDRESTORE:
case BACNET_REINIT_ABORTRESTORE:
if (dcc_communication_disabled()) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_COMMUNICATION_DISABLED;
} else {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code =
ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
}
break;
case BACNET_REINIT_ACTIVATE_CHANGES:
/* note: activate changes *after* the simple ack is sent */
Reinitialize_State = rd_data->state;
status = true;
break;
default:
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
}
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(void)
{
return Reinitialize_State;
}
unsigned Device_Count(void) unsigned Device_Count(void)
{ {
return 1; return 1;
@@ -323,6 +417,11 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
return status; return status;
} }
bool Device_Object_Name_ANSI_Init(const char *value)
{
return characterstring_init_ansi(&My_Object_Name, value);
}
BACNET_DEVICE_STATUS Device_System_Status(void) BACNET_DEVICE_STATUS Device_System_Status(void)
{ {
return System_Status; return System_Status;
+230 -60
View File
@@ -299,6 +299,23 @@ bool Network_Port_Name_Set(uint32_t object_instance, char *new_name)
return status; return status;
} }
/**
* @brief For a given object instance-number, returns the ASCII object-name
* @param object_instance - object-instance number of the object
* @return ASCII C string object name, or NULL if not found or not set.
*/
const char *Network_Port_Object_Name_ASCII(uint32_t object_instance)
{
unsigned index = 0; /* offset from instance lookup */
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
return Object_List[index].Object_Name;
}
return NULL;
}
/** /**
* Determines if a given Network Port instance is valid * Determines if a given Network Port instance is valid
* *
@@ -608,19 +625,19 @@ bool Network_Port_Quality_Set(
/** /**
* For a given object instance-number, loads the mac-address into * For a given object instance-number, loads the mac-address into
* an octet string. * a buffer and returns the length of the mac-address.
* Note: depends on Network_Type being set for this object * Note: depends on Network_Type being set for this object
* *
* @param object_instance - object-instance number of the object * @param object_instance - object-instance number of the object
* @param mac_address - holds the mac-address retrieved * @param mac_address - holds the mac-address retrieved
* @param mac_size - size of the mac-address buffer
* *
* @return true if mac-address was retrieved * @return the length of the mac-address retrieved, or zero if not found
*/ */
bool Network_Port_MAC_Address( uint8_t Network_Port_MAC_Address_Value(
uint32_t object_instance, BACNET_OCTET_STRING *mac_address) uint32_t object_instance, uint8_t *mac_address, size_t mac_size)
{ {
unsigned index = 0; /* offset from instance lookup */ unsigned index = 0; /* offset from instance lookup */
bool status = false;
uint8_t *mac = NULL; uint8_t *mac = NULL;
uint8_t ip_mac[4 + 2] = { 0 }; uint8_t ip_mac[4 + 2] = { 0 };
size_t mac_len = 0; size_t mac_len = 0;
@@ -653,12 +670,39 @@ bool Network_Port_MAC_Address(
default: default:
break; break;
} }
if (mac) { if (mac_len > 0) {
status = octetstring_init(mac_address, mac, mac_len); if (mac_size >= mac_len) {
memcpy(mac_address, mac, mac_len);
} else {
mac_len = 0;
}
} }
} }
return status; return mac_len;
}
/**
* For a given object instance-number, loads the mac-address into
* an octet string.
* Note: depends on Network_Type being set for this object
*
* @param object_instance - object-instance number of the object
* @param mac_address - holds the mac-address retrieved
*
* @return true if mac-address was retrieved
*/
bool Network_Port_MAC_Address(
uint32_t object_instance, BACNET_OCTET_STRING *mac_address)
{
uint8_t mac_len = 0;
if (mac_address) {
mac_len = Network_Port_MAC_Address_Value(object_instance,
mac_address->value, sizeof(mac_address->value));
}
return mac_len > 0;
} }
/** /**
@@ -838,6 +882,34 @@ bool Network_Port_Changes_Pending_Set(uint32_t object_instance, bool value)
return status; return status;
} }
/**
* @brief For a given object instance-number, activates any pending changes
* @param object_instance - object-instance number of the object
*/
void Network_Port_Changes_Pending_Activate(uint32_t object_instance)
{
unsigned index = 0;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
/* callback? something else? */
}
}
/**
* @brief For a given object instance-number, discards any pending changes
* @param object_instance - object-instance number of the object
*/
void Network_Port_Changes_Pending_Discard(uint32_t object_instance)
{
unsigned index = 0;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
/* callback? something else? */
}
}
/** /**
* For a given object instance-number, gets the MS/TP Max_Master value * For a given object instance-number, gets the MS/TP Max_Master value
* Note: depends on Network_Type being set to PORT_TYPE_MSTP for this object * Note: depends on Network_Type being set to PORT_TYPE_MSTP for this object
@@ -1127,6 +1199,33 @@ bool Network_Port_IP_DNS_Server(uint32_t object_instance,
return status; return status;
} }
/**
* @brief Encode a BACnetARRAY property element; a function template
* @param object_instance [in] BACnet network port object instance number
* @param index [in] array index requested:
* 0 to (array size - 1) for individual array members
* @param apdu [out] Buffer in which the APDU contents are built, or
* NULL to return the length of buffer if it had been built
* @return The length of the apdu encoded, or
* BACNET_STATUS_ERROR for an invalid array index
*/
static int Network_Port_IP_DNS_Server_Encode(
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
{
int apdu_len = 0;
BACNET_OCTET_STRING ip_address = { 0 };
if (index >= BIP_DNS_MAX) {
apdu_len = BACNET_STATUS_ERROR;
} else {
if (Network_Port_IP_DNS_Server(object_instance, index, &ip_address)) {
apdu_len = encode_application_octet_string(apdu, &ip_address);
}
}
return apdu_len;
}
/** /**
* For a given object instance-number, sets the ip-address * For a given object instance-number, sets the ip-address
* Note: depends on Network_Type being set for this object * Note: depends on Network_Type being set for this object
@@ -1882,6 +1981,33 @@ bool Network_Port_IPv6_DNS_Server(uint32_t object_instance,
return status; return status;
} }
/**
* @brief Encode a BACnetARRAY property element; a function template
* @param object_instance [in] BACnet network port object instance number
* @param index [in] array index requested:
* 0 to (array size - 1) for individual array members
* @param apdu [out] Buffer in which the APDU contents are built, or
* NULL to return the length of buffer if it had been built
* @return The length of the apdu encoded, or
* BACNET_STATUS_ERROR for an invalid array index
*/
static int Network_Port_IPv6_DNS_Server_Encode(
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
{
int apdu_len = 0;
BACNET_OCTET_STRING ip_address = { 0 };
if (index >= BIP_DNS_MAX) {
apdu_len = BACNET_STATUS_ERROR;
} else {
if (Network_Port_IPv6_DNS_Server(object_instance, index, &ip_address)) {
apdu_len = encode_application_octet_string(apdu, &ip_address);
}
}
return apdu_len;
}
/** /**
* For a given object instance-number, sets the ip-address * For a given object instance-number, sets the ip-address
* Note: depends on Network_Type being set for this object * Note: depends on Network_Type being set for this object
@@ -2186,6 +2312,34 @@ bool Network_Port_MSTP_Max_Info_Frames_Set(
return status; return status;
} }
/**
* Determine if the object property is a BACnetARRAY datatype
* @param object_property [in] BACnet object property
* @return true if the object property is a BACnetARRAY datatype
*/
bool Network_Port_BACnetArray_Property(BACNET_PROPERTY_ID object_property)
{
bool status = false;
switch (object_property) {
case PROP_EVENT_TIME_STAMPS:
case PROP_EVENT_MESSAGE_TEXTS:
case PROP_EVENT_MESSAGE_TEXTS_CONFIG:
case PROP_PROPERTY_LIST:
case PROP_TAGS:
case PROP_LINK_SPEEDS:
case PROP_IP_DNS_SERVER:
case PROP_IPV6_DNS_SERVER:
case PROP_ISSUER_CERTIFICATE_FILES:
status = true;
break;
default:
break;
}
return status;
}
/** /**
* ReadProperty handler for this object. For the given ReadProperty * ReadProperty handler for this object. For the given ReadProperty
* data, the application_data is loaded or the error flags are set. * data, the application_data is loaded or the error flags are set.
@@ -2328,32 +2482,13 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
apdu_len = encode_application_octet_string(&apdu[0], &octet_string); apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
break; break;
case PROP_IP_DNS_SERVER: case PROP_IP_DNS_SERVER:
if (rpdata->array_index == 0) { apdu_len = bacnet_array_encode(rpdata->object_instance,
/* Array element zero is the number of objects in the list */ rpdata->array_index, Network_Port_IP_DNS_Server_Encode,
apdu_len = encode_application_unsigned(&apdu[0], BIP_DNS_MAX); BIP_DNS_MAX, apdu, apdu_size);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) { if (apdu_len == BACNET_STATUS_ABORT) {
/* if no index was specified, then try to encode the entire list rpdata->error_code =
*/ ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
/* into one packet. */ } else if (apdu_len == BACNET_STATUS_ERROR) {
int len;
unsigned index;
for (index = 0; index < BIP_DNS_MAX; index++) {
Network_Port_IP_DNS_Server(
rpdata->object_instance, index, &octet_string);
len = encode_application_octet_string(
&apdu[apdu_len], &octet_string);
apdu_len += len;
}
} else if (rpdata->array_index <= BIP_DNS_MAX) {
/* index was specified; encode a single array element */
unsigned index;
index = rpdata->array_index - 1;
Network_Port_IP_DNS_Server(
rpdata->object_instance, index, &octet_string);
apdu_len =
encode_application_octet_string(&apdu[0], &octet_string);
} else {
/* index was specified, but out of range */
rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = BACNET_STATUS_ERROR; apdu_len = BACNET_STATUS_ERROR;
@@ -2412,32 +2547,13 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
apdu_len = encode_application_octet_string(&apdu[0], &octet_string); apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
break; break;
case PROP_IPV6_DNS_SERVER: case PROP_IPV6_DNS_SERVER:
if (rpdata->array_index == 0) { apdu_len = bacnet_array_encode(rpdata->object_instance,
/* Array element zero is the number of objects in the list */ rpdata->array_index, Network_Port_IPv6_DNS_Server_Encode,
apdu_len = encode_application_unsigned(&apdu[0], BIP_DNS_MAX); BIP_DNS_MAX, apdu, apdu_size);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) { if (apdu_len == BACNET_STATUS_ABORT) {
/* if no index was specified, then try to encode the entire list rpdata->error_code =
*/ ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
/* into one packet. */ } else if (apdu_len == BACNET_STATUS_ERROR) {
int len;
unsigned index;
for (index = 0; index < BIP_DNS_MAX; index++) {
Network_Port_IPv6_DNS_Server(
rpdata->object_instance, index, &octet_string);
len = encode_application_octet_string(
&apdu[apdu_len], &octet_string);
apdu_len += len;
}
} else if (rpdata->array_index <= BIP_DNS_MAX) {
/* index was specified; encode a single array element */
unsigned index;
index = rpdata->array_index - 1;
Network_Port_IPv6_DNS_Server(
rpdata->object_instance, index, &octet_string);
apdu_len =
encode_application_octet_string(&apdu[0], &octet_string);
} else {
/* index was specified, but out of range */
rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = BACNET_STATUS_ERROR; apdu_len = BACNET_STATUS_ERROR;
@@ -2469,6 +2585,14 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
(void)apdu_size; (void)apdu_size;
break; break;
} }
/* only array properties can have optional array indices */
if ((apdu_len >= 0) &&
(!Network_Port_BACnetArray_Property(rpdata->object_property)) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = BACNET_STATUS_ERROR;
}
return apdu_len; return apdu_len;
} }
@@ -2596,6 +2720,14 @@ int Network_Port_Read_Range_FDT(uint8_t *apdu, BACNET_READ_RANGE_DATA *pRequest)
return 0; return 0;
} }
/**
* ReadRange service handler
*
* @param apdu - place to encode the data
* @param pInfo - RR_PROP_INFO data
*
* @return number of bytes encoded
*/
bool Network_Port_Read_Range( bool Network_Port_Read_Range(
BACNET_READ_RANGE_DATA *pRequest, RR_PROP_INFO *pInfo) BACNET_READ_RANGE_DATA *pRequest, RR_PROP_INFO *pInfo)
{ {
@@ -2672,6 +2804,44 @@ bool Network_Port_Read_Range(
return status; return status;
} }
/**
* @brief Activate any of the changes pending for all network port objects
*/
void Network_Port_Changes_Activate(void)
{
unsigned i = 0;
for (i = 0; i < BACNET_NETWORK_PORTS_MAX; i++) {
if (Object_List[i].Changes_Pending) {
Network_Port_Changes_Pending_Activate(i);
Object_List[i].Changes_Pending = false;
}
}
}
/**
* @brief Activate any of the changes pending for all network port objects
*/
void Network_Port_Changes_Discard(void)
{
unsigned i = 0;
for (i = 0; i < BACNET_NETWORK_PORTS_MAX; i++) {
if (Object_List[i].Changes_Pending) {
Network_Port_Changes_Pending_Discard(i);
Object_List[i].Changes_Pending = false;
}
}
}
/**
* @brief Cleanup - useful if network port object are allocated on the heap
*/
void Network_Port_Cleanup(void)
{
/* do something interesting */
}
/** /**
* Initializes the Network Port object data * Initializes the Network Port object data
*/ */
+20
View File
@@ -68,6 +68,9 @@ extern "C" {
bool Network_Port_Name_Set( bool Network_Port_Name_Set(
uint32_t object_instance, uint32_t object_instance,
char *new_name); char *new_name);
BACNET_STACK_EXPORT
const char *Network_Port_Object_Name_ASCII(
uint32_t object_instance);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
char *Network_Port_Description( char *Network_Port_Description(
@@ -122,6 +125,11 @@ extern "C" {
uint32_t object_instance, uint32_t object_instance,
BACNET_OCTET_STRING *mac_address); BACNET_OCTET_STRING *mac_address);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
uint8_t Network_Port_MAC_Address_Value(
uint32_t object_instance,
uint8_t *mac_address,
size_t mac_size);
BACNET_STACK_EXPORT
bool Network_Port_MAC_Address_Set( bool Network_Port_MAC_Address_Set(
uint32_t object_instance, uint32_t object_instance,
uint8_t *mac_src, uint8_t *mac_src,
@@ -369,6 +377,12 @@ extern "C" {
bool Network_Port_Changes_Pending_Set( bool Network_Port_Changes_Pending_Set(
uint32_t instance, uint32_t instance,
bool flag); bool flag);
BACNET_STACK_EXPORT
void Network_Port_Changes_Pending_Activate(
uint32_t instance);
BACNET_STACK_EXPORT
void Network_Port_Changes_Pending_Discard(
uint32_t instance);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
bool Network_Port_Valid_Instance( bool Network_Port_Valid_Instance(
@@ -408,6 +422,12 @@ extern "C" {
bool Network_Port_Delete( bool Network_Port_Delete(
uint32_t object_instance); uint32_t object_instance);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
void Network_Port_Changes_Activate(
void);
BACNET_STACK_EXPORT
void Network_Port_Changes_Discard(
void);
BACNET_STACK_EXPORT
void Network_Port_Cleanup( void Network_Port_Cleanup(
void); void);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
+151 -27
View File
@@ -37,81 +37,205 @@
#include <stdio.h> /* Standard I/O */ #include <stdio.h> /* Standard I/O */
#include <stdlib.h> /* Standard Library */ #include <stdlib.h> /* Standard Library */
#include <stdarg.h> #include <stdarg.h>
#if DEBUG_ENABLED
#include <string.h>
#include <ctype.h>
#endif
#include "bacnet/basic/sys/debug.h" #include "bacnet/basic/sys/debug.h"
#if DEBUG_PRINTF_WITH_TIMESTAMP
#include "bacnet/datetime.h"
#endif
/** @file debug.c Debug print function */ /** @file debug.c Debug print function */
#if DEBUG_ENABLED #if DEBUG_PRINTF_WITH_TIMESTAMP
/**
* @brief Print timestamp with a printf string
* @param format - printf format string
* @param ... - variable arguments
* @note This function is only available if
* DEBUG_PRINTF_WITH_TIMESTAMP is non-zero
* and DEBUG_ENABLED is non-zero
*/
void debug_printf(const char *format, ...) void debug_printf(const char *format, ...)
{ {
#if DEBUG_ENABLED
va_list ap;
char stamp_str[64];
char buf[1024];
BACNET_DATE date;
BACNET_TIME time;
datetime_local(&date, &time, NULL, NULL);
sprintf(stamp_str, "[%02d:%02d:%02d.%03d]: ", time.hour, time.min,
time.sec, time.hundredths * 10);
va_start(ap, format);
vsprintf(buf, format, ap);
va_end(ap);
printf("%s%s", stamp_str, buf);
fflush(stdout);
#else
(void)format;
#endif
}
#else
/**
* @brief Print with a printf string
* @param format - printf format string
* @param ... - variable arguments
* @note This function is only available if
* DEBUG_ENABLED is non-zero
*/
void debug_printf(const char *format, ...)
{
#if DEBUG_ENABLED
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
vfprintf(stdout, format, ap); vfprintf(stdout, format, ap);
va_end(ap); va_end(ap);
fflush(stdout); fflush(stdout);
return;
}
#else #else
void debug_printf(const char *format, ...)
{
(void)format; (void)format;
#endif
} }
#endif #endif
#if PRINT_ENABLED /**
* @brief print format with HEX dump of a buffer
* @param offset - starting address to print to the left side
* @param buffer - buffer from which to print hex from
* @param buffer_length - number of bytes from the buffer to print
* @param format - printf format string
* @param ... - variable arguments
* @note This function is only available if DEBUG_ENABLED is non-zero
*/
void debug_printf_hex(
uint32_t offset,
const uint8_t *buffer,
size_t buffer_length,
const char *format, ...)
{
#if DEBUG_ENABLED
size_t i = 0;
bool new_line = true;
char line[16+1] = {0};
size_t remainder = 0;
va_list ap;
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
/* print the buffer after the formatted text */
if (buffer && buffer_length) {
for (i = 0; i < buffer_length; i++) {
if (new_line) {
new_line = false;
printf("%08x ", (unsigned int)(offset+i));
memset(line, '.', sizeof(line)-1);
}
printf("%02x ", buffer[i]);
if (isprint(buffer[i])) {
line[i%16] = buffer[i];
}
if ((i != 0) && (!((i+1)%16))) {
printf(" %s\n", line);
new_line = true;
}
}
remainder = buffer_length%16;
if (remainder) {
for (i = 0; i < (16-remainder); i++) {
printf(" ");
}
printf(" %s\n", line);
}
}
fflush(stdout);
#else
(void)offset;
(void)buffer;
(void)buffer_length;
(void)format;
#endif
}
/**
* @brief Print with a printf string
* @param format - printf format string
* @param ... - variable arguments
* @note This function is only available if
* PRINT_ENABLED is non-zero
* @return number of characters printed
*/
int debug_aprintf(const char *format, ...) int debug_aprintf(const char *format, ...)
{ {
int length = 0; int length = 0;
#if PRINT_ENABLED
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
length = vfprintf(stdout, format, ap); length = vfprintf(stdout, format, ap);
va_end(ap); va_end(ap);
fflush(stdout); fflush(stdout);
#else
(void)format;
#endif
return length; return length;
} }
/**
* @brief Print with a printf string
* @param stream - file stream to print to
* @param format - printf format string
* @param ... - variable arguments
* @note This function is only available if
* PRINT_ENABLED is non-zero
* @return number of characters printed
*/
int debug_fprintf(FILE *stream, const char *format, ...) int debug_fprintf(FILE *stream, const char *format, ...)
{ {
int length = 0; int length = 0;
#if PRINT_ENABLED
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
length = vfprintf(stream, format, ap); length = vfprintf(stream, format, ap);
va_end(ap); va_end(ap);
fflush(stream); fflush(stream);
#else
(void)format;
#endif
return length; return length;
} }
/**
* @brief Print with a perror string
* @param format - printf format string
* @param ... - variable arguments
* @note This function is only available if
* PRINT_ENABLED is non-zero
*/
void debug_perror(const char *format, ...) void debug_perror(const char *format, ...)
{ {
#if PRINT_ENABLED
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
vfprintf(stderr, format, ap); vfprintf(stderr, format, ap);
va_end(ap); va_end(ap);
fflush(stderr); fflush(stderr);
}
#else #else
int debug_aprintf(const char *format, ...)
{
(void)format; (void)format;
return 0;
}
int debug_fprintf(FILE *stream, const char *format, ...)
{
(void)stream;
(void)format;
return 0;
}
void debug_perror(const char *format, ...)
{
(void)format;
}
#endif #endif
}
/**
* @brief Print with a printf string that does nothing
* @param format - printf format string
* @param ... - variable arguments
* @note useful when used with defines such as PRINTF
*/
void debug_printf_disabled(const char *format, ...)
{
(void)format;
}
+16 -11
View File
@@ -34,6 +34,10 @@
#define DEBUG_ENABLED 0 #define DEBUG_ENABLED 0
#endif #endif
#ifndef DEBUG_PRINTF_WITH_TIMESTAMP
#define DEBUG_PRINTF_WITH_TIMESTAMP 0
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
@@ -55,17 +59,18 @@ extern "C" {
void debug_perror( void debug_perror(
const char *format, const char *format,
...); ...);
#if DEBUG_ENABLED BACNET_STACK_EXPORT
/* Nothing more here */ void debug_printf_hex(
#else uint32_t offset,
/* If your compiler supports it, this is more compact: const uint8_t *buffer,
inline void debug_printf( size_t buffer_length,
const char *format, const char *format, ...);
...) {
format = format; BACNET_STACK_EXPORT
} void debug_printf_disabled(
*/ const char *format,
#endif ...);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
+33
View File
@@ -172,6 +172,39 @@ uint8_t FIFO_Peek(FIFO_BUFFER const *b)
return 0; return 0;
} }
/**
* Peeks ahead from the front of the FIFO without removing any data.
* Limit the number of bytes peeked to the number of bytes available.
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - buffer to hold the peeked bytes
* @param length [in] - number of bytes to peek from the FIFO
* @return number of bytes peeked
*/
unsigned FIFO_Peek_Ahead(FIFO_BUFFER const *b, uint8_t* buffer, unsigned length)
{
unsigned count = 0;
unsigned index;
unsigned tail;
unsigned i;
if (b) {
count = FIFO_Count(b);
if (count > length) {
/* adjust to limit the number of bytes peeked */
count = length;
}
tail = b->tail;
for(i = 0; i < count; i++) {
index = tail % b->buffer_len;
buffer[i] = b->buffer[index];
tail++;
}
}
return count;
}
/** /**
* Gets a byte from the front of the FIFO, and removes it. * Gets a byte from the front of the FIFO, and removes it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is * Use FIFO_Empty() or FIFO_Available() function to see if there is
+6
View File
@@ -77,6 +77,12 @@ extern "C" {
uint8_t FIFO_Peek( uint8_t FIFO_Peek(
FIFO_BUFFER const *b); FIFO_BUFFER const *b);
BACNET_STACK_EXPORT
unsigned FIFO_Peek_Ahead(
FIFO_BUFFER const *b,
uint8_t* data_bytes,
unsigned length);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
uint8_t FIFO_Get( uint8_t FIFO_Get(
FIFO_BUFFER * b); FIFO_BUFFER * b);
+10
View File
@@ -35,6 +35,7 @@ static void testFIFOBuffer(void)
uint8_t test_data = 0; uint8_t test_data = 0;
unsigned index = 0; unsigned index = 0;
unsigned count = 0; unsigned count = 0;
unsigned test_count = 0;
bool status = 0; bool status = 0;
FIFO_Init(&test_buffer, data_store, sizeof(data_store)); FIFO_Init(&test_buffer, data_store, sizeof(data_store));
@@ -133,6 +134,15 @@ static void testFIFOBuffer(void)
zassert_false(FIFO_Empty(&test_buffer), NULL); zassert_false(FIFO_Empty(&test_buffer), NULL);
FIFO_Flush(&test_buffer); FIFO_Flush(&test_buffer);
zassert_true(FIFO_Empty(&test_buffer), NULL); zassert_true(FIFO_Empty(&test_buffer), NULL);
/* check the peak ahead feature */
status = FIFO_Add(&test_buffer, add_data, sizeof(add_data));
zassert_true(status, NULL);
count = FIFO_Count(&test_buffer);
test_count = FIFO_Peek_Ahead(&test_buffer, &test_add_data[0], count-1);
zassert_equal(count-1, test_count, NULL);
for (index = 0; index < test_count; index++) {
zassert_equal(test_add_data[index], add_data[index], NULL);
}
return; return;
} }