Add cloud bridge and provisioning support for ESP32 gateway
- Introduced DaliCloudBridge for MQTT communication with backend. - Added GatewayProvisioningStore for persisting cloud connection settings using NVS. - Updated CMakeLists.txt to include new source files. - Enhanced README.md with usage examples and configuration details.
This commit is contained in:
@@ -10,7 +10,10 @@ idf_component_register(
|
|||||||
"src/sequence.cpp"
|
"src/sequence.cpp"
|
||||||
"src/sequence_store.cpp"
|
"src/sequence_store.cpp"
|
||||||
"src/color.cpp"
|
"src/color.cpp"
|
||||||
|
"src/gateway_cloud.cpp"
|
||||||
|
"src/gateway_provisioning.cpp"
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
|
REQUIRES mqtt cjson nvs_flash
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
|
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
|
||||||
|
|||||||
@@ -47,3 +47,74 @@ std::vector<int> rgb = dali.dt8.getColourRGB(5);
|
|||||||
- Optional query support: provide a `transact` callback that returns the gateway reply; otherwise, query methods return `std::nullopt`.
|
- Optional query support: provide a `transact` callback that returns the gateway reply; otherwise, query methods return `std::nullopt`.
|
||||||
- `Dali` facade in `include/dali.hpp` mirrors `lib/dali/dali.dart` and wires `base`, `decode`, `dt1`, `dt8`, and `addr` together.
|
- `Dali` facade in `include/dali.hpp` mirrors `lib/dali/dali.dart` and wires `base`, `decode`, `dt1`, `dt8`, and `addr` together.
|
||||||
- The `t`, `d`, and `g` parameters in Dart are not required here; timing/gateway selection is driven by your callbacks.
|
- The `t`, `d`, and `g` parameters in Dart are not required here; timing/gateway selection is driven by your callbacks.
|
||||||
|
|
||||||
|
## Cloud Bridge (ESP32 Gateway)
|
||||||
|
|
||||||
|
The component now includes `DaliCloudBridge` in `include/gateway_cloud.hpp` to connect ESP32 gateways to the backend MQTT broker.
|
||||||
|
|
||||||
|
### Topics
|
||||||
|
|
||||||
|
- Downlink: `devices/<deviceID>/down`
|
||||||
|
- Uplink: `devices/<deviceID>/up`
|
||||||
|
- Status: `devices/<deviceID>/status`
|
||||||
|
- Register: `devices/<deviceID>/register`
|
||||||
|
|
||||||
|
### Downlink JSON Envelope
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "dali_cmd",
|
||||||
|
"seq": "123",
|
||||||
|
"op": "send|send_ext|query",
|
||||||
|
"addr": 5,
|
||||||
|
"cmd": 160
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uplink JSON Envelope
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "dali_resp",
|
||||||
|
"seq": "123",
|
||||||
|
"op": "query",
|
||||||
|
"ok": true,
|
||||||
|
"data": 255
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
GatewayCloudConfig cfg;
|
||||||
|
cfg.brokerURI = "mqtt://192.168.1.100:1883";
|
||||||
|
cfg.deviceID = "A1B2C3D4E5F6";
|
||||||
|
cfg.username = "device";
|
||||||
|
cfg.password = "A1B2C3D4E5F6";
|
||||||
|
|
||||||
|
DaliCloudBridge bridge(comm);
|
||||||
|
if (bridge.start(cfg)) {
|
||||||
|
bridge.publishStatus("online");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Provisioning via NVS
|
||||||
|
|
||||||
|
Use `GatewayProvisioningStore` to persist cloud connection settings:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
GatewayProvisioningStore store;
|
||||||
|
GatewayCloudConfig cfg;
|
||||||
|
cfg.brokerURI = "mqtt://192.168.1.100:1883";
|
||||||
|
cfg.deviceID = "A1B2C3D4E5F6";
|
||||||
|
cfg.username = "device";
|
||||||
|
cfg.password = "A1B2C3D4E5F6";
|
||||||
|
|
||||||
|
store.save(cfg);
|
||||||
|
|
||||||
|
GatewayCloudConfig loaded;
|
||||||
|
if (store.load(&loaded) == ESP_OK) {
|
||||||
|
DaliCloudBridge bridge(comm);
|
||||||
|
bridge.start(loaded);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
idf: '>=5.1'
|
idf: '>=5.1'
|
||||||
|
espressif/esp-mqtt: '*'
|
||||||
|
espressif/cjson: '*'
|
||||||
description: ESP DALI CPP library component for ESP-IDF
|
description: ESP DALI CPP library component for ESP-IDF
|
||||||
repository: git://github.com/tony-cloud/esp-dali-cpp.git
|
repository: git://github.com/tony-cloud/esp-dali-cpp.git
|
||||||
repository_info:
|
repository_info:
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "dt1.hpp"
|
#include "dt1.hpp"
|
||||||
#include "dt8.hpp"
|
#include "dt8.hpp"
|
||||||
#include "addr.hpp"
|
#include "addr.hpp"
|
||||||
|
#include "gateway_cloud.hpp"
|
||||||
|
#include "gateway_provisioning.hpp"
|
||||||
#include "color.hpp"
|
#include "color.hpp"
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dali_comm.hpp"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
#include "esp_event_base.h"
|
||||||
|
#include "mqtt_client.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct GatewayCloudConfig {
|
||||||
|
std::string brokerURI;
|
||||||
|
std::string deviceID;
|
||||||
|
std::string username = "device";
|
||||||
|
std::string password;
|
||||||
|
std::string topicPrefix = "devices";
|
||||||
|
int qos = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// DaliCloudBridge bridges MQTT cloud topics and local DALI frames.
|
||||||
|
class DaliCloudBridge {
|
||||||
|
public:
|
||||||
|
explicit DaliCloudBridge(DaliComm& comm);
|
||||||
|
|
||||||
|
bool start(const GatewayCloudConfig& config);
|
||||||
|
void stop();
|
||||||
|
bool isConnected() const;
|
||||||
|
|
||||||
|
bool publishStatus(const std::string& status);
|
||||||
|
bool publishRegister(const std::string& payloadJson);
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
static void mqttEventHandler(void* handler_args,
|
||||||
|
esp_event_base_t base,
|
||||||
|
int32_t event_id,
|
||||||
|
void* event_data);
|
||||||
|
void onMqttEvent(esp_mqtt_event_handle_t event);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool handleDownlink(const std::string& payload);
|
||||||
|
bool publishJSON(const std::string& topic, const std::string& payloadJson);
|
||||||
|
|
||||||
|
std::string topicDown() const;
|
||||||
|
std::string topicUp() const;
|
||||||
|
std::string topicStatus() const;
|
||||||
|
std::string topicRegister() const;
|
||||||
|
|
||||||
|
DaliComm& comm_;
|
||||||
|
GatewayCloudConfig config_;
|
||||||
|
std::atomic<bool> connected_{false};
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
esp_mqtt_client_handle_t client_ = nullptr;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gateway_cloud.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
extern "C" {
|
||||||
|
#include "esp_err.h"
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
using esp_err_t = int;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Stores/loads gateway cloud configuration using ESP-IDF NVS.
|
||||||
|
class GatewayProvisioningStore {
|
||||||
|
public:
|
||||||
|
explicit GatewayProvisioningStore(std::string nvsNamespace = "dali_cloud")
|
||||||
|
: nvsNamespace_(std::move(nvsNamespace)) {}
|
||||||
|
|
||||||
|
esp_err_t save(const GatewayCloudConfig& config) const;
|
||||||
|
esp_err_t load(GatewayCloudConfig* config) const;
|
||||||
|
esp_err_t clear() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string nvsNamespace_;
|
||||||
|
};
|
||||||
@@ -0,0 +1,241 @@
|
|||||||
|
#include "gateway_cloud.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
extern "C" {
|
||||||
|
#include "cJSON.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr const char* kTag = "dali_cloud_bridge";
|
||||||
|
|
||||||
|
std::string toString(const cJSON* item) {
|
||||||
|
if (item == nullptr) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (cJSON_IsString(item) && item->valuestring != nullptr) {
|
||||||
|
return std::string(item->valuestring);
|
||||||
|
}
|
||||||
|
if (cJSON_IsNumber(item)) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << item->valuedouble;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
int toInt(const cJSON* item, int fallback) {
|
||||||
|
if (item == nullptr || !cJSON_IsNumber(item)) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
return item->valueint;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DaliCloudBridge::DaliCloudBridge(DaliComm& comm) : comm_(comm) {}
|
||||||
|
|
||||||
|
bool DaliCloudBridge::start(const GatewayCloudConfig& config) {
|
||||||
|
config_ = config;
|
||||||
|
if (config_.brokerURI.empty() || config_.deviceID.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
if (client_ != nullptr) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_mqtt_client_config_t mqttCfg = {};
|
||||||
|
mqttCfg.broker.address.uri = config_.brokerURI.c_str();
|
||||||
|
mqttCfg.credentials.username = config_.username.empty() ? nullptr : config_.username.c_str();
|
||||||
|
mqttCfg.credentials.authentication.password =
|
||||||
|
config_.password.empty() ? nullptr : config_.password.c_str();
|
||||||
|
|
||||||
|
client_ = esp_mqtt_client_init(&mqttCfg);
|
||||||
|
if (client_ == nullptr) {
|
||||||
|
ESP_LOGE(kTag, "esp_mqtt_client_init failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_mqtt_client_register_event(client_, ESP_EVENT_ANY_ID, &DaliCloudBridge::mqttEventHandler,
|
||||||
|
this);
|
||||||
|
if (esp_mqtt_client_start(client_) != ESP_OK) {
|
||||||
|
ESP_LOGE(kTag, "esp_mqtt_client_start failed");
|
||||||
|
esp_mqtt_client_destroy(client_);
|
||||||
|
client_ = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
(void)config;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaliCloudBridge::stop() {
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
connected_.store(false);
|
||||||
|
if (client_ != nullptr) {
|
||||||
|
esp_mqtt_client_stop(client_);
|
||||||
|
esp_mqtt_client_destroy(client_);
|
||||||
|
client_ = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaliCloudBridge::isConnected() const { return connected_.load(); }
|
||||||
|
|
||||||
|
bool DaliCloudBridge::publishStatus(const std::string& status) {
|
||||||
|
std::string payload = "{\"type\":\"status\",\"status\":\"" + status + "\"}";
|
||||||
|
return publishJSON(topicStatus(), payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaliCloudBridge::publishRegister(const std::string& payloadJson) {
|
||||||
|
return publishJSON(topicRegister(), payloadJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaliCloudBridge::publishJSON(const std::string& topic, const std::string& payloadJson) {
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
if (client_ == nullptr || !connected_.load()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int msgID = esp_mqtt_client_publish(client_, topic.c_str(), payloadJson.c_str(),
|
||||||
|
static_cast<int>(payloadJson.size()), config_.qos, 0);
|
||||||
|
return msgID >= 0;
|
||||||
|
#else
|
||||||
|
(void)topic;
|
||||||
|
(void)payloadJson;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DaliCloudBridge::topicDown() const {
|
||||||
|
return config_.topicPrefix + "/" + config_.deviceID + "/down";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DaliCloudBridge::topicUp() const {
|
||||||
|
return config_.topicPrefix + "/" + config_.deviceID + "/up";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DaliCloudBridge::topicStatus() const {
|
||||||
|
return config_.topicPrefix + "/" + config_.deviceID + "/status";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DaliCloudBridge::topicRegister() const {
|
||||||
|
return config_.topicPrefix + "/" + config_.deviceID + "/register";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaliCloudBridge::handleDownlink(const std::string& payload) {
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
cJSON* root = cJSON_Parse(payload.c_str());
|
||||||
|
if (root == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cJSON* seqItem = cJSON_GetObjectItemCaseSensitive(root, "seq");
|
||||||
|
const cJSON* opItem = cJSON_GetObjectItemCaseSensitive(root, "op");
|
||||||
|
const cJSON* addrItem = cJSON_GetObjectItemCaseSensitive(root, "addr");
|
||||||
|
const cJSON* cmdItem = cJSON_GetObjectItemCaseSensitive(root, "cmd");
|
||||||
|
|
||||||
|
const std::string seq = toString(seqItem);
|
||||||
|
const std::string op = toString(opItem).empty() ? "send" : toString(opItem);
|
||||||
|
const int addr = toInt(addrItem, -1);
|
||||||
|
const int cmd = toInt(cmdItem, -1);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
bool hasData = false;
|
||||||
|
int data = -1;
|
||||||
|
std::string error = "";
|
||||||
|
|
||||||
|
if (addr < 0 || addr > 255 || cmd < 0 || cmd > 255) {
|
||||||
|
error = "invalid addr/cmd";
|
||||||
|
} else if (op == "send") {
|
||||||
|
ok = comm_.sendRaw(static_cast<uint8_t>(addr), static_cast<uint8_t>(cmd));
|
||||||
|
} else if (op == "send_ext") {
|
||||||
|
ok = comm_.sendExtRaw(static_cast<uint8_t>(addr), static_cast<uint8_t>(cmd));
|
||||||
|
} else if (op == "query") {
|
||||||
|
auto response = comm_.queryRaw(static_cast<uint8_t>(addr), static_cast<uint8_t>(cmd));
|
||||||
|
if (response.has_value()) {
|
||||||
|
ok = true;
|
||||||
|
hasData = true;
|
||||||
|
data = static_cast<int>(response.value());
|
||||||
|
} else {
|
||||||
|
error = "no response";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error = "unsupported op";
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON* resp = cJSON_CreateObject();
|
||||||
|
cJSON_AddStringToObject(resp, "type", "dali_resp");
|
||||||
|
cJSON_AddStringToObject(resp, "seq", seq.c_str());
|
||||||
|
cJSON_AddStringToObject(resp, "op", op.c_str());
|
||||||
|
cJSON_AddBoolToObject(resp, "ok", ok);
|
||||||
|
if (hasData) {
|
||||||
|
cJSON_AddNumberToObject(resp, "data", data);
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
cJSON_AddStringToObject(resp, "error", error.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
char* raw = cJSON_PrintUnformatted(resp);
|
||||||
|
std::string out = raw == nullptr ? "{}" : std::string(raw);
|
||||||
|
if (raw != nullptr) {
|
||||||
|
cJSON_free(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_Delete(resp);
|
||||||
|
cJSON_Delete(root);
|
||||||
|
|
||||||
|
return publishJSON(topicUp(), out);
|
||||||
|
#else
|
||||||
|
(void)payload;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
void DaliCloudBridge::mqttEventHandler(void* handler_args,
|
||||||
|
esp_event_base_t base,
|
||||||
|
int32_t event_id,
|
||||||
|
void* event_data) {
|
||||||
|
(void)base;
|
||||||
|
auto* self = static_cast<DaliCloudBridge*>(handler_args);
|
||||||
|
if (self == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self->onMqttEvent(static_cast<esp_mqtt_event_handle_t>(event_data));
|
||||||
|
(void)event_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaliCloudBridge::onMqttEvent(esp_mqtt_event_handle_t event) {
|
||||||
|
switch (event->event_id) {
|
||||||
|
case MQTT_EVENT_CONNECTED: {
|
||||||
|
connected_.store(true);
|
||||||
|
ESP_LOGI(kTag, "MQTT connected");
|
||||||
|
esp_mqtt_client_subscribe(client_, topicDown().c_str(), config_.qos);
|
||||||
|
publishStatus("online");
|
||||||
|
publishRegister("{\"type\":\"register\",\"status\":\"online\"}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MQTT_EVENT_DISCONNECTED:
|
||||||
|
connected_.store(false);
|
||||||
|
ESP_LOGW(kTag, "MQTT disconnected");
|
||||||
|
break;
|
||||||
|
case MQTT_EVENT_DATA: {
|
||||||
|
std::string topic(event->topic, event->topic_len);
|
||||||
|
std::string data(event->data, event->data_len);
|
||||||
|
if (topic == topicDown()) {
|
||||||
|
handleDownlink(data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
#include "gateway_provisioning.hpp"
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
extern "C" {
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "nvs.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr const char* kTag = "gateway_provision";
|
||||||
|
constexpr const char* kKeyBrokerURI = "broker_uri";
|
||||||
|
constexpr const char* kKeyDeviceID = "device_id";
|
||||||
|
constexpr const char* kKeyUsername = "username";
|
||||||
|
constexpr const char* kKeyPassword = "password";
|
||||||
|
constexpr const char* kKeyTopicPrefix = "topic_prefix";
|
||||||
|
constexpr const char* kKeyQos = "qos";
|
||||||
|
|
||||||
|
esp_err_t writeString(nvs_handle_t handle, const char* key, const std::string& value) {
|
||||||
|
return nvs_set_str(handle, key, value.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t readString(nvs_handle_t handle, const char* key, std::string* value) {
|
||||||
|
size_t required = 0;
|
||||||
|
esp_err_t err = nvs_get_str(handle, key, nullptr, &required);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
std::string buf(required, '\0');
|
||||||
|
err = nvs_get_str(handle, key, buf.data(), &required);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (!buf.empty() && buf.back() == '\0') {
|
||||||
|
buf.pop_back();
|
||||||
|
}
|
||||||
|
*value = buf;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
esp_err_t GatewayProvisioningStore::save(const GatewayCloudConfig& config) const {
|
||||||
|
nvs_handle_t handle;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writeString(handle, kKeyBrokerURI, config.brokerURI);
|
||||||
|
if (err == ESP_OK) err = writeString(handle, kKeyDeviceID, config.deviceID);
|
||||||
|
if (err == ESP_OK) err = writeString(handle, kKeyUsername, config.username);
|
||||||
|
if (err == ESP_OK) err = writeString(handle, kKeyPassword, config.password);
|
||||||
|
if (err == ESP_OK) err = writeString(handle, kKeyTopicPrefix, config.topicPrefix);
|
||||||
|
if (err == ESP_OK) err = nvs_set_i32(handle, kKeyQos, config.qos);
|
||||||
|
if (err == ESP_OK) err = nvs_commit(handle);
|
||||||
|
|
||||||
|
nvs_close(handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(kTag, "save failed: %s", esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t GatewayProvisioningStore::load(GatewayCloudConfig* config) const {
|
||||||
|
if (config == nullptr) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_handle_t handle;
|
||||||
|
esp_err_t err = nvs_open(nvsNamespace_.c_str(), NVS_READONLY, &handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = readString(handle, kKeyBrokerURI, &config->brokerURI);
|
||||||
|
if (err == ESP_OK) err = readString(handle, kKeyDeviceID, &config->deviceID);
|
||||||
|
if (err == ESP_OK) err = readString(handle, kKeyUsername, &config->username);
|
||||||
|
if (err == ESP_OK) err = readString(handle, kKeyPassword, &config->password);
|
||||||
|
|
||||||
|
esp_err_t topicErr = readString(handle, kKeyTopicPrefix, &config->topicPrefix);
|
||||||
|
if (topicErr != ESP_OK) {
|
||||||
|
config->topicPrefix = "devices";
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t qos = 1;
|
||||||
|
esp_err_t qosErr = nvs_get_i32(handle, kKeyQos, &qos);
|
||||||
|
if (qosErr == ESP_OK) {
|
||||||
|
config->qos = qos;
|
||||||
|
} else {
|
||||||
|
config->qos = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_close(handle);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t GatewayProvisioningStore::clear() const {
|
||||||
|
nvs_handle_t handle;
|
||||||
|
esp_err_t err = nvs_open(nvsNamespace_.c_str(), NVS_READWRITE, &handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = nvs_erase_all(handle);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
err = nvs_commit(handle);
|
||||||
|
}
|
||||||
|
nvs_close(handle);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
esp_err_t GatewayProvisioningStore::save(const GatewayCloudConfig& config) const {
|
||||||
|
(void)config;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t GatewayProvisioningStore::load(GatewayCloudConfig* config) const {
|
||||||
|
(void)config;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t GatewayProvisioningStore::clear() const { return -1; }
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user