Added Zephyr settings and basic device in subsys. (#697)
* Added Zephyr settings subsys to enable storing of BACnet values according to BACnet object property value path. * Added BACnet Basic features to enable basic samples. Refactored the zephyr BACnet profile B-SS sample to use BACnet basic subsys.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# CMake for BACnet settings library
|
||||
#
|
||||
# @author Steve Karg <skarg@users.sourceforge.net>
|
||||
# @date May 2024
|
||||
# @copyright SPDX-License-Identifier: MIT
|
||||
zephyr_library(bacnet_basic)
|
||||
|
||||
zephyr_library_include_directories(include)
|
||||
|
||||
zephyr_library_sources(
|
||||
bacnet_port.c
|
||||
bacnet_port_ipv4.c
|
||||
bacnet_port_ipv6.c
|
||||
bacnet_basic.c
|
||||
device.c
|
||||
server.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BACNET_BASIC_DEVICE_SHELL
|
||||
bacnet_shell_objects.c
|
||||
bacnet_shell_packets.c
|
||||
bacnet_shell_uptime.c
|
||||
)
|
||||
@@ -0,0 +1,34 @@
|
||||
# Kconfig - Subsystem configuration options
|
||||
#
|
||||
# @author Steve Karg <skarg@users.sourceforge.net>
|
||||
# @date May 2024
|
||||
# @copyright SPDX-License-Identifier: MIT
|
||||
menuconfig BACNETSTACK_BACNET_BASIC
|
||||
bool "BACNETSTACK_BACNET_BASIC"
|
||||
default n
|
||||
help
|
||||
This option enables a basic BACnet Device object and tasking
|
||||
|
||||
if BACNETSTACK_BACNET_BASIC
|
||||
|
||||
module = BACNETSTACK_BACNET_BASIC
|
||||
module-str = bacnet_basic
|
||||
|
||||
config BACNET_BASIC_DEVICE_OBJECT_NAME
|
||||
string "BACnet device object default name"
|
||||
default "Basic Server"
|
||||
help
|
||||
BACnet device object default name
|
||||
|
||||
config BACNET_BASIC_DEVICE_OBJECT_VERSION
|
||||
string "BACnet device object default application version string"
|
||||
default "1.0.0"
|
||||
help
|
||||
BACnet device object default application version string
|
||||
|
||||
config BACNET_BASIC_DEVICE_SHELL
|
||||
bool "BACnet Basic Device subsystem shell"
|
||||
depends on BACNETSTACK
|
||||
default y if SHELL
|
||||
|
||||
endif # BACNETSTACK_BACNET_SETTINGS
|
||||
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief BACnet Stack initialization and task handler
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date March 2024
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
/* BACnet Stack defines - first */
|
||||
#include "bacnet/bacdef.h"
|
||||
/* BACnet Stack core API */
|
||||
#include "bacnet/npdu.h"
|
||||
#include "bacnet/dcc.h"
|
||||
#include "bacnet/iam.h"
|
||||
/* BACnet Stack basic services */
|
||||
#include "bacnet/basic/sys/mstimer.h"
|
||||
#include "bacnet/basic/services.h"
|
||||
#include "bacnet/basic/tsm/tsm.h"
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
/* BACnet Stack basic objects */
|
||||
#include "bacnet/basic/object/device.h"
|
||||
/* objects */
|
||||
#if (BACNET_PROTOCOL_REVISION >= 17)
|
||||
#include "bacnet/basic/object/netport.h"
|
||||
#endif
|
||||
#include "bacnet/basic/object/device.h"
|
||||
/* me */
|
||||
#include "bacnet_basic/bacnet_basic.h"
|
||||
|
||||
/* 1s timer for basic non-critical timed tasks */
|
||||
static struct mstimer BACnet_Task_Timer;
|
||||
/* task timer for object functionality */
|
||||
static struct mstimer BACnet_Object_Timer;
|
||||
/* uptimer for BACnet task */
|
||||
static unsigned long BACnet_Uptime_Seconds;
|
||||
/* packet counter for BACnet task */
|
||||
static unsigned long BACnet_Packet_Count;
|
||||
/* local Device ID to track changes */
|
||||
static uint32_t Device_ID = 0xFFFFFFFF;
|
||||
|
||||
/**
|
||||
* @brief Get the BACnet device uptime in seconds
|
||||
* @return The number of seconds the BACnet device has been running
|
||||
*/
|
||||
unsigned long bacnet_basic_uptime_seconds(void)
|
||||
{
|
||||
return BACnet_Uptime_Seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the BACnet device uptime in seconds
|
||||
* @return The number of seconds the BACnet device has been running
|
||||
*/
|
||||
unsigned long bacnet_basic_packet_count(void)
|
||||
{
|
||||
return BACnet_Packet_Count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the BACnet device object, the service handlers, and timers
|
||||
*/
|
||||
void bacnet_basic_init(void)
|
||||
{
|
||||
/* set up our confirmed service unrecognized service handler - required! */
|
||||
apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service);
|
||||
/* we need to handle who-is to support dynamic device binding */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
|
||||
/* Set the handlers for any confirmed services that we support. */
|
||||
/* We must implement read property - it's required! */
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROP_MULTIPLE, handler_read_property_multiple);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, handler_write_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE, handler_write_property_multiple);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_SUBSCRIBE_COV, handler_cov_subscribe);
|
||||
/* handle communication so we can shutup when asked, or restart */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
||||
handler_device_communication_control);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_REINITIALIZE_DEVICE, handler_reinitialize_device);
|
||||
/* start the 1 second timer for non-critical cyclic tasks */
|
||||
mstimer_set(&BACnet_Task_Timer, 1000L);
|
||||
/* start the timer for more time sensitive object specific cyclic tasks */
|
||||
mstimer_set(&BACnet_Object_Timer, 100UL);
|
||||
}
|
||||
|
||||
/* local buffer for incoming PDUs to process */
|
||||
static uint8_t PDUBuffer[MAX_MPDU];
|
||||
|
||||
/**
|
||||
* @brief non-blocking BACnet task
|
||||
*/
|
||||
void bacnet_basic_task(void)
|
||||
{
|
||||
bool hello_world = false;
|
||||
uint16_t pdu_len = 0;
|
||||
BACNET_ADDRESS src = { 0 };
|
||||
uint32_t elapsed_milliseconds = 0;
|
||||
uint32_t elapsed_seconds = 0;
|
||||
|
||||
/* hello, World! */
|
||||
if (Device_ID != Device_Object_Instance_Number()) {
|
||||
Device_ID = Device_Object_Instance_Number();
|
||||
hello_world = true;
|
||||
}
|
||||
if (hello_world) {
|
||||
Send_I_Am(&Handler_Transmit_Buffer[0]);
|
||||
}
|
||||
/* handle non-time-critical cyclic tasks */
|
||||
if (mstimer_expired(&BACnet_Task_Timer)) {
|
||||
/* 1 second tasks */
|
||||
mstimer_reset(&BACnet_Task_Timer);
|
||||
/* presume that the elapsed time is the interval time */
|
||||
elapsed_milliseconds = mstimer_interval(&BACnet_Task_Timer);
|
||||
elapsed_seconds = elapsed_milliseconds/1000;
|
||||
BACnet_Uptime_Seconds += elapsed_seconds;
|
||||
dcc_timer_seconds(elapsed_seconds);
|
||||
datalink_maintenance_timer(elapsed_seconds);
|
||||
handler_cov_timer_seconds(elapsed_seconds);
|
||||
}
|
||||
while (!handler_cov_fsm()) {
|
||||
/* waiting for COV processing to be IDLE */
|
||||
}
|
||||
/* object specific cyclic tasks */
|
||||
if (mstimer_expired(&BACnet_Object_Timer)) {
|
||||
mstimer_reset(&BACnet_Object_Timer);
|
||||
elapsed_milliseconds = mstimer_interval(&BACnet_Object_Timer);
|
||||
Device_Timer(elapsed_milliseconds);
|
||||
}
|
||||
/* handle the messaging */
|
||||
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
|
||||
if (pdu_len) {
|
||||
npdu_handler(&src, &PDUBuffer[0], pdu_len);
|
||||
BACnet_Packet_Count++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief The BACnet/IPv4 datalink tasks for handling the device specific
|
||||
* data link layer
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date April 2024
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
/* BACnet definitions */
|
||||
#include "bacnet/bacdef.h"
|
||||
/* BACnet library API */
|
||||
#include "bacnet/basic/sys/mstimer.h"
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
#include "bacnet/basic/object/netport.h"
|
||||
#if defined(BACDL_BIP)
|
||||
#include "bacnet_basic/bacnet_port_ipv4.h"
|
||||
#elif defined(BACDL_BIP6)
|
||||
#include "bacnet_basic/bacnet_port_ipv6.h"
|
||||
#endif
|
||||
/* me! */
|
||||
#include "bacnet_basic/bacnet_port.h"
|
||||
|
||||
/* timer used to renew Foreign Device Registration */
|
||||
static struct mstimer BACnet_Task_Timer;
|
||||
|
||||
/**
|
||||
* @brief Periodic tasks for the BACnet datalink layer
|
||||
*/
|
||||
void bacnet_port_task(void)
|
||||
{
|
||||
uint32_t elapsed_milliseconds = 0;
|
||||
uint32_t elapsed_seconds = 0;
|
||||
|
||||
if (mstimer_expired(&BACnet_Task_Timer)) {
|
||||
/* 1 second tasks */
|
||||
mstimer_reset(&BACnet_Task_Timer);
|
||||
/* presume that the elapsed time is the interval time */
|
||||
elapsed_milliseconds = mstimer_interval(&BACnet_Task_Timer);
|
||||
elapsed_seconds = elapsed_milliseconds / 1000;
|
||||
#if defined(BACDL_BIP)
|
||||
bacnet_port_ipv4_task(elapsed_seconds);
|
||||
#elif defined(BACDL_BIP6)
|
||||
bacnet_port_ipv6_task(elapsed_seconds);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the datalink network port
|
||||
*/
|
||||
bool bacnet_port_init(void)
|
||||
{
|
||||
bool status = false;
|
||||
/* start the 1 second timer for non-critical cyclic tasks */
|
||||
mstimer_set(&BACnet_Task_Timer, 1000L);
|
||||
#if defined(BACDL_BIP)
|
||||
status = bacnet_port_ipv4_init();
|
||||
#elif defined(BACDL_BIP6)
|
||||
status = bacnet_port_ipv6_init();
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief The BACnet/IPv4 datalink tasks for handling the device specific
|
||||
* data link layer
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date April 2024
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
/* BACnet definitions */
|
||||
#include "bacnet/bacdef.h"
|
||||
/* BACnet library API */
|
||||
#include "bacnet/basic/object/netport.h"
|
||||
#include "bacnet/basic/bbmd/h_bbmd.h"
|
||||
#include "bacnet/datalink/bip.h"
|
||||
#include "bacnet/datalink/bvlc.h"
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
/* me! */
|
||||
#include "bacnet_basic/bacnet_port_ipv4.h"
|
||||
|
||||
#if defined(BACDL_BIP)
|
||||
|
||||
/* timer used to renew Foreign Device Registration */
|
||||
static uint16_t BBMD_Timer_Seconds;
|
||||
static uint16_t BBMD_TTL_Seconds = 60000;
|
||||
static BACNET_IP_ADDRESS BBMD_Address;
|
||||
|
||||
/**
|
||||
* @brief Initialize the datalink network port
|
||||
* @param ttl_seconds [in] The time-to-live in seconds for the Foreign Device Registration
|
||||
* @param bbmd_address [in] The address of the BBMD
|
||||
*/
|
||||
void bacnet_port_ipv4_foreign_device_init(
|
||||
const uint16_t ttl_seconds,
|
||||
const BACNET_IP_ADDRESS *bbmd_address)
|
||||
{
|
||||
BBMD_TTL_Seconds = ttl_seconds;
|
||||
if (bbmd_address) {
|
||||
memcpy(&BBMD_Address, bbmd_address, sizeof(BACNET_IP_ADDRESS));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Renew the Foreign Device Registration
|
||||
*/
|
||||
void bacnet_port_ipv4_task(uint16_t elapsed_seconds)
|
||||
{
|
||||
if (BBMD_Timer_Seconds) {
|
||||
if (BBMD_Timer_Seconds <= elapsed_seconds) {
|
||||
BBMD_Timer_Seconds = 0;
|
||||
} else {
|
||||
BBMD_Timer_Seconds -= elapsed_seconds;
|
||||
}
|
||||
if (BBMD_Timer_Seconds == 0) {
|
||||
if (BBMD_Address.port > 0) {
|
||||
(void)bvlc_register_with_bbmd(&BBMD_Address,
|
||||
BBMD_TTL_Seconds);
|
||||
}
|
||||
BBMD_Timer_Seconds = (uint16_t)BBMD_TTL_Seconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the network port object.
|
||||
*/
|
||||
bool bacnet_port_ipv4_init(void)
|
||||
{
|
||||
const uint32_t instance = 1;
|
||||
BACNET_IP_ADDRESS addr = { 0 };
|
||||
uint8_t prefix = 0;
|
||||
|
||||
if (!bip_init(NULL)) {
|
||||
return false;
|
||||
}
|
||||
Network_Port_Object_Instance_Number_Set(0, instance);
|
||||
Network_Port_Name_Set(instance, "BACnet/IP Port");
|
||||
Network_Port_Type_Set(instance, PORT_TYPE_BIP);
|
||||
bip_get_addr(&addr);
|
||||
prefix = bip_get_subnet_prefix();
|
||||
Network_Port_BIP_Port_Set(instance, addr.port);
|
||||
Network_Port_IP_Address_Set(instance, addr.address[0], addr.address[1],
|
||||
addr.address[2], addr.address[3]);
|
||||
Network_Port_IP_Subnet_Prefix_Set(instance, prefix);
|
||||
Network_Port_Link_Speed_Set(instance, 0.0);
|
||||
/* common NP data */
|
||||
Network_Port_Reliability_Set(instance, RELIABILITY_NO_FAULT_DETECTED);
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief The BACnet datalink tasks for handling the device specific
|
||||
* data link layer
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date April 2024
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
/* BACnet definitions */
|
||||
#include "bacnet/bacdef.h"
|
||||
/* BACnet library API */
|
||||
#include "bacnet/basic/object/netport.h"
|
||||
#include "bacnet/basic/bbmd6/h_bbmd6.h"
|
||||
#include "bacnet/datalink/bip6.h"
|
||||
#include "bacnet/datalink/bvlc6.h"
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
/* me! */
|
||||
#include "bacnet_basic/bacnet_port_ipv6.h"
|
||||
|
||||
#if defined(BACDL_BIP6)
|
||||
|
||||
/* timer used to renew Foreign Device Registration */
|
||||
static uint16_t BBMD_Timer_Seconds;
|
||||
static uint16_t BBMD_TTL_Seconds = 60000;
|
||||
static BACNET_IP6_ADDRESS BBMD_Address;
|
||||
|
||||
/**
|
||||
* @brief Initialize the datalink network port
|
||||
* @param ttl_seconds [in] The time-to-live in seconds for the Foreign Device Registration
|
||||
* @param bbmd_address [in] The address of the BBMD
|
||||
*/
|
||||
void bacnet_port_ipv6_foreign_device_init(
|
||||
const uint16_t ttl_seconds, const BACNET_IP6_ADDRESS *bbmd_address)
|
||||
{
|
||||
BBMD_TTL_Seconds = ttl_seconds;
|
||||
if (bbmd_address) {
|
||||
memcpy(&BBMD_Address, bbmd_address, sizeof(BACNET_IP6_ADDRESS));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Renew the Foreign Device Registration
|
||||
*/
|
||||
void bacnet_port_ipv6_task(uint16_t elapsed_seconds)
|
||||
{
|
||||
if (BBMD_Timer_Seconds) {
|
||||
if (BBMD_Timer_Seconds <= elapsed_seconds) {
|
||||
BBMD_Timer_Seconds = 0;
|
||||
} else {
|
||||
BBMD_Timer_Seconds -= elapsed_seconds;
|
||||
}
|
||||
if (BBMD_Timer_Seconds == 0) {
|
||||
if (BBMD_Address.port > 0) {
|
||||
(void)bvlc6_register_with_bbmd(&BBMD_Address,
|
||||
BBMD_TTL_Seconds);
|
||||
}
|
||||
BBMD_Timer_Seconds = BBMD_TTL_Seconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the network port object.
|
||||
* @return true if successful
|
||||
*/
|
||||
bool bacnet_port_ipv6_init(void)
|
||||
{
|
||||
uint32_t instance = 1;
|
||||
uint8_t prefix = 0;
|
||||
BACNET_ADDRESS addr = { 0 };
|
||||
BACNET_IP6_ADDRESS addr6 = { 0 };
|
||||
|
||||
if (!bip6_init(NULL)) {
|
||||
return false;
|
||||
}
|
||||
Network_Port_Object_Instance_Number_Set(0, instance);
|
||||
Network_Port_Name_Set(instance, "BACnet/IPv6 Port");
|
||||
Network_Port_Type_Set(instance, PORT_TYPE_BIP6);
|
||||
Network_Port_BIP6_Port_Set(instance, bip6_get_port());
|
||||
bip6_get_my_address(&addr);
|
||||
Network_Port_MAC_Address_Set(instance, &addr.mac[0], addr.mac_len);
|
||||
bip6_get_addr(&addr6);
|
||||
Network_Port_IPv6_Address_Set(instance, &addr6.address[0]);
|
||||
bip6_get_broadcast_addr(&addr6);
|
||||
Network_Port_IPv6_Multicast_Address_Set(instance, &addr6.address[0]);
|
||||
Network_Port_IPv6_Subnet_Prefix_Set(instance, prefix);
|
||||
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief BACnet shell commands for debugging and testing
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date May 2024
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <zephyr/shell/shell.h>
|
||||
/* BACnet definitions */
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bactext.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
/* BACnet objects API */
|
||||
#include "bacnet/basic/object/device.h"
|
||||
/* Basic BACnet */
|
||||
#include "bacnet_basic/bacnet_basic.h"
|
||||
|
||||
/**
|
||||
* @brief List all BACnet objects in this device
|
||||
* @param sh Shell
|
||||
* @param argc Number of arguments
|
||||
* @param argv Argument list
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
static int cmd_objects(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
int count;
|
||||
BACNET_OBJECT_TYPE object_type;
|
||||
uint32_t instance;
|
||||
uint32_t array_index;
|
||||
bool found;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
shell_print(sh, "List of BACnet Objects: [{");
|
||||
count = Device_Object_List_Count();
|
||||
for (array_index = 1; array_index <= count; array_index++) {
|
||||
found = Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance);
|
||||
if (found) {
|
||||
shell_print(sh, " \"%s-%u\"%c",
|
||||
bactext_object_type_name(object_type),
|
||||
instance,
|
||||
(array_index == count) ? ' ' : ',');
|
||||
}
|
||||
}
|
||||
shell_print(sh, "}] -- %d objects found", count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_SUBCMD_ADD((bacnet), objects, NULL, "list of BACnet objects", cmd_objects,
|
||||
1, 0);
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief The BACnet shell commands for debugging and testing
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date May 2024
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <zephyr/shell/shell.h>
|
||||
/* BACnet definitions */
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bactext.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
/* Basic BACnet */
|
||||
#include "bacnet_basic/bacnet_basic.h"
|
||||
|
||||
/**
|
||||
* @brief Print BACnet packet statistics
|
||||
* @param sh Shell
|
||||
* @param argc Number of arguments
|
||||
* @param argv Argument list
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
static int cmd_packets(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
shell_print(sh, "BACnet thread packets received: %ld",
|
||||
bacnet_basic_packet_count());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_SUBCMD_ADD((bacnet), packets, NULL, "BACnet task packet stats", cmd_packets,
|
||||
1, 0);
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief The BACnet shell commands for debugging and testing
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date May 2024
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <zephyr/shell/shell.h>
|
||||
/* BACnet definitions */
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bactext.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
/* Basic BACnet */
|
||||
#include "bacnet_basic/bacnet_basic.h"
|
||||
|
||||
/**
|
||||
* @brief Print BACnet uptime statistics
|
||||
* @param sh Shell
|
||||
* @param argc Number of arguments
|
||||
* @param argv Argument list
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
static int cmd_uptime(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
shell_print(sh, "BACnet thread uptime: %ld seconds",
|
||||
bacnet_basic_uptime_seconds());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_SUBCMD_ADD((bacnet), uptime, NULL, "BACnet task uptime", cmd_uptime,
|
||||
1, 0);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief BACnet Stack server initialization and task handler
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date March 2024
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdalign.h> /*TODO: Not std until C11! */
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/random/random.h>
|
||||
#include <bacnet_settings/bacnet_storage.h>
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
#include "bacnet_basic/bacnet_basic.h"
|
||||
#include "bacnet_basic/bacnet_port.h"
|
||||
#if defined(CONFIG_BACNETSTACK_BACNET_SETTINGS)
|
||||
#include "bacnet_settings/bacnet_storage.h"
|
||||
#endif
|
||||
|
||||
/* note: stack is minimally 2x to 3x of MAX_APDU */
|
||||
#ifndef CONFIG_BACNETSTACK_BACNET_SERVER_STACK_SIZE
|
||||
#define CONFIG_BACNETSTACK_BACNET_SERVER_STACK_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BACNETSTACK_BACNET_SERVER_PRIO
|
||||
#define CONFIG_BACNETSTACK_BACNET_SERVER_PRIO 10
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BACNETSTACK_BACNET_SERVER_APP_PRIORITY
|
||||
#define CONFIG_BACNETSTACK_BACNET_SERVER_APP_PRIORITY 90
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BACNETSTACK_LOG_LEVEL
|
||||
#define CONFIG_BACNETSTACK_LOG_LEVEL LOG_LEVEL_INF
|
||||
#endif
|
||||
|
||||
/* Logging module registration is already done in ports/zephyr/main.c */
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(bacnet, CONFIG_BACNETSTACK_LOG_LEVEL);
|
||||
|
||||
static struct k_thread server_thread_data;
|
||||
static K_THREAD_STACK_DEFINE(server_thread_stack,
|
||||
CONFIG_BACNETSTACK_BACNET_SERVER_STACK_SIZE);
|
||||
|
||||
/**
|
||||
* @brief BACnet Server Thread
|
||||
*/
|
||||
static void server_thread(void)
|
||||
{
|
||||
LOG_INF("BACnet Server: started");
|
||||
|
||||
#if defined(CONFIG_BACNETSTACK_BACNET_SETTINGS)
|
||||
bacnet_storage_init();
|
||||
#endif
|
||||
bacnet_basic_init();
|
||||
for (;;) {
|
||||
if (bacnet_port_init()) {
|
||||
break;
|
||||
} else {
|
||||
LOG_ERR("BACnet Server: port initialization failed");
|
||||
k_sleep(K_MSEC(1000));
|
||||
}
|
||||
}
|
||||
LOG_INF("BACnet Server: initialized");
|
||||
for (;;) {
|
||||
k_sleep(K_MSEC(10));
|
||||
bacnet_basic_task();
|
||||
bacnet_port_task();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief BACnet Server Thread initialization
|
||||
*/
|
||||
static int server_init(void)
|
||||
{
|
||||
k_thread_create(&server_thread_data, server_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(server_thread_stack),
|
||||
(k_thread_entry_t)server_thread, NULL, NULL, NULL,
|
||||
K_PRIO_PREEMPT(CONFIG_BACNETSTACK_BACNET_SERVER_PRIO), 0,
|
||||
K_NO_WAIT);
|
||||
k_thread_name_set(&server_thread_data, "bacnet_server");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(server_init, APPLICATION,
|
||||
CONFIG_BACNETSTACK_BACNET_SERVER_APP_PRIORITY);
|
||||
Reference in New Issue
Block a user