143 lines
4.5 KiB
C++
143 lines
4.5 KiB
C++
#include "bacnet_bridge.hpp"
|
|
#include "bridge.hpp"
|
|
#include "bridge_model.hpp"
|
|
#include "bridge_provisioning.hpp"
|
|
#include "dali_comm.hpp"
|
|
|
|
#include <vector>
|
|
|
|
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<unsigned>(len), len > 0 ? data[0] : 0U);
|
|
(void)data;
|
|
return false;
|
|
}
|
|
|
|
std::vector<uint8_t> readGateway(size_t len, uint32_t timeout_ms) {
|
|
ESP_LOGI(kTag, "placeholder DALI gateway read len=%u timeout=%u",
|
|
static_cast<unsigned>(len), static_cast<unsigned>(timeout_ms));
|
|
return {};
|
|
}
|
|
|
|
std::vector<uint8_t> transactGateway(const uint8_t* data, size_t len) {
|
|
ESP_LOGI(kTag, "placeholder DALI gateway transact len=%u first=0x%02X",
|
|
static_cast<unsigned>(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() ? "<none>" : 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));
|
|
}
|