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:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user