diff --git a/CMakeLists.txt b/CMakeLists.txt index d06c8923..41c25272 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1022,6 +1022,15 @@ if(BACNET_STACK_BUILD_APPS) ) endif() + if(BAC_ROUTING) + add_executable(gateway2 apps/gateway2/main.c apps/gateway2/gateway.h) + target_link_libraries(gateway2 PRIVATE ${PROJECT_NAME}) + target_compile_options(gateway2 PRIVATE + # Unreachable code because we have endless loop. + $<$:/wd4702> + ) + endif() + add_executable(getevent apps/getevent/main.c) target_link_libraries(getevent PRIVATE ${PROJECT_NAME}) diff --git a/Makefile b/Makefile index 8b252dde..10c03e5c 100644 --- a/Makefile +++ b/Makefile @@ -160,6 +160,14 @@ gateway: gateway-win32: $(MAKE) BACNET_PORT=win32 -s -B -C apps gateway +.PHONY: gateway2 +gateway2: + $(MAKE) -s -B -C apps $@ + +.PHONY: gateway2-win32 +gateway2-win32: + $(MAKE) BACNET_PORT=win32 -s -B -C apps gateway2 + .PHONY: piface piface: $(MAKE) CSTANDARD="-std=gnu11" LEGACY=true -s -C apps $@ @@ -543,6 +551,7 @@ clean: ports-clean $(MAKE) -s -C apps/router-ipv6 clean $(MAKE) -s -C apps/router-mstp clean $(MAKE) -s -C apps/gateway clean + $(MAKE) -s -C apps/gateway2 clean $(MAKE) -s -C apps/sc-hub clean $(MAKE) -s -C apps/fuzz-afl clean $(MAKE) -s -C apps/fuzz-libfuzzer clean diff --git a/apps/Makefile b/apps/Makefile index 2b74e947..bbd3bfa4 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -334,6 +334,10 @@ clean: gateway: $(BACNET_LIB_TARGET) $(MAKE) -B -C $@ +.PHONY: gateway2 +gateway2: $(BACNET_LIB_TARGET) + $(MAKE) -B -C $@ + .PHONY: abort abort: $(BACNET_LIB_TARGET) $(MAKE) -B -C $@ diff --git a/apps/gateway2/Makefile b/apps/gateway2/Makefile new file mode 100644 index 00000000..50540aba --- /dev/null +++ b/apps/gateway2/Makefile @@ -0,0 +1,97 @@ +#Makefile to build BACnet Application using GCC compiler + +# Executable file name +TARGET = bacgateway2 + +SRC := main.c + +BACNET_SRC_DIR ?= $(realpath ../../src) +BACNET_OBJECT_DIR = $(BACNET_SRC_DIR)/bacnet/basic/object + +BACNET_OBJECT_SRC := \ + $(BACNET_OBJECT_DIR)/gateway/gw_device.c \ + $(BACNET_OBJECT_DIR)/device.c \ + $(BACNET_OBJECT_DIR)/access_credential.c \ + $(BACNET_OBJECT_DIR)/access_door.c \ + $(BACNET_OBJECT_DIR)/access_point.c \ + $(BACNET_OBJECT_DIR)/access_rights.c \ + $(BACNET_OBJECT_DIR)/access_user.c \ + $(BACNET_OBJECT_DIR)/access_zone.c \ + $(BACNET_OBJECT_DIR)/ai.c \ + $(BACNET_OBJECT_DIR)/ao.c \ + $(BACNET_OBJECT_DIR)/av.c \ + $(BACNET_OBJECT_DIR)/acc.c \ + $(BACNET_OBJECT_DIR)/auditlog.c \ + $(BACNET_OBJECT_DIR)/bacfile.c \ + $(BACNET_OBJECT_DIR)/bi.c \ + $(BACNET_OBJECT_DIR)/bitstring_value.c \ + $(BACNET_OBJECT_DIR)/bo.c \ + $(BACNET_OBJECT_DIR)/blo.c \ + $(BACNET_OBJECT_DIR)/bv.c \ + $(BACNET_OBJECT_DIR)/calendar.c \ + $(BACNET_OBJECT_DIR)/channel.c \ + $(BACNET_OBJECT_DIR)/color_object.c \ + $(BACNET_OBJECT_DIR)/color_temperature.c \ + $(BACNET_OBJECT_DIR)/command.c \ + $(BACNET_OBJECT_DIR)/credential_data_input.c \ + $(BACNET_OBJECT_DIR)/csv.c \ + $(BACNET_OBJECT_DIR)/iv.c \ + $(BACNET_OBJECT_DIR)/lc.c \ + $(BACNET_OBJECT_DIR)/lo.c \ + $(BACNET_OBJECT_DIR)/loop.c \ + $(BACNET_OBJECT_DIR)/lsp.c \ + $(BACNET_OBJECT_DIR)/lsz.c \ + $(BACNET_OBJECT_DIR)/ms-input.c \ + $(BACNET_OBJECT_DIR)/mso.c \ + $(BACNET_OBJECT_DIR)/msv.c \ + $(BACNET_OBJECT_DIR)/nc.c \ + $(BACNET_OBJECT_DIR)/netport.c \ + $(BACNET_OBJECT_DIR)/osv.c \ + $(BACNET_OBJECT_DIR)/piv.c \ + $(BACNET_OBJECT_DIR)/program.c \ + $(BACNET_OBJECT_DIR)/schedule.c \ + $(BACNET_OBJECT_DIR)/structured_view.c \ + $(BACNET_OBJECT_DIR)/time_value.c \ + $(BACNET_OBJECT_DIR)/timer.c \ + $(BACNET_OBJECT_DIR)/trendlog.c + +BACNET_BASIC_SRC = \ + $(wildcard $(BACNET_SRC_DIR)/bacnet/basic/*.c) \ + $(wildcard $(BACNET_SRC_DIR)/bacnet/basic/binding/*.c) \ + $(wildcard $(BACNET_SRC_DIR)/bacnet/basic/sys/*.c) \ + $(BACNET_SRC_DIR)/bacnet/basic/npdu/h_routed_npdu.c \ + $(BACNET_SRC_DIR)/bacnet/basic/npdu/s_router.c \ + $(BACNET_SRC_DIR)/bacnet/basic/tsm/tsm.c \ + $(wildcard $(BACNET_SRC_DIR)/bacnet/basic/service/*.c) + +# TARGET_EXT is defined in apps/Makefile as .exe or nothing +TARGET_BIN = ${TARGET}$(TARGET_EXT) + +SRCS := $(SRC) $(BACNET_OBJECT_SRC) $(BACNET_BASIC_SRC) + +OBJS := $(SRCS:.c=.o) + +CFLAGS += -DBAC_ROUTING + +.PHONY: all +all: Makefile ${TARGET_BIN} + +${TARGET_BIN}: ${OBJS} + ${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@ + size $@ + cp $@ ../../bin + +.c.o: + ${CC} -c ${CFLAGS} $*.c -o $@ + +.PHONY: depend +depend: + rm -f .depend + ${CC} -MM ${CFLAGS} *.c >> .depend + +.PHONY: clean +clean: + rm -f core ${TARGET_BIN} ${OBJS} $(TARGET).map + +.PHONY: include +include: .depend diff --git a/apps/gateway2/gateway.h b/apps/gateway2/gateway.h new file mode 100644 index 00000000..6bac9722 --- /dev/null +++ b/apps/gateway2/gateway.h @@ -0,0 +1,42 @@ +/** + * @file + * @brief Header for example gateway (ie, BACnet Router and Devices) + * using the BACnet Stack. + * @author Tom Brennan + * @date 2010 + * @copyright SPDX-License-Identifier: MIT + */ +#ifndef BACNET_GATEWAY_H_ +#define BACNET_GATEWAY_H_ + +#include "bacnet/config.h" + +/** @defgroup GatewayDemo Demo of a BACnet virtual gateway (multiple Device). + * @ingroup Demos + * This is a basic demonstration of a BACnet Router with child devices (ie, + * gateway) appearing on a virtual BACnet network behind the Router. + * This is an extension of the ServerDemo project. + */ + +/* Device configuration definitions. */ +#define FIRST_DEVICE_NUMBER 260001 +#define VIRTUAL_DNET 2709 /* your choice of number here */ +#define DEV_NAME_BASE "Gateway Demo Device" +#define DEV_DESCR_GATEWAY "Gateway Device and Router" +#define DEV_DESCR_REMOTE "Routed Remote Device" +#define VIRTUAL_DEVICE_COUNT 10 +#define VIRTUAL_DEVICE_INDEX_OFFSET 1 + +#if VIRTUAL_DEVICE_COUNT >= MAX_NUM_DEVICES +#ifdef _MSC_VER +#pragma message( \ + "VIRTUAL_DEVICE_COUNT >= MAX_NUM_DEVICES, adjusting to MAX_NUM_DEVICES-1") +#else +#warning \ + "VIRTUAL_DEVICE_COUNT >= MAX_NUM_DEVICES, adjusting to MAX_NUM_DEVICES-1" +#endif +#undef VIRTUAL_DEVICE_COUNT +#define VIRTUAL_DEVICE_COUNT (MAX_NUM_DEVICES - 1) +#endif + +#endif diff --git a/apps/gateway2/main.c b/apps/gateway2/main.c new file mode 100644 index 00000000..98f7bb5f --- /dev/null +++ b/apps/gateway2/main.c @@ -0,0 +1,339 @@ +/** + * @file + * @brief Example virtual gateway application using the BACnet Stack. + * Code for this project began with code from the demo/server project and + * Paul Chapman's vmac project. + * @author Tom Brennan + * @author Hyeongjun Kim + * @date 2026 + * @copyright SPDX-License-Identifier: MIT + */ +#include +#include +#include +#include +#include +#include +#include +/* BACnet Stack defines - first */ +#include "bacnet/bacdef.h" +/* BACnet Stack API */ +#include "bacnet/bacdcode.h" +#include "bacnet/npdu.h" +#include "bacnet/apdu.h" +#include "bacnet/iam.h" +#include "bacnet/dcc.h" +#include "bacnet/version.h" +/* some demo stuff needed */ +#include "bacnet/basic/binding/address.h" +#include "bacnet/basic/tsm/tsm.h" +#include "bacnet/basic/services.h" +#include "bacnet/basic/sys/debug.h" +#include "bacnet/datalink/datalink.h" +#include "bacnet/datalink/dlenv.h" +/* include the device object */ +#include "bacnet/basic/object/device.h" +#include "bacnet/basic/object/bacfile.h" +#include "bacnet/basic/object/lc.h" +#include "bacnet/basic/object/ai.h" +#include "bacnet/basic/object/ao.h" +#ifdef BACNET_TEST_VMAC +#include "bacnet/basic/bbmd6/vmac.h" +#endif +/* me! */ +#include "gateway.h" + +/* Prototypes */ + +/* (Doxygen note: The next two lines pull all the following Javadoc + * into the GatewayDemo module.) */ +/** @addtogroup GatewayDemo */ +/*@{*/ + +/** Buffer used for receiving */ +static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; + +/** The list of DNETs that our router can reach. + * Only one entry since we don't support downstream routers. + */ +int DNET_list[2] = { + VIRTUAL_DNET, -1 /* Need -1 terminator */ +}; + +/* current version of the BACnet stack */ +static const char *BACnet_Version = BACNET_VERSION_TEXT; + +/* Virtual devices start at index 1 (gateway is at 0) */ +static unsigned Routed_Device_Index = 1; + +/** Initialize the Device Objects and each of the child Object instances. + * @param first_object_instance Set the first (gateway) Device to this + instance number, and subsequent devices to incremented values. + */ +static void Devices_Init(uint32_t first_object_instance) +{ + int i; + int dev_idx; + int instance_number = 0; + char nameText[MAX_DEV_NAME_LEN]; + char descText[MAX_DEV_DESC_LEN]; + BACNET_CHARACTER_STRING name_string; + + /* Gateway Device has already been initialized. + * But give it a better Description. */ + Routed_Device_Set_Description(DEV_DESCR_GATEWAY, strlen(DEV_DESCR_GATEWAY)); + + /* Gateway - analog_input */ + instance_number = 1000; + Analog_Input_Create(instance_number); + Analog_Input_Name_Set(instance_number, "Gateway Analog Input"); + Analog_Input_Present_Value_Set(instance_number, 100.0); + + /* Gateway - analog_onput */ + instance_number = 1001; + Analog_Output_Create(instance_number); + Analog_Output_Name_Set(instance_number, "Gateway Analog Output"); + + Analog_Output_Present_Value_Set(instance_number, 50.0, BACNET_MAX_PRIORITY); + + /* Now initialize the remote Device objects. */ + for (i = 0; i < VIRTUAL_DEVICE_COUNT; i++) { + dev_idx = i + 1; + snprintf( + nameText, MAX_DEV_NAME_LEN, "%s %d", DEV_NAME_BASE, dev_idx + 1); + snprintf( + descText, MAX_DEV_DESC_LEN, "%s %d", DEV_DESCR_REMOTE, dev_idx); + characterstring_init_ansi(&name_string, nameText); + + Add_Routed_Device( + (first_object_instance + dev_idx), &name_string, descText); + + /* Gateway - analog_input */ + instance_number = dev_idx * 10000 + 1000; + Analog_Input_Create(instance_number); + Analog_Input_Name_Set(instance_number, "Gateway Analog Input"); + Analog_Input_Present_Value_Set(instance_number, 0.1 + (float)dev_idx); + + /* Gateway - analog_onput */ + instance_number = dev_idx * 10000 + 1001; + Analog_Output_Create(instance_number); + Analog_Output_Name_Set(instance_number, "Gateway Analog Output"); + Analog_Output_Relinquish_Default_Set(instance_number, 100); + Analog_Output_Present_Value_Set( + instance_number, 0.9 + (float)i, BACNET_MAX_PRIORITY); + } +} + +/** Initialize the BACnet Device Addresses for each Device object. + * The gateway has already gotten the normal address (eg, PC's IP for BIP) and + * the remote devices get + * - For BIP, the IP address reversed, and 4th byte equal to index. + * (Eg, 11.22.33.44 for the gateway becomes 44.33.22.01 for the first remote + * device.) This is sure to be unique! The port number stays the same. + * - For MS/TP, [Steve inserts a good idea here] + */ +static void Initialize_Device_Addresses(void) +{ + int i = 0; /* First entry is Gateway Device */ + uint32_t virtual_mac = 0; + BACNET_ADDRESS virtual_address = { 0 }; + DEVICE_OBJECT_DATA *pDev = NULL; + /* Setup info for the main gateway device first */ + pDev = Get_Routed_Device_Object(i); + + /* we can't use datalink_get_my_address() since it is + mapped to routed_get_my_address() in this app + to get the parent device address */ +#if defined(BACDL_BIP) + bip_get_my_address(&virtual_address); +#elif defined(BACDL_MSTP) + dlmstp_get_my_address(&virtual_address); +#elif defined(BACDL_ARCNET) + arcnet_get_my_address(&virtual_address); +#elif defined(BACDL_ETHERNET) + ethernet_get_my_address(&virtual_address); +#elif defined(BACDL_BIP6) + bip6_get_my_address(&virtual_address); +#else +#error "No support for this Data Link Layer type " +#endif + bacnet_address_copy(&pDev->bacDevAddr, &virtual_address); + /* broadcast an I-Am on startup */ + Send_I_Am(&Handler_Transmit_Buffer[0]); + + /* Virtual devices start at index 1 (gateway is at 0) */ + for (i = 1; i < Get_Num_Managed_Devices(); i++) { + pDev = Get_Routed_Device_Object(i); + if (pDev == NULL) { + continue; + } + /* start with the router address */ + bacnet_address_copy(&pDev->bacDevAddr, &virtual_address); + /* add the network number to each gateway device */ + pDev->bacDevAddr.net = VIRTUAL_DNET; + /* use a virtual MAC for each gateway device */ + virtual_mac = pDev->bacObj.Object_Instance_Number; + encode_unsigned24(&pDev->bacDevAddr.adr[0], virtual_mac); + pDev->bacDevAddr.len = 3; + } +} + +/** Initialize the handlers we will utilize. + * @see Device_Init, apdu_set_unconfirmed_handler, apdu_set_confirmed_handler + */ +static void Init_Service_Handlers(uint32_t first_object_instance) +{ + Device_Init(NULL); + Routing_Device_Init(first_object_instance); + + /* we need to handle who-is to support dynamic device binding + * For the gateway, we will use the unicast variety so we can + * get back through switches to different subnets. + * Don't need the routed versions, since the npdu handler calls + * each device in turn. + */ + apdu_set_unconfirmed_handler( + SERVICE_UNCONFIRMED_WHO_IS, handler_who_is_unicast); + apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has); + /* set the handler for all the services we don't implement */ + /* It is required to send the proper reject message... */ + apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service); + /* Set the handlers for any confirmed services that we support. */ + /* We must implement read property - it's required! */ + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property); + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_READ_PROP_MULTIPLE, handler_read_property_multiple); + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_WRITE_PROPERTY, handler_write_property); + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_READ_RANGE, handler_read_range); +#if defined BACNET_BACKUP_RESTORE + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_ATOMIC_READ_FILE, handler_atomic_read_file); + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_ATOMIC_WRITE_FILE, handler_atomic_write_file); +#endif + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_REINITIALIZE_DEVICE, handler_reinitialize_device); + apdu_set_unconfirmed_handler( + SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, handler_timesync_utc); + apdu_set_unconfirmed_handler( + SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, handler_timesync); + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_SUBSCRIBE_COV, handler_cov_subscribe); + /* handle communication so we can shutup when asked */ + apdu_set_confirmed_handler( + SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, + handler_device_communication_control); +} + +/** Main function of server demo. + * + * @see Device_Set_Object_Instance_Number, dlenv_init, Send_I_Am, + * datalink_receive, npdu_handler, + * dcc_timer_seconds, datalink_maintenance_timer, + * handler_cov_task, tsm_timer_milliseconds + * + * @param argc [in] Arg count. + * @param argv [in] Takes one argument: the Device Instance #. + * @return 0 on success. + */ +int main(int argc, char *argv[]) +{ + BACNET_ADDRESS src = { 0 }; /* address where message came from */ + uint16_t pdu_len = 0; + unsigned timeout = 1; /* milliseconds */ + time_t last_seconds = 0; + time_t current_seconds = 0; + uint32_t elapsed_seconds = 0; + uint32_t elapsed_milliseconds = 0; + uint32_t first_object_instance = FIRST_DEVICE_NUMBER; +#ifdef BACNET_TEST_VMAC + /* Router data */ + BACNET_DEVICE_PROFILE *device; + BACNET_VMAC_ADDRESS adr; +#endif + + /* allow the device ID to be set */ + if (argc > 1) { + first_object_instance = strtol(argv[1], NULL, 0); + if ((first_object_instance == 0) || + (first_object_instance > BACNET_MAX_INSTANCE)) { + printf("Error: Invalid Object Instance %s \n", argv[1]); + printf( + "Provide a number from 1 to %lu \n", + (unsigned long)BACNET_MAX_INSTANCE); + exit(1); + } + } + printf( + "BACnet Router Demo\n" + "BACnet Stack Version %s\n" + "BACnet Device ID: %u\n" + "Max APDU: %d\n" + "Max Devices: %d\n" + "Virtual Devices Count: %d\n", + BACnet_Version, first_object_instance, MAX_APDU, MAX_NUM_DEVICES, + VIRTUAL_DEVICE_COUNT); + Init_Service_Handlers(first_object_instance); + dlenv_init(); + atexit(datalink_cleanup); + Devices_Init(first_object_instance); + Initialize_Device_Addresses(); + +#ifdef BACNET_TEST_VMAC + /* initialize vmac table and router device */ + device = vmac_initialize(99, 2001); + debug_printf(device->name, "ROUTER:%u", vmac_get_subnet()); +#endif + /* configure the timeout values */ + last_seconds = time(NULL); + + /* broadcast an I-am-router-to-network on startup */ + printf("Remote Network DNET Number %d \n", DNET_list[0]); + Send_I_Am_Router_To_Network(DNET_list); + Send_Network_Number_Is(NULL, DNET_list[0], NETWORK_NUMBER_CONFIGURED); + + handler_cov_init(); + + /* loop forever */ + for (;;) { + /* input */ + current_seconds = time(NULL); + + /* returns 0 bytes on timeout */ + pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); + + /* process */ + if (pdu_len) { + routing_npdu_handler(&src, DNET_list, &Rx_Buf[0], pdu_len); + } + /* at least one second has passed */ + elapsed_seconds = current_seconds - last_seconds; + if (elapsed_seconds) { + last_seconds = current_seconds; + dcc_timer_seconds(elapsed_seconds); + datalink_maintenance_timer(elapsed_seconds); + dlenv_maintenance_timer(elapsed_seconds); + elapsed_milliseconds = elapsed_seconds * 1000; + tsm_timer_milliseconds(elapsed_milliseconds); + Device_Timer(elapsed_milliseconds); + } + + handler_cov_task(); + + if (Routed_Device_Index < Get_Num_Managed_Devices()) { + Get_Routed_Device_Object(Routed_Device_Index); + /* broadcast an I-Am for each routed Device now */ + Send_I_Am(&Handler_Transmit_Buffer[0]); + Routed_Device_Index++; + } + } + /* Dummy return */ + return 0; +} + +/* @} */ + +/* End group GatewayDemo */ diff --git a/src/bacnet/basic/object/acc.c b/src/bacnet/basic/object/acc.c index 6ca19c4d..1ef6ed24 100644 --- a/src/bacnet/basic/object/acc.c +++ b/src/bacnet/basic/object/acc.c @@ -17,10 +17,18 @@ #include "bacnet/rp.h" #include "bacnet/wp.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" +/* me! */ #include "bacnet/basic/object/acc.h" /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List = NULL; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_ACCUMULATOR; diff --git a/src/bacnet/basic/object/access_credential.c b/src/bacnet/basic/object/access_credential.c index 7dcb6f3a..9b563c23 100644 --- a/src/bacnet/basic/object/access_credential.c +++ b/src/bacnet/basic/object/access_credential.c @@ -14,14 +14,23 @@ /* BACnet Stack API */ #include "bacnet/bacdcode.h" #include "bacnet/bacapp.h" +#include "bacnet/bacenum.h" #include "bacnet/wp.h" #include "bacnet/proplist.h" #include "bacnet/basic/object/access_credential.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" static bool Access_Credential_Initialized = false; -static ACCESS_CREDENTIAL_DESCR ac_descr[MAX_ACCESS_CREDENTIALS]; +static ACCESS_CREDENTIAL_DESCR ac_descrs[MAX_NUM_DEVICES] + [MAX_ACCESS_CREDENTIALS]; +#ifdef BAC_ROUTING +#define ac_descr (ac_descrs[Routed_Device_Object_Index()]) +#else +#define ac_descr (ac_descrs[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -90,24 +99,38 @@ void Access_Credential_Writable_Property_List( void Access_Credential_Init(void) { unsigned i; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif if (!Access_Credential_Initialized) { Access_Credential_Initialized = true; - - for (i = 0; i < MAX_ACCESS_CREDENTIALS; i++) { - ac_descr[i].global_identifier = - 0; /* set to some meaningful value */ - ac_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; - ac_descr[i].credential_status = false; - ac_descr[i].reasons_count = 0; - ac_descr[i].auth_factors_count = 0; - memset(&ac_descr[i].activation_time, 0, sizeof(BACNET_DATE_TIME)); - memset(&ac_descr[i].expiration_time, 0, sizeof(BACNET_DATE_TIME)); - ac_descr[i].credential_disable = ACCESS_CREDENTIAL_DISABLE_NONE; - ac_descr[i].assigned_access_rights_count = 0; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (i = 0; i < MAX_ACCESS_CREDENTIALS; i++) { + ac_descr[i].global_identifier = + 0; /* set to some meaningful value */ + ac_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; + ac_descr[i].credential_status = false; + ac_descr[i].reasons_count = 0; + ac_descr[i].auth_factors_count = 0; + memset( + &ac_descr[i].activation_time, 0, sizeof(BACNET_DATE_TIME)); + memset( + &ac_descr[i].expiration_time, 0, sizeof(BACNET_DATE_TIME)); + ac_descr[i].credential_disable = ACCESS_CREDENTIAL_DISABLE_NONE; + ac_descr[i].assigned_access_rights_count = 0; + } } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif + return; } diff --git a/src/bacnet/basic/object/access_door.c b/src/bacnet/basic/object/access_door.c index 249781ba..67e665f0 100644 --- a/src/bacnet/basic/object/access_door.c +++ b/src/bacnet/basic/object/access_door.c @@ -16,10 +16,17 @@ #include "bacnet/wp.h" #include "access_door.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" static bool Access_Door_Initialized = false; -static ACCESS_DOOR_DESCR ad_descr[MAX_ACCESS_DOORS]; +static ACCESS_DOOR_DESCR ad_descrs[MAX_NUM_DEVICES][MAX_ACCESS_DOORS]; +#ifdef BAC_ROUTING +#define ad_descr (ad_descrs[Routed_Device_Object_Index()]) +#else +#define ad_descr (ad_descrs[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -94,32 +101,45 @@ void Access_Door_Writable_Property_List( void Access_Door_Init(void) { unsigned i, j; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif if (!Access_Door_Initialized) { Access_Door_Initialized = true; - /* initialize all the access door priority arrays to NULL */ - for (i = 0; i < MAX_ACCESS_DOORS; i++) { - ad_descr[i].relinquish_default = DOOR_VALUE_LOCK; - ad_descr[i].event_state = EVENT_STATE_NORMAL; - ad_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; - ad_descr[i].out_of_service = false; - ad_descr[i].door_status = DOOR_STATUS_CLOSED; - ad_descr[i].lock_status = LOCK_STATUS_LOCKED; - ad_descr[i].secured_status = DOOR_SECURED_STATUS_SECURED; - ad_descr[i].door_pulse_time = 30; /* 3s */ - ad_descr[i].door_extended_pulse_time = 50; /* 5s */ - ad_descr[i].door_unlock_delay_time = 0; /* 0s */ - ad_descr[i].door_open_too_long_time = 300; /* 30s */ - ad_descr[i].door_alarm_state = DOOR_ALARM_STATE_NORMAL; - for (j = 0; j < BACNET_MAX_PRIORITY; j++) { - ad_descr[i].value_active[j] = false; - /* just to fill in */ - ad_descr[i].priority_array[j] = DOOR_VALUE_LOCK; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + /* initialize all the access door priority arrays to NULL */ + for (i = 0; i < MAX_ACCESS_DOORS; i++) { + ad_descr[i].relinquish_default = DOOR_VALUE_LOCK; + ad_descr[i].event_state = EVENT_STATE_NORMAL; + ad_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; + ad_descr[i].out_of_service = false; + ad_descr[i].door_status = DOOR_STATUS_CLOSED; + ad_descr[i].lock_status = LOCK_STATUS_LOCKED; + ad_descr[i].secured_status = DOOR_SECURED_STATUS_SECURED; + ad_descr[i].door_pulse_time = 30; /* 3s */ + ad_descr[i].door_extended_pulse_time = 50; /* 5s */ + ad_descr[i].door_unlock_delay_time = 0; /* 0s */ + ad_descr[i].door_open_too_long_time = 300; /* 30s */ + ad_descr[i].door_alarm_state = DOOR_ALARM_STATE_NORMAL; + for (j = 0; j < BACNET_MAX_PRIORITY; j++) { + ad_descr[i].value_active[j] = false; + /* just to fill in */ + ad_descr[i].priority_array[j] = DOOR_VALUE_LOCK; + } } } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif + return; } diff --git a/src/bacnet/basic/object/access_point.c b/src/bacnet/basic/object/access_point.c index 6c868a58..46394b2b 100644 --- a/src/bacnet/basic/object/access_point.c +++ b/src/bacnet/basic/object/access_point.c @@ -16,10 +16,17 @@ #include "bacnet/wp.h" #include "access_point.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" static bool Access_Point_Initialized = false; -static ACCESS_POINT_DESCR ap_descr[MAX_ACCESS_POINTS]; +static ACCESS_POINT_DESCR ap_descrs[MAX_NUM_DEVICES][MAX_ACCESS_POINTS]; +#ifdef BAC_ROUTING +#define ap_descr (ap_descrs[Routed_Device_Object_Index()]) +#else +#define ap_descr (ap_descrs[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -93,27 +100,43 @@ void Access_Point_Writable_Property_List( void Access_Point_Init(void) { unsigned i; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif if (!Access_Point_Initialized) { Access_Point_Initialized = true; - for (i = 0; i < MAX_ACCESS_POINTS; i++) { - ap_descr[i].event_state = EVENT_STATE_NORMAL; - ap_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; - ap_descr[i].out_of_service = false; - ap_descr[i].authentication_status = AUTHENTICATION_STATUS_NOT_READY; - ap_descr[i].active_authentication_policy = 0; - ap_descr[i].number_of_authentication_policies = 0; - ap_descr[i].authorization_mode = AUTHORIZATION_MODE_AUTHORIZE; - ap_descr[i].access_event = ACCESS_EVENT_NONE; - /* timestamp uninitialized */ - /* access_event_credential should be set to some meaningful value */ - ap_descr[i].num_doors = 0; - /* fill in the access doors with proper ids */ - ap_descr[i].priority_for_writing = 16; /* lowest possible for now */ + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (i = 0; i < MAX_ACCESS_POINTS; i++) { + ap_descr[i].event_state = EVENT_STATE_NORMAL; + ap_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; + ap_descr[i].out_of_service = false; + ap_descr[i].authentication_status = + AUTHENTICATION_STATUS_NOT_READY; + ap_descr[i].active_authentication_policy = 0; + ap_descr[i].number_of_authentication_policies = 0; + ap_descr[i].authorization_mode = AUTHORIZATION_MODE_AUTHORIZE; + ap_descr[i].access_event = ACCESS_EVENT_NONE; + /* timestamp uninitialized */ + /* access_event_credential should be set to some meaningful + * value */ + ap_descr[i].num_doors = 0; + /* fill in the access doors with proper ids */ + ap_descr[i].priority_for_writing = + 16; /* lowest possible for now */ + } } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif + return; } diff --git a/src/bacnet/basic/object/access_rights.c b/src/bacnet/basic/object/access_rights.c index f334ca80..69522a7b 100644 --- a/src/bacnet/basic/object/access_rights.c +++ b/src/bacnet/basic/object/access_rights.c @@ -17,12 +17,19 @@ #include "bacnet/proplist.h" #include "bacnet/wp.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "access_rights.h" static bool Access_Rights_Initialized = false; -static ACCESS_RIGHTS_DESCR ar_descr[MAX_ACCESS_RIGHTS]; +static ACCESS_RIGHTS_DESCR ar_descrs[MAX_NUM_DEVICES][MAX_ACCESS_RIGHTS]; +#ifdef BAC_ROUTING +#define ar_descr (ar_descrs[Routed_Device_Object_Index()]) +#else +#define ar_descr (ar_descrs[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -90,21 +97,35 @@ void Access_Rights_Writable_Property_List( void Access_Rights_Init(void) { unsigned i; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif if (!Access_Rights_Initialized) { Access_Rights_Initialized = true; - for (i = 0; i < MAX_ACCESS_RIGHTS; i++) { - ar_descr[i].global_identifier = - 0; /* set to some meaningful value */ - ar_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; - ar_descr[i].enable = false; - ar_descr[i].negative_access_rules_count = 0; - ar_descr[i].positive_access_rules_count = 0; - /* fill in the positive and negative access rules with proper ids */ + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (i = 0; i < MAX_ACCESS_RIGHTS; i++) { + ar_descr[i].global_identifier = + 0; /* set to some meaningful value */ + ar_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; + ar_descr[i].enable = false; + ar_descr[i].negative_access_rules_count = 0; + ar_descr[i].positive_access_rules_count = 0; + /* fill in the positive and negative access rules with proper + * ids */ + } } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif + return; } diff --git a/src/bacnet/basic/object/access_user.c b/src/bacnet/basic/object/access_user.c index ad8d2348..e01d1f12 100644 --- a/src/bacnet/basic/object/access_user.c +++ b/src/bacnet/basic/object/access_user.c @@ -17,10 +17,17 @@ #include "bacnet/wp.h" #include "access_user.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" static bool Access_User_Initialized = false; -static ACCESS_USER_DESCR au_descr[MAX_ACCESS_USERS]; +static ACCESS_USER_DESCR au_descrs[MAX_NUM_DEVICES][MAX_ACCESS_USERS]; +#ifdef BAC_ROUTING +#define au_descr (au_descrs[Routed_Device_Object_Index()]) +#else +#define au_descr (au_descrs[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -79,20 +86,33 @@ void Access_User_Writable_Property_List( void Access_User_Init(void) { unsigned i; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif if (!Access_User_Initialized) { Access_User_Initialized = true; - for (i = 0; i < MAX_ACCESS_USERS; i++) { - au_descr[i].global_identifier = - 0; /* set to some meaningful value */ - au_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; - au_descr[i].user_type = ACCESS_USER_TYPE_PERSON; - au_descr[i].credentials_count = 0; - /* fill in the credentials with proper ids */ + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (i = 0; i < MAX_ACCESS_USERS; i++) { + au_descr[i].global_identifier = + 0; /* set to some meaningful value */ + au_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; + au_descr[i].user_type = ACCESS_USER_TYPE_PERSON; + au_descr[i].credentials_count = 0; + /* fill in the credentials with proper ids */ + } } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif + return; } diff --git a/src/bacnet/basic/object/access_zone.c b/src/bacnet/basic/object/access_zone.c index 515b43b1..762b06f5 100644 --- a/src/bacnet/basic/object/access_zone.c +++ b/src/bacnet/basic/object/access_zone.c @@ -15,12 +15,19 @@ #include "bacnet/bacapp.h" #include "bacnet/wp.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "access_zone.h" static bool Access_Zone_Initialized = false; -static ACCESS_ZONE_DESCR az_descr[MAX_ACCESS_ZONES]; +static ACCESS_ZONE_DESCR az_descrs[MAX_NUM_DEVICES][MAX_ACCESS_ZONES]; +#ifdef BAC_ROUTING +#define az_descr (az_descrs[Routed_Device_Object_Index()]) +#else +#define az_descr (az_descrs[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -81,23 +88,37 @@ void Access_Zone_Writable_Property_List( void Access_Zone_Init(void) { unsigned i; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif if (!Access_Zone_Initialized) { Access_Zone_Initialized = true; - for (i = 0; i < MAX_ACCESS_ZONES; i++) { - az_descr[i].global_identifier = - 0; /* set to some meaningful value */ - az_descr[i].occupancy_state = ACCESS_ZONE_OCCUPANCY_STATE_DISABLED; - az_descr[i].event_state = EVENT_STATE_NORMAL; - az_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; - az_descr[i].out_of_service = false; - az_descr[i].entry_points_count = 0; - az_descr[i].exit_points_count = 0; - /* fill in the entry points and exit points with proper ids */ + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (i = 0; i < MAX_ACCESS_ZONES; i++) { + az_descr[i].global_identifier = + 0; /* set to some meaningful value */ + az_descr[i].occupancy_state = + ACCESS_ZONE_OCCUPANCY_STATE_DISABLED; + az_descr[i].event_state = EVENT_STATE_NORMAL; + az_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; + az_descr[i].out_of_service = false; + az_descr[i].entry_points_count = 0; + az_descr[i].exit_points_count = 0; + /* fill in the entry points and exit points with proper ids */ + } } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif + return; } diff --git a/src/bacnet/basic/object/ai.c b/src/bacnet/basic/object/ai.c index e88ead77..c8b6c646 100644 --- a/src/bacnet/basic/object/ai.c +++ b/src/bacnet/basic/object/ai.c @@ -22,11 +22,18 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/basic/sys/debug.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/ai.h" /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_ANALOG_INPUT; @@ -2138,17 +2145,30 @@ bool Analog_Input_Delete(uint32_t object_instance) void Analog_Input_Cleanup(void) { struct analog_input_descr *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -2156,9 +2176,23 @@ void Analog_Input_Cleanup(void) */ void Analog_Input_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif #if defined(INTRINSIC_REPORTING) /* Set handler for GetEventInformation function */ handler_get_event_information_set( diff --git a/src/bacnet/basic/object/ao.c b/src/bacnet/basic/object/ao.c index ed4be266..2cbd2d17 100644 --- a/src/bacnet/basic/object/ao.c +++ b/src/bacnet/basic/object/ao.c @@ -28,6 +28,8 @@ #include "bacnet/wp.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "ao.h" @@ -49,7 +51,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_ANALOG_OUTPUT; /* callback for present value writes */ @@ -1399,17 +1406,30 @@ bool Analog_Output_Delete(uint32_t object_instance) void Analog_Output_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1417,7 +1437,21 @@ void Analog_Output_Cleanup(void) */ void Analog_Output_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/auditlog.c b/src/bacnet/basic/object/auditlog.c index 609fa3f8..2a8c21b5 100644 --- a/src/bacnet/basic/object/auditlog.c +++ b/src/bacnet/basic/object/auditlog.c @@ -88,6 +88,8 @@ #include "bacnet/wp.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "auditlog.h" @@ -106,7 +108,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif static const int32_t Properties_Required[] = { /* required properties that are supported for this object */ @@ -1519,18 +1526,31 @@ bool Audit_Log_Delete(uint32_t object_instance) void Audit_Log_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - Audit_Log_Records_Cleanup(pObject->Records); - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + Audit_Log_Records_Cleanup(pObject->Records); + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1538,7 +1558,21 @@ void Audit_Log_Cleanup(void) */ void Audit_Log_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/av.c b/src/bacnet/basic/object/av.c index 3d4d8256..48b38856 100644 --- a/src/bacnet/basic/object/av.c +++ b/src/bacnet/basic/object/av.c @@ -25,11 +25,18 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/basic/sys/debug.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/av.h" /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_ANALOG_VALUE; /* callback for present value writes */ @@ -1897,17 +1904,30 @@ bool Analog_Value_Delete(uint32_t object_instance) void Analog_Value_Cleanup(void) { struct analog_value_descr *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1915,9 +1935,23 @@ void Analog_Value_Cleanup(void) */ void Analog_Value_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif #if defined(INTRINSIC_REPORTING) /* Set handler for GetEventInformation function */ handler_get_event_information_set( diff --git a/src/bacnet/basic/object/bacfile.c b/src/bacnet/basic/object/bacfile.c index bf917997..a69b83d1 100644 --- a/src/bacnet/basic/object/bacfile.c +++ b/src/bacnet/basic/object/bacfile.c @@ -28,6 +28,8 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/basic/tsm/tsm.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" struct object_data { char *Object_Name; @@ -40,7 +42,12 @@ struct object_data { bool Archive : 1; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_FILE; /* These three arrays are used by the ReadPropertyMultiple handler */ @@ -1315,20 +1322,33 @@ bool bacfile_delete(uint32_t object_instance) void bacfile_cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject->Pathname); - free(pObject->File_Type); - free(pObject->Object_Name); - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject->Pathname); + free(pObject->File_Type); + free(pObject->Object_Name); + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1336,7 +1356,21 @@ void bacfile_cleanup(void) */ void bacfile_init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/bi.c b/src/bacnet/basic/object/bi.c index deef5595..e4b32515 100644 --- a/src/bacnet/basic/object/bi.c +++ b/src/bacnet/basic/object/bi.c @@ -27,6 +27,8 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/basic/sys/debug.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/bi.h" @@ -61,7 +63,12 @@ struct object_data { #endif }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_BINARY_INPUT; /* callback for present value writes */ @@ -1424,17 +1431,30 @@ uint32_t Binary_Input_Create(uint32_t object_instance) void Binary_Input_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1461,9 +1481,23 @@ bool Binary_Input_Delete(uint32_t object_instance) */ void Binary_Input_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** diff --git a/src/bacnet/basic/object/bitstring_value.c b/src/bacnet/basic/object/bitstring_value.c index 21dec29d..b626ae83 100644 --- a/src/bacnet/basic/object/bitstring_value.c +++ b/src/bacnet/basic/object/bitstring_value.c @@ -22,6 +22,8 @@ #include "bacnet/wp.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bitstring_value.h" @@ -36,7 +38,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* callback for present value writes */ static bitstring_value_write_present_value_callback BitString_Value_Write_Present_Value_Callback; @@ -920,17 +927,30 @@ bool BitString_Value_Delete(uint32_t object_instance) void BitString_Value_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -938,7 +958,21 @@ void BitString_Value_Cleanup(void) */ void BitString_Value_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/blo.c b/src/bacnet/basic/object/blo.c index 77858b47..1a0a5b7d 100644 --- a/src/bacnet/basic/object/blo.c +++ b/src/bacnet/basic/object/blo.c @@ -21,6 +21,8 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/proplist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/blo.h" @@ -51,7 +53,12 @@ struct object_data { bool Polarity : 1; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* callback for present value writes */ static binary_lighting_output_write_value_callback Binary_Lighting_Output_Write_Value_Callback; @@ -1656,17 +1663,30 @@ bool Binary_Lighting_Output_Delete(uint32_t object_instance) void Binary_Lighting_Output_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1674,7 +1694,21 @@ void Binary_Lighting_Output_Cleanup(void) */ void Binary_Lighting_Output_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/bo.c b/src/bacnet/basic/object/bo.c index 23657fe9..70b0fb98 100644 --- a/src/bacnet/basic/object/bo.c +++ b/src/bacnet/basic/object/bo.c @@ -29,6 +29,8 @@ #include "bacnet/wp.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bo.h" @@ -49,7 +51,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_BINARY_OUTPUT; /* callback for present value writes */ @@ -1354,17 +1361,30 @@ uint32_t Binary_Output_Create(uint32_t object_instance) void Binary_Output_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1389,7 +1409,21 @@ bool Binary_Output_Delete(uint32_t object_instance) */ void Binary_Output_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/bv.c b/src/bacnet/basic/object/bv.c index 4b120824..295ad12d 100644 --- a/src/bacnet/basic/object/bv.c +++ b/src/bacnet/basic/object/bv.c @@ -60,7 +60,12 @@ struct object_data { #endif }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_BINARY_VALUE; /* callback for present value writes */ @@ -1328,17 +1333,30 @@ uint32_t Binary_Value_Create(uint32_t object_instance) void Binary_Value_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1363,9 +1381,23 @@ bool Binary_Value_Delete(uint32_t object_instance) */ void Binary_Value_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** diff --git a/src/bacnet/basic/object/calendar.c b/src/bacnet/basic/object/calendar.c index 7d16a637..3f800fb0 100644 --- a/src/bacnet/basic/object/calendar.c +++ b/src/bacnet/basic/object/calendar.c @@ -30,6 +30,8 @@ #include "bacnet/wp.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "calendar.h" @@ -43,7 +45,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* callback for present value writes */ static calendar_write_present_value_callback Calendar_Write_Present_Value_Callback; @@ -802,19 +809,32 @@ bool Calendar_Delete(uint32_t object_instance) void Calendar_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - Calendar_Date_List_Clean(pObject->Date_List); - Keylist_Delete(pObject->Date_List); - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + Calendar_Date_List_Clean(pObject->Date_List); + Keylist_Delete(pObject->Date_List); + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -822,7 +842,21 @@ void Calendar_Cleanup(void) */ void Calendar_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/channel.c b/src/bacnet/basic/object/channel.c index 30151bea..b490b5de 100644 --- a/src/bacnet/basic/object/channel.c +++ b/src/bacnet/basic/object/channel.c @@ -26,6 +26,8 @@ #if defined(CHANNEL_LIGHTING_COMMAND) || defined(CHANNEL_COLOR_COMMAND) #include "bacnet/lighting.h" #endif +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/channel.h" @@ -51,7 +53,12 @@ struct object_data { }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* Internal write property callback */ static write_property_function Write_Property_Internal_Callback; /* Write Property notification callbacks for logging or other purposes */ @@ -1567,17 +1574,30 @@ bool Channel_Delete(uint32_t object_instance) void Channel_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1585,7 +1605,21 @@ void Channel_Cleanup(void) */ void Channel_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/color_object.c b/src/bacnet/basic/object/color_object.c index 66a9f3fd..c98c630c 100644 --- a/src/bacnet/basic/object/color_object.c +++ b/src/bacnet/basic/object/color_object.c @@ -58,7 +58,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* callback for present value writes */ static color_write_present_value_callback Color_Write_Present_Value_Callback; @@ -1275,17 +1280,30 @@ bool Color_Delete(uint32_t object_instance) void Color_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1293,7 +1311,21 @@ void Color_Cleanup(void) */ void Color_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/color_temperature.c b/src/bacnet/basic/object/color_temperature.c index 2e051d1d..be36f907 100644 --- a/src/bacnet/basic/object/color_temperature.c +++ b/src/bacnet/basic/object/color_temperature.c @@ -29,6 +29,8 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/basic/sys/linear.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "color_temperature.h" @@ -51,7 +53,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* callback for present value writes */ static color_temperature_write_present_value_callback Color_Temperature_Write_Present_Value_Callback; @@ -1725,17 +1732,30 @@ bool Color_Temperature_Delete(uint32_t object_instance) void Color_Temperature_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1743,7 +1763,21 @@ void Color_Temperature_Cleanup(void) */ void Color_Temperature_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/command.c b/src/bacnet/basic/object/command.c index f7dbe05b..00c208a5 100644 --- a/src/bacnet/basic/object/command.c +++ b/src/bacnet/basic/object/command.c @@ -28,10 +28,17 @@ #include "bacnet/proplist.h" #include "bacnet/timestamp.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me!*/ #include "bacnet/basic/object/command.h" -static COMMAND_DESCR Command_Descr[MAX_COMMANDS]; +static COMMAND_DESCR Command_Descrs[MAX_NUM_DEVICES][MAX_COMMANDS]; +#ifdef BAC_ROUTING +#define Command_Descr (Command_Descrs[Routed_Device_Object_Index()]) +#else +#define Command_Descr (Command_Descrs[0]) +#endif /* These arrays are used by the ReadPropertyMultiple handler */ static const int32_t Command_Properties_Required[] = { @@ -107,12 +114,27 @@ void Command_Writable_Property_List( */ void Command_Init(void) { + uint16_t dev_id; unsigned i; - for (i = 0; i < MAX_COMMANDS; i++) { - Command_Descr[i].Present_Value = 0; - Command_Descr[i].In_Process = false; - Command_Descr[i].All_Writes_Successful = true; /* Optimistic default */ +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (i = 0; i < MAX_COMMANDS; i++) { + Command_Descr[i].Present_Value = 0; + Command_Descr[i].In_Process = false; + Command_Descr[i].All_Writes_Successful = + true; /* Optimistic default */ + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** diff --git a/src/bacnet/basic/object/credential_data_input.c b/src/bacnet/basic/object/credential_data_input.c index 3db6fb60..c2869abe 100644 --- a/src/bacnet/basic/object/credential_data_input.c +++ b/src/bacnet/basic/object/credential_data_input.c @@ -16,12 +16,20 @@ #include "bacnet/bacapp.h" #include "bacnet/wp.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/credential_data_input.h" static bool Credential_Data_Input_Initialized = false; -static CREDENTIAL_DATA_INPUT_DESCR cdi_descr[MAX_CREDENTIAL_DATA_INPUTS]; +static CREDENTIAL_DATA_INPUT_DESCR cdi_descrs[MAX_NUM_DEVICES] + [MAX_CREDENTIAL_DATA_INPUTS]; +#ifdef BAC_ROUTING +#define cdi_descr (cdi_descrs[Routed_Device_Object_Index()]) +#else +#define cdi_descr (cdi_descrs[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -93,25 +101,37 @@ void Credential_Data_Input_Writable_Property_List( */ void Credential_Data_Input_Init(void) { + uint16_t dev_id; unsigned i; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif if (!Credential_Data_Input_Initialized) { Credential_Data_Input_Initialized = true; - for (i = 0; i < MAX_CREDENTIAL_DATA_INPUTS; i++) { - /* there should be a meaningful setup for present value */ - cdi_descr[i].present_value.format_type = - AUTHENTICATION_FACTOR_UNDEFINED; - cdi_descr[i].present_value.format_class = 0; - octetstring_init(&cdi_descr[i].present_value.value, NULL, 0); - cdi_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; - cdi_descr[i].out_of_service = false; - /* set supported formats */ - cdi_descr[i].supported_formats_count = 0; - /* timestamp uninitialized */ + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (i = 0; i < MAX_CREDENTIAL_DATA_INPUTS; i++) { + /* there should be a meaningful setup for present value */ + cdi_descr[i].present_value.format_type = + AUTHENTICATION_FACTOR_UNDEFINED; + cdi_descr[i].present_value.format_class = 0; + octetstring_init(&cdi_descr[i].present_value.value, NULL, 0); + cdi_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; + cdi_descr[i].out_of_service = false; + /* set supported formats */ + cdi_descr[i].supported_formats_count = 0; + /* timestamp uninitialized */ + } } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif return; } diff --git a/src/bacnet/basic/object/csv.c b/src/bacnet/basic/object/csv.c index b1f17805..857f1773 100644 --- a/src/bacnet/basic/object/csv.c +++ b/src/bacnet/basic/object/csv.c @@ -21,9 +21,16 @@ #include "bacnet/basic/object/csv.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List = NULL; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_CHARACTERSTRING_VALUE; @@ -207,18 +214,31 @@ bool CharacterString_Value_Delete(uint32_t object_instance) */ void CharacterString_Value_Cleanup(void) { - struct object_data *pObject = NULL; + struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -237,9 +257,23 @@ CharacterString_Value_Object(uint32_t object_instance) */ void CharacterString_Value_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** diff --git a/src/bacnet/basic/object/device.c b/src/bacnet/basic/object/device.c index 91fdeff6..2854b34e 100644 --- a/src/bacnet/basic/object/device.c +++ b/src/bacnet/basic/object/device.c @@ -3942,12 +3942,31 @@ void Device_local_reporting(void) BACNET_OBJECT_TYPE object_type = OBJECT_NONE; uint32_t idx = 0; +/* loop for all objects */ +#ifdef BAC_ROUTING + uint16_t dev_id = 0; + uint16_t current_dev_id = Routed_Device_Object_Index(); + for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) { + Set_Routed_Device_Object_Index(dev_id); + objects_count = Device_Object_List_Count(); + for (idx = 1; idx <= objects_count; idx++) { + Device_Object_List_Identifier(idx, &object_type, &object_instance); + pObject = Device_Object_Functions_Find(object_type); + if (pObject != NULL) { + if (pObject->Object_Valid_Instance && + pObject->Object_Valid_Instance(object_instance)) { + if (pObject->Object_Intrinsic_Reporting) { + pObject->Object_Intrinsic_Reporting(object_instance); + } + } + } + } + } + Set_Routed_Device_Object_Index(current_dev_id); +#else objects_count = Device_Object_List_Count(); - - /* loop for all objects */ for (idx = 1; idx <= objects_count; idx++) { Device_Object_List_Identifier(idx, &object_type, &object_instance); - pObject = Device_Object_Functions_Find(object_type); if (pObject != NULL) { if (pObject->Object_Valid_Instance && @@ -3958,6 +3977,7 @@ void Device_local_reporting(void) } } } +#endif } #endif @@ -4090,6 +4110,45 @@ void Device_Timer(uint16_t milliseconds) unsigned count = 0; uint32_t instance; +#ifdef BAC_ROUTING + uint16_t dev_id = 0; + uint16_t current_dev_id = Routed_Device_Object_Index(); + /* TODO: Multi-device Backup/Restore support + * Currently only Gateway (dev_id=0) supports Backup/Restore. + * Virtual devices are blocked by Routed_Device_Service_Approval(). + * Plan to support after discussing with maintainer. + * + * To enable per-device Backup/Restore: + * 1. Move Backup-related static variables to DEVICE_OBJECT_DATA: + * - Backup_State, Backup_Failure_Timeout_Milliseconds + * - Backup_Failure_Timeout, Configuration_Files[] + * - Last_Restore_Time, Backup/Restore_Preparation_Time + * 2. Modify Routed_Device_Service_Approval() to allow RD on virtual devices + * 3. Call Device_Backup_Failure_Timeout_Countdown() inside the for loop + * for each device + */ + Device_Backup_Failure_Timeout_Countdown(milliseconds); + for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) { + Set_Routed_Device_Object_Index(dev_id); + pObject = Object_Table; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + count = 0; + if (pObject->Object_Count) { + count = pObject->Object_Count(); + } + while (count) { + count--; + if ((pObject->Object_Timer) && + (pObject->Object_Index_To_Instance)) { + instance = pObject->Object_Index_To_Instance(count); + pObject->Object_Timer(instance, milliseconds); + } + } + pObject++; + } + } + Set_Routed_Device_Object_Index(current_dev_id); +#else Device_Backup_Failure_Timeout_Countdown(milliseconds); pObject = Object_Table; while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { @@ -4107,6 +4166,7 @@ void Device_Timer(uint16_t milliseconds) } pObject++; } +#endif } #ifdef BAC_ROUTING diff --git a/src/bacnet/basic/object/device.h b/src/bacnet/basic/object/device.h index 09a7dcfd..27e9f60d 100644 --- a/src/bacnet/basic/object/device.h +++ b/src/bacnet/basic/object/device.h @@ -536,6 +536,13 @@ int Routed_Device_Service_Approval( uint8_t *apdu_buff, uint8_t invoke_id); +BACNET_STACK_EXPORT +uint16_t Routed_Device_Object_Index(void); +BACNET_STACK_EXPORT +bool Set_Routed_Device_Object_Index(uint16_t idx); +BACNET_STACK_EXPORT +uint16_t Get_Num_Managed_Devices(void); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/bacnet/basic/object/gateway/gw_device.c b/src/bacnet/basic/object/gateway/gw_device.c index 13a94546..fca270eb 100644 --- a/src/bacnet/basic/object/gateway/gw_device.c +++ b/src/bacnet/basic/object/gateway/gw_device.c @@ -40,6 +40,7 @@ #include "bacnet/basic/object/bacfile.h" /* os specific includes */ #include "bacnet/basic/sys/mstimer.h" +#include "bacnet/basic/sys/debug.h" /* forward prototypes */ int Routed_Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata); @@ -74,6 +75,43 @@ uint16_t Num_Managed_Devices = 0; */ uint16_t iCurrent_Device_Idx = 0; +/** Get the current routed device object index. + * @return Index of the currently active routed device in Devices[] array + */ +uint16_t Routed_Device_Object_Index(void) +{ + return iCurrent_Device_Idx; +} + +/** Get the number of managed devices. + * @return Number of devices currently managed (including gateway) + */ +uint16_t Get_Num_Managed_Devices(void) +{ + return Num_Managed_Devices; +} + +/** Set the current routed device object index. + * @param idx [in] Index of the routed device to set as current + * @return true if index is valid and set, false if index exceeds + * MAX_NUM_DEVICES + */ +bool Set_Routed_Device_Object_Index(uint16_t idx) +{ + if (idx >= MAX_NUM_DEVICES) { + debug_fprintf( + stderr, + "Set_Routed_Device_Object_Index: idx(%u) >= MAX_NUM_DEVICES(%u)\n", + (unsigned)idx, (unsigned)MAX_NUM_DEVICES); + + return false; + } + + iCurrent_Device_Idx = idx; + + return true; +} + /* void Routing_Device_Init(uint32_t first_object_instance) is * found in device.c */ diff --git a/src/bacnet/basic/object/iv.c b/src/bacnet/basic/object/iv.c index 4ea40d71..a7466dbc 100644 --- a/src/bacnet/basic/object/iv.c +++ b/src/bacnet/basic/object/iv.c @@ -29,7 +29,12 @@ #include "bacnet/basic/object/iv.h" /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List = NULL; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_INTEGER_VALUE; /* callback for present value writes */ @@ -855,19 +860,31 @@ bool Integer_Value_Delete(uint32_t object_instance) */ void Integer_Value_Cleanup(void) { - if (Object_List) { - struct integer_object *pObject; + struct integer_object *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -875,7 +892,21 @@ void Integer_Value_Cleanup(void) */ void Integer_Value_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/lc.c b/src/bacnet/basic/object/lc.c index 24845d0b..60695801 100644 --- a/src/bacnet/basic/object/lc.c +++ b/src/bacnet/basic/object/lc.c @@ -23,6 +23,8 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/debug.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* from Table 12-33. Requested_Shed_Level Default Values and Power Targets */ #define DEFAULT_VALUE_PERCENT 100 @@ -97,7 +99,12 @@ struct object_data { const char *Description; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Load_Control_Properties_Required[] = { @@ -2227,17 +2234,30 @@ bool Load_Control_Delete(uint32_t object_instance) void Load_Control_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -2245,7 +2265,21 @@ void Load_Control_Cleanup(void) */ void Load_Control_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/lo.c b/src/bacnet/basic/object/lo.c index 3eb7ba88..f22df622 100644 --- a/src/bacnet/basic/object/lo.c +++ b/src/bacnet/basic/object/lo.c @@ -26,6 +26,8 @@ #include "bacnet/basic/sys/lighting_command.h" #include "bacnet/bactext.h" #include "bacnet/proplist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/lo.h" @@ -59,7 +61,12 @@ struct object_data { bool Color_Override : 1; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* callback for present value writes */ static lighting_command_tracking_value_callback Lighting_Command_Tracking_Value_Callback; @@ -3920,17 +3927,30 @@ bool Lighting_Output_Delete(uint32_t object_instance) void Lighting_Output_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -3938,7 +3958,21 @@ void Lighting_Output_Cleanup(void) */ void Lighting_Output_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/loop.c b/src/bacnet/basic/object/loop.c index e25ba60a..d0ed0150 100644 --- a/src/bacnet/basic/object/loop.c +++ b/src/bacnet/basic/object/loop.c @@ -34,7 +34,12 @@ #include "bacnet/basic/object/loop.h" /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List = NULL; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_LOOP; /* handling for manipulated and reference properties */ @@ -2315,18 +2320,30 @@ bool Loop_Delete(uint32_t object_instance) void Loop_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -2342,7 +2359,21 @@ size_t Loop_Size(void) */ void Loop_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/lsp.c b/src/bacnet/basic/object/lsp.c index f93a7174..a9a799f4 100644 --- a/src/bacnet/basic/object/lsp.c +++ b/src/bacnet/basic/object/lsp.c @@ -16,10 +16,13 @@ #include "bacnet/bacapp.h" #include "bacnet/rp.h" #include "bacnet/wp.h" -#include "bacnet/basic/object/lsp.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/proplist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" +/* me! */ +#include "bacnet/basic/object/lsp.h" struct object_data { bool Out_Of_Service : 1; @@ -33,7 +36,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_LIFE_SAFETY_POINT; @@ -799,17 +807,30 @@ bool Life_Safety_Point_Delete(uint32_t object_instance) void Life_Safety_Point_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -817,7 +838,21 @@ void Life_Safety_Point_Cleanup(void) */ void Life_Safety_Point_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/lsz.c b/src/bacnet/basic/object/lsz.c index a94a3400..fe69e314 100644 --- a/src/bacnet/basic/object/lsz.c +++ b/src/bacnet/basic/object/lsz.c @@ -26,6 +26,8 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/proplist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/lsz.h" @@ -43,7 +45,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_LIFE_SAFETY_ZONE; @@ -985,17 +992,30 @@ bool Life_Safety_Zone_Delete(uint32_t object_instance) void Life_Safety_Zone_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1003,7 +1023,21 @@ void Life_Safety_Zone_Cleanup(void) */ void Life_Safety_Zone_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/ms-input.c b/src/bacnet/basic/object/ms-input.c index fb237395..f575c42f 100644 --- a/src/bacnet/basic/object/ms-input.c +++ b/src/bacnet/basic/object/ms-input.c @@ -20,6 +20,8 @@ #include "bacnet/wp.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/ms-input.h" @@ -36,7 +38,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_MULTI_STATE_INPUT; /* callback for present value writes */ @@ -1082,17 +1089,30 @@ bool Multistate_Input_Delete(uint32_t object_instance) void Multistate_Input_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1100,7 +1120,21 @@ void Multistate_Input_Cleanup(void) */ void Multistate_Input_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/mso.c b/src/bacnet/basic/object/mso.c index af879f05..49f5634e 100644 --- a/src/bacnet/basic/object/mso.c +++ b/src/bacnet/basic/object/mso.c @@ -28,6 +28,8 @@ #include "bacnet/proplist.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "mso.h" @@ -45,7 +47,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_MULTI_STATE_OUTPUT; /* callback for present value writes */ @@ -1380,17 +1387,30 @@ bool Multistate_Output_Delete(uint32_t object_instance) void Multistate_Output_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1398,7 +1418,21 @@ void Multistate_Output_Cleanup(void) */ void Multistate_Output_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/msv.c b/src/bacnet/basic/object/msv.c index 8b4b0291..d6d9a45e 100644 --- a/src/bacnet/basic/object/msv.c +++ b/src/bacnet/basic/object/msv.c @@ -20,6 +20,8 @@ #include "bacnet/wp.h" #include "bacnet/basic/sys/keylist.h" #include "bacnet/basic/services.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "bacnet/basic/object/msv.h" @@ -36,7 +38,12 @@ struct object_data { void *Context; }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_MULTI_STATE_VALUE; /* callback for present value writes */ @@ -1083,17 +1090,30 @@ bool Multistate_Value_Delete(uint32_t object_instance) void Multistate_Value_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1101,7 +1121,21 @@ void Multistate_Value_Cleanup(void) */ void Multistate_Value_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/nc.c b/src/bacnet/basic/object/nc.c index 57f3a110..f98d9235 100644 --- a/src/bacnet/basic/object/nc.c +++ b/src/bacnet/basic/object/nc.c @@ -34,7 +34,13 @@ #endif #if defined(INTRINSIC_REPORTING) -static NOTIFICATION_CLASS_INFO NC_Info[MAX_NOTIFICATION_CLASSES]; +static NOTIFICATION_CLASS_INFO NC_Infos[MAX_NUM_DEVICES] + [MAX_NOTIFICATION_CLASSES]; +#ifdef BAC_ROUTING +#define NC_Info (NC_Infos[Routed_Device_Object_Index()]) +#else +#define NC_Info (NC_Infos[0]) +#endif /* buffer for sending event messages */ static uint8_t Event_Buffer[MAX_APDU]; @@ -119,25 +125,38 @@ static void Notification_Class_I_Am_Router_To_Network_Handler( void Notification_Class_Init(void) { + uint16_t dev_id; uint8_t NotifyIdx = 0; unsigned i; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - for (NotifyIdx = 0; NotifyIdx < MAX_NOTIFICATION_CLASSES; NotifyIdx++) { - /* init with zeros */ - memset(&NC_Info[NotifyIdx], 0x00, sizeof(NOTIFICATION_CLASS_INFO)); - /* set the basic parameters */ - NC_Info[NotifyIdx].Ack_Required = 0; - /* The lowest priority for Normal message = 255 */ - NC_Info[NotifyIdx].Priority[TRANSITION_TO_OFFNORMAL] = 255; - NC_Info[NotifyIdx].Priority[TRANSITION_TO_FAULT] = 255; - NC_Info[NotifyIdx].Priority[TRANSITION_TO_NORMAL] = 255; - /* note: default uses wildcard device destination */ - for (i = 0; i < NC_MAX_RECIPIENTS; i++) { - BACNET_DESTINATION *destination; - destination = &NC_Info[NotifyIdx].Recipient_List[i]; - bacnet_destination_default_init(destination); + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (NotifyIdx = 0; NotifyIdx < MAX_NOTIFICATION_CLASSES; NotifyIdx++) { + /* init with zeros */ + memset(&NC_Info[NotifyIdx], 0x00, sizeof(NOTIFICATION_CLASS_INFO)); + /* set the basic parameters */ + NC_Info[NotifyIdx].Ack_Required = 0; + /* The lowest priority for Normal message = 255 */ + NC_Info[NotifyIdx].Priority[TRANSITION_TO_OFFNORMAL] = 255; + NC_Info[NotifyIdx].Priority[TRANSITION_TO_FAULT] = 255; + NC_Info[NotifyIdx].Priority[TRANSITION_TO_NORMAL] = 255; + /* note: default uses wildcard device destination */ + for (i = 0; i < NC_MAX_RECIPIENTS; i++) { + BACNET_DESTINATION *destination; + destination = &NC_Info[NotifyIdx].Recipient_List[i]; + bacnet_destination_default_init(destination); + } } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif npdu_set_i_am_router_to_network_handler( Notification_Class_I_Am_Router_To_Network_Handler); diff --git a/src/bacnet/basic/object/netport.c b/src/bacnet/basic/object/netport.c index 9e6ff8ac..1997261c 100644 --- a/src/bacnet/basic/object/netport.c +++ b/src/bacnet/basic/object/netport.c @@ -25,6 +25,7 @@ #include "bacnet/datalink/bvlc6.h" #include "bacnet/datalink/datalink.h" #include "bacnet/basic/binding/address.h" +/* BACnet Stack Objects */ #include "bacnet/basic/object/device.h" /* me */ #include "bacnet/basic/object/netport.h" @@ -129,7 +130,13 @@ struct object_data { #define BACNET_NETWORK_PORTS_MAX 1 #endif -static struct object_data Object_List[BACNET_NETWORK_PORTS_MAX]; +static struct object_data Object_Lists[MAX_NUM_DEVICES] + [BACNET_NETWORK_PORTS_MAX]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* BACnetARRAY of REAL, is an array of the link speeds supported by this network port */ @@ -4833,13 +4840,27 @@ void Network_Port_Cleanup(void) { #if defined(BACDL_BSC) && defined(BACNET_SECURE_CONNECT_ROUTING_TABLE) unsigned index = 0; - for (index = 0; index < BACNET_NETWORK_PORTS_MAX; index++) { - BACNET_SC_PARAMS *sc = &Object_List[index].Network.BSC.Parameters; - if (sc->Routing_Table) { - Keylist_Delete(sc->Routing_Table); - sc->Routing_Table = NULL; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (index = 0; index < BACNET_NETWORK_PORTS_MAX; index++) { + BACNET_SC_PARAMS *sc = &Object_List[index].Network.BSC.Parameters; + if (sc->Routing_Table) { + Keylist_Delete(sc->Routing_Table); + sc->Routing_Table = NULL; + } } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif #endif } @@ -4881,35 +4902,46 @@ void Network_Port_Context_Set(uint32_t object_instance, void *context) void Network_Port_Init(void) { unsigned index = 0; + uint16_t dev_id = 0; +#ifdef BAC_ROUTING + const uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif #ifdef BACDL_BSC BACNET_SC_PARAMS *sc; #endif /* BACDL_BSC */ /* do something interesting */ - - for (index = 0; index < BACNET_NETWORK_PORTS_MAX; index++) { - memset(&Object_List[index], 0, sizeof(Object_List[index])); -#ifdef BACDL_BSC - Object_List[index].Network_Type = PORT_TYPE_BSC; - sc = &Object_List[index].Network.BSC.Parameters; - Object_List[index].Activate_Changes = - Network_Port_SC_Pending_Params_Apply; - Object_List[index].Discard_Changes = - Network_Port_SC_Pending_Params_Discard; -#ifdef BACNET_SECURE_CONNECT_ROUTING_TABLE - sc->Routing_Table = Keylist_Create(); + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); #endif - sc->SC_Failed_Connection_Requests_Count = 0; + for (index = 0; index < BACNET_NETWORK_PORTS_MAX; index++) { + memset(&Object_List[index], 0, sizeof(Object_List[index])); +#ifdef BACDL_BSC + Object_List[index].Network_Type = PORT_TYPE_BSC; + sc = &Object_List[index].Network.BSC.Parameters; + Object_List[index].Activate_Changes = + Network_Port_SC_Pending_Params_Apply; + Object_List[index].Discard_Changes = + Network_Port_SC_Pending_Params_Discard; +#ifdef BACNET_SECURE_CONNECT_ROUTING_TABLE + sc->Routing_Table = Keylist_Create(); +#endif + sc->SC_Failed_Connection_Requests_Count = 0; #if BSC_CONF_HUB_FUNCTIONS_NUM != 0 - sc->SC_Hub_Function_Connection_Status_Count = 0; + sc->SC_Hub_Function_Connection_Status_Count = 0; #endif #if BSC_CONF_HUB_CONNECTORS_NUM != 0 - sc->SC_Direct_Connect_Connection_Status_Count = 0; + sc->SC_Direct_Connect_Connection_Status_Count = 0; #endif - (void)sc; + (void)sc; #endif /* BACDL_BSC */ + } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } #ifdef BACDL_BSC diff --git a/src/bacnet/basic/object/osv.c b/src/bacnet/basic/object/osv.c index 0dbdae6a..713d4029 100644 --- a/src/bacnet/basic/object/osv.c +++ b/src/bacnet/basic/object/osv.c @@ -31,7 +31,12 @@ struct object_data { }; /* Key List for storing object data sorted by instance number */ -static OS_Keylist Object_List = NULL; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -167,12 +172,24 @@ bool OctetString_Value_Delete(uint32_t object_instance) void OctetString_Value_Init(void) { #ifdef MAX_OCTETSTRING_VALUES +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); + unsigned i = 0; + uint16_t dev_id; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { + Set_Routed_Device_Object_Index(dev_id); + for (i = 0; i < MAX_OCTETSTRING_VALUES; i++) { + OctetString_Value_Create(i); + } + } + Set_Routed_Device_Object_Index(current_dev_id); +#else unsigned i = 0; - for (i = 0; i < MAX_OCTETSTRING_VALUES; i++) { OctetString_Value_Create(i); } #endif +#endif } /** diff --git a/src/bacnet/basic/object/piv.c b/src/bacnet/basic/object/piv.c index 3f728ff1..91530444 100644 --- a/src/bacnet/basic/object/piv.c +++ b/src/bacnet/basic/object/piv.c @@ -22,7 +22,12 @@ #include "bacnet/basic/object/piv.h" /* Key List for storing object data sorted by instance number */ -static OS_Keylist Object_List = NULL; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_POSITIVE_INTEGER_VALUE; @@ -171,8 +176,22 @@ bool PositiveInteger_Value_Delete(uint32_t object_instance) void PositiveInteger_Value_Init(void) { #ifdef MAX_POSITIVEINTEGER_VALUES +#ifdef BAC_ROUTING + unsigned i = 0; + uint16_t dev_id; + uint16_t current_dev_id = Routed_Device_Object_Index(); + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { + Set_Routed_Device_Object_Index(dev_id); + if (!Object_List) { + Object_List = Keylist_Create(); + } + for (i = 0; i < MAX_POSITIVEINTEGER_VALUES; i++) { + PositiveInteger_Value_Create(i); + } + } + Set_Routed_Device_Object_Index(current_dev_id); +#else unsigned i = 0; - if (!Object_List) { Object_List = Keylist_Create(); } @@ -180,6 +199,7 @@ void PositiveInteger_Value_Init(void) PositiveInteger_Value_Create(i); } #endif +#endif } /** diff --git a/src/bacnet/basic/object/program.c b/src/bacnet/basic/object/program.c index cf020ac4..1fbe69e4 100644 --- a/src/bacnet/basic/object/program.c +++ b/src/bacnet/basic/object/program.c @@ -30,7 +30,12 @@ #include "bacnet/basic/object/program.h" /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List = NULL; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_PROGRAM; @@ -1426,18 +1431,30 @@ bool Program_Delete(uint32_t object_instance) void Program_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1445,7 +1462,21 @@ void Program_Cleanup(void) */ void Program_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/schedule.c b/src/bacnet/basic/object/schedule.c index 13140033..3b74ed16 100644 --- a/src/bacnet/basic/object/schedule.c +++ b/src/bacnet/basic/object/schedule.c @@ -25,7 +25,12 @@ #define MAX_SCHEDULES 4 #endif -static SCHEDULE_DESCR Schedule_Descr[MAX_SCHEDULES]; +static SCHEDULE_DESCR Schedule_Descrs[MAX_NUM_DEVICES][MAX_SCHEDULES]; +#ifdef BAC_ROUTING +#define Schedule_Descr (Schedule_Descrs[Routed_Device_Object_Index()]) +#else +#define Schedule_Descr (Schedule_Descrs[0]) +#endif static const int32_t Schedule_Properties_Required[] = { /* list of required properties */ @@ -134,6 +139,7 @@ SCHEDULE_DESCR *Schedule_Object(uint32_t object_instance) */ void Schedule_Init(void) { + uint16_t dev_id; unsigned i, j; BACNET_DATE start_date = { 0 }, end_date = { 0 }; SCHEDULE_DESCR *psched; @@ -141,6 +147,9 @@ void Schedule_Init(void) unsigned e; BACNET_SPECIAL_EVENT *event; #endif +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif /* whole year, change as necessary */ datetime_set_date(&start_date, 0, 1, 1); @@ -149,38 +158,49 @@ void Schedule_Init(void) datetime_set_date(&end_date, 0, 12, 31); datetime_wildcard_year_set(&end_date); datetime_wildcard_weekday_set(&end_date); - for (i = 0; i < MAX_SCHEDULES; i++, psched++) { - psched = &Schedule_Descr[i]; - datetime_copy_date(&psched->Start_Date, &start_date); - datetime_copy_date(&psched->End_Date, &end_date); - for (j = 0; j < BACNET_WEEKLY_SCHEDULE_SIZE; j++) { - psched->Weekly_Schedule[j].TV_Count = 0; - } - memcpy( - &psched->Present_Value, &psched->Schedule_Default, - sizeof(psched->Present_Value)); - psched->Schedule_Default.context_specific = false; - psched->Schedule_Default.tag = BACNET_APPLICATION_TAG_REAL; - psched->Schedule_Default.type.Real = 21.0f; /* 21 C, room temperature */ - psched->obj_prop_ref_cnt = 0; /* no references, add as needed */ - psched->Priority_For_Writing = 16; /* lowest priority */ - psched->Out_Of_Service = false; -#if BACNET_EXCEPTION_SCHEDULE_SIZE - for (e = 0; e < BACNET_EXCEPTION_SCHEDULE_SIZE; e++) { - event = &psched->Exception_Schedule[e]; - event->periodTag = BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY; - event->period.calendarEntry.tag = BACNET_CALENDAR_DATE_RANGE; - datetime_copy_date( - &event->period.calendarEntry.type.DateRange.startdate, - &start_date); - datetime_copy_date( - &event->period.calendarEntry.type.DateRange.enddate, &end_date); - event->period.calendarEntry.next = NULL; - event->timeValues.TV_Count = 0; - event->priority = 16; - } + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); #endif + for (i = 0; i < MAX_SCHEDULES; i++) { + psched = &Schedule_Descr[i]; + datetime_copy_date(&psched->Start_Date, &start_date); + datetime_copy_date(&psched->End_Date, &end_date); + for (j = 0; j < BACNET_WEEKLY_SCHEDULE_SIZE; j++) { + psched->Weekly_Schedule[j].TV_Count = 0; + } + memcpy( + &psched->Present_Value, &psched->Schedule_Default, + sizeof(psched->Present_Value)); + psched->Schedule_Default.context_specific = false; + psched->Schedule_Default.tag = BACNET_APPLICATION_TAG_REAL; + psched->Schedule_Default.type.Real = + 21.0f; /* 21 C, room temperature */ + psched->obj_prop_ref_cnt = 0; /* no references, add as needed */ + psched->Priority_For_Writing = 16; /* lowest priority */ + psched->Out_Of_Service = false; +#if BACNET_EXCEPTION_SCHEDULE_SIZE + for (e = 0; e < BACNET_EXCEPTION_SCHEDULE_SIZE; e++) { + event = &psched->Exception_Schedule[e]; + event->periodTag = BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY; + event->period.calendarEntry.tag = BACNET_CALENDAR_DATE_RANGE; + datetime_copy_date( + &event->period.calendarEntry.type.DateRange.startdate, + &start_date); + datetime_copy_date( + &event->period.calendarEntry.type.DateRange.enddate, + &end_date); + event->period.calendarEntry.next = NULL; + event->timeValues.TV_Count = 0; + event->priority = 16; + } +#endif + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** diff --git a/src/bacnet/basic/object/structured_view.c b/src/bacnet/basic/object/structured_view.c index b5ddef43..45b7d8d8 100644 --- a/src/bacnet/basic/object/structured_view.c +++ b/src/bacnet/basic/object/structured_view.c @@ -21,6 +21,8 @@ #include "bacnet/proplist.h" #include "bacnet/rp.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "structured_view.h" @@ -36,7 +38,12 @@ struct object_data { }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -1844,15 +1851,28 @@ bool Structured_View_Delete(uint32_t object_instance) void Structured_View_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - Structured_View_Object_Free(pObject); - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + Structured_View_Object_Free(pObject); + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -1868,7 +1888,21 @@ size_t Structured_View_Size(void) */ void Structured_View_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/time_value.c b/src/bacnet/basic/object/time_value.c index ed0c45a1..8efb4bf4 100644 --- a/src/bacnet/basic/object/time_value.c +++ b/src/bacnet/basic/object/time_value.c @@ -30,6 +30,8 @@ #include "bacnet/wp.h" #include "bacnet/basic/services.h" #include "bacnet/basic/sys/keylist.h" +/* BACnet Stack Objects */ +#include "bacnet/basic/object/device.h" /* me! */ #include "time_value.h" @@ -44,7 +46,12 @@ struct object_data { }; /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* callback for present value writes */ static time_value_write_present_value_callback Time_Value_Write_Present_Value_Callback; @@ -891,17 +898,30 @@ bool Time_Value_Delete(uint32_t object_instance) void Time_Value_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -909,7 +929,21 @@ void Time_Value_Cleanup(void) */ void Time_Value_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/timer.c b/src/bacnet/basic/object/timer.c index 80cb05b5..7ee187de 100644 --- a/src/bacnet/basic/object/timer.c +++ b/src/bacnet/basic/object/timer.c @@ -35,7 +35,12 @@ #endif /* Key List for storing the object data sorted by instance number */ -static OS_Keylist Object_List = NULL; +static OS_Keylist Object_Lists[MAX_NUM_DEVICES]; +#ifdef BAC_ROUTING +#define Object_List (Object_Lists[Routed_Device_Object_Index()]) +#else +#define Object_List (Object_Lists[0]) +#endif /* common object type */ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_TIMER; static write_property_function Write_Property_Internal_Callback; @@ -2386,18 +2391,30 @@ bool Timer_Delete(uint32_t object_instance) void Timer_Cleanup(void) { struct object_data *pObject; + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif - if (Object_List) { - do { - pObject = Keylist_Data_Pop(Object_List); - if (pObject) { - free(pObject); - } - } while (pObject); - - Keylist_Delete(Object_List); - Object_List = NULL; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (Object_List) { + do { + pObject = Keylist_Data_Pop(Object_List); + if (pObject) { + free(pObject); + } + } while (pObject); + Keylist_Delete(Object_List); + Object_List = NULL; + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } /** @@ -2405,7 +2422,21 @@ void Timer_Cleanup(void) */ void Timer_Init(void) { - if (!Object_List) { - Object_List = Keylist_Create(); + uint16_t dev_id; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif + + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + if (!Object_List) { + Object_List = Keylist_Create(); + } } + +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif } diff --git a/src/bacnet/basic/object/trendlog.c b/src/bacnet/basic/object/trendlog.c index 72e7b540..892e8854 100644 --- a/src/bacnet/basic/object/trendlog.c +++ b/src/bacnet/basic/object/trendlog.c @@ -30,8 +30,19 @@ #define MAX_TREND_LOGS 8 #endif -static TL_DATA_REC Logs[MAX_TREND_LOGS][TL_MAX_ENTRIES]; -static TL_LOG_INFO LogInfo[MAX_TREND_LOGS]; +static TL_DATA_REC Logs_Records[MAX_NUM_DEVICES][MAX_TREND_LOGS] + [TL_MAX_ENTRIES]; +#ifdef BAC_ROUTING +#define Logs (Logs_Records[Routed_Device_Object_Index()]) +#else +#define Logs (Logs_Records[0]) +#endif +static TL_LOG_INFO LogInfos[MAX_NUM_DEVICES][MAX_TREND_LOGS]; +#ifdef BAC_ROUTING +#define LogInfo (LogInfos[Routed_Device_Object_Index()]) +#else +#define LogInfo (LogInfos[0]) +#endif /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Trend_Log_Properties_Required[] = { @@ -195,85 +206,98 @@ static bacnet_time_t Trend_Log_Epoch_Seconds_Now(void) void Trend_Log_Init(void) { static bool initialized = false; + uint16_t dev_id; int iLog; int iEntry; BACNET_DATE_TIME bdatetime = { 0 }; bacnet_time_t tClock; uint8_t month; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); +#endif if (!initialized) { initialized = true; /* initialize all the values */ - for (iLog = 0; iLog < MAX_TREND_LOGS; iLog++) { - /* - * Do we need to do anything here? - * Trend logs are usually assumed to survive over resets - * and are frequently implemented using Battery Backed RAM - * If they are implemented using Flash or SD cards or some - * such mechanism there may be some RAM based setup needed - * for log management purposes. - * We probably need to look at inserting LOG_INTERRUPTED - * entries into any active logs if the power down or reset - * may have caused us to miss readings. - */ + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(dev_id); +#endif + for (iLog = 0; iLog < MAX_TREND_LOGS; iLog++) { + /* + * Do we need to do anything here? + * Trend logs are usually assumed to survive over resets + * and are frequently implemented using Battery Backed RAM + * If they are implemented using Flash or SD cards or some + * such mechanism there may be some RAM based setup needed + * for log management purposes. + * We probably need to look at inserting LOG_INTERRUPTED + * entries into any active logs if the power down or reset + * may have caused us to miss readings. + */ - /* We will just fill the logs with some entries for testing - * purposes. - */ - /* Different month for each log */ - month = iLog + 1; - datetime_set_values(&bdatetime, 2009, month, 1, 0, 0, 0, 0); - tClock = datetime_seconds_since_epoch(&bdatetime); - for (iEntry = 0; iEntry < TL_MAX_ENTRIES; iEntry++) { - Logs[iLog][iEntry].tTimeStamp = tClock; - Logs[iLog][iEntry].ucRecType = TL_TYPE_REAL; - Logs[iLog][iEntry].Datum.fReal = - (float)(iEntry + (iLog * TL_MAX_ENTRIES)); - /* Put status flags with every second log */ - if ((iLog & 1) == 0) { - Logs[iLog][iEntry].ucStatus = 128; - } else { - Logs[iLog][iEntry].ucStatus = 0; + /* We will just fill the logs with some entries for testing + * purposes. + */ + /* Different month for each log */ + month = iLog + 1; + datetime_set_values(&bdatetime, 2009, month, 1, 0, 0, 0, 0); + tClock = datetime_seconds_since_epoch(&bdatetime); + for (iEntry = 0; iEntry < TL_MAX_ENTRIES; iEntry++) { + Logs[iLog][iEntry].tTimeStamp = tClock; + Logs[iLog][iEntry].ucRecType = TL_TYPE_REAL; + Logs[iLog][iEntry].Datum.fReal = + (float)(iEntry + (iLog * TL_MAX_ENTRIES)); + /* Put status flags with every second log */ + if ((iLog & 1) == 0) { + Logs[iLog][iEntry].ucStatus = 128; + } else { + Logs[iLog][iEntry].ucStatus = 0; + } + /* advance 15 minutes, in seconds */ + tClock += 900; } - /* advance 15 minutes, in seconds */ - tClock += 900; + + LogInfo[iLog].tLastDataTime = tClock - 900; + LogInfo[iLog].bAlignIntervals = true; + LogInfo[iLog].bEnable = true; + LogInfo[iLog].bStopWhenFull = false; + LogInfo[iLog].bTrigger = false; + LogInfo[iLog].LoggingType = LOGGING_TYPE_POLLED; + LogInfo[iLog].Source.arrayIndex = 0; + LogInfo[iLog].ucTimeFlags = 0; + LogInfo[iLog].ulIntervalOffset = 0; + LogInfo[iLog].iIndex = 0; + LogInfo[iLog].ulLogInterval = 900; + LogInfo[iLog].ulRecordCount = TL_MAX_ENTRIES; + LogInfo[iLog].ulTotalRecordCount = 10000; + + LogInfo[iLog].Source.deviceIdentifier.instance = + Device_Object_Instance_Number(); + LogInfo[iLog].Source.deviceIdentifier.type = OBJECT_DEVICE; + LogInfo[iLog].Source.objectIdentifier.instance = iLog; + LogInfo[iLog].Source.objectIdentifier.type = + OBJECT_ANALOG_INPUT; + LogInfo[iLog].Source.arrayIndex = BACNET_ARRAY_ALL; + LogInfo[iLog].Source.propertyIdentifier = PROP_PRESENT_VALUE; + + datetime_set_values( + &LogInfo[iLog].StartTime, 2009, 1, 1, 0, 0, 0, 0); + LogInfo[iLog].tStartTime = + TL_BAC_Time_To_Local(&LogInfo[iLog].StartTime); + datetime_set_values( + &LogInfo[iLog].StopTime, 2020, 12, 22, 23, 59, 59, 99); + LogInfo[iLog].tStopTime = + TL_BAC_Time_To_Local(&LogInfo[iLog].StopTime); } - - LogInfo[iLog].tLastDataTime = tClock - 900; - LogInfo[iLog].bAlignIntervals = true; - LogInfo[iLog].bEnable = true; - LogInfo[iLog].bStopWhenFull = false; - LogInfo[iLog].bTrigger = false; - LogInfo[iLog].LoggingType = LOGGING_TYPE_POLLED; - LogInfo[iLog].Source.arrayIndex = 0; - LogInfo[iLog].ucTimeFlags = 0; - LogInfo[iLog].ulIntervalOffset = 0; - LogInfo[iLog].iIndex = 0; - LogInfo[iLog].ulLogInterval = 900; - LogInfo[iLog].ulRecordCount = TL_MAX_ENTRIES; - LogInfo[iLog].ulTotalRecordCount = 10000; - - LogInfo[iLog].Source.deviceIdentifier.instance = - Device_Object_Instance_Number(); - LogInfo[iLog].Source.deviceIdentifier.type = OBJECT_DEVICE; - LogInfo[iLog].Source.objectIdentifier.instance = iLog; - LogInfo[iLog].Source.objectIdentifier.type = OBJECT_ANALOG_INPUT; - LogInfo[iLog].Source.arrayIndex = BACNET_ARRAY_ALL; - LogInfo[iLog].Source.propertyIdentifier = PROP_PRESENT_VALUE; - - datetime_set_values( - &LogInfo[iLog].StartTime, 2009, 1, 1, 0, 0, 0, 0); - LogInfo[iLog].tStartTime = - TL_BAC_Time_To_Local(&LogInfo[iLog].StartTime); - datetime_set_values( - &LogInfo[iLog].StopTime, 2020, 12, 22, 23, 59, 59, 99); - LogInfo[iLog].tStopTime = - TL_BAC_Time_To_Local(&LogInfo[iLog].StopTime); } } +#ifdef BAC_ROUTING + Set_Routed_Device_Object_Index(current_dev_id); +#endif return; } diff --git a/src/bacnet/basic/service/h_cov.c b/src/bacnet/basic/service/h_cov.c index 03fee5d7..6ef0c7c8 100644 --- a/src/bacnet/basic/service/h_cov.c +++ b/src/bacnet/basic/service/h_cov.c @@ -60,7 +60,14 @@ typedef struct BACnet_COV_Subscription { #ifndef MAX_COV_SUBCRIPTIONS #define MAX_COV_SUBCRIPTIONS 128 #endif -static BACNET_COV_SUBSCRIPTION COV_Subscriptions[MAX_COV_SUBCRIPTIONS]; + +static BACNET_COV_SUBSCRIPTION COV_Subscriptions_List[MAX_NUM_DEVICES] + [MAX_COV_SUBCRIPTIONS]; +#ifdef BAC_ROUTING +#define COV_Subscriptions (COV_Subscriptions_List[Routed_Device_Object_Index()]) +#else +#define COV_Subscriptions (COV_Subscriptions_List[0]) +#endif #ifndef MAX_COV_ADDRESSES #define MAX_COV_ADDRESSES 16 #endif @@ -97,6 +104,32 @@ static void cov_address_remove_unused(void) unsigned cov_index = 0; bool found = false; +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); + uint16_t dev_id = 0; + for (cov_index = 0; cov_index < MAX_COV_ADDRESSES; cov_index++) { + if (COV_Addresses[cov_index].valid) { + found = false; + for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) { + Set_Routed_Device_Object_Index(dev_id); + for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { + if ((COV_Subscriptions[index].flag.valid) && + (COV_Subscriptions[index].dest_index == cov_index)) { + found = true; + break; + } + } + if (found) { + break; + } + } + if (!found) { + COV_Addresses[cov_index].valid = false; + } + } + } + Set_Routed_Device_Object_Index(current_dev_id); +#else for (cov_index = 0; cov_index < MAX_COV_ADDRESSES; cov_index++) { if (COV_Addresses[cov_index].valid) { found = false; @@ -112,6 +145,7 @@ static void cov_address_remove_unused(void) } } } +#endif } /** @@ -320,7 +354,27 @@ int handler_cov_encode_subscriptions(uint8_t *apdu, int max_apdu) void handler_cov_init(void) { unsigned index = 0; - +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); + uint16_t dev_id = 0; + for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { + Set_Routed_Device_Object_Index(dev_id); + for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { + /* initialize with invalid COV address */ + COV_Subscriptions[index].flag.valid = false; + COV_Subscriptions[index].dest_index = MAX_COV_ADDRESSES; + COV_Subscriptions[index].subscriberProcessIdentifier = 0; + COV_Subscriptions[index].monitoredObjectIdentifier.type = + OBJECT_ANALOG_INPUT; + COV_Subscriptions[index].monitoredObjectIdentifier.instance = 0; + COV_Subscriptions[index].flag.issueConfirmedNotifications = false; + COV_Subscriptions[index].invokeID = 0; + COV_Subscriptions[index].lifetime = 0; + COV_Subscriptions[index].flag.send_requested = false; + } + } + Set_Routed_Device_Object_Index(current_dev_id); +#else for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { /* initialize with invalid COV address */ COV_Subscriptions[index].flag.valid = false; @@ -334,6 +388,7 @@ void handler_cov_init(void) COV_Subscriptions[index].lifetime = 0; COV_Subscriptions[index].flag.send_requested = false; } +#endif for (index = 0; index < MAX_COV_ADDRESSES; index++) { COV_Addresses[index].valid = false; } @@ -587,7 +642,27 @@ void handler_cov_timer_seconds(uint32_t elapsed_seconds) { unsigned index = 0; uint32_t lifetime_seconds = 0; - +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); + uint16_t dev_id = 0; + if (elapsed_seconds) { + /* handle the subscription timeouts */ + for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) { + Set_Routed_Device_Object_Index(dev_id); + for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { + if (COV_Subscriptions[index].flag.valid) { + lifetime_seconds = COV_Subscriptions[index].lifetime; + if (lifetime_seconds) { + /* only expire COV with definite lifetimes */ + cov_lifetime_expiration_handler( + index, elapsed_seconds, lifetime_seconds); + } + } + } + } + } + Set_Routed_Device_Object_Index(current_dev_id); +#else if (elapsed_seconds) { /* handle the subscription timeouts */ for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { @@ -601,24 +676,38 @@ void handler_cov_timer_seconds(uint32_t elapsed_seconds) } } } +#endif } bool handler_cov_fsm(void) { - static int index = 0; + static int indices[MAX_NUM_DEVICES] = { 0 }; +#ifdef BAC_ROUTING + const int dev_id = Routed_Device_Object_Index(); +#else + const int dev_id = 0; +#endif + BACNET_OBJECT_TYPE object_type = MAX_BACNET_OBJECT_TYPE; uint32_t object_instance = 0; bool status = false; bool send = false; BACNET_PROPERTY_VALUE value_list[MAX_COV_PROPERTIES] = { 0 }; + /* states for transmitting */ - static enum { + typedef enum cov_fsm_state { COV_STATE_IDLE = 0, COV_STATE_MARK, COV_STATE_CLEAR, COV_STATE_FREE, COV_STATE_SEND - } cov_task_state = COV_STATE_IDLE; + } cov_fsm_state_t; + static cov_fsm_state_t cov_task_states[MAX_NUM_DEVICES] = { + COV_STATE_IDLE + }; + + int index = indices[dev_id]; + cov_fsm_state_t cov_task_state = cov_task_states[dev_id]; switch (cov_task_state) { case COV_STATE_IDLE: @@ -735,12 +824,26 @@ bool handler_cov_fsm(void) cov_task_state = COV_STATE_IDLE; break; } + + indices[dev_id] = index; + cov_task_states[dev_id] = cov_task_state; + return (cov_task_state == COV_STATE_IDLE); } void handler_cov_task(void) { +#ifdef BAC_ROUTING + uint16_t current_dev_id = Routed_Device_Object_Index(); + uint16_t dev_id = 0; + for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) { + Set_Routed_Device_Object_Index(dev_id); + handler_cov_fsm(); + } + Set_Routed_Device_Object_Index(current_dev_id); +#else handler_cov_fsm(); +#endif } static bool cov_subscribe( diff --git a/src/bacnet/npdu.c b/src/bacnet/npdu.c index 6bfb0845..45fc2e42 100644 --- a/src/bacnet/npdu.c +++ b/src/bacnet/npdu.c @@ -15,6 +15,12 @@ #include "bacnet/bacint.h" #include "bacnet/npdu.h" #include "bacnet/apdu.h" +/* BACnet routing support */ +#ifdef BAC_ROUTING +#include "bacnet/basic/sys/debug.h" +#include "bacnet/basic/object/device.h" +#include "bacnet/datalink/datalink.h" +#endif /** Copy the npdu_data structure information from src to dest. * @param dest [out] The 'to' structure @@ -35,6 +41,42 @@ void npdu_copy_data(BACNET_NPDU_DATA *dest, const BACNET_NPDU_DATA *src) return; } +#ifdef BAC_ROUTING +/** Encode NPDU source address for routing. + * Sets the source address based on whether this is a virtual device + * or a gateway device. + * @param src [out] Pointer to store the source address + * @return 0 on success, -1 if device object not found + */ +static int npdu_encode_pdu_routing(BACNET_ADDRESS *src) +{ + DEVICE_OBJECT_DATA *pDev = NULL; + bool is_routed_device = false; + /* get the currently active routed device object */ + pDev = Get_Routed_Device_Object(-1); + if (pDev == NULL) { + debug_fprintf(stderr, "Device object not found\n"); + return -1; + } + + is_routed_device = (pDev->bacDevAddr.net != 0); + + if (is_routed_device) { + bacnet_address_copy(src, &pDev->bacDevAddr); + debug_fprintf( + stdout, "Virtual Device NPDU: SNET=%d, Instance=%u\n", + pDev->bacDevAddr.net, pDev->bacObj.Object_Instance_Number); + } else { + datalink_get_my_address(src); + debug_fprintf( + stdout, "Gateway Device NPDU: Instance=%u\n", + pDev->bacObj.Object_Instance_Number); + } + + return 0; +} +#endif + /* The following ICI parameters are exchanged with the @@ -87,10 +129,12 @@ ABORT.indication Yes Yes Yes No * @param dest [in] The routing destination information if the message must * be routed to reach its destination. If dest->net and dest->len are 0, * there is no routing destination information. - * @param src [in] The routing source information if the message was routed + * @param src [in,out] The routing source information if the message was routed * from another BACnet network. If src->net and src->len are 0, there is no * routing source information. This src describes the original source of the * message when it had to be routed to reach this BACnet Device. + * @note When BAC_ROUTING is defined, src is populated with the active routed + * device or datalink address before encoding. * @param npdu_data [in] The structure which describes how the NCPI and other * NPDU bytes should be encoded. * @return On success, returns the number of bytes which were encoded into @@ -105,6 +149,13 @@ int npdu_encode_pdu( int len = 0; /* return value - number of octets loaded in this function */ uint8_t i = 0; /* counter */ +#ifdef BAC_ROUTING + /* populate src with the active routed device address or datalink address */ + if (src) { + (void)npdu_encode_pdu_routing(src); + } +#endif + if (npdu_data) { /* protocol version */ if (npdu) {