feat(gateway_bacnet): enhance BACnet object binding with out_of_service and reliability fields
feat(gateway_bacnet): add functions to clear BACnet objects and set their states feat(gateway_bridge): implement discovery inventory management and scanning functionality fix(gateway_bridge): update handleGet to support new inventory and effective model actions refactor(gateway_bridge): improve BACnet binding handling and reliability reporting Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -30,6 +30,8 @@ struct GatewayBacnetObjectBinding {
|
||||
BridgeObjectType object_type{BridgeObjectType::unknown};
|
||||
uint32_t object_instance{0};
|
||||
std::string property{"presentValue"};
|
||||
bool out_of_service{false};
|
||||
uint32_t reliability{0};
|
||||
};
|
||||
|
||||
struct GatewayBacnetServerStatus {
|
||||
|
||||
@@ -48,7 +48,11 @@ bool gateway_bacnet_stack_upsert_object(
|
||||
gateway_bacnet_object_kind_t object_kind,
|
||||
uint32_t object_instance,
|
||||
const char* object_name,
|
||||
const char* description);
|
||||
const char* description,
|
||||
bool out_of_service,
|
||||
uint32_t reliability);
|
||||
|
||||
bool gateway_bacnet_stack_clear_objects(void);
|
||||
|
||||
void gateway_bacnet_stack_send_i_am(void);
|
||||
void gateway_bacnet_stack_poll(uint16_t elapsed_ms);
|
||||
|
||||
@@ -124,6 +124,8 @@ struct GatewayBacnetServer::RuntimeBinding {
|
||||
uint32_t object_instance{0};
|
||||
std::string model_id;
|
||||
std::string property{"presentValue"};
|
||||
bool out_of_service{false};
|
||||
uint32_t reliability{0};
|
||||
GatewayBacnetWriteCallback write_callback;
|
||||
};
|
||||
|
||||
@@ -168,12 +170,9 @@ esp_err_t GatewayBacnetServer::registerChannel(
|
||||
|
||||
bindings.erase(std::remove_if(bindings.begin(), bindings.end(), [](const auto& binding) {
|
||||
return !IsSupportedObjectType(binding.object_type) ||
|
||||
binding.object_instance > kMaxBacnetInstance;
|
||||
binding.object_instance > kMaxBacnetInstance;
|
||||
}),
|
||||
bindings.end());
|
||||
if (bindings.empty()) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
LockGuard guard(lock_);
|
||||
if (started_ && !configCompatible(config)) {
|
||||
@@ -183,6 +182,9 @@ esp_err_t GatewayBacnetServer::registerChannel(
|
||||
auto channel = std::find_if(channels_.begin(), channels_.end(), [gateway_id](const auto& item) {
|
||||
return item.gateway_id == gateway_id;
|
||||
});
|
||||
if (bindings.empty() && !started_ && channel == channels_.end()) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
ChannelRegistration registration{gateway_id, config, std::move(bindings),
|
||||
std::move(write_callback)};
|
||||
if (channel == channels_.end()) {
|
||||
@@ -240,6 +242,10 @@ esp_err_t GatewayBacnetServer::rebuildObjectsLocked() {
|
||||
runtime_bindings_.clear();
|
||||
std::set<std::pair<BridgeObjectType, uint32_t>> used_objects;
|
||||
|
||||
if (!gateway_bacnet_stack_clear_objects()) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
for (const auto& channel : channels_) {
|
||||
for (const auto& binding : channel.bindings) {
|
||||
const auto key = std::make_pair(binding.object_type, binding.object_instance);
|
||||
@@ -254,7 +260,9 @@ esp_err_t GatewayBacnetServer::rebuildObjectsLocked() {
|
||||
const std::string name = ObjectName(binding);
|
||||
if (!gateway_bacnet_stack_upsert_object(ToBacnetKind(binding.object_type),
|
||||
binding.object_instance, name.c_str(),
|
||||
binding.model_id.c_str())) {
|
||||
binding.model_id.c_str(),
|
||||
binding.out_of_service,
|
||||
binding.reliability)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
runtime_bindings_.push_back(RuntimeBinding{channel.gateway_id,
|
||||
@@ -263,6 +271,8 @@ esp_err_t GatewayBacnetServer::rebuildObjectsLocked() {
|
||||
binding.model_id,
|
||||
binding.property.empty() ? "presentValue"
|
||||
: binding.property,
|
||||
binding.out_of_service,
|
||||
binding.reliability,
|
||||
channel.write_callback});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,91 @@ static const char Multistate_Value_States[] =
|
||||
"State 15\0"
|
||||
"State 16\0";
|
||||
|
||||
static bool clear_analog_value_objects(void)
|
||||
{
|
||||
unsigned count = Analog_Value_Count();
|
||||
while (count > 0) {
|
||||
count--;
|
||||
Analog_Value_Delete(Analog_Value_Index_To_Instance(count));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool clear_analog_output_objects(void)
|
||||
{
|
||||
unsigned count = Analog_Output_Count();
|
||||
while (count > 0) {
|
||||
count--;
|
||||
Analog_Output_Delete(Analog_Output_Index_To_Instance(count));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool clear_binary_value_objects(void)
|
||||
{
|
||||
unsigned count = Binary_Value_Count();
|
||||
while (count > 0) {
|
||||
count--;
|
||||
Binary_Value_Delete(Binary_Value_Index_To_Instance(count));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool clear_binary_output_objects(void)
|
||||
{
|
||||
unsigned count = Binary_Output_Count();
|
||||
while (count > 0) {
|
||||
count--;
|
||||
Binary_Output_Delete(Binary_Output_Index_To_Instance(count));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool clear_multistate_value_objects(void)
|
||||
{
|
||||
unsigned count = Multistate_Value_Count();
|
||||
while (count > 0) {
|
||||
count--;
|
||||
Multistate_Value_Delete(Multistate_Value_Index_To_Instance(count));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_analog_value_state(
|
||||
uint32_t object_instance, bool out_of_service, BACNET_RELIABILITY reliability)
|
||||
{
|
||||
Analog_Value_Out_Of_Service_Set(object_instance, out_of_service);
|
||||
Analog_Value_Reliability_Set(object_instance, reliability);
|
||||
}
|
||||
|
||||
static void set_analog_output_state(
|
||||
uint32_t object_instance, bool out_of_service, BACNET_RELIABILITY reliability)
|
||||
{
|
||||
Analog_Output_Out_Of_Service_Set(object_instance, out_of_service);
|
||||
Analog_Output_Reliability_Set(object_instance, reliability);
|
||||
}
|
||||
|
||||
static void set_binary_value_state(
|
||||
uint32_t object_instance, bool out_of_service, BACNET_RELIABILITY reliability)
|
||||
{
|
||||
Binary_Value_Out_Of_Service_Set(object_instance, out_of_service);
|
||||
Binary_Value_Reliability_Set(object_instance, reliability);
|
||||
}
|
||||
|
||||
static void set_binary_output_state(
|
||||
uint32_t object_instance, bool out_of_service, BACNET_RELIABILITY reliability)
|
||||
{
|
||||
Binary_Output_Out_Of_Service_Set(object_instance, out_of_service);
|
||||
Binary_Output_Reliability_Set(object_instance, reliability);
|
||||
}
|
||||
|
||||
static void set_multistate_value_state(
|
||||
uint32_t object_instance, bool out_of_service, BACNET_RELIABILITY reliability)
|
||||
{
|
||||
Multistate_Value_Out_Of_Service_Set(object_instance, out_of_service);
|
||||
Multistate_Value_Reliability_Set(object_instance, reliability);
|
||||
}
|
||||
|
||||
static void notify_write_real(
|
||||
gateway_bacnet_object_kind_t object_kind, uint32_t object_instance, double value)
|
||||
{
|
||||
@@ -209,7 +294,9 @@ bool gateway_bacnet_stack_upsert_object(
|
||||
gateway_bacnet_object_kind_t object_kind,
|
||||
uint32_t object_instance,
|
||||
const char* object_name,
|
||||
const char* description)
|
||||
const char* description,
|
||||
bool out_of_service,
|
||||
uint32_t reliability)
|
||||
{
|
||||
if (!object_name || object_name[0] == '\0') {
|
||||
object_name = "DALI BACnet Object";
|
||||
@@ -218,6 +305,8 @@ bool gateway_bacnet_stack_upsert_object(
|
||||
description = "";
|
||||
}
|
||||
|
||||
BACNET_RELIABILITY object_reliability = (BACNET_RELIABILITY)reliability;
|
||||
|
||||
switch (object_kind) {
|
||||
case GW_BACNET_OBJECT_ANALOG_VALUE:
|
||||
if (!Analog_Value_Valid_Instance(object_instance)) {
|
||||
@@ -227,6 +316,7 @@ bool gateway_bacnet_stack_upsert_object(
|
||||
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);
|
||||
set_analog_value_state(object_instance, out_of_service, object_reliability);
|
||||
return true;
|
||||
case GW_BACNET_OBJECT_ANALOG_OUTPUT:
|
||||
if (!Analog_Output_Valid_Instance(object_instance)) {
|
||||
@@ -236,6 +326,7 @@ bool gateway_bacnet_stack_upsert_object(
|
||||
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);
|
||||
set_analog_output_state(object_instance, out_of_service, object_reliability);
|
||||
return true;
|
||||
case GW_BACNET_OBJECT_BINARY_VALUE:
|
||||
if (!Binary_Value_Valid_Instance(object_instance)) {
|
||||
@@ -245,6 +336,7 @@ bool gateway_bacnet_stack_upsert_object(
|
||||
Binary_Value_Description_Set(object_instance, description);
|
||||
Binary_Value_Write_Enable(object_instance);
|
||||
Binary_Value_Present_Value_Set(object_instance, BINARY_INACTIVE);
|
||||
set_binary_value_state(object_instance, out_of_service, object_reliability);
|
||||
return true;
|
||||
case GW_BACNET_OBJECT_BINARY_OUTPUT:
|
||||
if (!Binary_Output_Valid_Instance(object_instance)) {
|
||||
@@ -253,6 +345,7 @@ bool gateway_bacnet_stack_upsert_object(
|
||||
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);
|
||||
set_binary_output_state(object_instance, out_of_service, object_reliability);
|
||||
return true;
|
||||
case GW_BACNET_OBJECT_MULTI_STATE_VALUE:
|
||||
if (!Multistate_Value_Valid_Instance(object_instance)) {
|
||||
@@ -263,12 +356,22 @@ bool gateway_bacnet_stack_upsert_object(
|
||||
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);
|
||||
set_multistate_value_state(object_instance, out_of_service, object_reliability);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool gateway_bacnet_stack_clear_objects(void)
|
||||
{
|
||||
return clear_analog_value_objects() &&
|
||||
clear_analog_output_objects() &&
|
||||
clear_binary_value_objects() &&
|
||||
clear_binary_output_objects() &&
|
||||
clear_multistate_value_objects();
|
||||
}
|
||||
|
||||
void gateway_bacnet_stack_send_i_am(void)
|
||||
{
|
||||
Send_I_Am(&Handler_Transmit_Buffer[0]);
|
||||
|
||||
Reference in New Issue
Block a user