#include "bacnet_bridge.hpp" #include "bridge.hpp" #include "bridge_model.hpp" #include "bridge_provisioning.hpp" #include "dali_comm.hpp" #include extern "C" { #include "esp_log.h" #include "nvs_flash.h" } namespace { constexpr const char* kTag = "dali_bridge_example"; bool writeGateway(const uint8_t* data, size_t len) { ESP_LOGI(kTag, "placeholder DALI gateway write len=%u first=0x%02X", static_cast(len), len > 0 ? data[0] : 0U); (void)data; return false; } std::vector readGateway(size_t len, uint32_t timeout_ms) { ESP_LOGI(kTag, "placeholder DALI gateway read len=%u timeout=%u", static_cast(len), static_cast(timeout_ms)); return {}; } std::vector transactGateway(const uint8_t* data, size_t len) { ESP_LOGI(kTag, "placeholder DALI gateway transact len=%u first=0x%02X", static_cast(len), len > 0 ? data[0] : 0U); (void)data; return {}; } BridgeModel makeBrightnessModel() { BridgeModel model; model.id = "line-1-brightness"; model.name = "Line 1 brightness"; model.dali.shortAddress = 1; model.operation = BridgeOperation::setBrightness; model.valueEncoding = BridgeValueEncoding::integer; model.valueTransform.clampMin = 0; model.valueTransform.clampMax = 254; return model; } BridgeModel makeStatusQueryModel() { BridgeModel model; model.id = "line-1-status"; model.name = "Line 1 status"; model.dali.shortAddress = 1; model.operation = BridgeOperation::getStatus; 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; } void logResult(const char* label, const DaliBridgeResult& result) { ESP_LOGI(kTag, "%s ok=%d op=%s data=%d error=%s", label, result.ok, bridgeOperationToString(result.operation), result.data.value_or(-1), result.error.empty() ? "" : result.error.c_str()); } } // namespace extern "C" void app_main(void) { esp_err_t nvs_err = nvs_flash_init(); if (nvs_err != ESP_OK) { ESP_LOGW(kTag, "nvs_flash_init failed: %s", esp_err_to_name(nvs_err)); } BridgeProvisioningStore provisioning_store; BridgeRuntimeConfig runtime_config; if (provisioning_store.load(&runtime_config) != ESP_OK || runtime_config.models.empty()) { runtime_config = makeDefaultRuntimeConfig(); provisioning_store.save(runtime_config); } static DaliComm comm(writeGateway, readGateway, transactGateway); static DaliBridgeEngine engine(comm); for (const auto& model : runtime_config.models) { 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"; logResult("status query", engine.execute(status_request)); }