Skip to content

Commit 31f6525

Browse files
implementing kvstore for esp32
1 parent cde853b commit 31f6525

File tree

2 files changed

+342
-0
lines changed

2 files changed

+342
-0
lines changed

src/kvstore/implementation/ESP32.cpp

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
/*
2+
* This file is part of Arduino_KVStore.
3+
*
4+
* Copyright (c) 2024 Arduino SA
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
#if defined(ARDUINO_ARCH_ESP32)
12+
#include "ESP32.h"
13+
#include "nvs.h"
14+
#include "nvs_flash.h"
15+
16+
bool ESP32KVStore::begin(const char* name, bool readOnly, const char* partition_label) {
17+
if(_started){
18+
return false;
19+
}
20+
_readOnly = readOnly;
21+
esp_err_t err = ESP_OK;
22+
if (partition_label != NULL) {
23+
err = nvs_flash_init_partition(partition_label);
24+
if (err) {
25+
log_e("nvs_flash_init_partition failed: %s", nvs_error(err));
26+
return false;
27+
}
28+
err = nvs_open_from_partition(partition_label, name, readOnly ? NVS_READONLY : NVS_READWRITE, &_handle);
29+
} else {
30+
err = nvs_open(name, readOnly ? NVS_READONLY : NVS_READWRITE, &_handle);
31+
}
32+
if(err){
33+
log_e("nvs_open failed: %s", nvs_error(err));
34+
return false;
35+
}
36+
_started = true;
37+
return true;
38+
}
39+
40+
bool ESP32KVStore::begin() {
41+
return begin(DEFAULT_KVSTORE_NAME);
42+
}
43+
44+
bool ESP32KVStore::end() {
45+
if(!_started){
46+
return false;
47+
}
48+
nvs_close(_handle);
49+
_started = false;
50+
51+
return true;
52+
}
53+
54+
bool ESP32KVStore::clear() {
55+
if(!_started || _readOnly){
56+
return false;
57+
}
58+
esp_err_t err = nvs_erase_all(_handle);
59+
if(err){
60+
log_e("nvs_erase_all fail: %s", nvs_error(err));
61+
return false;
62+
}
63+
err = nvs_commit(_handle);
64+
if(err){
65+
log_e("nvs_commit fail: %s", nvs_error(err));
66+
return false;
67+
}
68+
return true;
69+
}
70+
71+
typename KVStoreInterface::res_t ESP32KVStore::remove(const key_t& key) {
72+
if(!_started || !key || _readOnly){
73+
return false;
74+
}
75+
esp_err_t err = nvs_erase_key(_handle, key);
76+
if(err){
77+
log_e("nvs_erase_key fail: %s %s", key, nvs_error(err));
78+
return false;
79+
}
80+
err = nvs_commit(_handle);
81+
if(err){
82+
log_e("nvs_commit fail: %s %s", key, nvs_error(err));
83+
return false;
84+
}
85+
return true;
86+
}
87+
88+
typename KVStoreInterface::res_t ESP32KVStore::putBytes(const key_t& key, const uint8_t value[], size_t len) {
89+
if(!_started || !key || !value || !len || _readOnly){
90+
return 0;
91+
}
92+
esp_err_t err = nvs_set_blob(_handle, key, value, len);
93+
if(err){
94+
log_e("nvs_set_blob fail: %s %s", key, nvs_error(err));
95+
return 0;
96+
}
97+
err = nvs_commit(_handle);
98+
if(err){
99+
log_e("nvs_commit fail: %s %s", key, nvs_error(err));
100+
return 0;
101+
}
102+
return len;
103+
}
104+
105+
typename KVStoreInterface::res_t ESP32KVStore::getBytes(const key_t& key, uint8_t buf[], size_t maxLen) const {
106+
size_t len = getBytesLength(key);
107+
if(!len || !buf || !maxLen){
108+
return len;
109+
}
110+
if(len > maxLen){
111+
log_e("not enough space in buffer: %u < %u", maxLen, len);
112+
return 0;
113+
}
114+
esp_err_t err = nvs_get_blob(_handle, key, buf, &len);
115+
if(err){
116+
log_e("nvs_get_blob fail: %s %s", key, nvs_error(err));
117+
return 0;
118+
}
119+
return len;
120+
}
121+
122+
size_t ESP32KVStore::getBytesLength(const key_t& key) const {
123+
if(!_started || !key){
124+
return 0;
125+
}
126+
esp_err_t err = ESP_OK;
127+
128+
int8_t mt1; uint8_t mt2; int16_t mt3; uint16_t mt4;
129+
int32_t mt5; uint32_t mt6; int64_t mt7; uint64_t mt8;
130+
size_t len = 0;
131+
if ((err = nvs_get_i8(_handle, key, &mt1)) == ESP_OK) { len = sizeof(mt1);
132+
} else if((err = nvs_get_u8(_handle, key, &mt2)) == ESP_OK) { len = sizeof(mt2);
133+
} else if((err = nvs_get_i16(_handle, key, &mt3)) == ESP_OK) { len = sizeof(mt3);
134+
} else if((err = nvs_get_u16(_handle, key, &mt4)) == ESP_OK) { len = sizeof(mt4);
135+
} else if((err = nvs_get_i32(_handle, key, &mt5)) == ESP_OK) { len = sizeof(mt5);
136+
} else if((err = nvs_get_u32(_handle, key, &mt6)) == ESP_OK) { len = sizeof(mt6);
137+
} else if((err = nvs_get_i64(_handle, key, &mt7)) == ESP_OK) { len = sizeof(mt7);
138+
} else if((err = nvs_get_u64(_handle, key, &mt8)) == ESP_OK) { len = sizeof(mt8);
139+
} else if((err = nvs_get_str(_handle, key, NULL, &len)) == ESP_OK) {
140+
} else if((err = nvs_get_blob(_handle, key, NULL, &len)) == ESP_OK) {}
141+
142+
if(err){
143+
log_e("nvs_get_blob len fail: %s %s", key, nvs_error(err));
144+
return 0;
145+
}
146+
return len;
147+
}
148+
149+
150+
bool ESP32KVStore::exists(const key_t& key) const {
151+
return getType(key) != PT_INVALID;
152+
}
153+
154+
ESP32KVStore::Type ESP32KVStore::getType(const key_t& key) const {
155+
if(!_started || !key || strlen(key)>15){
156+
return PT_INVALID;
157+
}
158+
int8_t mt1; uint8_t mt2; int16_t mt3; uint16_t mt4;
159+
int32_t mt5; uint32_t mt6; int64_t mt7; uint64_t mt8;
160+
size_t len = 0;
161+
if(nvs_get_i8(_handle, key, &mt1) == ESP_OK) return PT_I8;
162+
if(nvs_get_u8(_handle, key, &mt2) == ESP_OK) return PT_U8;
163+
if(nvs_get_i16(_handle, key, &mt3) == ESP_OK) return PT_I16;
164+
if(nvs_get_u16(_handle, key, &mt4) == ESP_OK) return PT_U16;
165+
if(nvs_get_i32(_handle, key, &mt5) == ESP_OK) return PT_I32;
166+
if(nvs_get_u32(_handle, key, &mt6) == ESP_OK) return PT_U32;
167+
if(nvs_get_i64(_handle, key, &mt7) == ESP_OK) return PT_I64;
168+
if(nvs_get_u64(_handle, key, &mt8) == ESP_OK) return PT_U64;
169+
if(nvs_get_str(_handle, key, NULL, &len) == ESP_OK) return PT_STR;
170+
if(nvs_get_blob(_handle, key, NULL, &len) == ESP_OK) return PT_BLOB;
171+
return PT_INVALID;
172+
}
173+
174+
175+
176+
typename KVStoreInterface::res_t ESP32KVStore::_put(
177+
const key_t& key, const uint8_t value[], size_t len, KVStoreInterface::Type t) {
178+
if(!_started || !key || _readOnly){
179+
return 0;
180+
}
181+
182+
esp_err_t err;
183+
switch(t) {
184+
case PT_I8:
185+
err = nvs_set_i8(_handle, key, *((int8_t*) value));
186+
break;
187+
case PT_U8:
188+
err = nvs_set_u8(_handle, key, *((uint8_t*) value));
189+
break;
190+
case PT_I16:
191+
err = nvs_set_i16(_handle, key, *((int16_t*) value));
192+
break;
193+
case PT_U16:
194+
err = nvs_set_u16(_handle, key, *((uint16_t*) value));
195+
break;
196+
case PT_I32:
197+
err = nvs_set_i32(_handle, key, *((int32_t*) value));
198+
break;
199+
case PT_U32:
200+
err = nvs_set_u32(_handle, key, *((uint32_t*) value));
201+
break;
202+
case PT_I64:
203+
err = nvs_set_i64(_handle, key, *((int64_t*) value));
204+
break;
205+
case PT_U64:
206+
err = nvs_set_u64(_handle, key, *((uint64_t*) value));
207+
break;
208+
case PT_STR:
209+
err = nvs_set_str(_handle, key, (char*)value);
210+
break;
211+
case PT_BLOB:
212+
err = nvs_set_blob(_handle, key, value, len);
213+
break;
214+
case PT_FLOAT:
215+
err = nvs_set_u32(_handle, key, *((uint32_t*) value));
216+
break;
217+
case PT_DOUBLE:
218+
err = nvs_set_u64(_handle, key, *((uint64_t*) value));
219+
break;
220+
case PT_INVALID:
221+
default:
222+
log_e("nvs_set fail: invalid type");
223+
return 0;
224+
}
225+
226+
if(err){
227+
log_e("nvs_set_ fail: %s %s", key, nvs_error(err)); // TODO put type
228+
return 0;
229+
}
230+
231+
err = nvs_commit(_handle);
232+
if(err){
233+
log_e("nvs_commit fail: %s %s", key, nvs_error(err));
234+
return 0;
235+
}
236+
237+
return len;
238+
}
239+
240+
typename KVStoreInterface::res_t ESP32KVStore::_get(const key_t& key, uint8_t value[], size_t len, Type t) {
241+
if(!_started || !key){
242+
return 0;
243+
}
244+
245+
esp_err_t err;
246+
switch(t) {
247+
case PT_I8:
248+
err = nvs_get_i8(_handle, key, (int8_t*) value);
249+
break;
250+
case PT_U8:
251+
err = nvs_get_u8(_handle, key, (uint8_t*) value);
252+
break;
253+
case PT_I16:
254+
err = nvs_get_i16(_handle, key, (int16_t*) value);
255+
break;
256+
case PT_U16:
257+
err = nvs_get_u16(_handle, key, (uint16_t*) value);
258+
break;
259+
case PT_I32:
260+
err = nvs_get_i32(_handle, key, (int32_t*) value);
261+
break;
262+
case PT_U32:
263+
err = nvs_get_u32(_handle, key, (uint32_t*) value);
264+
break;
265+
case PT_I64:
266+
err = nvs_get_i64(_handle, key, (int64_t*) value);
267+
break;
268+
case PT_U64:
269+
err = nvs_get_u64(_handle, key, (uint64_t*) value);
270+
break;
271+
case PT_STR:
272+
err = nvs_get_str(_handle, key, (char*)value, &len);
273+
break;
274+
case PT_BLOB:
275+
err = nvs_get_blob(_handle, key, value, &len);
276+
break;
277+
case PT_FLOAT:
278+
err = nvs_get_u32(_handle, key, (uint32_t*) value);
279+
break;
280+
case PT_DOUBLE:
281+
err = nvs_get_u64(_handle, key, (uint64_t*) value);
282+
break;
283+
case PT_INVALID:
284+
default:
285+
log_e("nvs_get fail: invalid type");
286+
break;
287+
}
288+
289+
if(err){
290+
log_e("nvs_get_ fail: %s %s", key, nvs_error(err)); // TODO put type
291+
return 0;
292+
}
293+
294+
return len;
295+
}
296+
297+
#endif // defined(ARDUINO_ARCH_ESP32)

src/kvstore/implementation/ESP32.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* This file is part of Arduino_KVStore.
3+
*
4+
* Copyright (c) 2024 Arduino SA
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
#pragma once
11+
12+
#include "../kvstore.h"
13+
#include <Arduino.h>
14+
#include <string>
15+
16+
using namespace std;
17+
18+
constexpr char DEFAULT_KVSTORE_NAME[] = "arduino";
19+
20+
class ESP32KVStore: public KVStoreInterface {
21+
public:
22+
ESP32KVStore(): name(DEFAULT_KVSTORE_NAME) {}
23+
24+
bool begin() override;
25+
bool begin(const char* name, bool readOnly=false, const char* partitionLabel=nullptr);
26+
bool end() override;
27+
bool clear() override;
28+
29+
typename KVStoreInterface::res_t remove(const key_t& key) override;
30+
bool exists(const key_t& key) const override;
31+
typename KVStoreInterface::res_t putBytes(const key_t& key, const uint8_t b[], size_t s) override;
32+
typename KVStoreInterface::res_t getBytes(const key_t& key, uint8_t b[], size_t s) const override;
33+
size_t getBytesLength(const key_t& key) const override;
34+
35+
Type getType(const key_t& key) const;
36+
37+
protected:
38+
res_t _put(const key_t& key, const uint8_t value[], size_t len, Type t);
39+
res_t _get(const key_t& key, uint8_t value[], size_t len, Type t);
40+
private:
41+
const char* name;
42+
uint32_t _handle;
43+
bool _started;
44+
bool _readOnly;
45+
};

0 commit comments

Comments
 (0)