diff --git a/src/bacnet/bacaddr.c b/src/bacnet/bacaddr.c index 1e9c3927..b0788e1f 100644 --- a/src/bacnet/bacaddr.c +++ b/src/bacnet/bacaddr.c @@ -415,3 +415,127 @@ int decode_context_bacnet_address( { return bacnet_address_context_decode(apdu, MAX_APDU, tag_number, value); } + +/** + * @brief Encode a BACnetVMACEntry value + * + * BACnetVMACEntry ::= SEQUENCE { + * virtual-mac-address[0]OctetString, -- maximum size 6 octets + * native-mac-address[1]OctetString + * + * @param apdu - buffer of data to be encoded + * @param apdu_size - number of bytes in the buffer + * @param value - decoded value, if decoded (if not NULL) + * + * @return the number of apdu bytes consumed, or #BACNET_STATUS_ERROR (-1) + */ +int bacnet_vmac_entry_data_encode(uint8_t *apdu, const BACNET_VMAC_ENTRY *value) +{ + int apdu_len = 0, len; + BACNET_OCTET_STRING address = { 0 }; + + if (!value) { + return 0; + } + /* virtual-mac-address [0] OctetString */ + octetstring_init( + &address, value->virtual_mac_address.adr, + value->virtual_mac_address.len); + len = encode_context_octet_string(apdu, 0, &address); + apdu_len += len; + if (apdu) { + apdu += len; + } + /* native-mac-address */ + octetstring_init( + &address, value->native_mac_address, value->native_mac_address_len); + len = encode_context_octet_string(apdu, 1, &address); + apdu_len += len; + + return apdu_len; +} + +/** + * @brief Encode a BACnetVMACEntry value + * @param apdu - buffer of data to be encoded + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return the number of apdu bytes encoded, or 0 if not encoded + */ +int bacnet_vmac_entry_encode( + uint8_t *apdu, uint32_t apdu_size, const BACNET_VMAC_ENTRY *value) +{ + size_t apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = bacnet_vmac_entry_data_encode(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = bacnet_vmac_entry_data_encode(apdu, value); + } + + return apdu_len; +} + +/** + * @brief Decodes a BACnetVMACEntry value from a buffer + * From clause 21. FORMAL DESCRIPTION OF APPLICATION PROTOCOL DATA UNITS + * + * BACnetVMACEntry ::= SEQUENCE { + * virtual-mac-address [0] OctetString, -- maximum size 6 octets + * native-mac-address [1] OctetString + * + * @param apdu - buffer of data to be decoded + * @param apdu_size - number of bytes in the buffer + * @param value - decoded value, if decoded (if not NULL) + * + * @return the number of apdu bytes consumed, or #BACNET_STATUS_ERROR (-1) + */ +int bacnet_vmac_entry_decode( + const uint8_t *apdu, uint32_t apdu_size, BACNET_VMAC_ENTRY *value) +{ + int len = 0; + int apdu_len = 0; + size_t i = 0; + BACNET_OCTET_STRING mac_addr = { 0 }; + + /* virtual-mac-address [0] OctetString */ + len = bacnet_octet_string_context_decode( + &apdu[apdu_len], apdu_size - apdu_len, 0, &mac_addr); + if (len <= 0) { + return BACNET_STATUS_ERROR; + } + if (value) { + if (mac_addr.length > sizeof(value->virtual_mac_address.adr)) { + return BACNET_STATUS_ERROR; + } + /* bounds checking - passed! */ + value->virtual_mac_address.len = mac_addr.length; + /* copy address */ + for (i = 0; i < mac_addr.length; i++) { + value->virtual_mac_address.adr[i] = mac_addr.value[i]; + } + } + apdu_len += len; + /* native-mac-address [1] OctetString */ + len = bacnet_octet_string_context_decode( + &apdu[apdu_len], apdu_size - apdu_len, 1, &mac_addr); + if (len <= 0) { + return BACNET_STATUS_ERROR; + } + if (value) { + if (mac_addr.length > sizeof(value->native_mac_address)) { + return BACNET_STATUS_ERROR; + } + /* bounds checking - passed! */ + value->native_mac_address_len = mac_addr.length; + /* copy address */ + for (i = 0; i < mac_addr.length; i++) { + value->native_mac_address[i] = mac_addr.value[i]; + } + } + apdu_len += len; + + return apdu_len; +} diff --git a/src/bacnet/bacaddr.h b/src/bacnet/bacaddr.h index ba84c4a3..cb7a2e71 100644 --- a/src/bacnet/bacaddr.h +++ b/src/bacnet/bacaddr.h @@ -14,6 +14,22 @@ /* BACnet Stack defines - first */ #include "bacnet/bacdef.h" +/* define the max MAC as big as IPv6 + port number */ +#ifndef BACNET_VMAC_MAC_MAX +#define BACNET_VMAC_MAC_MAX 18 +#endif + +/** BACnetVMACEntry ::= SEQUENCE { + * virtual-mac-address[0]OctetString, -- maximum size 6 octets + * native-mac-address[1]OctetString + */ +typedef struct BACnetVMACEntry { + BACNET_MAC_ADDRESS virtual_mac_address; + uint8_t native_mac_address_len; + uint8_t native_mac_address[BACNET_VMAC_MAC_MAX]; + struct BACnetVMACEntry *next; +} BACNET_VMAC_ENTRY; + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -62,6 +78,16 @@ BACNET_STACK_EXPORT int decode_context_bacnet_address( const uint8_t *apdu, uint8_t tag_number, BACNET_ADDRESS *destination); +BACNET_STACK_EXPORT +int bacnet_vmac_entry_data_encode( + uint8_t *apdu, const BACNET_VMAC_ENTRY *value); +BACNET_STACK_EXPORT +int bacnet_vmac_entry_encode( + uint8_t *apdu, uint32_t apdu_size, const BACNET_VMAC_ENTRY *value); +BACNET_STACK_EXPORT +int bacnet_vmac_entry_decode( + const uint8_t *apdu, uint32_t apdu_size, BACNET_VMAC_ENTRY *value); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/bacnet/basic/bbmd6/vmac.c b/src/bacnet/basic/bbmd6/vmac.c index 1f7f1562..20c734f7 100644 --- a/src/bacnet/basic/bbmd6/vmac.c +++ b/src/bacnet/basic/bbmd6/vmac.c @@ -119,6 +119,45 @@ struct vmac_data *VMAC_Find_By_Key(uint32_t device_id) return Keylist_Data(VMAC_List, device_id); } +/** + * Finds a VMAC in the list by seeking the list index + * + * @param index - Index that shall be returned + * @param device_id - BACnet device object instance number + * + * @return true if the device_id and vmac are found + */ +bool VMAC_Entry_By_Index(int index, uint32_t *device_id, struct vmac_data *vmac) +{ + bool status = false; + struct vmac_data *data; + KEY key = 0; + uint8_t i; + + data = Keylist_Data_Index(VMAC_List, index); + if (data) { + /* virtual MAC is the Device ID */ + status = Keylist_Index_Key(VMAC_List, index, &key); + if (status) { + if (device_id) { + *device_id = key; + } + if (vmac) { + for (i = 0; i < sizeof(vmac->mac); i++) { + if (i < data->mac_len) { + vmac->mac[i] = data->mac[i]; + } else { + break; + } + } + vmac->mac_len = data->mac_len; + } + } + } + + return status; +} + /** Compare the VMAC address * * @param vmac1 - VMAC address that will be compared to vmac2 diff --git a/src/bacnet/basic/bbmd6/vmac.h b/src/bacnet/basic/bbmd6/vmac.h index 1943f96b..d1ed6a16 100644 --- a/src/bacnet/basic/bbmd6/vmac.h +++ b/src/bacnet/basic/bbmd6/vmac.h @@ -35,6 +35,9 @@ unsigned int VMAC_Count(void); BACNET_STACK_EXPORT struct vmac_data *VMAC_Find_By_Key(uint32_t device_id); BACNET_STACK_EXPORT +bool VMAC_Entry_By_Index( + int index, uint32_t *device_id, struct vmac_data *vmac); +BACNET_STACK_EXPORT bool VMAC_Find_By_Data(const struct vmac_data *vmac, uint32_t *device_id); BACNET_STACK_EXPORT bool VMAC_Add(uint32_t device_id, const struct vmac_data *pVMAC); diff --git a/src/bacnet/basic/object/netport.c b/src/bacnet/basic/object/netport.c index 9c235e08..d35ae37d 100644 --- a/src/bacnet/basic/object/netport.c +++ b/src/bacnet/basic/object/netport.c @@ -85,6 +85,10 @@ struct ethernet_port { uint8_t MAC_Address[6]; }; +struct bacnet_zigbee_port { + uint8_t MAC_Address[3]; +}; + struct mstp_port { uint8_t MAC_Address; uint8_t Max_Master; @@ -114,6 +118,7 @@ struct object_data { struct bacnet_ipv4_port IPv4; struct bacnet_ipv6_port IPv6; struct ethernet_port Ethernet; + struct bacnet_zigbee_port Zigbee; struct mstp_port MSTP; struct bsc_port BSC; } Network; @@ -163,6 +168,20 @@ static const int Ethernet_Port_Properties_Optional[] = { -1 }; +static const int Zigbee_Port_Properties_Optional[] = { + /* unordered list of optional properties */ + PROP_DESCRIPTION, + PROP_MAC_ADDRESS, + PROP_VIRTUAL_MAC_ADDRESS_TABLE, +#if (BACNET_PROTOCOL_REVISION >= 24) + PROP_APDU_LENGTH, + PROP_NETWORK_NUMBER, + PROP_NETWORK_NUMBER_QUALITY, + PROP_LINK_SPEED, +#endif + -1 +}; + static const int MSTP_Port_Properties_Optional[] = { /* unordered list of optional properties */ PROP_DESCRIPTION, @@ -224,6 +243,7 @@ static const int BIP6_Port_Properties_Optional[] = { PROP_IPV6_DEFAULT_GATEWAY, PROP_BACNET_IPV6_MULTICAST_ADDRESS, PROP_IPV6_DNS_SERVER, + PROP_VIRTUAL_MAC_ADDRESS_TABLE, #if defined(BACDL_BIP6) && (BACNET_NETWORK_PORT_IP_DHCP_ENABLED) PROP_IPV6_AUTO_ADDRESSING_ENABLE, PROP_IPV6_DHCP_LEASE_TIME, @@ -337,6 +357,9 @@ void Network_Port_Property_List( case PORT_TYPE_BIP6: *pOptional = BIP6_Port_Properties_Optional; break; + case PORT_TYPE_ZIGBEE: + *pOptional = Zigbee_Port_Properties_Optional; + break; case PORT_TYPE_ETHERNET: default: *pOptional = Ethernet_Port_Properties_Optional; @@ -857,6 +880,10 @@ uint8_t Network_Port_MAC_Address_Value( mac_len = sizeof(Object_List[index].Network.Ethernet.MAC_Address); break; + case PORT_TYPE_ZIGBEE: + mac = &Object_List[index].Network.Zigbee.MAC_Address[0]; + mac_len = sizeof(Object_List[index].Network.Zigbee.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); @@ -941,6 +968,11 @@ bool Network_Port_MAC_Address_Set( mac_size = sizeof(Object_List[index].Network.Ethernet.MAC_Address); break; + case PORT_TYPE_ZIGBEE: + mac_dest = &Object_List[index].Network.Zigbee.MAC_Address[0]; + mac_size = + sizeof(Object_List[index].Network.Zigbee.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); @@ -3909,6 +3941,35 @@ bool Network_Port_MSTP_Max_Info_Frames_Set( return status; } +/** + * @brief Encode a Calendar entity list complex data type + * + * @param object_instance - object-instance number of the object + * @param apdu - the APDU buffer + * @param apdu_size - size of the apdu buffer. + * + * @return bytes encoded or zero on error. + */ +static int Network_Port_Virtual_MAC_Table_Encode( + uint32_t object_instance, uint8_t *apdu, int max_apdu) +{ + int apdu_len = 0; + unsigned index = 0; + + (void)apdu; + (void)max_apdu; + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (Object_List[index].Network_Type == PORT_TYPE_BIP6) { + /* fixme: add abstraction to get the BACnetLIST */ + } else if (Object_List[index].Network_Type == PORT_TYPE_ZIGBEE) { + /* fixme: add abstraction to get the BACnetLIST */ + } + } + + return apdu_len; +} + /** * ReadProperty handler for this object. For the given ReadProperty * data, the application_data is loaded or the error flags are set. @@ -4190,6 +4251,11 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) apdu_len = encode_application_character_string(&apdu[0], &char_string); break; + case PROP_VIRTUAL_MAC_ADDRESS_TABLE: + /* BACnetLIST of BACnetVMACEntry */ + apdu_len = Network_Port_Virtual_MAC_Table_Encode( + rpdata->object_instance, apdu, apdu_size); + break; #ifdef BACDL_BSC case PROP_MAX_BVLC_LENGTH_ACCEPTED: apdu_len = encode_application_unsigned( diff --git a/src/bacnet/config.h b/src/bacnet/config.h index 00e08c29..8626267a 100644 --- a/src/bacnet/config.h +++ b/src/bacnet/config.h @@ -32,6 +32,7 @@ #define BACDL_BIP #define BACDL_BIP6 #define BACDL_BSC +#define BACDL_ZIGBEE #endif #if defined(BACDL_ETHERNET) @@ -73,6 +74,13 @@ #define BACDL_SOME_DATALINK_ENABLED 1 #endif +#if defined(BACDL_ZIGBEE) +#if defined(BACDL_SOME_DATALINK_ENABLED) +#define BACDL_MULTIPLE 1 +#endif +#define BACDL_SOME_DATALINK_ENABLED 1 +#endif + #if defined(BACDL_CUSTOM) #if defined(BACDL_SOME_DATALINK_ENABLED) #define BACDL_MULTIPLE 1 @@ -137,6 +145,8 @@ /* #define MAX_APDU 128 */ #elif defined(BACDL_BIP6) #define MAX_APDU 1476 +#elif defined(BACDL_ZIGBEE) +#define MAX_APDU 480 #elif defined(BACDL_MSTP) && !defined(BACNET_SECURITY) /* note: MS/TP extended frames can be up to 1476 bytes */ #define MAX_APDU 480 diff --git a/src/bacnet/datalink/bzll.h b/src/bacnet/datalink/bzll.h new file mode 100644 index 00000000..2d81ba9c --- /dev/null +++ b/src/bacnet/datalink/bzll.h @@ -0,0 +1,62 @@ +/** + * @file + * @brief A BACnet/ZigBee Data Link Layer (BZLL) + * @author Steve Karg + * @date July 2025 + * @copyright SPDX-License-Identifier: MIT + * @defgroup DL_ZIGBEE BACnet/ZigBee Data Link Layer (BZLL) + * @ingroup DataLink + */ +#ifndef BACNET_ZIGBEE_LINK_LAYER_H +#define BACNET_ZIGBEE_LINK_LAYER_H + +#include +#include +#include +/* BACnet Stack defines - first */ +#include "bacnet/bacdef.h" +/* BACnet Stack API */ +#include "bacnet/npdu.h" + +/* ZigBee Cluster Library (ZCL) client to server frame */ +#define BZLL_HEADER_MAX (1 + 1) +#define BZLL_MPDU_MAX (BZLL_HEADER_MAX + MAX_PDU) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +BACNET_STACK_EXPORT +bool bzll_valid(void); +BACNET_STACK_EXPORT +void bzll_cleanup(void); +BACNET_STACK_EXPORT +bool bzll_init(char *interface_name); + +BACNET_STACK_EXPORT +int bzll_send_pdu( + BACNET_ADDRESS *dest, + BACNET_NPDU_DATA *npdu_data, + uint8_t *pdu, + unsigned pdu_len); + +BACNET_STACK_EXPORT +uint16_t bzll_receive( + BACNET_ADDRESS *src, uint8_t *pdu, uint16_t max_pdu, unsigned timeout); +BACNET_STACK_EXPORT +int bzll_send(uint8_t *mtu, int mtu_len); + +BACNET_STACK_EXPORT +void bzll_set_my_address(const BACNET_ADDRESS *my_address); +BACNET_STACK_EXPORT +void bzll_get_my_address(BACNET_ADDRESS *my_address); +BACNET_STACK_EXPORT +void bzll_get_broadcast_address(BACNET_ADDRESS *dest); + +BACNET_STACK_EXPORT +void bzll_maintenance_timer(uint16_t seconds); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif diff --git a/src/bacnet/datalink/datalink.c b/src/bacnet/datalink/datalink.c index 647ceecf..c402b363 100644 --- a/src/bacnet/datalink/datalink.c +++ b/src/bacnet/datalink/datalink.c @@ -30,6 +30,9 @@ #if defined(BACDL_MSTP) #include "bacnet/datalink/dlmstp.h" #endif +#if defined(BACDL_ZIGBEE) +#include "bacnet/datalink/bzll.h" +#endif #if defined(BACDL_BSC) #include "bacnet/datalink/bsc/bsc-datalink.h" #endif @@ -41,6 +44,7 @@ static enum { DATALINK_BIP, DATALINK_BIP6, DATALINK_MSTP, + DATALINK_ZIGBEE, DATALINK_BSC } Datalink_Transport; @@ -74,6 +78,11 @@ void datalink_set(char *datalink_string) Datalink_Transport = DATALINK_MSTP; } #endif +#if defined(BACDL_ZIGBEE) + else if (bacnet_stricmp("zigbee", datalink_string) == 0) { + Datalink_Transport = DATALINK_ARCNET; + } +#endif #if defined(BACDL_BSC) else if (bacnet_stricmp("bsc", datalink_string) == 0) { Datalink_Transport = DATALINK_BSC; @@ -114,6 +123,11 @@ bool datalink_init(char *ifname) status = dlmstp_init(ifname); break; #endif +#if defined(BACDL_ZIGBEE) + case DATALINK_ZIGBEE: + status = bzll_init(ifname); + break; +#endif #if defined(BACDL_BSC) case DATALINK_BSC: status = bsc_init(ifname); @@ -163,6 +177,11 @@ int datalink_send_pdu( bytes = dlmstp_send_pdu(dest, npdu_data, pdu, pdu_len); break; #endif +#if defined(BACDL_ZIGBEE) + case DATALINK_ZIGBEE: + bytes = bzll_send_pdu(dest, npdu_data, pdu, pdu_len); + break; +#endif #if defined(BACDL_BSC) case DATALINK_BSC: bytes = bsc_send_pdu(dest, npdu_data, pdu, pdu_len); @@ -208,6 +227,11 @@ uint16_t datalink_receive( bytes = dlmstp_receive(src, pdu, max_pdu, timeout); break; #endif +#if defined(BACDL_ZIGBEE) + case DATALINK_ZIGBEE: + bytes = bzll_receive(src, pdu, max_pdu, timeout); + break; +#endif #if defined(BACDL_BSC) case DATALINK_BSC: bytes = bsc_receive(src, pdu, max_pdu, timeout); @@ -250,6 +274,11 @@ void datalink_cleanup(void) dlmstp_cleanup(); break; #endif +#if defined(BACDL_ZIGBEE) + case DATALINK_ZIGBEE: + bytes = bzll_cleanup(); + break; +#endif #if defined(BACDL_BSC) case DATALINK_BSC: bsc_cleanup(); @@ -290,6 +319,11 @@ void datalink_get_broadcast_address(BACNET_ADDRESS *dest) dlmstp_get_broadcast_address(dest); break; #endif +#if defined(BACDL_ZIGBEE) + case DATALINK_ZIGBEE: + bytes = bzll_get_broadcast_address(dest); + break; +#endif #if defined(BACDL_BSC) case DATALINK_BSC: bsc_get_broadcast_address(dest); @@ -330,6 +364,11 @@ void datalink_get_my_address(BACNET_ADDRESS *my_address) dlmstp_get_my_address(my_address); break; #endif +#if defined(BACDL_ZIGBEE) + case DATALINK_ZIGBEE: + bytes = bzll_get_my_address(my_address); + break; +#endif #if defined(BACDL_BSC) case DATALINK_BSC: bsc_get_my_address(my_address); @@ -371,6 +410,11 @@ void datalink_set_interface(char *ifname) (void)ifname; break; #endif +#if defined(BACDL_ZIGBEE) + case DATALINK_ZIGBEE: + (void)ifname; + break; +#endif #if defined(BACDL_BSC) case DATALINK_BSC: (void)ifname; @@ -408,6 +452,11 @@ void datalink_maintenance_timer(uint16_t seconds) case DATALINK_MSTP: break; #endif +#if defined(BACDL_ZIGBEE) + case DATALINK_ZIGBEE: + bzll_maintenance_timer(seconds); + break; +#endif #if defined(BACDL_BSC) case DATALINK_BSC: bsc_maintenance_timer(seconds); diff --git a/src/bacnet/datalink/datalink.h b/src/bacnet/datalink/datalink.h index dab988ca..83a0e1c0 100644 --- a/src/bacnet/datalink/datalink.h +++ b/src/bacnet/datalink/datalink.h @@ -31,7 +31,9 @@ #include "bacnet/datalink/bvlc6.h" #include "bacnet/basic/bbmd6/h_bbmd6.h" #endif - +#if defined(BACDL_ZIGBEE) +#include "bacnet/datalink/bzll.h" +#endif #if defined(BACDL_BSC) #include "bacnet/datalink/bsc/bsc-conf.h" #include "bacnet/datalink/bsc/bsc-datalink.h" @@ -104,6 +106,18 @@ void routed_get_my_address(BACNET_ADDRESS *my_address); #define datalink_get_my_address bip6_get_my_address #define datalink_maintenance_timer(s) bvlc6_maintenance_timer(s) +#elif defined(BACDL_ZIGBEE) && !defined(BACDL_MULTIPLE) +/* A BACnet/ZigBee Data Link Layer (BZLL) */ +#define MAX_MPDU BZLL_MPDU_MAX + +#define datalink_init bzll_init +#define datalink_send_pdu bzll_send_pdu +#define datalink_receive bzll_receive +#define datalink_cleanup bzll_cleanup +#define datalink_get_broadcast_address bzll_get_broadcast_address +#define datalink_get_my_address bzll_get_my_address +#define datalink_maintenance_timer bzll_maintenance_timer + #elif defined(BACDL_BSC) && !defined(BACDL_MULTIPLE) #define MAX_MPDU BVLC_SC_NPDU_SIZE_CONF diff --git a/src/bacnet/datalink/dlenv.c b/src/bacnet/datalink/dlenv.c index 70e4b213..d0c976f8 100644 --- a/src/bacnet/datalink/dlenv.c +++ b/src/bacnet/datalink/dlenv.c @@ -580,6 +580,34 @@ void dlenv_network_port_bip6_init(uint32_t instance) Network_Port_Changes_Pending_Set(instance, false); } +/** + * Datalink network port object settings + */ +void dlenv_network_port_zigbee_init(uint32_t instance) +{ + BACNET_ADDRESS addr = { 0 }; + char *pEnv = NULL; + + pEnv = getenv("BACNET_ZIGBEE_DEBUG"); + if (pEnv) { + dlenv_debug_enable(); + } + Network_Port_Object_Instance_Number_Set(0, instance); + Network_Port_Name_Set(instance, "BACnet Zigbee Link Layer Port"); + Network_Port_Type_Set(instance, PORT_TYPE_ZIGBEE); + addr.mac_len = encode_unsigned24(&addr.mac[0], instance); + Network_Port_MAC_Address_Set(instance, &addr.mac[0], addr.mac_len); + Network_Port_Reliability_Set(instance, RELIABILITY_NO_FAULT_DETECTED); + Network_Port_Link_Speed_Set(instance, 0.0); + Network_Port_Out_Of_Service_Set(instance, false); + Network_Port_Quality_Set(instance, PORT_QUALITY_UNKNOWN); + Network_Port_APDU_Length_Set(instance, MAX_APDU); + Network_Port_Network_Number_Set(instance, 0); + /* last thing - clear pending changes - we don't want to set these + since they are already set */ + Network_Port_Changes_Pending_Set(instance, false); +} + /** * @brief Datalink network port object settings */ @@ -929,6 +957,9 @@ void dlenv_init(void) #elif defined(BACDL_ARCNET) datalink_set("arcnet"); port_type = PORT_TYPE_ARCNET; +#elif defined(BACDL_ZIGBEE) + datalink_set("zigbee"); + port_type = PORT_TYPE_ZIGBEE; #elif defined(BACDL_BSC) datalink_set("bsc"); port_type = PORT_TYPE_BSC; @@ -950,6 +981,8 @@ void dlenv_init(void) port_type = PORT_TYPE_ETHERNET; #elif defined(BACDL_ARCNET) port_type = PORT_TYPE_ARCNET; +#elif defined(BACDL_ZIGBEE) + port_type = PORT_TYPE_ZIGBEE; #elif defined(BACDL_BSC) port_type = PORT_TYPE_BSC; #else @@ -967,6 +1000,9 @@ void dlenv_init(void) case PORT_TYPE_BIP6: dlenv_network_port_bip6_init(Network_Port_Instance); break; + case PORT_TYPE_ZIGBEE: + dlenv_network_port_zigbee_init(Network_Port_Instance); + break; case PORT_TYPE_BSC: dlenv_network_port_bsc_init(); bacnet_secure_connect_network_port_init(Network_Port_Instance); diff --git a/test/bacnet/bacaddr/src/main.c b/test/bacnet/bacaddr/src/main.c index 8a7c2927..94147780 100644 --- a/test/bacnet/bacaddr/src/main.c +++ b/test/bacnet/bacaddr/src/main.c @@ -249,6 +249,60 @@ static void test_BACnetAddress_Codec(void) } } +#if defined(CONFIG_ZTEST_NEW_API) +ZTEST(bacnet_address_tests, test_bacnet_vmac_entry_codec) +#else +static void test_bacnet_vmac_entry_codec(void) +#endif +{ + uint8_t apdu[MAX_APDU]; + BACNET_VMAC_ENTRY value = { 0 }, test_value = { 0 }; + int test_len = 0, apdu_len = 0, null_len = 0; + unsigned i; + + value.virtual_mac_address.adr[0] = 1; + value.virtual_mac_address.adr[1] = 2; + value.virtual_mac_address.adr[2] = 3; + value.virtual_mac_address.len = 3; + value.native_mac_address[0] = 4; + value.native_mac_address[1] = 5; + value.native_mac_address[2] = 6; + value.native_mac_address[3] = 7; + value.native_mac_address_len = 4; + null_len = bacnet_vmac_entry_encode(NULL, sizeof(apdu), &value); + apdu_len = bacnet_vmac_entry_encode(apdu, sizeof(apdu), &value); + zassert_true(apdu_len > 0, NULL); + zassert_true(null_len > 0, NULL); + zassert_equal(apdu_len, null_len, NULL); + test_len = bacnet_vmac_entry_decode(apdu, sizeof(apdu), &test_value); + zassert_equal( + apdu_len, test_len, "apdu_len=%d test_len=%d", apdu_len, test_len); + zassert_equal( + value.virtual_mac_address.len, test_value.virtual_mac_address.len, + NULL); + for (i = 0; i < value.virtual_mac_address.len; i++) { + zassert_equal( + value.virtual_mac_address.adr[i], + test_value.virtual_mac_address.adr[i], NULL); + } + zassert_equal( + value.native_mac_address_len, test_value.native_mac_address_len, NULL); + for (i = 0; i < value.native_mac_address_len; i++) { + zassert_equal( + value.native_mac_address[i], test_value.native_mac_address[i], + NULL); + } + /* negative tests - NULL value */ + test_len = bacnet_vmac_entry_decode(apdu, sizeof(apdu), NULL); + zassert_equal(apdu_len, test_len, NULL); + /* negative tests - apdu too short */ + while (apdu_len) { + apdu_len--; + test_len = bacnet_vmac_entry_decode(apdu, apdu_len, &test_value); + zassert_equal(test_len, BACNET_STATUS_ERROR, NULL); + } +} + /** * @} */ @@ -260,7 +314,8 @@ void test_main(void) ztest_test_suite( bacnet_address_tests, ztest_unit_test(test_BACNET_ADDRESS), ztest_unit_test(test_BACNET_MAC_ADDRESS), - ztest_unit_test(test_BACnetAddress_Codec)); + ztest_unit_test(test_BACnetAddress_Codec), + ztest_unit_test(test_bacnet_vmac_entry_codec)); ztest_run_test_suite(bacnet_address_tests); } diff --git a/test/bacnet/basic/bbmd6/src/main.c b/test/bacnet/basic/bbmd6/src/main.c index d2b6f528..a6e9c12f 100644 --- a/test/bacnet/basic/bbmd6/src/main.c +++ b/test/bacnet/basic/bbmd6/src/main.c @@ -223,6 +223,9 @@ static void test_Execute_Virtual_Address_Resolution(void) uint32_t old_device_id = 0; int result = 0; int function_len = 0; + unsigned int count = 0; + int index = 0; + bool status = false; test_setup(); mtu_len = bvlc6_encode_virtual_address_resolution( @@ -273,6 +276,12 @@ static void test_Execute_Virtual_Address_Resolution(void) assert(bvlc6_get_function_code() == BVLC6_VIRTUAL_ADDRESS_RESOLUTION); assert(VMAC_Find_By_Key(TD.Device_ID) != NULL); + count = VMAC_Count(); + for (index = 0; index < count; index++) { + status = VMAC_Entry_By_Index(index, &test_vmac_src, NULL); + assert(VMAC_Find_By_Key(test_vmac_src) != NULL); + } + test_cleanup(); } diff --git a/test/bacnet/basic/object/netport/CMakeLists.txt b/test/bacnet/basic/object/netport/CMakeLists.txt index 17fe577b..f4b55e49 100644 --- a/test/bacnet/basic/object/netport/CMakeLists.txt +++ b/test/bacnet/basic/object/netport/CMakeLists.txt @@ -7,17 +7,11 @@ project(test_${basename} VERSION 1.0.0 LANGUAGES C) - string(REGEX REPLACE "/test/bacnet/[a-zA-Z_/-]*$" "/src" SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -string(REGEX REPLACE - "/test/bacnet/[a-zA-Z_/-]*$" - "/ports" - PORTS_DIR - ${CMAKE_CURRENT_SOURCE_DIR}) string(REGEX REPLACE "/test/bacnet/[a-zA-Z_/-]*$" "/test" @@ -44,14 +38,7 @@ include_directories( ${TST_DIR}/ztest/include ) -if(ZEPHYR_BASE) - message(FATAL_ERROR "ZEPHYR_BASE env variable defined. Use zephyr/CMakeLists.txt for Zephyr build") -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - message(STATUS "Netport test: building for linux") - set(BACNET_PORT_DIRECTORY_PATH ${CMAKE_CURRENT_LIST_DIR}/ports/linux) - - add_executable(${PROJECT_NAME} - ${PORTS_DIR}/linux/datetime-init.c +add_executable(${PROJECT_NAME} # File(s) under test ${SRC_DIR}/bacnet/basic/object/bacfile.c ${SRC_DIR}/bacnet/basic/object/netport.c @@ -95,62 +82,9 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") ${SRC_DIR}/bacnet/datalink/bsc/bsc-util.c # Test and test library files ${TST_DIR}/bacnet/basic/object/test/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/datetime_local.c ${TST_DIR}/bacnet/basic/object/test/property_test.c ./src/main.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) - -elseif(APPLE) - set(BACNET_PORT_DIRECTORY_PATH ${CMAKE_CURRENT_LIST_DIR}/ports/bsd) - add_executable(${PROJECT_NAME} - ${PORTS_DIR}/bsd/datetime-init.c - # File(s) under test - ${SRC_DIR}/bacnet/basic/object/bacfile.c - ${SRC_DIR}/bacnet/basic/object/netport.c - ${SRC_DIR}/bacnet/basic/object/sc_netport.c - # Support files and stubs (pathname alphabetical) - ${SRC_DIR}/bacnet/access_rule.c - ${SRC_DIR}/bacnet/arf.c - ${SRC_DIR}/bacnet/bacaction.c - ${SRC_DIR}/bacnet/bacaddr.c - ${SRC_DIR}/bacnet/bacapp.c - ${SRC_DIR}/bacnet/bacdcode.c - ${SRC_DIR}/bacnet/bacdest.c - ${SRC_DIR}/bacnet/bacdevobjpropref.c - ${SRC_DIR}/bacnet/bacerror.c - ${SRC_DIR}/bacnet/bacint.c - ${SRC_DIR}/bacnet/baclog.c - ${SRC_DIR}/bacnet/bacreal.c - ${SRC_DIR}/bacnet/bacstr.c - ${SRC_DIR}/bacnet/bactext.c - ${SRC_DIR}/bacnet/datetime.c - ${SRC_DIR}/bacnet/indtext.c - ${SRC_DIR}/bacnet/hostnport.c - ${SRC_DIR}/bacnet/lighting.c - ${SRC_DIR}/bacnet/proplist.c - ${SRC_DIR}/bacnet/property.c - ${SRC_DIR}/bacnet/timestamp.c - ${SRC_DIR}/bacnet/wp.c - ${SRC_DIR}/bacnet/weeklyschedule.c - ${SRC_DIR}/bacnet/bactimevalue.c - ${SRC_DIR}/bacnet/dailyschedule.c - ${SRC_DIR}/bacnet/calendar_entry.c - ${SRC_DIR}/bacnet/special_event.c - ${SRC_DIR}/bacnet/channel_value.c - ${SRC_DIR}/bacnet/secure_connect.c - ${SRC_DIR}/bacnet/basic/sys/debug.c - ${SRC_DIR}/bacnet/basic/sys/bigend.c - ${SRC_DIR}/bacnet/basic/sys/days.c - ${SRC_DIR}/bacnet/basic/sys/keylist.c - ${SRC_DIR}/bacnet/datalink/bvlc.c - ${SRC_DIR}/bacnet/datalink/bvlc6.c - ${SRC_DIR}/bacnet/datalink/bsc/bsc-util.c - # Test and test library files - ${TST_DIR}/bacnet/basic/object/test/device_mock.c - ${TST_DIR}/bacnet/basic/object/test/property_test.c - ./src/main.c - ${ZTST_DIR}/ztest_mock.c - ${ZTST_DIR}/ztest.c - ) -endif()