feat(gateway_network): integrate GatewayBridgeService and add bridge handling

- Updated CMakeLists.txt to require gateway_bridge component.
- Modified GatewayNetworkService to include a pointer to GatewayBridgeService.
- Added new HTTP handlers for bridge GET and POST requests.
- Implemented query utility functions for handling request parameters.
- Enhanced response handling for bridge actions with JSON responses.

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Tony
2026-05-01 03:54:02 +08:00
parent 2c1aa28d4f
commit d16c289626
19 changed files with 3186 additions and 10 deletions
@@ -0,0 +1,288 @@
#include "gateway_bacnet_stack_port.h"
#include <stddef.h>
#include <string.h>
#include "bacnet/apdu.h"
#include "bacnet/basic/binding/address.h"
#include "bacnet/basic/object/ao.h"
#include "bacnet/basic/object/av.h"
#include "bacnet/basic/object/bo.h"
#include "bacnet/basic/object/bv.h"
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/msv.h"
#include "bacnet/basic/service/h_apdu.h"
#include "bacnet/basic/services.h"
#include "bacnet/basic/tsm/tsm.h"
#include "bacnet/bacdef.h"
#include "bacnet/npdu.h"
#include "bip.h"
static gateway_bacnet_stack_write_callback_t Write_Callback;
static void* Write_Callback_Context;
static uint8_t Rx_Buffer[BIP_MPDU_MAX];
static const char Multistate_Value_States[] =
"State 1\0"
"State 2\0"
"State 3\0"
"State 4\0"
"State 5\0"
"State 6\0"
"State 7\0"
"State 8\0"
"State 9\0"
"State 10\0"
"State 11\0"
"State 12\0"
"State 13\0"
"State 14\0"
"State 15\0"
"State 16\0";
static void notify_write_real(
gateway_bacnet_object_kind_t object_kind, uint32_t object_instance, double value)
{
if (Write_Callback) {
gateway_bacnet_write_value_t write_value = {
.kind = GW_BACNET_WRITE_VALUE_REAL,
.real_value = value,
.boolean_value = false,
.unsigned_value = 0,
};
Write_Callback(object_kind, object_instance, &write_value, Write_Callback_Context);
}
}
static void notify_write_boolean(
gateway_bacnet_object_kind_t object_kind, uint32_t object_instance, bool value)
{
if (Write_Callback) {
gateway_bacnet_write_value_t write_value = {
.kind = GW_BACNET_WRITE_VALUE_BOOLEAN,
.real_value = 0.0,
.boolean_value = value,
.unsigned_value = 0,
};
Write_Callback(object_kind, object_instance, &write_value, Write_Callback_Context);
}
}
static void notify_write_unsigned(
gateway_bacnet_object_kind_t object_kind, uint32_t object_instance, uint32_t value)
{
if (Write_Callback) {
gateway_bacnet_write_value_t write_value = {
.kind = GW_BACNET_WRITE_VALUE_UNSIGNED,
.real_value = 0.0,
.boolean_value = false,
.unsigned_value = value,
};
Write_Callback(object_kind, object_instance, &write_value, Write_Callback_Context);
}
}
static void analog_value_write(uint32_t object_instance, float old_value, float value)
{
(void)old_value;
notify_write_real(GW_BACNET_OBJECT_ANALOG_VALUE, object_instance, value);
}
static void analog_output_write(uint32_t object_instance, float old_value, float value)
{
(void)old_value;
notify_write_real(GW_BACNET_OBJECT_ANALOG_OUTPUT, object_instance, value);
}
static void binary_value_write(
uint32_t object_instance, BACNET_BINARY_PV old_value, BACNET_BINARY_PV value)
{
(void)old_value;
notify_write_boolean(GW_BACNET_OBJECT_BINARY_VALUE, object_instance, value == BINARY_ACTIVE);
}
static void binary_output_write(
uint32_t object_instance, BACNET_BINARY_PV old_value, BACNET_BINARY_PV value)
{
(void)old_value;
notify_write_boolean(GW_BACNET_OBJECT_BINARY_OUTPUT, object_instance, value == BINARY_ACTIVE);
}
static void multistate_value_write(uint32_t object_instance, uint32_t old_value, uint32_t value)
{
(void)old_value;
notify_write_unsigned(GW_BACNET_OBJECT_MULTI_STATE_VALUE, object_instance, value);
}
static object_functions_t Object_Table[] = {
{ OBJECT_DEVICE, NULL, Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number, Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists, DeviceGetRRInfo, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, Device_Writable_Property_List },
{ OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance, Analog_Value_Object_Name,
Analog_Value_Read_Property, Analog_Value_Write_Property, Analog_Value_Property_Lists,
NULL, NULL, Analog_Value_Encode_Value_List, Analog_Value_Change_Of_Value,
Analog_Value_Change_Of_Value_Clear, NULL, NULL, NULL, Analog_Value_Create,
Analog_Value_Delete, NULL, Analog_Value_Writable_Property_List },
{ OBJECT_ANALOG_OUTPUT, Analog_Output_Init, Analog_Output_Count,
Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance, Analog_Output_Object_Name,
Analog_Output_Read_Property, Analog_Output_Write_Property, Analog_Output_Property_Lists,
NULL, NULL, Analog_Output_Encode_Value_List, Analog_Output_Change_Of_Value,
Analog_Output_Change_Of_Value_Clear, NULL, NULL, NULL, Analog_Output_Create,
Analog_Output_Delete, NULL, Analog_Output_Writable_Property_List },
{ OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count,
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance, Binary_Value_Object_Name,
Binary_Value_Read_Property, Binary_Value_Write_Property, Binary_Value_Property_Lists,
NULL, NULL, Binary_Value_Encode_Value_List, Binary_Value_Change_Of_Value,
Binary_Value_Change_Of_Value_Clear, NULL, NULL, NULL, Binary_Value_Create,
Binary_Value_Delete, NULL, Binary_Value_Writable_Property_List },
{ OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count,
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance, Binary_Output_Object_Name,
Binary_Output_Read_Property, Binary_Output_Write_Property, Binary_Output_Property_Lists,
NULL, NULL, Binary_Output_Encode_Value_List, Binary_Output_Change_Of_Value,
Binary_Output_Change_Of_Value_Clear, NULL, NULL, NULL, Binary_Output_Create,
Binary_Output_Delete, NULL, Binary_Output_Writable_Property_List },
{ OBJECT_MULTI_STATE_VALUE, Multistate_Value_Init, Multistate_Value_Count,
Multistate_Value_Index_To_Instance, Multistate_Value_Valid_Instance,
Multistate_Value_Object_Name, Multistate_Value_Read_Property,
Multistate_Value_Write_Property, Multistate_Value_Property_Lists, NULL, NULL,
Multistate_Value_Encode_Value_List, Multistate_Value_Change_Of_Value,
Multistate_Value_Change_Of_Value_Clear, NULL, NULL, NULL, Multistate_Value_Create,
Multistate_Value_Delete, NULL, Multistate_Value_Writable_Property_List },
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
};
bool gateway_bacnet_stack_start(
uint32_t device_instance,
const char* device_name,
uint16_t udp_port,
gateway_bacnet_stack_write_callback_t write_callback,
void* callback_context)
{
if (!device_name || device_name[0] == '\0') {
device_name = "DALI Gateway";
}
if (udp_port == 0) {
udp_port = 47808;
}
Write_Callback = write_callback;
Write_Callback_Context = callback_context;
address_init();
Device_Set_Object_Instance_Number(device_instance);
Device_Init(Object_Table);
Device_Object_Name_ANSI_Init(device_name);
Device_Set_Vendor_Name("TonyCloud", strlen("TonyCloud"));
Device_Set_Vendor_Identifier(260);
Device_Set_Model_Name("DALI Gateway", strlen("DALI Gateway"));
Device_Set_Description("DALI BACnet/IP bridge", strlen("DALI BACnet/IP bridge"));
Analog_Value_Write_Present_Value_Callback_Set(analog_value_write);
Analog_Output_Write_Present_Value_Callback_Set(analog_output_write);
Binary_Value_Write_Present_Value_Callback_Set(binary_value_write);
Binary_Output_Write_Present_Value_Callback_Set(binary_output_write);
Multistate_Value_Write_Present_Value_Callback_Set(multistate_value_write);
apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
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_DEVICE_COMMUNICATION_CONTROL, handler_device_communication_control);
return bip_init(udp_port);
}
void gateway_bacnet_stack_cleanup(void)
{
bip_cleanup();
Write_Callback = NULL;
Write_Callback_Context = NULL;
}
bool gateway_bacnet_stack_upsert_object(
gateway_bacnet_object_kind_t object_kind,
uint32_t object_instance,
const char* object_name,
const char* description)
{
if (!object_name || object_name[0] == '\0') {
object_name = "DALI BACnet Object";
}
if (!description) {
description = "";
}
switch (object_kind) {
case GW_BACNET_OBJECT_ANALOG_VALUE:
if (!Analog_Value_Valid_Instance(object_instance)) {
Analog_Value_Create(object_instance);
}
Analog_Value_Name_Set(object_instance, object_name);
Analog_Value_Description_Set(object_instance, description);
Analog_Value_Units_Set(object_instance, UNITS_PERCENT);
Analog_Value_Present_Value_Set(object_instance, 0.0f, BACNET_NO_PRIORITY);
return true;
case GW_BACNET_OBJECT_ANALOG_OUTPUT:
if (!Analog_Output_Valid_Instance(object_instance)) {
Analog_Output_Create(object_instance);
}
Analog_Output_Name_Set(object_instance, object_name);
Analog_Output_Description_Set(object_instance, description);
Analog_Output_Units_Set(object_instance, UNITS_PERCENT);
Analog_Output_Present_Value_Set(object_instance, 0.0f, BACNET_MAX_PRIORITY);
return true;
case GW_BACNET_OBJECT_BINARY_VALUE:
if (!Binary_Value_Valid_Instance(object_instance)) {
Binary_Value_Create(object_instance);
}
Binary_Value_Name_Set(object_instance, object_name);
Binary_Value_Description_Set(object_instance, description);
Binary_Value_Write_Enable(object_instance);
Binary_Value_Present_Value_Set(object_instance, BINARY_INACTIVE);
return true;
case GW_BACNET_OBJECT_BINARY_OUTPUT:
if (!Binary_Output_Valid_Instance(object_instance)) {
Binary_Output_Create(object_instance);
}
Binary_Output_Name_Set(object_instance, object_name);
Binary_Output_Description_Set(object_instance, description);
Binary_Output_Present_Value_Set(object_instance, BINARY_INACTIVE, BACNET_MAX_PRIORITY);
return true;
case GW_BACNET_OBJECT_MULTI_STATE_VALUE:
if (!Multistate_Value_Valid_Instance(object_instance)) {
Multistate_Value_Create(object_instance);
}
Multistate_Value_Name_Set(object_instance, object_name);
Multistate_Value_Description_Set(object_instance, description);
Multistate_Value_State_Text_List_Set(object_instance, Multistate_Value_States);
Multistate_Value_Write_Enable(object_instance);
Multistate_Value_Present_Value_Set(object_instance, 1);
return true;
default:
return false;
}
}
void gateway_bacnet_stack_send_i_am(void)
{
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
void gateway_bacnet_stack_poll(uint16_t elapsed_ms)
{
BACNET_ADDRESS src = { 0 };
uint16_t pdu_len = bip_receive(&src, Rx_Buffer, sizeof(Rx_Buffer), 0);
if (pdu_len > 0) {
npdu_handler(&src, Rx_Buffer, pdu_len);
}
if (elapsed_ms > 0) {
tsm_timer_milliseconds(elapsed_ms);
Device_Timer(elapsed_ms);
}
}