Refactor DALI component: remove BACnet bridge support and update related documentation

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Tony
2026-05-04 02:25:39 +08:00
parent 402d6a451b
commit fa4acef881
9 changed files with 6 additions and 181 deletions
-1
View File
@@ -6,7 +6,6 @@ idf_component_register(
"src/bridge.cpp"
"src/bridge_model.cpp"
"src/bridge_provisioning.cpp"
"src/bacnet_bridge.cpp"
"src/decode.cpp"
"src/device.cpp"
"src/dt1.cpp"
+4 -5
View File
@@ -50,9 +50,8 @@ The component now includes a protocol-agnostic bridge layer for mapping external
- `bridge_model.hpp` defines the strongly typed mapping model: protocol kind, external point, DALI target, default operation, and value transform.
- `bridge.hpp` provides `DaliBridgeEngine`, which resolves models and dispatches requests into `DaliComm`, `DaliBase`, and `DaliDT8`.
- `bridge_provisioning.hpp` provides `BridgeProvisioningStore` for persisting bridge models and shared protocol config in ESP-IDF NVS.
- Modbus runtime support is owned by the native gateway project in `gateway/components/gateway_modbus`.
- `bacnet_bridge.hpp` provides a BACnet skeleton adapter keyed by object type, instance, and property bindings.
- `bridge_provisioning.hpp` provides `BridgeProvisioningStore` for persisting bridge models in ESP-IDF NVS.
- Modbus and BACnet runtime support are owned by the native gateway project in `gateway/components/gateway_modbus` and `gateway/components/gateway_bacnet`.
### Example Model Mapping
@@ -107,7 +106,7 @@ Query-style operations return `data` when available and may include decoded flag
## Bridge Provisioning via NVS
Use `BridgeProvisioningStore` to persist bridge models and shared protocol-specific config such as BACnet:
Use `BridgeProvisioningStore` to persist bridge models:
```cpp
BridgeRuntimeConfig runtime;
@@ -224,4 +223,4 @@ idf.py set-target esp32s3
idf.py build
```
The example persists its bridge config in NVS, starts a real Modbus TCP listener, registers Modbus and BACnet bridge models, and routes Modbus writes through the shared bridge engine. The DALI gateway callbacks are still placeholders where you should connect your UART or transport driver.
The example persists its bridge config in NVS, registers generic bridge models, and routes requests through the shared bridge engine. The DALI gateway callbacks are still placeholders where you should connect your UART or transport driver. Use `gateway/apps/gateway` to exercise the gateway-owned Modbus and BACnet runtimes.
+2 -3
View File
@@ -1,6 +1,6 @@
# ESP32-S3 Bridge Example
This ESP-IDF example wires `dali_cpp` into a standalone application and demonstrates how to register strongly typed bridge and BACnet models. Modbus runtime support now lives in the native gateway project.
This ESP-IDF example wires `dali_cpp` into a standalone application and demonstrates how to register strongly typed bridge models. Modbus and BACnet runtime support now live in the native gateway project.
## Environment
@@ -21,9 +21,8 @@ idf.py build
- `DaliBridgeEngine` resolving model bindings.
- `BridgeProvisioningStore` loading and saving model/config state in NVS.
- `DaliBacnetBridge` mapping BACnet property writes to DALI brightness percentage updates.
- Placeholder DALI gateway callbacks where you can connect your UART transport.
## Modbus Notes
The gateway implementation in `gateway/components/gateway_modbus` owns Modbus TCP, generated DALI point tables, and provisioned Modbus overrides. Use `gateway/apps/gateway` to exercise Modbus behavior.
The gateway implementation in `gateway/components/gateway_modbus` owns Modbus TCP, generated DALI point tables, and provisioned Modbus overrides. `gateway/components/gateway_bacnet` owns BACnet/IP object publishing and present-value routing. Use `gateway/apps/gateway` to exercise protocol behavior.
-37
View File
@@ -1,4 +1,3 @@
#include "bacnet_bridge.hpp"
#include "bridge.hpp"
#include "bridge_model.hpp"
#include "bridge_provisioning.hpp"
@@ -56,32 +55,10 @@ BridgeModel makeStatusQueryModel() {
return model;
}
BridgeModel makeBacnetBrightnessModel() {
BridgeModel model;
model.id = "bacnet-zone-2";
model.name = "BACnet zone 2 level";
model.protocol = BridgeProtocolKind::bacnet;
model.external.network = "floor-2";
model.external.device = "bacnet-controller";
model.external.objectType = BridgeObjectType::analogOutput;
model.external.objectInstance = 2;
model.external.property = "presentValue";
model.dali.shortAddress = 2;
model.operation = BridgeOperation::setBrightnessPercent;
model.valueEncoding = BridgeValueEncoding::percentage;
return model;
}
BridgeRuntimeConfig makeDefaultRuntimeConfig() {
BridgeRuntimeConfig config;
config.models.push_back(makeBrightnessModel());
config.models.push_back(makeStatusQueryModel());
config.models.push_back(makeBacnetBrightnessModel());
BacnetBridgeConfig bacnet;
bacnet.deviceInstance = 1001;
bacnet.localAddress = "192.168.10.20";
config.bacnet = bacnet;
config.metadata["example"] = "esp32s3_bridge";
return config;
@@ -115,26 +92,12 @@ extern "C" void app_main(void) {
engine.upsertModel(model);
}
static DaliBacnetBridge bacnet(engine);
BacnetBridgeConfig bacnet_config = runtime_config.bacnet.value_or(BacnetBridgeConfig{});
bacnet.setConfig(bacnet_config);
for (const auto& binding : bacnet.describeObjects()) {
ESP_LOGI(kTag, "bacnet binding model=%s object=%s:%d property=%s",
binding.modelID.c_str(), bridgeObjectTypeToString(binding.objectType),
binding.objectInstance, binding.property.c_str());
}
DaliBridgeRequest brightness_request;
brightness_request.sequence = "startup-brightness";
brightness_request.modelID = "line-1-brightness";
brightness_request.value = 180;
logResult("bridge brightness", engine.execute(brightness_request));
const DaliBridgeResult bacnet_result =
bacnet.handlePropertyWrite(BridgeObjectType::analogOutput, 2, "presentValue", 75.0);
logResult("bacnet write", bacnet_result);
DaliBridgeRequest status_request;
status_request.sequence = "startup-status";
status_request.modelID = "line-1-status";
-44
View File
@@ -1,44 +0,0 @@
#pragma once
#include "bridge.hpp"
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
struct BacnetBridgeConfig {
uint32_t deviceInstance = 4194303;
std::string localAddress;
uint16_t udpPort = 47808;
};
struct BacnetObjectBinding {
std::string modelID;
BridgeObjectType objectType = BridgeObjectType::unknown;
int objectInstance = -1;
std::string property;
BridgeOperation operation = BridgeOperation::unknown;
BridgeDaliTarget target;
};
class DaliBacnetBridge {
public:
explicit DaliBacnetBridge(DaliBridgeEngine& engine);
void setConfig(const BacnetBridgeConfig& config);
const BacnetBridgeConfig& config() const;
DaliBridgeResult handlePropertyWrite(BridgeObjectType objectType,
int objectInstance,
const std::string& property,
const DaliValue& value) const;
std::optional<BacnetObjectBinding> findObject(BridgeObjectType objectType,
int objectInstance,
const std::string& property) const;
std::vector<BacnetObjectBinding> describeObjects() const;
private:
DaliBridgeEngine& engine_;
BacnetBridgeConfig config_;
};
-3
View File
@@ -1,9 +1,7 @@
#pragma once
#include "bacnet_bridge.hpp"
#include "bridge_model.hpp"
#include <optional>
#include <string>
#include <vector>
@@ -17,7 +15,6 @@ using esp_err_t = int;
struct BridgeRuntimeConfig {
std::vector<BridgeModel> models;
std::optional<BacnetBridgeConfig> bacnet;
DaliValue::Object metadata;
static BridgeRuntimeConfig fromJson(const DaliValue::Object& json);
-1
View File
@@ -1,7 +1,6 @@
#pragma once
#include "base.hpp"
#include "bacnet_bridge.hpp"
#include "bridge.hpp"
#include "bridge_model.hpp"
#include "bridge_provisioning.hpp"
-65
View File
@@ -1,65 +0,0 @@
#include "bacnet_bridge.hpp"
#include <utility>
DaliBacnetBridge::DaliBacnetBridge(DaliBridgeEngine& engine) : engine_(engine) {}
void DaliBacnetBridge::setConfig(const BacnetBridgeConfig& config) { config_ = config; }
const BacnetBridgeConfig& DaliBacnetBridge::config() const { return config_; }
DaliBridgeResult DaliBacnetBridge::handlePropertyWrite(BridgeObjectType objectType,
int objectInstance,
const std::string& property,
const DaliValue& value) const {
const auto binding = findObject(objectType, objectInstance, property);
DaliBridgeRequest request;
request.sequence = "bacnet-" + std::to_string(objectInstance);
request.value = value;
if (!binding.has_value()) {
DaliBridgeResult result;
result.sequence = request.sequence;
result.error = "unmapped bacnet object";
return result;
}
request.modelID = binding->modelID;
return engine_.execute(request);
}
std::optional<BacnetObjectBinding> DaliBacnetBridge::findObject(BridgeObjectType objectType,
int objectInstance,
const std::string& property) const {
for (const auto& model : engine_.listModels()) {
if (model.protocol != BridgeProtocolKind::bacnet) {
continue;
}
if (model.external.objectType != objectType) {
continue;
}
if (model.external.objectInstance.value_or(-1) != objectInstance) {
continue;
}
if (!model.external.property.empty() && model.external.property != property) {
continue;
}
return BacnetObjectBinding{model.id, objectType, objectInstance, property,
model.operation, model.dali};
}
return std::nullopt;
}
std::vector<BacnetObjectBinding> DaliBacnetBridge::describeObjects() const {
std::vector<BacnetObjectBinding> bindings;
for (const auto& model : engine_.listModels()) {
if (model.protocol != BridgeProtocolKind::bacnet || !model.external.objectInstance.has_value()) {
continue;
}
bindings.push_back(BacnetObjectBinding{model.id, model.external.objectType,
model.external.objectInstance.value(),
model.external.property, model.operation,
model.dali});
}
return bindings;
}
-22
View File
@@ -101,26 +101,6 @@ esp_err_t readString(nvs_handle_t handle, const char* key, std::string* value) {
return ESP_OK;
}
std::optional<BacnetBridgeConfig> bacnetFromJson(const DaliValue* value) {
if (value == nullptr || value->asObject() == nullptr) {
return std::nullopt;
}
const auto& json = *value->asObject();
BacnetBridgeConfig config;
config.deviceInstance = static_cast<uint32_t>(getObjectInt(json, "deviceInstance").value_or(4194303));
config.localAddress = getObjectString(json, "localAddress").value_or("");
config.udpPort = static_cast<uint16_t>(getObjectInt(json, "udpPort").value_or(47808));
return config;
}
DaliValue bacnetToJson(const BacnetBridgeConfig& config) {
DaliValue::Object out;
out["deviceInstance"] = static_cast<int64_t>(config.deviceInstance);
out["localAddress"] = config.localAddress;
out["udpPort"] = static_cast<int>(config.udpPort);
return DaliValue(std::move(out));
}
esp_err_t saveJsonObject(const std::string& nvs_namespace, const char* key,
const DaliValue::Object& object) {
if (key == nullptr || key[0] == '\0') {
@@ -227,7 +207,6 @@ BridgeRuntimeConfig BridgeRuntimeConfig::fromJson(const DaliValue::Object& json)
}
}
}
config.bacnet = bacnetFromJson(getObjectValue(json, "bacnet"));
if (const auto* metadata = getObjectValue(json, "meta")) {
if (const auto* object = metadata->asObject()) {
config.metadata = *object;
@@ -244,7 +223,6 @@ DaliValue::Object BridgeRuntimeConfig::toJson() const {
modelsValue.emplace_back(model.toJson());
}
out["models"] = std::move(modelsValue);
if (bacnet.has_value()) out["bacnet"] = bacnetToJson(bacnet.value());
if (!metadata.empty()) out["meta"] = metadata;
return out;
}