Added BACnet Zigbee Link Layer (#1052)

This commit is contained in:
Steve Karg
2025-07-28 13:06:48 -05:00
committed by GitHub
parent 85ba0b2315
commit b326563a3c
13 changed files with 497 additions and 70 deletions
+124
View File
@@ -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;
}
+26
View File
@@ -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 */
+39
View File
@@ -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
+3
View File
@@ -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);
+66
View File
@@ -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(
+10
View File
@@ -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
+62
View File
@@ -0,0 +1,62 @@
/**
* @file
* @brief A BACnet/ZigBee Data Link Layer (BZLL)
* @author Steve Karg <skarg@users.sourceforge.net>
* @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 <stdbool.h>
#include <stdint.h>
#include <stddef.h>
/* 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
+49
View File
@@ -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);
+15 -1
View File
@@ -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
+36
View File
@@ -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);
+56 -1
View File
@@ -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);
}
+9
View File
@@ -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();
}
@@ -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
# 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()