From 77360ad46f283697661268d0373f4048467637be Mon Sep 17 00:00:00 2001 From: skarg Date: Thu, 30 Aug 2018 01:19:31 +0000 Subject: [PATCH] Added example Network Port object --- bacnet-stack/Makefile | 3 +- bacnet-stack/demo/abort/Makefile | 1 + bacnet-stack/demo/dcc/Makefile | 1 + bacnet-stack/demo/epics/Makefile | 1 + bacnet-stack/demo/error/Makefile | 1 + bacnet-stack/demo/gateway/Makefile | 1 + bacnet-stack/demo/getevent/Makefile | 1 + bacnet-stack/demo/handler/dlenv.c | 85 + bacnet-stack/demo/iam/Makefile | 1 + bacnet-stack/demo/iamrouter/Makefile | 1 + bacnet-stack/demo/initrouter/Makefile | 1 + bacnet-stack/demo/object/device-client.c | 20 + bacnet-stack/demo/object/device.c | 20 + bacnet-stack/demo/object/netport.c | 1895 ++++++++++++++++++++++ bacnet-stack/demo/object/netport.h | 245 +++ bacnet-stack/demo/object/netport.mak | 42 + bacnet-stack/demo/piface/Makefile | 5 +- bacnet-stack/demo/piface/device.c | 20 + bacnet-stack/demo/ptransfer/Makefile | 1 + bacnet-stack/demo/readbdt/Makefile | 1 + bacnet-stack/demo/readfile/Makefile | 1 + bacnet-stack/demo/readprop/Makefile | 1 + bacnet-stack/demo/readpropm/Makefile | 1 + bacnet-stack/demo/readrange/Makefile | 1 + bacnet-stack/demo/reinit/Makefile | 1 + bacnet-stack/demo/router-ipv6/Makefile | 1 + bacnet-stack/demo/scov/Makefile | 1 + bacnet-stack/demo/server/Makefile | 1 + bacnet-stack/demo/timesync/Makefile | 1 + bacnet-stack/demo/ucov/Makefile | 1 + bacnet-stack/demo/uevent/Makefile | 1 + bacnet-stack/demo/uptransfer/Makefile | 1 + bacnet-stack/demo/whohas/Makefile | 1 + bacnet-stack/demo/whois/Makefile | 1 + bacnet-stack/demo/whoisrouter/Makefile | 1 + bacnet-stack/demo/writefile/Makefile | 1 + bacnet-stack/demo/writeprop/Makefile | 1 + bacnet-stack/demo/writepropm/Makefile | 1 + bacnet-stack/include/bacenum.h | 13 + 39 files changed, 2374 insertions(+), 3 deletions(-) create mode 100644 bacnet-stack/demo/object/netport.c create mode 100644 bacnet-stack/demo/object/netport.h create mode 100644 bacnet-stack/demo/object/netport.mak diff --git a/bacnet-stack/Makefile b/bacnet-stack/Makefile index ffa7d44b..72f425b9 100644 --- a/bacnet-stack/Makefile +++ b/bacnet-stack/Makefile @@ -17,6 +17,7 @@ MY_BACNET_DEFINES += -DBACFILE MY_BACNET_DEFINES += -DINTRINSIC_REPORTING MY_BACNET_DEFINES += -DBACNET_TIME_MASTER MY_BACNET_DEFINES += -DBACNET_PROPERTY_LISTS=1 +MY_BACNET_DEFINES += -DBACNET_PROTOCOL_REVISION=17 BACNET_DEFINES ?= $(MY_BACNET_DEFINES) # un-comment the next line to build in uci integration @@ -73,7 +74,7 @@ gateway: $(MAKE) -B -s -C demo gateway server: - $(MAKE) -B -C demo server + $(MAKE) -j -B -C demo server mstpcap: $(MAKE) -B -C demo mstpcap diff --git a/bacnet-stack/demo/abort/Makefile b/bacnet-stack/demo/abort/Makefile index 2cce0f74..439a185d 100644 --- a/bacnet-stack/demo/abort/Makefile +++ b/bacnet-stack/demo/abort/Makefile @@ -9,6 +9,7 @@ TARGET = bacabort TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/dcc/Makefile b/bacnet-stack/demo/dcc/Makefile index 1ddc8981..a2e8a3b1 100644 --- a/bacnet-stack/demo/dcc/Makefile +++ b/bacnet-stack/demo/dcc/Makefile @@ -9,6 +9,7 @@ TARGET = bacdcc TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/epics/Makefile b/bacnet-stack/demo/epics/Makefile index 01ddb04b..09910060 100644 --- a/bacnet-stack/demo/epics/Makefile +++ b/bacnet-stack/demo/epics/Makefile @@ -9,6 +9,7 @@ TARGET = bacepics TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/error/Makefile b/bacnet-stack/demo/error/Makefile index 3ca05df8..9088a4b1 100644 --- a/bacnet-stack/demo/error/Makefile +++ b/bacnet-stack/demo/error/Makefile @@ -9,6 +9,7 @@ TARGET = bacerror TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/gateway/Makefile b/bacnet-stack/demo/gateway/Makefile index c662e839..3999a1e0 100644 --- a/bacnet-stack/demo/gateway/Makefile +++ b/bacnet-stack/demo/gateway/Makefile @@ -33,6 +33,7 @@ SRCS = main.c \ $(BACNET_OBJECT)/mso.c \ $(BACNET_OBJECT)/msv.c \ $(BACNET_OBJECT)/nc.c \ + $(BACNET_OBJECT)/netport.c \ $(BACNET_OBJECT)/osv.c \ $(BACNET_OBJECT)/piv.c \ $(BACNET_OBJECT)/schedule.c \ diff --git a/bacnet-stack/demo/getevent/Makefile b/bacnet-stack/demo/getevent/Makefile index 3a90a91e..a85a4638 100644 --- a/bacnet-stack/demo/getevent/Makefile +++ b/bacnet-stack/demo/getevent/Makefile @@ -15,6 +15,7 @@ TARGET = bacge TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/handler/dlenv.c b/bacnet-stack/demo/handler/dlenv.c index 2d1f5a65..aaac5a76 100644 --- a/bacnet-stack/demo/handler/dlenv.c +++ b/bacnet-stack/demo/handler/dlenv.c @@ -35,6 +35,9 @@ #include "handlers.h" #include "dlenv.h" #include "tsm.h" +#if (BACNET_PROTOCOL_REVISION >= 17) +#include "netport.h" +#endif /** @file dlenv.c Initialize the DataLink configuration. */ @@ -164,6 +167,9 @@ int dlenv_register_as_foreign_device( pEnv = getenv(bbmd_env); if (pEnv) { bbmd_address = bip_getaddrbyname(pEnv); + } else if (entry_number == 1) { + /* BDT 1 is self (note: can be overridden) */ + bbmd_address = bip_get_addr(); } if (bbmd_address) { bbmd_port = 0xBAC0; @@ -174,6 +180,9 @@ int dlenv_register_as_foreign_device( if (bbmd_port > 0xFFFF) { bbmd_port = 0xBAC0; } + } else if (entry_number == 1) { + /* BDT 1 is self (note: can be overridden) */ + bbmd_port = bip_get_port(); } bbmd_mask = 0xFFFFFFFF; sprintf(bbmd_env,"BACNET_BDT_MASK_%u", entry_number); @@ -200,6 +209,81 @@ int dlenv_register_as_foreign_device( return retval; } +#if (BACNET_PROTOCOL_REVISION >= 17) +#if defined(BACDL_BIP) +/** + * Datalink network port object settings + */ +static void dlenv_network_port_init(void) +{ + uint32_t instance = 0; + uint32_t address = 0; + uint32_t broadcast = 0; + uint32_t test_broadcast = 0; + uint32_t mask = 0; + uint16_t port = 0; + uint8_t mac[4+2] = {0}; + uint8_t prefix = 0; + + instance = Network_Port_Index_To_Instance(0); + Network_Port_Name_Set(instance, "BACnet/IP Port"); + Network_Port_Type_Set(instance, PORT_TYPE_BIP); + port = bip_get_port(); + Network_Port_BIP_Port_Set(instance, port); + address = bip_get_addr(); + memcpy(&mac[0], &address, 4); + memcpy(&mac[4], &port, 2); + Network_Port_MAC_Address_Set(instance, &mac[0], 6); + broadcast = bip_get_broadcast_addr(); + for (prefix = 0; prefix < 32; prefix++) { + mask = htonl((0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF); + test_broadcast = (address & mask) | (~mask); + if (test_broadcast == broadcast) { + break; + } + } + Network_Port_IP_Subnet_Prefix_Set(instance, prefix); +} +#elif defined(BACDL_MSTP) +/** + * Datalink network port object settings + */ +static void dlenv_network_port_init(void) +{ + uint32_t instance = 0; + uint8_t mac[1] = {0}; + + instance = Network_Port_Index_To_Instance(0); + Network_Port_Name_Set(instance, "MS/TP Port"); + Network_Port_MSTP_Max_Master_Set(instance, dlmstp_max_master()); + Network_Port_MSTP_Max_Info_Frames_Set(instance, dlmstp_max_info_frames()); + Network_Port_Link_Speed_Set(instance, dlmstp_baud_rate()); + mac[0] = dlmstp_mac_address(); + Network_Port_MAC_Address_Set(instance, &mac[0], 1); +} +#elif defined(BACDL_BIP6) +/** + * Datalink network port object settings + */ +static void dlenv_network_port_init(void) +{ + uint32_t instance = 0; + const char *bip_port_name = ; + + instance = Network_Port_Index_To_Instance(0); + Network_Port_Name_Set(instance, "BACnet/IPv6 Port"); + +} +#endif +#else +/** + * Datalink network port object settings + */ +static void dlenv_network_port_init(void) +{ + /* do nothing */ +} +#endif /** Datalink maintenance timer * @ingroup DataLink @@ -385,5 +469,6 @@ void dlenv_init( tsm_invokeID_set((uint8_t) strtol(pEnv, NULL, 0)); } #endif + dlenv_network_port_init(); dlenv_register_as_foreign_device(); } diff --git a/bacnet-stack/demo/iam/Makefile b/bacnet-stack/demo/iam/Makefile index 4b14a98b..45d37514 100644 --- a/bacnet-stack/demo/iam/Makefile +++ b/bacnet-stack/demo/iam/Makefile @@ -9,6 +9,7 @@ TARGET = baciam TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/iamrouter/Makefile b/bacnet-stack/demo/iamrouter/Makefile index 8c332083..a73a1f45 100644 --- a/bacnet-stack/demo/iamrouter/Makefile +++ b/bacnet-stack/demo/iamrouter/Makefile @@ -9,6 +9,7 @@ TARGET = baciamr TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/initrouter/Makefile b/bacnet-stack/demo/initrouter/Makefile index ae7352e4..0046787d 100644 --- a/bacnet-stack/demo/initrouter/Makefile +++ b/bacnet-stack/demo/initrouter/Makefile @@ -9,6 +9,7 @@ TARGET = bacinitr TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/object/device-client.c b/bacnet-stack/demo/object/device-client.c index 311ab206..90727ab9 100644 --- a/bacnet-stack/demo/object/device-client.c +++ b/bacnet-stack/demo/object/device-client.c @@ -47,6 +47,9 @@ #include "handlers.h" #include "datalink.h" #include "address.h" +#if (BACNET_PROTOCOL_REVISION >= 17) +#include "netport.h" +#endif /* include the device object */ #include "device.h" /* me */ @@ -133,6 +136,23 @@ static object_functions_t Object_Table[] = { NULL /* COV */ , NULL /* COV Clear */ , NULL /* Intrinsic Reporting */ }, +#if (BACNET_PROTOCOL_REVISION >= 17) + {OBJECT_NETWORK_PORT, + Network_Port_Init, + Network_Port_Count, + Network_Port_Index_To_Instance, + Network_Port_Valid_Instance, + Network_Port_Object_Name, + Network_Port_Read_Property, + Network_Port_Write_Property, + Network_Port_Property_Lists, + NULL /* ReadRangeInfo */ , + NULL /* Iterator */ , + NULL /* Value_Lists */ , + NULL /* COV */ , + NULL /* COV Clear */ , + NULL /* Intrinsic Reporting */ }, +#endif {MAX_BACNET_OBJECT_TYPE, NULL /* Init */ , NULL /* Count */ , diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index 57278bce..4915f9eb 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -63,6 +63,9 @@ #include "ms-input.h" #include "mso.h" #include "msv.h" +#if (BACNET_PROTOCOL_REVISION >= 17) +#include "netport.h" +#endif #include "osv.h" #include "piv.h" #include "schedule.h" @@ -113,6 +116,23 @@ static object_functions_t My_Object_Table[] = { NULL /* COV */ , NULL /* COV Clear */ , NULL /* Intrinsic Reporting */ }, +#if (BACNET_PROTOCOL_REVISION >= 17) + {OBJECT_NETWORK_PORT, + Network_Port_Init, + Network_Port_Count, + Network_Port_Index_To_Instance, + Network_Port_Valid_Instance, + Network_Port_Object_Name, + Network_Port_Read_Property, + Network_Port_Write_Property, + Network_Port_Property_Lists, + NULL /* ReadRangeInfo */ , + NULL /* Iterator */ , + NULL /* Value_Lists */ , + NULL /* COV */ , + NULL /* COV Clear */ , + NULL /* Intrinsic Reporting */ }, +#endif {OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, diff --git a/bacnet-stack/demo/object/netport.c b/bacnet-stack/demo/object/netport.c new file mode 100644 index 00000000..d4ce3386 --- /dev/null +++ b/bacnet-stack/demo/object/netport.c @@ -0,0 +1,1895 @@ +/** + * @file + * @author Steve Karg + * @date 2016 + * @brief Network port objects, customize for your use + * + * @section DESCRIPTION + * + * The Network Port object provides access to the configuration + * and properties of network ports of a device. + * + * @section LICENSE + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "address.h" +#include "bacdef.h" +#include "bacapp.h" +#include "bacdcode.h" +#include "npdu.h" +#include "apdu.h" +#include "device.h" +/* me */ +#include "netport.h" + +#define BIP_DNS_MAX 3 +struct bacnet_ipv4_port { + uint8_t IP_Address[4]; + uint8_t IP_Subnet_Prefix; + uint8_t IP_Gateway[4]; + uint8_t IP_DNS_Server[BIP_DNS_MAX][4]; + uint16_t Port; + uint8_t Mode; + bool IP_DHCP_Enable; + uint32_t IP_DHCP_Lease_Seconds; + uint32_t IP_DHCP_Lease_Seconds_Remaining; + uint32_t IP_DHCP_Server[4]; + bool IP_NAT_Traversal; + uint32_t IP_Global_Address[4]; + bool BBMD_Accept_FD_Registrations; +}; + +struct bacnet_ipv6_port { + uint8_t MAC_Address[4]; + uint8_t IP_Address[16]; + uint8_t IP_Prefix; + uint16_t Port; +}; + +struct ethernet_port { + uint8_t MAC_Address[6]; +}; + +struct mstp_port { + uint8_t MAC_Address; + uint8_t Max_Master; + uint8_t Max_Info_Frames; +}; + +struct object_data { + uint32_t Instance_Number; + char *Object_Name; + uint8_t Reliability; + bool Out_Of_Service:1; + bool Changes_Pending:1; + uint8_t Network_Type; + uint16_t Network_Number; + uint8_t Quality; + uint16_t APDU_Length; + uint32_t Link_Speed; + union { + struct bacnet_ipv4_port IPv4; + struct bacnet_ipv6_port IPv6; + struct ethernet_port Ethernet; + struct mstp_port MSTP; + } Network; +}; +#ifndef BACNET_NETWORK_PORTS_MAX +#define BACNET_NETWORK_PORTS_MAX 1 +#endif +struct object_data Object_List[BACNET_NETWORK_PORTS_MAX]; + +/* These three arrays are used by the ReadPropertyMultiple handler */ +static const int Network_Port_Properties_Required[] = { + PROP_OBJECT_IDENTIFIER, + PROP_OBJECT_NAME, + PROP_OBJECT_TYPE, + PROP_STATUS_FLAGS, + PROP_RELIABILITY, + PROP_OUT_OF_SERVICE, + PROP_NETWORK_TYPE, + PROP_PROTOCOL_LEVEL, + PROP_NETWORK_NUMBER, + PROP_NETWORK_NUMBER_QUALITY, + PROP_CHANGES_PENDING, + PROP_APDU_LENGTH, + PROP_LINK_SPEED, + -1 +}; + +static const int Network_Port_Properties_Optional[] = { + PROP_MAC_ADDRESS, + PROP_MAX_APDU_LENGTH_ACCEPTED, +#if defined(BACDL_MSTP) + PROP_MAX_MASTER, + PROP_MAX_INFO_FRAMES, +#elif defined(BACDL_BIP) + PROP_BACNET_IP_MODE, + PROP_IP_ADDRESS, + PROP_BACNET_IP_UDP_PORT, + PROP_IP_SUBNET_MASK, + PROP_IP_DEFAULT_GATEWAY, + PROP_IP_DNS_SERVER, +#if defined(BBMD_ENABLED) + PROP_BBMD_ACCEPT_FD_REGISTRATIONS, + PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE, + PROP_BBMD_FOREIGN_DEVICE_TABLE, +#endif +#endif + -1 +}; + +static const int Network_Port_Properties_Proprietary[] = { + -1 +}; + +/** + * Returns the list of required, optional, and proprietary properties. + * Used by ReadPropertyMultiple service. + * + * @param pRequired - pointer to list of int terminated by -1, of + * BACnet required properties for this object. + * @param pOptional - pointer to list of int terminated by -1, of + * BACnet optkional properties for this object. + * @param pProprietary - pointer to list of int terminated by -1, of + * BACnet proprietary properties for this object. + */ +void Network_Port_Property_Lists( + const int **pRequired, + const int **pOptional, + const int **pProprietary) +{ + if (pRequired) { + *pRequired = Network_Port_Properties_Required; + } + if (pOptional) { + *pOptional = Network_Port_Properties_Optional; + } + if (pProprietary) { + *pProprietary = Network_Port_Properties_Proprietary; + } + + return; +} + +/** + * For a given object instance-number, loads the object-name into + * a characterstring. Note that the object name must be unique + * within this device. + * + * @param object_instance - object-instance number of the object + * @param object_name - holds the object-name retrieved + * + * @return true if object-name was retrieved + */ +bool Network_Port_Object_Name( + uint32_t object_instance, + BACNET_CHARACTER_STRING *object_name) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + status = characterstring_init_ansi(object_name, + Object_List[index].Object_Name); + } + + return status; +} + +/** + * For a given object instance-number, sets the object-name + * Note that the object name must be unique within this device. + * + * @param object_instance - object-instance number of the object + * @param new_name - holds the object-name to be written + * Expecting a pointer to a static ANSI C string for zero copy. + * + * @return true if object-name was set + */ +bool Network_Port_Name_Set( + uint32_t object_instance, + char *new_name) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].Object_Name = new_name; + } + + return status; +} + +/** + * Determines if a given Network Port instance is valid + * + * @param object_instance - object-instance number of the object + * + * @return true if the instance is valid, and false if not + */ +bool Network_Port_Valid_Instance( + uint32_t object_instance) +{ + unsigned index = 0; /* offset from instance lookup */ + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + return true; + } + + return false; +} + +/** + * Determines the number of Network Port objects + * + * @return Number of Network Port objects + */ +unsigned Network_Port_Count( + void) +{ + return BACNET_NETWORK_PORTS_MAX; +} + +/** + * Determines the object instance-number for a given 0..N index + * of Network Port objects where N is Network_Port_Count(). + * + * @param index - 0..BACNET_NETWORK_PORTS_MAX value + * + * @return object instance-number for the given index, or BACNET_MAX_INSTANCE + * for an invalid index. + */ +uint32_t Network_Port_Index_To_Instance( + unsigned index) +{ + if (index < BACNET_NETWORK_PORTS_MAX) { + return Object_List[index].Instance_Number; + } + + return BACNET_MAX_INSTANCE; +} + +/** + * For a given object instance-number, determines a 0..N index + * of Network Port objects where N is Network_Port_Count(). + * + * @param object_instance - object-instance number of the object + * + * @return index for the given instance-number, or BACNET_NETWORK_PORTS_MAX + * if not valid. + */ +unsigned Network_Port_Instance_To_Index( + uint32_t object_instance) +{ + unsigned index = 0; + + for (index = 0; index < BACNET_NETWORK_PORTS_MAX; index++) { + if (Object_List[index].Instance_Number == object_instance) { + return index; + } + } + + return BACNET_NETWORK_PORTS_MAX; +} + +/** + * For the Network Port object, set the instance number. + * + * @param index - 0..BACNET_NETWORK_PORTS_MAX value + * @param object_instance - object-instance number of the object + * + * @return true if values are within range and property is set. + */ +bool Network_Port_Set_Network_Port_Instance_ID( + unsigned index, + uint32_t object_instance) +{ + bool status = false; /* return value */ + + if (index < BACNET_NETWORK_PORTS_MAX) { + if (object_instance <= BACNET_MAX_INSTANCE) { + Object_List[index].Instance_Number = object_instance; + status = true; + } + } + + return status; +} + +/** + * For a given object instance-number, returns the out-of-service + * property value + * + * @param object_instance - object-instance number of the object + * + * @return out-of-service property value + */ +bool Network_Port_Out_Of_Service( + uint32_t object_instance) +{ + bool oos_flag = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + oos_flag = Object_List[index].Out_Of_Service; + } + + return oos_flag; +} + +/** + * For a given object instance-number, sets the out-of-service property value + * + * @param object_instance - object-instance number of the object + * @param value - boolean out-of-service value + * + * @return true if the out-of-service property value was set + */ +bool Network_Port_Out_Of_Service_Set( + uint32_t object_instance, + bool value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].Out_Of_Service = value; + status = true; + } + + return status; +} + +/** + * For a given object instance-number, gets the reliability. + * + * @param object_instance - object-instance number of the object + * + * @return reliability value + */ +BACNET_RELIABILITY Network_Port_Reliability( + uint32_t object_instance) +{ + BACNET_RELIABILITY reliability = RELIABILITY_NO_FAULT_DETECTED; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + reliability = Object_List[index].Reliability; + } + + return reliability; +} + +/** + * For a given object instance-number, sets the reliability + * + * @param object_instance - object-instance number of the object + * @param value - reliability enumerated value + * + * @return true if values are within range and property is set. + */ +bool Network_Port_Reliability_Set( + uint32_t object_instance, + BACNET_RELIABILITY value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].Reliability = (uint8_t)value; + status = true; + } + + return status; +} + +/** + * For a given object instance-number, gets the BACnet Network Type. + * + * @param object_instance - object-instance number of the object + * + * @return BACnet network type value + */ +uint8_t Network_Port_Type( + uint32_t object_instance) +{ + uint8_t port_type = PORT_TYPE_NON_BACNET; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + port_type = Object_List[index].Network_Type; + } + + return port_type; +} + +/** + * For a given object instance-number, sets the BACnet port type + * + * @param object_instance - object-instance number of the object + * @param value - network port type 0-63 are defined by ASHRAE. + * Values from 64-255 may be used by others subject to the + * procedures and constraints described in Clause 23. + * + * @return true if values are within range and property is set. + */ +bool Network_Port_Type_Set( + uint32_t object_instance, + uint8_t value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].Network_Type = value; + status = true; + } + + return status; +} + +/** + * For a given object instance-number, gets the BACnet Network Number. + * + * @param object_instance - object-instance number of the object + * + * @return BACnet network type value + */ +uint16_t Network_Port_Network_Number( + uint32_t object_instance) +{ + uint16_t network_number = 0; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + network_number = Object_List[index].Network_Number; + } + + return network_number; +} + +/** + * For a given object instance-number, sets the BACnet Network Number + * + * @param object_instance - object-instance number of the object + * @param value - network number 0..65534 + * + * @return true if values are within range and property is set. + */ +bool Network_Port_Network_Number_Set( + uint32_t object_instance, + uint16_t value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].Network_Number = value; + status = true; + } + + return status; +} + +/** + * For a given object instance-number, gets the quality property + * + * @param object_instance - object-instance number of the object + * + * @return quality property value + */ +BACNET_PORT_QUALITY Network_Port_Quality( + uint32_t object_instance) +{ + BACNET_PORT_QUALITY value = PORT_QUALITY_UNKNOWN; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + value = Object_List[index].Quality; + } + + return value; +} + +/** + * For a given object instance-number, sets the quality property + * + * @param object_instance - object-instance number of the object + * @param value - quality enumerated value + * + * @return true if values are within range and property is set. + */ +bool Network_Port_Quality_Set( + uint32_t object_instance, + BACNET_PORT_QUALITY value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].Quality = (uint8_t)value; + status = true; + } + + return status; +} + +/** + * For a given object instance-number, loads the mac-address into + * an octet string. + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param mac_address - holds the mac-address retrieved + * + * @return true if mac-address was retrieved + */ +bool Network_Port_MAC_Address( + uint32_t object_instance, + BACNET_OCTET_STRING *mac_address) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + uint8_t *mac = NULL; + uint8_t ip_mac[4+2] = {0}; + size_t mac_len = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + switch (Object_List[index].Network_Type) { + case PORT_TYPE_ETHERNET: + mac = &Object_List[index].Network.Ethernet.MAC_Address[0]; + mac_len = sizeof(Object_List[index].Network.Ethernet.MAC_Address); + break; + case PORT_TYPE_MSTP: + mac = &Object_List[index].Network.MSTP.MAC_Address; + mac_len = sizeof(Object_List[index].Network.MSTP.MAC_Address); + break; + case PORT_TYPE_BIP: + memcpy(&ip_mac[0], + &Object_List[index].Network.IPv4.IP_Address, 4); + memcpy(&ip_mac[4], + &Object_List[index].Network.IPv4.Port, 2); + mac = &ip_mac[0]; + mac_len = sizeof(ip_mac); + break; + case PORT_TYPE_BIP6: + mac = &Object_List[index].Network.IPv6.MAC_Address[0]; + mac_len = sizeof(Object_List[index].Network.IPv6.MAC_Address); + break; + default: + break; + } + if (mac) { + status = octetstring_init(mac_address, mac, mac_len); + } + } + + return status; +} + +/** + * For a given object instance-number, sets the mac-address and it's length + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param new_name - holds the object-name to be written + * Expecting a pointer to a static ANSI C string for zero copy. + * + * @return true if object-name was set + */ +bool Network_Port_MAC_Address_Set( + uint32_t object_instance, + uint8_t *mac_src, + uint8_t mac_len) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + size_t mac_size = 0; + uint8_t *mac_dest = NULL; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + switch (Object_List[index].Network_Type) { + case PORT_TYPE_ETHERNET: + mac_dest = &Object_List[index].Network.Ethernet.MAC_Address[0]; + mac_size = sizeof(Object_List[index].Network.Ethernet.MAC_Address); + break; + case PORT_TYPE_MSTP: + mac_dest = &Object_List[index].Network.MSTP.MAC_Address; + mac_size = sizeof(Object_List[index].Network.MSTP.MAC_Address); + break; + case PORT_TYPE_BIP: + /* no need to set - created from IP address and UPD Port */ + break; + case PORT_TYPE_BIP6: + mac_dest = &Object_List[index].Network.IPv6.MAC_Address[0]; + mac_size = sizeof(Object_List[index].Network.IPv6.MAC_Address); + break; + default: + break; + } + if (mac_src && mac_dest && (mac_len == mac_size)) { + memcpy(mac_dest, mac_src, mac_size); + status = true; + } + } + + return status; +} + +/** + * For a given object instance-number, gets the BACnet Network Number. + * + * @param object_instance - object-instance number of the object + * + * @return APDU length for this network port + */ +uint16_t Network_Port_APDU_Length( + uint32_t object_instance) +{ + uint16_t value = 0; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + value = Object_List[index].APDU_Length; + } + + return value; +} + +/** + * For a given object instance-number, sets the BACnet Network Number + * + * @param object_instance - object-instance number of the object + * @param value - APDU length 0..65535 + * + * @return true if values are within range and property is set. + */ +bool Network_Port_APDU_Length_Set( + uint32_t object_instance, + uint16_t value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].APDU_Length = value; + status = true; + } + + return status; +} + + + uint32_t Network_Port_Link_Speed( + uint32_t object_instance); + bool Network_Port_Link_Speed_Set( + uint32_t object_instance, + uint32_t value); + +/** + * For a given object instance-number, gets the network communication rate + * as the number of bits per second. A value of 0 indicates an unknown + * communication rate. + * + * @param object_instance - object-instance number of the object + * + * @return Link_Speed for this network port, or 0 if unknown + */ +uint32_t Network_Port_Link_Speed( + uint32_t object_instance) +{ + uint32_t value = 0; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + value = Object_List[index].Link_Speed; + } + + return value; +} + +/** + * For a given object instance-number, sets the Link_Speed + * + * @param object_instance - object-instance number of the object + * @param value - APDU length 0..65535 + * + * @return true if values are within range and property is set. + */ +bool Network_Port_Link_Speed_Set( + uint32_t object_instance, + uint32_t value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].Link_Speed = value; + status = true; + } + + return status; +} + +/** + * For a given object instance-number, returns the changes-pending + * property value + * + * @param object_instance - object-instance number of the object + * + * @return changes-pending property value + */ +bool Network_Port_Changes_Pending( + uint32_t object_instance) +{ + bool flag = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + flag = Object_List[index].Changes_Pending; + } + + return flag; +} + +/** + * For a given object instance-number, sets the changes-pending property value + * + * @param object_instance - object-instance number of the object + * @param value - boolean changes-pending value + * + * @return true if the changes-pending property value was set + */ +bool Network_Port_Changes_Pending_Set( + uint32_t object_instance, + bool value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + Object_List[index].Changes_Pending = value; + status = true; + } + + return status; +} + +/** + * For a given object instance-number, gets the MS/TP Max_Master value + * Note: depends on Network_Type being set to PORT_TYPE_MSTP for this object + * + * @param object_instance - object-instance number of the object + * + * @return MS/TP Max_Master value + */ +uint8_t Network_Port_MSTP_Max_Master( + uint32_t object_instance) +{ + uint8_t value = 0; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_MSTP) { + value = Object_List[index].Network.MSTP.Max_Master; + } + } + + return value; +} + +/** + * For a given object instance-number, sets the MS/TP Max_Master value + * Note: depends on Network_Type being set to PORT_TYPE_MSTP for this object + * + * @param object_instance - object-instance number of the object + * @param value - MS/TP Max_Master value 0..127 + * + * @return true if values are within range and property is set. + */ +bool Network_Port_MSTP_Max_Master_Set( + uint32_t object_instance, + uint8_t value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_MSTP) { + if (value <= 127) { + if (Object_List[index].Network.MSTP.Max_Master != value) { + Object_List[index].Changes_Pending = true; + } + Object_List[index].Network.MSTP.Max_Master = value; + status = true; + } + } + } + + return status; +} + +/** + * For a given object instance-number, loads the ip-address into + * an octet string. + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param ip_address - holds the mac-address retrieved + * + * @return true if ip-address was retrieved + */ +bool Network_Port_IP_Address( + uint32_t object_instance, + BACNET_OCTET_STRING *ip_address) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + status = octetstring_init(ip_address, + &Object_List[index].Network.IPv4.IP_Address[0], 4); + } + } + + return status; +} + +/** + * For a given object instance-number, sets the ip-address + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param a - ip-address first octet + * @param b - ip-address first octet + * @param c - ip-address first octet + * @param d - ip-address first octet + * + * @return true if ip-address was set + */ +bool Network_Port_IP_Address_Set( + uint32_t object_instance, + uint8_t a, uint8_t b, uint8_t c, uint8_t d) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + Object_List[index].Network.IPv4.IP_Address[0] = a; + Object_List[index].Network.IPv4.IP_Address[1] = b; + Object_List[index].Network.IPv4.IP_Address[2] = c; + Object_List[index].Network.IPv4.IP_Address[3] = d; + } + } + + return status; +} + +/** + * For a given object instance-number, loads the subnet-mask-address into + * an octet string. + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param subnet-mask - holds the mac-address retrieved + * + * @return true if ip-address was retrieved + */ +bool Network_Port_IP_Subnet( + uint32_t object_instance, + BACNET_OCTET_STRING *subnet_mask) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + uint32_t mask = 0; + uint32_t prefix = 0; + uint8_t ip_mask[4] = {0}; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + prefix = Object_List[index].Network.IPv4.IP_Subnet_Prefix; + mask = (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF; + encode_unsigned32(ip_mask, mask); + status = octetstring_init(subnet_mask, ip_mask, sizeof(ip_mask)); + } + } + + return status; +} + +/** + * For a given object instance-number, gets the BACnet/IP Subnet prefix value + * Note: depends on Network_Type being set to PORT_TYPE_BIP for this object + * + * @param object_instance - object-instance number of the object + * + * @return BACnet/IP subnet prefix value + */ +uint8_t Network_Port_IP_Subnet_Prefix( + uint32_t object_instance) +{ + uint8_t value = 0; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + value = Object_List[index].Network.IPv4.IP_Subnet_Prefix; + } + } + + return value; +} + +/** + * For a given object instance-number, sets the BACnet/IP Subnet prefix value + * Note: depends on Network_Type being set to PORT_TYPE_BIP for this object + * + * @param object_instance - object-instance number of the object + * @param value - BACnet/IP Subnet prefix value 1..32 + * + * @return true if values are within range and property is set. + */ +bool Network_Port_IP_Subnet_Prefix_Set( + uint32_t object_instance, + uint8_t value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + if (value <= 32) { + if (Object_List[index].Network.IPv4.IP_Subnet_Prefix != value) { + Object_List[index].Changes_Pending = true; + } + Object_List[index].Network.IPv4.IP_Subnet_Prefix = value; + status = true; + } + } + } + + return status; +} + +/** + * For a given object instance-number, loads the gateway ip-address into + * an octet string. + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param ip_address - holds the ip-address retrieved + * + * @return true if ip-address was retrieved + */ +bool Network_Port_IP_Gateway( + uint32_t object_instance, + BACNET_OCTET_STRING *ip_address) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + status = octetstring_init(ip_address, + &Object_List[index].Network.IPv4.IP_Gateway[0], 4); + } + } + + return status; +} + +/** + * For a given object instance-number, sets the gateway ip-address + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param a - ip-address first octet + * @param b - ip-address first octet + * @param c - ip-address first octet + * @param d - ip-address first octet + * + * @return true if ip-address was set + */ +bool Network_Port_IP_Gateway_Set( + uint32_t object_instance, + uint8_t a, uint8_t b, uint8_t c, uint8_t d) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + Object_List[index].Network.IPv4.IP_Gateway[0] = a; + Object_List[index].Network.IPv4.IP_Gateway[1] = b; + Object_List[index].Network.IPv4.IP_Gateway[2] = c; + Object_List[index].Network.IPv4.IP_Gateway[3] = d; + } + } + + return status; +} + +/** + * For a given object instance-number, loads the subnet-mask-address into + * an octet string. + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param dns_index - 0=primary, 1=secondary, 3=tertierary + * @param ip_address - holds the mac-address retrieved + * + * @return true if ip-address was retrieved + */ +bool Network_Port_IP_DNS_Server( + uint32_t object_instance, + unsigned dns_index, + BACNET_OCTET_STRING *ip_address) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + if (dns_index < BIP_DNS_MAX) { + status = octetstring_init(ip_address, + &Object_List[index].Network.IPv4.IP_DNS_Server[dns_index][0], + 4); + } + } + } + + return status; +} + +/** + * For a given object instance-number, sets the ip-address + * Note: depends on Network_Type being set for this object + * + * @param object_instance - object-instance number of the object + * @param index - 0=primary, 1=secondary, 3=tertierary + * @param a - ip-address first octet + * @param b - ip-address first octet + * @param c - ip-address first octet + * @param d - ip-address first octet + * + * @return true if ip-address was set + */ +bool Network_Port_IP_DNS_Server_Set( + uint32_t object_instance, + unsigned dns_index, + uint8_t a, uint8_t b, uint8_t c, uint8_t d) +{ + unsigned index = 0; /* offset from instance lookup */ + bool status = false; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + if (dns_index < BIP_DNS_MAX) { + Object_List[index].Network.IPv4.IP_DNS_Server[dns_index][0] = a; + Object_List[index].Network.IPv4.IP_DNS_Server[dns_index][1] = b; + Object_List[index].Network.IPv4.IP_DNS_Server[dns_index][2] = c; + Object_List[index].Network.IPv4.IP_DNS_Server[dns_index][3] = d; + } + } + } + + return status; +} + +/** + * For a given object instance-number, gets the BACnet/IP UDP Port number + * Note: depends on Network_Type being set to PORT_TYPE_BIP for this object + * + * @param object_instance - object-instance number of the object + * + * @return BACnet/IP UDP Port number + */ +uint16_t Network_Port_BIP_Port( + uint32_t object_instance) +{ + uint16_t value = 0; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + value = Object_List[index].Network.IPv4.Port; + } + } + + return value; +} + +/** + * For a given object instance-number, sets the BACnet/IP UDP Port number + * Note: depends on Network_Type being set to PORT_TYPE_BIP for this object + * + * @param object_instance - object-instance number of the object + * @param value - BACnet/IP UDP Port number (default=0xBAC0) + * + * @return true if values are within range and property is set. + */ +bool Network_Port_BIP_Port_Set( + uint32_t object_instance, + uint16_t value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + if (value <= 32) { + if (Object_List[index].Network.IPv4.Port != value) { + Object_List[index].Changes_Pending = true; + } + Object_List[index].Network.IPv4.Port = value; + status = true; + } + } + } + + return status; +} + +/** + * For a given object instance-number, gets the BACnet/IP UDP Port number + * Note: depends on Network_Type being set to PORT_TYPE_BIP for this object + * + * @param object_instance - object-instance number of the object + * + * @return BACnet/IP UDP Port number + */ +BACNET_IP_MODE Network_Port_BIP_Mode( + uint32_t object_instance) +{ + BACNET_IP_MODE value = 0; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + value = Object_List[index].Network.IPv4.Mode; + } + } + + return value; +} + +/** + * For a given object instance-number, sets the BACnet/IP UDP Port number + * Note: depends on Network_Type being set to PORT_TYPE_BIP for this object + * + * @param object_instance - object-instance number of the object + * @param value - BACnet/IP UDP Port number (default=0xBAC0) + * + * @return true if values are within range and property is set. + */ +bool Network_Port_BIP_Mode_Set( + uint32_t object_instance, + BACNET_IP_MODE value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP) { + if (value <= 32) { + if (Object_List[index].Network.IPv4.Mode != value) { + Object_List[index].Changes_Pending = true; + } + Object_List[index].Network.IPv4.Mode = value; + status = true; + } + } + } + + return status; +} + +/** + * For a given object instance-number, returns the BBMD-Accept-FD-Registrations + * property value + * + * @param object_instance - object-instance number of the object + * + * @return BBMD-Accept-FD-Registrations property value + */ +bool Network_Port_BBMD_Accept_FD_Registrations( + uint32_t object_instance) +{ + bool flag = false; + unsigned index = 0; + struct bacnet_ipv4_port *ipv4 = NULL; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + ipv4 = &Object_List[index].Network.IPv4; + flag = ipv4->BBMD_Accept_FD_Registrations; + } + + return flag; +} + +/** + * For a given object instance-number, sets the BBMD-Accept-FD-Registrations + * property value + * + * @param object_instance - object-instance number of the object + * @param flag - boolean changes-pending flag + * + * @return true if the BBMD-Accept-FD-Registrations property value was set + */ +bool Network_Port_BBMD_Accept_FD_Registrations_Set( + uint32_t object_instance, + bool flag) +{ + bool status = false; + unsigned index = 0; + struct bacnet_ipv4_port *ipv4 = NULL; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + ipv4 = &Object_List[index].Network.IPv4; + if (flag != ipv4->BBMD_Accept_FD_Registrations) { + ipv4->BBMD_Accept_FD_Registrations = flag; + Object_List[index].Changes_Pending = true; + } + status = true; + } + + return status; +} + +/** + * For a given object instance-number, gets the MS/TP Max_Info_Frames value + * Note: depends on Network_Type being set to PORT_TYPE_MSTP for this object + * + * @param object_instance - object-instance number of the object + * + * @return MS/TP Max_Info_Frames value + */ +uint8_t Network_Port_MSTP_Max_Info_Frames( + uint32_t object_instance) +{ + uint8_t value = 0; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_MSTP) { + value = Object_List[index].Network.MSTP.Max_Info_Frames; + } + } + + return value; +} + +/** + * For a given object instance-number, sets the MS/TP Max_Info_Frames value + * Note: depends on Network_Type being set to PORT_TYPE_MSTP for this object + * + * @param object_instance - object-instance number of the object + * @param value - MS/TP Max_Info_Frames value 0..255 + * + * @return true if values are within range and property is set. + */ +bool Network_Port_MSTP_Max_Info_Frames_Set( + uint32_t object_instance, + uint8_t value) +{ + bool status = false; + unsigned index = 0; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_MSTP) { + if (Object_List[index].Network.MSTP.Max_Info_Frames != value) { + Object_List[index].Changes_Pending = true; + } + Object_List[index].Network.MSTP.Max_Info_Frames = value; + status = true; + } + } + + return status; +} + +/** + * ReadProperty handler for this object. For the given ReadProperty + * data, the application_data is loaded or the error flags are set. + * + * @param rpdata - BACNET_READ_PROPERTY_DATA data, including + * requested data and space for the reply, or error response. + * + * @return number of APDU bytes in the response, or + * BACNET_STATUS_ERROR on error. + */ +int Network_Port_Read_Property( + BACNET_READ_PROPERTY_DATA *rpdata) +{ + int apdu_len = 0; + BACNET_BIT_STRING bit_string; + BACNET_OCTET_STRING octet_string; + BACNET_CHARACTER_STRING char_string; + uint8_t *apdu = NULL; + + if ((rpdata == NULL) || + (rpdata->application_data == NULL) || + (rpdata->application_data_len == 0)) { + return 0; + } + apdu = rpdata->application_data; + switch (rpdata->object_property) { + case PROP_OBJECT_IDENTIFIER: + apdu_len = + encode_application_object_id(&apdu[0], OBJECT_NETWORK_PORT, + rpdata->object_instance); + break; + case PROP_OBJECT_NAME: + Network_Port_Object_Name(rpdata->object_instance, &char_string); + apdu_len = encode_application_character_string(&apdu[0], &char_string); + break; + case PROP_OBJECT_TYPE: + apdu_len = encode_application_enumerated(&apdu[0], OBJECT_NETWORK_PORT); + break; + case PROP_STATUS_FLAGS: + bitstring_init(&bit_string); + bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false); + if (Network_Port_Reliability(rpdata->object_instance) == + RELIABILITY_NO_FAULT_DETECTED) { + bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false); + } else { + bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, true); + } + bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false); + if (Network_Port_Out_Of_Service(rpdata->object_instance)) { + bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, + true); + } else { + bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, + false); + } + apdu_len = encode_application_bitstring(&apdu[0], &bit_string); + break; + case PROP_RELIABILITY: + apdu_len = encode_application_enumerated(&apdu[0], + Network_Port_Reliability(rpdata->object_instance)); + break; + case PROP_OUT_OF_SERVICE: + apdu_len = encode_application_boolean(&apdu[0], + Network_Port_Out_Of_Service(rpdata->object_instance)); + break; + case PROP_NETWORK_TYPE: + apdu_len = encode_application_enumerated(&apdu[0], + Network_Port_Type(rpdata->object_instance)); + break; + case PROP_PROTOCOL_LEVEL: + apdu_len = encode_application_enumerated(&apdu[0], + BACNET_PROTOCOL_LEVEL_BACNET_APPLICATION); + break; + case PROP_NETWORK_NUMBER: + apdu_len = encode_application_unsigned(&apdu[0], + Network_Port_Network_Number(rpdata->object_instance)); + break; + case PROP_NETWORK_NUMBER_QUALITY: + apdu_len = encode_application_enumerated(&apdu[0], + Network_Port_Quality(rpdata->object_instance)); + break; + case PROP_MAC_ADDRESS: + Network_Port_MAC_Address(rpdata->object_instance, &octet_string); + apdu_len = encode_application_octet_string(&apdu[0], &octet_string); + break; + case PROP_MAX_APDU_LENGTH_ACCEPTED: + apdu_len = encode_application_unsigned(&apdu[0], + Network_Port_APDU_Length(rpdata->object_instance)); + break; + case PROP_LINK_SPEED: + apdu_len = encode_application_unsigned(&apdu[0], + Network_Port_Link_Speed(rpdata->object_instance)); + break; + case PROP_CHANGES_PENDING: + apdu_len = encode_application_boolean(&apdu[0], + Network_Port_Changes_Pending(rpdata->object_instance)); + break; + case PROP_APDU_LENGTH: + apdu_len = encode_application_unsigned(&apdu[0], + Network_Port_APDU_Length(rpdata->object_instance)); + break; +#if defined(BACDL_MSTP) + case PROP_MAX_MASTER: + apdu_len = encode_application_unsigned(&apdu[0], + Network_Port_MSTP_Max_Master(rpdata->object_instance)); + break; + case PROP_MAX_INFO_FRAMES: + apdu_len = encode_application_unsigned(&apdu[0], + Network_Port_MSTP_Max_Info_Frames(rpdata->object_instance)); + break; +#endif +#if defined(BACDL_BIP) + case PROP_BACNET_IP_MODE: + apdu_len = encode_application_enumerated(&apdu[0], + Network_Port_BIP_Mode(rpdata->object_instance)); + break; + case PROP_IP_ADDRESS: + Network_Port_IP_Address(rpdata->object_instance, &octet_string); + apdu_len = encode_application_octet_string(&apdu[0], &octet_string); + break; + case PROP_BACNET_IP_UDP_PORT: + apdu_len = encode_application_unsigned(&apdu[0], + Network_Port_BIP_Port(rpdata->object_instance)); + break; + case PROP_IP_SUBNET_MASK: + Network_Port_IP_Subnet(rpdata->object_instance, &octet_string); + apdu_len = encode_application_octet_string(&apdu[0], &octet_string); + break; + case PROP_IP_DEFAULT_GATEWAY: + Network_Port_IP_Gateway(rpdata->object_instance, &octet_string); + apdu_len = encode_application_octet_string(&apdu[0], &octet_string); + break; + case PROP_IP_DNS_SERVER: + if (rpdata->array_index == 0) + /* Array element zero is the number of objects in the list */ + apdu_len = encode_application_unsigned(&apdu[0], BIP_DNS_MAX); + else if (rpdata->array_index == BACNET_ARRAY_ALL) { + /* if no index was specified, then try to encode the entire list */ + /* into one packet. */ + int len; + for (unsigned i = 0; i < BIP_DNS_MAX; i++) { + Network_Port_IP_DNS_Server(rpdata->object_instance, i, + &octet_string); + len = encode_application_octet_string(&apdu[apdu_len], + &octet_string); + apdu_len += len; + } + } else if (rpdata->array_index <= BIP_DNS_MAX) { + /* index was specified; encode a single array element */ + unsigned index; + index = rpdata->array_index - 1; + Network_Port_IP_DNS_Server(rpdata->object_instance, index, + &octet_string); + apdu_len = encode_application_octet_string(&apdu[0], + &octet_string); + } else { + /* index was specified, but out of range */ + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; + apdu_len = BACNET_STATUS_ERROR; + } + break; +#if defined(BBMD_ENABLED) + case PROP_BBMD_ACCEPT_FD_REGISTRATIONS: + apdu_len = encode_application_boolean(&apdu[0], + Network_Port_BBMD_Accept_FD_Registrations( + rpdata->object_instance)); + break; + case PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE: + case PROP_BBMD_FOREIGN_DEVICE_TABLE: + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_READ_ACCESS_DENIED; + apdu_len = BACNET_STATUS_ERROR; + break; +#endif +#endif + default: + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; + apdu_len = BACNET_STATUS_ERROR; + break; + } + + return apdu_len; +} + +/** + * WriteProperty handler for this object. For the given WriteProperty + * data, the application_data is loaded or the error flags are set. + * + * @param wp_data - BACNET_WRITE_PROPERTY_DATA data, including + * requested data and space for the reply, or error response. + * + * @return false if an error is loaded, true if no errors + */ +bool Network_Port_Write_Property( + BACNET_WRITE_PROPERTY_DATA * wp_data) +{ + bool status = false; /* return value */ + int len = 0; + BACNET_APPLICATION_DATA_VALUE value; + + if (!Network_Port_Valid_Instance(wp_data->object_instance)) { + wp_data->error_class = ERROR_CLASS_OBJECT; + wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT; + return false; + } + /* decode the some of the request */ + len = + bacapp_decode_application_data(wp_data->application_data, + wp_data->application_data_len, &value); + if (len < 0) { + /* error while decoding - a value larger than we can handle */ + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + return false; + } + if ((wp_data->object_property != PROP_LINK_SPEEDS) && + (wp_data->object_property != PROP_IP_DNS_SERVER) && + (wp_data->object_property != PROP_IPV6_DNS_SERVER) && + (wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS) && + (wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS_CONFIG) && + (wp_data->object_property != PROP_TAGS) && + (wp_data->array_index != BACNET_ARRAY_ALL)) { + /* only array properties can have array options */ + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; + return false; + } + /* FIXME: len < application_data_len: more data? */ + switch (wp_data->object_property) { + case PROP_MAX_MASTER: + if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { + if (value.type.Unsigned_Int <= 255) { + status = Network_Port_MSTP_Max_Master_Set( + wp_data->object_instance, value.type.Unsigned_Int); + if (!status) { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; + } + break; + case PROP_MAX_INFO_FRAMES: + if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { + if (value.type.Unsigned_Int <= 255) { + status = Network_Port_MSTP_Max_Info_Frames_Set( + wp_data->object_instance, value.type.Unsigned_Int); + if (!status) { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + status = true; + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; + } + break; + case PROP_OBJECT_IDENTIFIER: + case PROP_OBJECT_NAME: + case PROP_OBJECT_TYPE: + case PROP_STATUS_FLAGS: + case PROP_RELIABILITY: + case PROP_OUT_OF_SERVICE: + case PROP_NETWORK_TYPE: + case PROP_PROTOCOL_LEVEL: + case PROP_NETWORK_NUMBER: + case PROP_NETWORK_NUMBER_QUALITY: + case PROP_MAC_ADDRESS: + case PROP_MAX_APDU_LENGTH_ACCEPTED: + case PROP_LINK_SPEED: + case PROP_CHANGES_PENDING: + case PROP_APDU_LENGTH: + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + break; + default: + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; + break; + } + + return status; +} + +/** + * ReadRange service handler for the BACnet/IP BDT. + * + * @param apdu - place to encode the data + * @param apdu - BACNET_READ_RANGE_DATA data + * + * @return number of bytes encoded + */ +int Network_Port_Read_Range_BDT( + uint8_t * apdu, + BACNET_READ_RANGE_DATA * pRequest) +{ + return 0; +} + +/** + * ReadRange service handler for the BACnet/IP FDT. + * + * @param apdu - place to encode the data + * @param apdu - BACNET_READ_RANGE_DATA data + * + * @return number of bytes encoded + */ +int Network_Port_Read_Range_FDT( + uint8_t * apdu, + BACNET_READ_RANGE_DATA * pRequest) +{ + return 0; +} + +bool Network_Port_Read_Range( + BACNET_READ_RANGE_DATA * pRequest, + RR_PROP_INFO * pInfo) +{ + /* return value */ + bool status = false; + + switch (pRequest->object_property) { + /* required properties */ + case PROP_OBJECT_IDENTIFIER: + case PROP_OBJECT_NAME: + case PROP_OBJECT_TYPE: + case PROP_STATUS_FLAGS: + case PROP_RELIABILITY: + case PROP_OUT_OF_SERVICE: + case PROP_NETWORK_TYPE: + case PROP_PROTOCOL_LEVEL: + case PROP_NETWORK_NUMBER: + case PROP_NETWORK_NUMBER_QUALITY: + case PROP_CHANGES_PENDING: + case PROP_APDU_LENGTH: + case PROP_LINK_SPEED: + /* optional properties */ + case PROP_MAC_ADDRESS: + case PROP_MAX_APDU_LENGTH_ACCEPTED: +#if defined(BACDL_MSTP) + case PROP_MAX_MASTER: + case PROP_MAX_INFO_FRAMES: +#elif defined(BACDL_BIP) + case PROP_BACNET_IP_MODE: + case PROP_IP_ADDRESS: + case PROP_BACNET_IP_UDP_PORT: + case PROP_IP_SUBNET_MASK: + case PROP_IP_DEFAULT_GATEWAY: + case PROP_IP_DNS_SERVER: +#if defined(BBMD_ENABLED) + case PROP_BBMD_ACCEPT_FD_REGISTRATIONS: +#endif +#endif + pRequest->error_class = ERROR_CLASS_SERVICES; + pRequest->error_code = ERROR_CODE_PROPERTY_IS_NOT_A_LIST; + break; + case PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE: +#if defined(BACDL_BIP) && defined(BBMD_ENABLED) + pInfo->RequestTypes = RR_BY_POSITION; + pInfo->Handler = Network_Port_Read_Range_BDT; + status = true; +#else + pRequest->error_class = ERROR_CLASS_PROPERTY; + pRequest->error_code = ERROR_CODE_UNKNOWN_PROPERTY; +#endif + break; + case PROP_BBMD_FOREIGN_DEVICE_TABLE: +#if defined(BACDL_BIP) && defined(BBMD_ENABLED) + pInfo->RequestTypes = RR_BY_POSITION; + pInfo->Handler = Network_Port_Read_Range_FDT; + status = true; +#else + pRequest->error_class = ERROR_CLASS_PROPERTY; + pRequest->error_code = ERROR_CODE_UNKNOWN_PROPERTY; +#endif + break; + default: + pRequest->error_class = ERROR_CLASS_PROPERTY; + pRequest->error_code = ERROR_CODE_UNKNOWN_PROPERTY; + break; + } + + return status; +} + +/** + * Initializes the Network Port object data + */ +void Network_Port_Init( + void) +{ + unsigned index = 0; + + for (index = 0; index < BACNET_NETWORK_PORTS_MAX; index++) { + Object_List[index].Instance_Number = index + 1; + Object_List[index].Reliability = RELIABILITY_NO_FAULT_DETECTED; + Object_List[index].Out_Of_Service = false; + Object_List[index].Network_Number = 0; + Object_List[index].Quality = PORT_QUALITY_UNKNOWN; + Object_List[index].APDU_Length = MAX_APDU; + Object_List[index].Link_Speed = 0; +#if defined(BACDL_MSTP) + Object_List[index].Object_Name = "MS/TP Port"; + Object_List[index].Link_Speed = 9600; + Object_List[index].Network_Type = PORT_TYPE_MSTP; + Object_List[index].Network.MSTP.MAC_Address = 255; + Object_List[index].Network.MSTP.Baud_Rate = 9600; + Object_List[index].Network.MSTP.Max_Master = 127; + Object_List[index].Network.MSTP.Max_Info_Frames = 1; +#elif defined(BACDL_BIP) + Object_List[index].Object_Name = "BACnet/IP Port"; + Object_List[index].Link_Speed = 0; + Object_List[index].Network_Type = PORT_TYPE_BIP; + Object_List[index].Network.IPv4.IP_Address[0] = 0; + Object_List[index].Network.IPv4.IP_Address[1] = 0; + Object_List[index].Network.IPv4.IP_Address[2] = 0; + Object_List[index].Network.IPv4.IP_Address[3] = 0; + Object_List[index].Network.IPv4.Port = 0xBAC0; + Object_List[index].Network.IPv4.IP_Subnet_Prefix = 24; + Object_List[index].Network.IPv4.IP_Gateway[0] = 0; + Object_List[index].Network.IPv4.IP_Gateway[1] = 0; + Object_List[index].Network.IPv4.IP_Gateway[2] = 0; + Object_List[index].Network.IPv4.IP_Gateway[3] = 0; +#endif + } +} + +#ifdef BACNET_UNIT_TEST +#include +#include +#include "ctest.h" + +bool WPValidateArgType( + BACNET_APPLICATION_DATA_VALUE * pValue, + uint8_t ucExpectedTag, + BACNET_ERROR_CLASS * pErrorClass, + BACNET_ERROR_CODE * pErrorCode) +{ + pValue = pValue; + ucExpectedTag = ucExpectedTag; + pErrorClass = pErrorClass; + pErrorCode = pErrorCode; + + return false; +} + +void test_network_port( + Test * pTest) +{ + uint8_t apdu[MAX_APDU] = { 0 }; + int len = 0; + int test_len = 0; + BACNET_READ_PROPERTY_DATA rpdata; + /* for decode value data */ + BACNET_APPLICATION_DATA_VALUE value; + const int *pRequired = NULL; + const int *pOptional = NULL; + const int *pProprietary = NULL; + unsigned count = 0; + unsigned index = 0; + + Network_Port_init(); + count = Network_Port_Count(); + for (index = 0; index < count; index++) { + rpdata.application_data = &apdu[0]; + rpdata.application_data_len = sizeof(apdu); + rpdata.object_type = OBJECT_NETWORK_PORT; + rpdata.object_instance = Network_Port_Index_To_Instance(index); + Network_Port_Property_Lists(&pRequired, &pOptional, &pProprietary); + while ((*pRequired) != -1) { + rpdata.object_property = *pRequired; + rpdata.array_index = BACNET_ARRAY_ALL; + len = Network_Port_Read_Property(&rpdata); + ct_test(pTest, len != 0); + test_len = bacapp_decode_application_data( + rpdata.application_data, + (uint8_t) rpdata.application_data_len, + &value); + ct_test(pTest, test_len >= 0); + if (test_len < 0) { + printf("\n"); + } + pRequired++; + } + while ((*pOptional) != -1) { + rpdata.object_property = *pOptional; + rpdata.array_index = BACNET_ARRAY_ALL; + len = Network_Port_Read_Property(&rpdata); + ct_test(pTest, len != 0); + test_len = bacapp_decode_application_data( + rpdata.application_data, + (uint8_t) rpdata.application_data_len, + &value); + ct_test(pTest, test_len >= 0); + if (test_len < 0) { + printf("\n"); + } + pOptional++; + } + } + + return; +} + +#ifdef TEST_NETWORK_PORT +int main( + void) +{ + Test *pTest; + bool rc; + + pTest = ct_create("BACnet Network Port", NULL); + /* individual tests */ + rc = ct_addTestFunction(pTest, test_network_port); + assert(rc); + + ct_setStream(pTest, stdout); + ct_run(pTest); + (void) ct_report(pTest); + ct_destroy(pTest); + + return 0; +} +#endif +#endif /* TEST */ + diff --git a/bacnet-stack/demo/object/netport.h b/bacnet-stack/demo/object/netport.h new file mode 100644 index 00000000..e5e4ba17 --- /dev/null +++ b/bacnet-stack/demo/object/netport.h @@ -0,0 +1,245 @@ +/** + * @file + * @author Steve Karg + * @date 2016 + * @brief Network port objects, customize for your use + * + * @section DESCRIPTION + * + * The Network Port object provides access to the configuration + * and properties of network ports of a device. + * + * @section LICENSE + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef NETPORT_H +#define NETPORT_H + +#include +#include +#include "bacdef.h" +#include "bacenum.h" +#include "apdu.h" +#include "rp.h" +#include "wp.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + void Network_Port_Property_Lists( + const int **pRequired, + const int **pOptional, + const int **pProprietary); + + bool Network_Port_Object_Name( + uint32_t object_instance, + BACNET_CHARACTER_STRING * object_name); + bool Network_Port_Name_Set( + uint32_t object_instance, + char *new_name); + + char *Network_Port_Description( + uint32_t instance); + bool Network_Port_Description_Set( + uint32_t instance, + char *new_name); + + BACNET_RELIABILITY Network_Port_Reliability( + uint32_t object_instance); + bool Network_Port_Reliability_Set( + uint32_t object_instance, + BACNET_RELIABILITY value); + + bool Network_Port_Out_Of_Service( + uint32_t instance); + bool Network_Port_Out_Of_Service_Set( + uint32_t instance, + bool oos_flag); + + uint8_t Network_Port_Type( + uint32_t object_instance); + bool Network_Port_Type_Set( + uint32_t object_instance, + uint8_t value); + + uint16_t Network_Port_Network_Number( + uint32_t object_instance); + bool Network_Port_Network_Number_Set( + uint32_t object_instance, + uint16_t value); + + BACNET_PORT_QUALITY Network_Port_Quality( + uint32_t object_instance); + bool Network_Port_Quality_Set( + uint32_t object_instance, + BACNET_PORT_QUALITY value); + + bool Network_Port_MAC_Address( + uint32_t object_instance, + BACNET_OCTET_STRING *mac_address); + bool Network_Port_MAC_Address_Set( + uint32_t object_instance, + uint8_t *mac_src, + uint8_t mac_len); + + uint16_t Network_Port_APDU_Length( + uint32_t object_instance); + bool Network_Port_APDU_Length_Set( + uint32_t object_instance, + uint16_t value); + + uint8_t Network_Port_MSTP_Max_Master( + uint32_t object_instance); + bool Network_Port_MSTP_Max_Master_Set( + uint32_t object_instance, + uint8_t value); + + uint8_t Network_Port_MSTP_Max_Info_Frames( + uint32_t object_instance); + bool Network_Port_MSTP_Max_Info_Frames_Set( + uint32_t object_instance, + uint8_t value); + + uint32_t Network_Port_Link_Speed( + uint32_t object_instance); + bool Network_Port_Link_Speed_Set( + uint32_t object_instance, + uint32_t value); + + bool Network_Port_IP_Address( + uint32_t object_instance, + BACNET_OCTET_STRING *ip_address); + bool Network_Port_IP_Address_Get( + uint32_t object_instance, + uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d); + bool Network_Port_IP_Address_Set( + uint32_t object_instance, + uint8_t a, uint8_t b, uint8_t c, uint8_t d); + + uint8_t Network_Port_IP_Subnet_Prefix( + uint32_t object_instance); + bool Network_Port_IP_Subnet_Prefix_Set( + uint32_t object_instance, + uint8_t value); + + bool Network_Port_IP_Subnet( + uint32_t object_instance, + BACNET_OCTET_STRING *subnet_mask); + bool Network_Port_IP_Subnet_Get( + uint32_t object_instance, + uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d); + bool Network_Port_IP_Subnet_Set( + uint32_t object_instance, + uint8_t a, uint8_t b, uint8_t c, uint8_t d); + + bool Network_Port_IP_Gateway( + uint32_t object_instance, + BACNET_OCTET_STRING *subnet_mask); + bool Network_Port_IP_Gateway_Get( + uint32_t object_instance, + uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d); + bool Network_Port_IP_Gateway_Set( + uint32_t object_instance, + uint8_t a, uint8_t b, uint8_t c, uint8_t d); + + bool Network_Port_IP_DNS_Server( + uint32_t object_instance, + unsigned index, + BACNET_OCTET_STRING *subnet_mask); + bool Network_Port_IP_DNS_Server_Get( + uint32_t object_instance, + unsigned index, + uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d); + bool Network_Port_IP_DNS_Server_Set( + uint32_t object_instance, + unsigned index, + uint8_t a, uint8_t b, uint8_t c, uint8_t d); + + uint16_t Network_Port_BIP_Port( + uint32_t object_instance); + bool Network_Port_BIP_Port_Set( + uint32_t object_instance, + uint16_t value); + + BACNET_IP_MODE Network_Port_BIP_Mode( + uint32_t object_instance); + bool Network_Port_BIP_Mode_Set( + uint32_t object_instance, + BACNET_IP_MODE value); + + bool Network_Port_BBMD_Accept_FD_Registrations( + uint32_t object_instance); + bool Network_Port_BBMD_Accept_FD_Registrations_Set( + uint32_t object_instance, + bool value); + + bool Network_Port_Changes_Pending( + uint32_t instance); + bool Network_Port_Changes_Pending_Set( + uint32_t instance, + bool flag); + + bool Network_Port_Valid_Instance( + uint32_t object_instance); + unsigned Network_Port_Count( + void); + uint32_t Network_Port_Index_To_Instance( + unsigned find_index); + unsigned Network_Port_Instance_To_Index( + uint32_t object_instance); + + bool Network_Port_Set_Network_Port_Instance_ID( + unsigned index, + uint32_t object_instance); + + int Network_Port_Read_Range_BDT( + uint8_t * apdu, + BACNET_READ_RANGE_DATA * pRequest); + int Network_Port_Read_Range_FDT( + uint8_t * apdu, + BACNET_READ_RANGE_DATA * pRequest); + bool Network_Port_Read_Range( + BACNET_READ_RANGE_DATA * pRequest, + RR_PROP_INFO * pInfo); + + bool Network_Port_Create( + uint32_t object_instance); + bool Network_Port_Delete( + uint32_t object_instance); + void Network_Port_Cleanup( + void); + void Network_Port_Init( + void); + + /* handling for read property service */ + int Network_Port_Read_Property( + BACNET_READ_PROPERTY_DATA * rpdata); + + /* handling for write property service */ + bool Network_Port_Write_Property( + BACNET_WRITE_PROPERTY_DATA * wp_data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif diff --git a/bacnet-stack/demo/object/netport.mak b/bacnet-stack/demo/object/netport.mak new file mode 100644 index 00000000..f2793b12 --- /dev/null +++ b/bacnet-stack/demo/object/netport.mak @@ -0,0 +1,42 @@ +#Makefile to build test case +CC = gcc +SRC_DIR = ../../src +TEST_DIR = ../../test +INCLUDES = -I../../include -I$(TEST_DIR) -I. +DEFINES = -DBIG_ENDIAN=0 -DBACNET_UNIT_TEST -DBACAPP_ALL -DTEST_NETWORK_PORT + +CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g + +SRCS = netport.c \ + $(SRC_DIR)/bacdcode.c \ + $(SRC_DIR)/bacint.c \ + $(SRC_DIR)/bacstr.c \ + $(SRC_DIR)/bacreal.c \ + $(SRC_DIR)/datetime.c \ + $(SRC_DIR)/bacapp.c \ + $(SRC_DIR)/bacdevobjpropref.c \ + $(SRC_DIR)/bactext.c \ + $(SRC_DIR)/lighting.c \ + $(SRC_DIR)/indtext.c \ + $(TEST_DIR)/ctest.c + +TARGET = network_port + +all: ${TARGET} + +OBJS = ${SRCS:.c=.o} + +${TARGET}: ${OBJS} + ${CC} -o $@ ${OBJS} + +.c.o: + ${CC} -c ${CFLAGS} $*.c -o $@ + +depend: + rm -f .depend + ${CC} -MM ${CFLAGS} *.c >> .depend + +clean: + rm -rf core ${TARGET} $(OBJS) + +include: .depend diff --git a/bacnet-stack/demo/piface/Makefile b/bacnet-stack/demo/piface/Makefile index 07727afc..01c3279a 100644 --- a/bacnet-stack/demo/piface/Makefile +++ b/bacnet-stack/demo/piface/Makefile @@ -83,7 +83,8 @@ DEMOSRC = \ OBJSRC = \ $(BACNET_OBJECT)/bi.c \ - $(BACNET_OBJECT)/bo.c + $(BACNET_OBJECT)/bo.c \ + $(BACNET_OBJECT)/netport.c # core BACnet stack files CORESRC = \ @@ -171,8 +172,8 @@ OPTIMIZATION = -Os $(OPTIMIZE_FLAGS) DEBUGGING = -DNDEBUG endif +BFLAGS += -DBACNET_PROTOCOL_REVISION=17 BFLAGS += -DMAX_TSM_TRANSACTIONS=1 -BFLAGS += -DWRITE_PROPERTY BFLAGS += -DMAX_BINARY_INPUTS=4 BFLAGS += -DMAX_BINARY_OUTPUTS=8 diff --git a/bacnet-stack/demo/piface/device.c b/bacnet-stack/demo/piface/device.c index 7cb0fcac..57f40809 100644 --- a/bacnet-stack/demo/piface/device.c +++ b/bacnet-stack/demo/piface/device.c @@ -46,6 +46,9 @@ #include "device.h" #include "bi.h" #include "bo.h" +#if (BACNET_PROTOCOL_REVISION >= 17) +#include "netport.h" +#endif /* local forward (semi-private) and external prototypes */ int Device_Read_Property_Local( @@ -76,6 +79,23 @@ static object_functions_t My_Object_Table[] = { NULL /* COV */ , NULL /* COV Clear */ , NULL /* Intrinsic Reporting */ }, +#if (BACNET_PROTOCOL_REVISION >= 17) + {OBJECT_NETWORK_PORT, + Network_Port_Init, + Network_Port_Count, + Network_Port_Index_To_Instance, + Network_Port_Valid_Instance, + Network_Port_Object_Name, + Network_Port_Read_Property, + Network_Port_Write_Property, + Network_Port_Property_Lists, + NULL /* ReadRangeInfo */ , + NULL /* Iterator */ , + NULL /* Value_Lists */ , + NULL /* COV */ , + NULL /* COV Clear */ , + NULL /* Intrinsic Reporting */ }, +#endif {OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count, diff --git a/bacnet-stack/demo/ptransfer/Makefile b/bacnet-stack/demo/ptransfer/Makefile index b1b9867d..2f01a776 100644 --- a/bacnet-stack/demo/ptransfer/Makefile +++ b/bacnet-stack/demo/ptransfer/Makefile @@ -15,6 +15,7 @@ TARGET = ptransfer TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/readbdt/Makefile b/bacnet-stack/demo/readbdt/Makefile index bed0d5c8..929864e5 100644 --- a/bacnet-stack/demo/readbdt/Makefile +++ b/bacnet-stack/demo/readbdt/Makefile @@ -9,6 +9,7 @@ TARGET = bacrbdt TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/readfile/Makefile b/bacnet-stack/demo/readfile/Makefile index 235f65c7..3548774a 100644 --- a/bacnet-stack/demo/readfile/Makefile +++ b/bacnet-stack/demo/readfile/Makefile @@ -9,6 +9,7 @@ TARGET = bacarf TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/readprop/Makefile b/bacnet-stack/demo/readprop/Makefile index 836ee012..4aab27a5 100644 --- a/bacnet-stack/demo/readprop/Makefile +++ b/bacnet-stack/demo/readprop/Makefile @@ -15,6 +15,7 @@ TARGET = bacrp TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/readpropm/Makefile b/bacnet-stack/demo/readpropm/Makefile index 271aa735..12630050 100644 --- a/bacnet-stack/demo/readpropm/Makefile +++ b/bacnet-stack/demo/readpropm/Makefile @@ -10,6 +10,7 @@ TARGET = bacrpm TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/readrange/Makefile b/bacnet-stack/demo/readrange/Makefile index ab5b6b34..67b3b435 100644 --- a/bacnet-stack/demo/readrange/Makefile +++ b/bacnet-stack/demo/readrange/Makefile @@ -15,6 +15,7 @@ TARGET = bacrr TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/reinit/Makefile b/bacnet-stack/demo/reinit/Makefile index 42984e9f..52e64950 100644 --- a/bacnet-stack/demo/reinit/Makefile +++ b/bacnet-stack/demo/reinit/Makefile @@ -10,6 +10,7 @@ TARGET = bacrd TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/router-ipv6/Makefile b/bacnet-stack/demo/router-ipv6/Makefile index 920c6887..23a4516a 100644 --- a/bacnet-stack/demo/router-ipv6/Makefile +++ b/bacnet-stack/demo/router-ipv6/Makefile @@ -16,6 +16,7 @@ BACNET_HANDLER_DIR = ../handler BACNET_OBJECT_DIR = ../object SRC = main.c \ + $(BACNET_OBJECT_DIR)/netport.c \ $(BACNET_OBJECT_DIR)/device-client.c PORT_BIP6_SRC = \ diff --git a/bacnet-stack/demo/scov/Makefile b/bacnet-stack/demo/scov/Makefile index 763de597..9349f6b0 100644 --- a/bacnet-stack/demo/scov/Makefile +++ b/bacnet-stack/demo/scov/Makefile @@ -15,6 +15,7 @@ TARGET = bacscov TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/server/Makefile b/bacnet-stack/demo/server/Makefile index 0ba1b741..43e768a0 100644 --- a/bacnet-stack/demo/server/Makefile +++ b/bacnet-stack/demo/server/Makefile @@ -32,6 +32,7 @@ OBJECT_SRC = \ $(BACNET_OBJECT)/osv.c \ $(BACNET_OBJECT)/piv.c \ $(BACNET_OBJECT)/nc.c \ + $(BACNET_OBJECT)/netport.c \ $(BACNET_OBJECT)/trendlog.c \ $(BACNET_OBJECT)/schedule.c \ $(BACNET_OBJECT)/access_credential.c \ diff --git a/bacnet-stack/demo/timesync/Makefile b/bacnet-stack/demo/timesync/Makefile index 28ce9043..99c09b34 100644 --- a/bacnet-stack/demo/timesync/Makefile +++ b/bacnet-stack/demo/timesync/Makefile @@ -10,6 +10,7 @@ TARGET = bacts TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/ucov/Makefile b/bacnet-stack/demo/ucov/Makefile index 703cd74f..806e30b7 100644 --- a/bacnet-stack/demo/ucov/Makefile +++ b/bacnet-stack/demo/ucov/Makefile @@ -10,6 +10,7 @@ TARGET = bacucov TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/uevent/Makefile b/bacnet-stack/demo/uevent/Makefile index e83dd307..3f96cc07 100644 --- a/bacnet-stack/demo/uevent/Makefile +++ b/bacnet-stack/demo/uevent/Makefile @@ -10,6 +10,7 @@ TARGET = bacuevent TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/uptransfer/Makefile b/bacnet-stack/demo/uptransfer/Makefile index 8281c24c..4c1b6d1a 100644 --- a/bacnet-stack/demo/uptransfer/Makefile +++ b/bacnet-stack/demo/uptransfer/Makefile @@ -15,6 +15,7 @@ TARGET = bacupt TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/whohas/Makefile b/bacnet-stack/demo/whohas/Makefile index 57387a3e..39dd148e 100644 --- a/bacnet-stack/demo/whohas/Makefile +++ b/bacnet-stack/demo/whohas/Makefile @@ -10,6 +10,7 @@ TARGET = bacwh TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/whois/Makefile b/bacnet-stack/demo/whois/Makefile index 2c117481..640313bd 100644 --- a/bacnet-stack/demo/whois/Makefile +++ b/bacnet-stack/demo/whois/Makefile @@ -9,6 +9,7 @@ TARGET = bacwi TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/whoisrouter/Makefile b/bacnet-stack/demo/whoisrouter/Makefile index 4940d32e..b48220c1 100644 --- a/bacnet-stack/demo/whoisrouter/Makefile +++ b/bacnet-stack/demo/whoisrouter/Makefile @@ -9,6 +9,7 @@ TARGET = bacwir TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/writefile/Makefile b/bacnet-stack/demo/writefile/Makefile index f26b1fe4..a2cee74e 100644 --- a/bacnet-stack/demo/writefile/Makefile +++ b/bacnet-stack/demo/writefile/Makefile @@ -10,6 +10,7 @@ TARGET = bacawf TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/writeprop/Makefile b/bacnet-stack/demo/writeprop/Makefile index 5a9587f7..e3890331 100644 --- a/bacnet-stack/demo/writeprop/Makefile +++ b/bacnet-stack/demo/writeprop/Makefile @@ -10,6 +10,7 @@ TARGET = bacwp TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/demo/writepropm/Makefile b/bacnet-stack/demo/writepropm/Makefile index 064dc687..069152e1 100644 --- a/bacnet-stack/demo/writepropm/Makefile +++ b/bacnet-stack/demo/writepropm/Makefile @@ -10,6 +10,7 @@ TARGET = bacwpm TARGET_BIN = ${TARGET}$(TARGET_EXT) SRCS = main.c \ + ../object/netport.c \ ../object/device-client.c OBJS = ${SRCS:.c=.o} diff --git a/bacnet-stack/include/bacenum.h b/bacnet-stack/include/bacenum.h index 2c190fd6..c8a3f212 100644 --- a/bacnet-stack/include/bacenum.h +++ b/bacnet-stack/include/bacenum.h @@ -2346,4 +2346,17 @@ typedef enum BACnetNetworkPortCommand_T { NETWORK_PORT_COMMAND_PROPRIETARY_MAX = 255 } BACNET_NETWORK_PORT_COMMAND; +typedef enum BACnetProtocolLevel_T { + BACNET_PROTOCOL_LEVEL_PHYSICAL=0, + BACNET_PROTOCOL_LEVEL_PROTOCOL=1, + BACNET_PROTOCOL_LEVEL_BACNET_APPLICATION=2, + BACNET_PROTOCOL_LEVEL_NON_BACNET_APPLICATION=3 +} BACNET_PROTOCOL_LEVEL; + +typedef enum BACnetIPMode_T { + BACNET_IP_MODE_NORMAL = 0, + BACNET_IP_MODE_FOREIGN = 1, + BACNET_IP_MODE_BBMD = 2 +} BACNET_IP_MODE; + #endif /* end of BACENUM_H */