Added BACnet Zigbee Link Layer (#1052)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user