Enhance DALI bridge: add BridgeOperation and BridgeDaliTarget support, refactor address resolution and provisioning methods

This commit is contained in:
Tony
2026-05-02 21:33:57 +08:00
parent 16907857c0
commit 307c480aa0
8 changed files with 285 additions and 102 deletions
+2
View File
@@ -18,6 +18,8 @@ struct BacnetObjectBinding {
BridgeObjectType objectType = BridgeObjectType::unknown; BridgeObjectType objectType = BridgeObjectType::unknown;
int objectInstance = -1; int objectInstance = -1;
std::string property; std::string property;
BridgeOperation operation = BridgeOperation::unknown;
BridgeDaliTarget target;
}; };
class DaliBacnetBridge { class DaliBacnetBridge {
+2 -2
View File
@@ -55,8 +55,8 @@ class DaliBridgeEngine {
DaliBridgeResult executeResolved(const DaliBridgeRequest& request, DaliBridgeResult executeResolved(const DaliBridgeRequest& request,
const BridgeModel* model, const BridgeModel* model,
BridgeOperation operation); BridgeOperation operation);
std::optional<int> resolveShortAddress(const DaliBridgeRequest& request, std::optional<int> resolveTargetAddress(const DaliBridgeRequest& request,
const BridgeModel* model) const; const BridgeModel* model) const;
std::optional<int> resolveRawAddress(const DaliBridgeRequest& request, std::optional<int> resolveRawAddress(const DaliBridgeRequest& request,
const BridgeModel* model) const; const BridgeModel* model) const;
std::optional<int> resolveRawCommand(const DaliBridgeRequest& request, std::optional<int> resolveRawCommand(const DaliBridgeRequest& request,
+13
View File
@@ -25,6 +25,12 @@ enum class BridgeObjectType {
multiStateValue = 9, multiStateValue = 9,
}; };
enum class BridgeDaliTargetKind {
shortAddress = 0,
group = 1,
broadcast = 2,
};
enum class BridgeOperation { enum class BridgeOperation {
unknown = 0, unknown = 0,
send = 1, send = 1,
@@ -46,6 +52,7 @@ enum class BridgeOperation {
getEmergencyFailureStatus = 17, getEmergencyFailureStatus = 17,
startEmergencyFunctionTest = 18, startEmergencyFunctionTest = 18,
stopEmergencyTest = 19, stopEmergencyTest = 19,
startEmergencyDurationTest = 20,
}; };
enum class BridgeValueEncoding { enum class BridgeValueEncoding {
@@ -80,12 +87,15 @@ struct BridgeExternalPoint {
}; };
struct BridgeDaliTarget { struct BridgeDaliTarget {
BridgeDaliTargetKind kind = BridgeDaliTargetKind::shortAddress;
std::optional<int> shortAddress; std::optional<int> shortAddress;
std::optional<int> groupAddress;
std::optional<int> rawAddress; std::optional<int> rawAddress;
std::optional<int> rawCommand; std::optional<int> rawCommand;
static BridgeDaliTarget fromJson(const DaliValue::Object* json); static BridgeDaliTarget fromJson(const DaliValue::Object* json);
DaliValue::Object toJson() const; DaliValue::Object toJson() const;
std::optional<int> logicalAddress() const;
}; };
struct BridgeModel { struct BridgeModel {
@@ -110,6 +120,9 @@ BridgeProtocolKind bridgeProtocolKindFromString(const std::string& value);
const char* bridgeObjectTypeToString(BridgeObjectType type); const char* bridgeObjectTypeToString(BridgeObjectType type);
BridgeObjectType bridgeObjectTypeFromString(const std::string& value); BridgeObjectType bridgeObjectTypeFromString(const std::string& value);
const char* bridgeDaliTargetKindToString(BridgeDaliTargetKind kind);
BridgeDaliTargetKind bridgeDaliTargetKindFromString(const std::string& value);
const char* bridgeOperationToString(BridgeOperation operation); const char* bridgeOperationToString(BridgeOperation operation);
BridgeOperation bridgeOperationFromString(const std::string& value); BridgeOperation bridgeOperationFromString(const std::string& value);
+3
View File
@@ -34,6 +34,9 @@ class BridgeProvisioningStore {
esp_err_t save(const BridgeRuntimeConfig& config) const; esp_err_t save(const BridgeRuntimeConfig& config) const;
esp_err_t load(BridgeRuntimeConfig* config) const; esp_err_t load(BridgeRuntimeConfig* config) const;
esp_err_t clear() const; esp_err_t clear() const;
esp_err_t saveObject(const char* key, const DaliValue::Object& object) const;
esp_err_t loadObject(const char* key, DaliValue::Object* object) const;
esp_err_t clearKey(const char* key) const;
private: private:
std::string nvsNamespace_; std::string nvsNamespace_;
+4 -2
View File
@@ -44,7 +44,8 @@ std::optional<BacnetObjectBinding> DaliBacnetBridge::findObject(BridgeObjectType
if (!model.external.property.empty() && model.external.property != property) { if (!model.external.property.empty() && model.external.property != property) {
continue; continue;
} }
return BacnetObjectBinding{model.id, objectType, objectInstance, property}; return BacnetObjectBinding{model.id, objectType, objectInstance, property,
model.operation, model.dali};
} }
return std::nullopt; return std::nullopt;
} }
@@ -57,7 +58,8 @@ std::vector<BacnetObjectBinding> DaliBacnetBridge::describeObjects() const {
} }
bindings.push_back(BacnetObjectBinding{model.id, model.external.objectType, bindings.push_back(BacnetObjectBinding{model.id, model.external.objectType,
model.external.objectInstance.value(), model.external.objectInstance.value(),
model.external.property}); model.external.property, model.operation,
model.dali});
} }
return bindings; return bindings;
} }
+42 -33
View File
@@ -135,7 +135,7 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
return result; return result;
} }
case BridgeOperation::setBrightness: { case BridgeOperation::setBrightness: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
const auto value = resolveIntValue(request, model); const auto value = resolveIntValue(request, model);
if (!address.has_value() || !value.has_value()) { if (!address.has_value() || !value.has_value()) {
result.error = "missing address/value"; result.error = "missing address/value";
@@ -146,7 +146,7 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::setBrightnessPercent: { case BridgeOperation::setBrightnessPercent: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
const auto value = resolveDoubleValue(request); const auto value = resolveDoubleValue(request);
if (!address.has_value() || !value.has_value()) { if (!address.has_value() || !value.has_value()) {
result.error = "missing address/value"; result.error = "missing address/value";
@@ -157,43 +157,43 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::on: { case BridgeOperation::on: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
result.ok = base_.on(address.value()); result.ok = base_.on(address.value());
break; break;
} }
case BridgeOperation::off: { case BridgeOperation::off: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
result.ok = base_.off(address.value()); result.ok = base_.off(address.value());
break; break;
} }
case BridgeOperation::recallMaxLevel: { case BridgeOperation::recallMaxLevel: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
result.ok = base_.recallMaxLevel(address.value()); result.ok = base_.recallMaxLevel(address.value());
break; break;
} }
case BridgeOperation::recallMinLevel: { case BridgeOperation::recallMinLevel: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
result.ok = base_.recallMinLevel(address.value()); result.ok = base_.recallMinLevel(address.value());
break; break;
} }
case BridgeOperation::setColorTemperature: { case BridgeOperation::setColorTemperature: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
const auto value = resolveIntValue(request, model); const auto value = resolveIntValue(request, model);
if (!address.has_value() || !value.has_value()) { if (!address.has_value() || !value.has_value()) {
result.error = "missing address/value"; result.error = "missing address/value";
@@ -204,9 +204,9 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::getBrightness: { case BridgeOperation::getBrightness: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
const auto value = base_.getBright(address.value()); const auto value = base_.getBright(address.value());
@@ -219,9 +219,9 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::getStatus: { case BridgeOperation::getStatus: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
const auto value = base_.getStatus(address.value()); const auto value = base_.getStatus(address.value());
@@ -235,9 +235,9 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::getColorTemperature: { case BridgeOperation::getColorTemperature: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
const auto value = dt8_.getColorTemperature(address.value()); const auto value = dt8_.getColorTemperature(address.value());
@@ -250,9 +250,9 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::getColorStatus: { case BridgeOperation::getColorStatus: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
const auto value = dt8_.getColorStatus(address.value()); const auto value = dt8_.getColorStatus(address.value());
@@ -273,9 +273,9 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::getEmergencyLevel: { case BridgeOperation::getEmergencyLevel: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
const auto value = dt1_.getEmergencyLevel(address.value()); const auto value = dt1_.getEmergencyLevel(address.value());
@@ -288,9 +288,9 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::getEmergencyStatus: { case BridgeOperation::getEmergencyStatus: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
const auto status = dt1_.getEmergencyStatusDecoded(address.value()); const auto status = dt1_.getEmergencyStatusDecoded(address.value());
@@ -311,9 +311,9 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::getEmergencyFailureStatus: { case BridgeOperation::getEmergencyFailureStatus: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
const auto status = dt1_.getDT1TestStatusDetailed(address.value()); const auto status = dt1_.getDT1TestStatusDetailed(address.value());
@@ -337,18 +337,27 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
break; break;
} }
case BridgeOperation::startEmergencyFunctionTest: { case BridgeOperation::startEmergencyFunctionTest: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result; return result;
} }
result.ok = dt1_.startFunctionTestCmd(address.value()); result.ok = dt1_.startFunctionTestCmd(address.value());
break; break;
} }
case BridgeOperation::stopEmergencyTest: { case BridgeOperation::startEmergencyDurationTest: {
const auto address = resolveShortAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing short address"; result.error = "missing target address";
return result;
}
result.ok = dt1_.startDurationTestCmd(address.value());
break;
}
case BridgeOperation::stopEmergencyTest: {
const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) {
result.error = "missing target address";
return result; return result;
} }
result.ok = dt1_.stopTest(address.value()); result.ok = dt1_.stopTest(address.value());
@@ -366,13 +375,13 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
return result; return result;
} }
std::optional<int> DaliBridgeEngine::resolveShortAddress(const DaliBridgeRequest& request, std::optional<int> DaliBridgeEngine::resolveTargetAddress(const DaliBridgeRequest& request,
const BridgeModel* model) const { const BridgeModel* model) const {
if (request.shortAddress.has_value()) { if (request.shortAddress.has_value()) {
return request.shortAddress; return request.shortAddress;
} }
if (model != nullptr) { if (model != nullptr) {
return model->dali.shortAddress; return model->dali.logicalAddress();
} }
return std::nullopt; return std::nullopt;
} }
+92 -2
View File
@@ -7,6 +7,9 @@
namespace { namespace {
constexpr int kDaliGroupBaseAddress = 64;
constexpr int kDaliBroadcastAddress = 127;
std::string normalize(const std::string& value) { std::string normalize(const std::string& value) {
std::string out = value; std::string out = value;
std::transform(out.begin(), out.end(), out.begin(), [](unsigned char ch) { std::transform(out.begin(), out.end(), out.begin(), [](unsigned char ch) {
@@ -88,7 +91,37 @@ BridgeDaliTarget BridgeDaliTarget::fromJson(const DaliValue::Object* json) {
if (json == nullptr) { if (json == nullptr) {
return target; return target;
} }
target.shortAddress = getObjectInt(*json, "shortAddress"); const auto explicit_kind = bridgeDaliTargetKindFromString(
getObjectString(*json, "kind")
.value_or(getObjectString(*json, "targetKind").value_or("")));
const auto shared_address = getObjectInt(*json, "address");
const auto short_address = getObjectInt(*json, "shortAddress");
const auto group_address = getObjectInt(*json, "groupAddress").has_value()
? getObjectInt(*json, "groupAddress")
: getObjectInt(*json, "group");
const bool broadcast = getObjectBool(*json, "broadcast").value_or(false);
target.kind = explicit_kind;
if (explicit_kind == BridgeDaliTargetKind::shortAddress) {
target.shortAddress = shared_address;
} else if (explicit_kind == BridgeDaliTargetKind::group) {
target.groupAddress = shared_address;
}
if (short_address.has_value()) {
target.shortAddress = short_address;
if (explicit_kind != BridgeDaliTargetKind::broadcast) {
target.kind = BridgeDaliTargetKind::shortAddress;
}
}
if (group_address.has_value()) {
target.groupAddress = group_address;
if (explicit_kind != BridgeDaliTargetKind::broadcast) {
target.kind = BridgeDaliTargetKind::group;
}
}
if (broadcast) {
target.kind = BridgeDaliTargetKind::broadcast;
}
target.rawAddress = getObjectInt(*json, "rawAddress"); target.rawAddress = getObjectInt(*json, "rawAddress");
target.rawCommand = getObjectInt(*json, "rawCommand"); target.rawCommand = getObjectInt(*json, "rawCommand");
return target; return target;
@@ -96,12 +129,44 @@ BridgeDaliTarget BridgeDaliTarget::fromJson(const DaliValue::Object* json) {
DaliValue::Object BridgeDaliTarget::toJson() const { DaliValue::Object BridgeDaliTarget::toJson() const {
DaliValue::Object out; DaliValue::Object out;
if (shortAddress.has_value()) out["shortAddress"] = shortAddress.value(); out["kind"] = bridgeDaliTargetKindToString(kind);
switch (kind) {
case BridgeDaliTargetKind::shortAddress:
if (shortAddress.has_value()) {
out["address"] = shortAddress.value();
out["shortAddress"] = shortAddress.value();
}
break;
case BridgeDaliTargetKind::group:
if (groupAddress.has_value()) {
out["address"] = groupAddress.value();
out["groupAddress"] = groupAddress.value();
}
break;
case BridgeDaliTargetKind::broadcast:
out["broadcast"] = true;
break;
}
if (rawAddress.has_value()) out["rawAddress"] = rawAddress.value(); if (rawAddress.has_value()) out["rawAddress"] = rawAddress.value();
if (rawCommand.has_value()) out["rawCommand"] = rawCommand.value(); if (rawCommand.has_value()) out["rawCommand"] = rawCommand.value();
return out; return out;
} }
std::optional<int> BridgeDaliTarget::logicalAddress() const {
switch (kind) {
case BridgeDaliTargetKind::shortAddress:
return shortAddress;
case BridgeDaliTargetKind::group:
if (!groupAddress.has_value()) {
return std::nullopt;
}
return kDaliGroupBaseAddress + groupAddress.value();
case BridgeDaliTargetKind::broadcast:
return kDaliBroadcastAddress;
}
return std::nullopt;
}
BridgeModel BridgeModel::fromJson(const DaliValue::Object& json) { BridgeModel BridgeModel::fromJson(const DaliValue::Object& json) {
BridgeModel model; BridgeModel model;
model.id = getObjectString(json, "id").value_or(""); model.id = getObjectString(json, "id").value_or("");
@@ -210,6 +275,26 @@ BridgeObjectType bridgeObjectTypeFromString(const std::string& value) {
return BridgeObjectType::unknown; return BridgeObjectType::unknown;
} }
const char* bridgeDaliTargetKindToString(BridgeDaliTargetKind kind) {
switch (kind) {
case BridgeDaliTargetKind::shortAddress:
return "short_address";
case BridgeDaliTargetKind::group:
return "group";
case BridgeDaliTargetKind::broadcast:
return "broadcast";
default:
return "short_address";
}
}
BridgeDaliTargetKind bridgeDaliTargetKindFromString(const std::string& value) {
const std::string normalized = normalize(value);
if (normalized == "group") return BridgeDaliTargetKind::group;
if (normalized == "broadcast") return BridgeDaliTargetKind::broadcast;
return BridgeDaliTargetKind::shortAddress;
}
const char* bridgeOperationToString(BridgeOperation operation) { const char* bridgeOperationToString(BridgeOperation operation) {
switch (operation) { switch (operation) {
case BridgeOperation::send: case BridgeOperation::send:
@@ -250,6 +335,8 @@ const char* bridgeOperationToString(BridgeOperation operation) {
return "start_emergency_function_test"; return "start_emergency_function_test";
case BridgeOperation::stopEmergencyTest: case BridgeOperation::stopEmergencyTest:
return "stop_emergency_test"; return "stop_emergency_test";
case BridgeOperation::startEmergencyDurationTest:
return "start_emergency_duration_test";
case BridgeOperation::unknown: case BridgeOperation::unknown:
default: default:
return "unknown"; return "unknown";
@@ -279,6 +366,9 @@ BridgeOperation bridgeOperationFromString(const std::string& value) {
return BridgeOperation::startEmergencyFunctionTest; return BridgeOperation::startEmergencyFunctionTest;
} }
if (normalized == "stop_emergency_test") return BridgeOperation::stopEmergencyTest; if (normalized == "stop_emergency_test") return BridgeOperation::stopEmergencyTest;
if (normalized == "start_emergency_duration_test") {
return BridgeOperation::startEmergencyDurationTest;
}
return BridgeOperation::unknown; return BridgeOperation::unknown;
} }
+127 -63
View File
@@ -143,6 +143,98 @@ DaliValue bacnetToJson(const BacnetBridgeConfig& config) {
return DaliValue(std::move(out)); 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') {
return ESP_ERR_INVALID_ARG;
}
nvs_handle_t handle;
esp_err_t err = nvs_open(nvs_namespace.c_str(), NVS_READWRITE, &handle);
if (err != ESP_OK) {
ESP_LOGE(kTag, "nvs_open(save %s) failed: %s", key, esp_err_to_name(err));
return err;
}
cJSON* root = toCjson(DaliValue(object));
char* raw = cJSON_PrintUnformatted(root);
if (raw == nullptr) {
cJSON_Delete(root);
nvs_close(handle);
return ESP_ERR_NO_MEM;
}
err = nvs_set_str(handle, key, raw);
if (err == ESP_OK) {
err = nvs_commit(handle);
}
cJSON_Delete(root);
cJSON_free(raw);
nvs_close(handle);
if (err != ESP_OK) {
ESP_LOGE(kTag, "save %s failed: %s", key, esp_err_to_name(err));
}
return err;
}
esp_err_t loadJsonObject(const std::string& nvs_namespace, const char* key,
DaliValue::Object* object) {
if (object == nullptr || key == nullptr || key[0] == '\0') {
return ESP_ERR_INVALID_ARG;
}
nvs_handle_t handle;
esp_err_t err = nvs_open(nvs_namespace.c_str(), NVS_READONLY, &handle);
if (err != ESP_OK) {
return err;
}
std::string payload;
err = readString(handle, key, &payload);
nvs_close(handle);
if (err != ESP_OK) {
return err;
}
cJSON* root = cJSON_Parse(payload.c_str());
if (root == nullptr) {
return ESP_ERR_INVALID_RESPONSE;
}
const DaliValue value = fromCjson(root);
cJSON_Delete(root);
const auto* parsed = value.asObject();
if (parsed == nullptr) {
return ESP_ERR_INVALID_RESPONSE;
}
*object = *parsed;
return ESP_OK;
}
esp_err_t clearStoredKey(const std::string& nvs_namespace, const char* key) {
if (key == nullptr || key[0] == '\0') {
return ESP_ERR_INVALID_ARG;
}
nvs_handle_t handle;
esp_err_t err = nvs_open(nvs_namespace.c_str(), NVS_READWRITE, &handle);
if (err != ESP_OK) {
return err;
}
err = nvs_erase_key(handle, key);
if (err == ESP_ERR_NVS_NOT_FOUND) {
err = ESP_OK;
}
if (err == ESP_OK) {
err = nvs_commit(handle);
}
nvs_close(handle);
return err;
}
} // namespace } // namespace
BridgeRuntimeConfig BridgeRuntimeConfig::fromJson(const DaliValue::Object& json) { BridgeRuntimeConfig BridgeRuntimeConfig::fromJson(const DaliValue::Object& json) {
@@ -182,33 +274,7 @@ DaliValue::Object BridgeRuntimeConfig::toJson() const {
} }
esp_err_t BridgeProvisioningStore::save(const BridgeRuntimeConfig& config) const { esp_err_t BridgeProvisioningStore::save(const BridgeRuntimeConfig& config) const {
nvs_handle_t handle; return saveJsonObject(nvsNamespace_, kKeyConfig, config.toJson());
esp_err_t err = nvs_open(nvsNamespace_.c_str(), NVS_READWRITE, &handle);
if (err != ESP_OK) {
ESP_LOGE(kTag, "nvs_open(save) failed: %s", esp_err_to_name(err));
return err;
}
cJSON* root = toCjson(DaliValue(config.toJson()));
char* raw = cJSON_PrintUnformatted(root);
if (raw == nullptr) {
cJSON_Delete(root);
nvs_close(handle);
return ESP_ERR_NO_MEM;
}
err = nvs_set_str(handle, kKeyConfig, raw);
if (err == ESP_OK) {
err = nvs_commit(handle);
}
cJSON_Delete(root);
cJSON_free(raw);
nvs_close(handle);
if (err != ESP_OK) {
ESP_LOGE(kTag, "save failed: %s", esp_err_to_name(err));
}
return err;
} }
esp_err_t BridgeProvisioningStore::load(BridgeRuntimeConfig* config) const { esp_err_t BridgeProvisioningStore::load(BridgeRuntimeConfig* config) const {
@@ -216,51 +282,31 @@ esp_err_t BridgeProvisioningStore::load(BridgeRuntimeConfig* config) const {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
nvs_handle_t handle; DaliValue::Object object;
esp_err_t err = nvs_open(nvsNamespace_.c_str(), NVS_READONLY, &handle); const esp_err_t err = loadJsonObject(nvsNamespace_, kKeyConfig, &object);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }
std::string payload; *config = BridgeRuntimeConfig::fromJson(object);
err = readString(handle, kKeyConfig, &payload);
nvs_close(handle);
if (err != ESP_OK) {
return err;
}
cJSON* root = cJSON_Parse(payload.c_str());
if (root == nullptr) {
return ESP_ERR_INVALID_RESPONSE;
}
const DaliValue value = fromCjson(root);
cJSON_Delete(root);
const auto* object = value.asObject();
if (object == nullptr) {
return ESP_ERR_INVALID_RESPONSE;
}
*config = BridgeRuntimeConfig::fromJson(*object);
return ESP_OK; return ESP_OK;
} }
esp_err_t BridgeProvisioningStore::clear() const { esp_err_t BridgeProvisioningStore::clear() const {
nvs_handle_t handle; return clearStoredKey(nvsNamespace_, kKeyConfig);
esp_err_t err = nvs_open(nvsNamespace_.c_str(), NVS_READWRITE, &handle); }
if (err != ESP_OK) {
return err;
}
err = nvs_erase_key(handle, kKeyConfig); esp_err_t BridgeProvisioningStore::saveObject(const char* key,
if (err == ESP_ERR_NVS_NOT_FOUND) { const DaliValue::Object& object) const {
err = ESP_OK; return saveJsonObject(nvsNamespace_, key, object);
} }
if (err == ESP_OK) {
err = nvs_commit(handle); esp_err_t BridgeProvisioningStore::loadObject(const char* key, DaliValue::Object* object) const {
} return loadJsonObject(nvsNamespace_, key, object);
nvs_close(handle); }
return err;
esp_err_t BridgeProvisioningStore::clearKey(const char* key) const {
return clearStoredKey(nvsNamespace_, key);
} }
#else #else
@@ -284,4 +330,22 @@ esp_err_t BridgeProvisioningStore::load(BridgeRuntimeConfig* config) const {
esp_err_t BridgeProvisioningStore::clear() const { return -1; } esp_err_t BridgeProvisioningStore::clear() const { return -1; }
esp_err_t BridgeProvisioningStore::saveObject(const char* key,
const DaliValue::Object& object) const {
(void)key;
(void)object;
return -1;
}
esp_err_t BridgeProvisioningStore::loadObject(const char* key, DaliValue::Object* object) const {
(void)key;
(void)object;
return -1;
}
esp_err_t BridgeProvisioningStore::clearKey(const char* key) const {
(void)key;
return -1;
}
#endif #endif