9
9
10
10
#include "py/mpconfig.h"
11
11
#include "py/obj.h"
12
+ #include "py/objstr.h"
12
13
#include "py/runtime.h"
13
14
#include "mperror.h"
14
15
#include "updater.h"
@@ -233,8 +234,41 @@ STATIC mp_obj_t mod_pycom_pulses_get (mp_obj_t gpio, mp_obj_t timeout) {
233
234
}
234
235
STATIC MP_DEFINE_CONST_FUN_OBJ_2 (mod_pycom_pulses_get_obj , mod_pycom_pulses_get );
235
236
237
+
238
+
239
+ /*
240
+ * nvs_setstring/nvs_getstring: support for NVS string storage and,
241
+ * thanks to JSON/other serializers, pretty much any datastructure.
242
+ */
243
+ STATIC mp_obj_t mod_pycom_nvs_setstring (mp_obj_t _key , mp_obj_t _value ) {
244
+ const char * key = mp_obj_str_get_str (_key );
245
+ const char * value = mp_obj_str_get_str (_value );
246
+ if (strlen (value ) >= 1984 ) {
247
+ // orwell error: maximum length (including null character) is 1984 bytes
248
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , "value too long (max: 1984)" ));
249
+ return mp_const_none ;
250
+ }
251
+ esp_err_t esp_err = nvs_set_str (pycom_nvs_handle , key , value );
252
+ if (ESP_OK == esp_err ) {
253
+ nvs_commit (pycom_nvs_handle );
254
+ } else if (ESP_ERR_NVS_NOT_ENOUGH_SPACE == esp_err || ESP_ERR_NVS_PAGE_FULL == esp_err || ESP_ERR_NVS_NO_FREE_PAGES == esp_err ) {
255
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "no space available" ));
256
+ } else if (ESP_ERR_NVS_INVALID_NAME == esp_err || ESP_ERR_NVS_KEY_TOO_LONG == esp_err ) {
257
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , "invalid key (or too long)" ));
258
+ } else {
259
+ // not ESP_OK, but not reporting? TODO:check this...
260
+ }
261
+ return mp_const_none ;
262
+ }
263
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (mod_pycom_nvs_setstring_obj , mod_pycom_nvs_setstring );
264
+
265
+
236
266
STATIC mp_obj_t mod_pycom_nvs_set (mp_obj_t _key , mp_obj_t _value ) {
237
267
const char * key = mp_obj_str_get_str (_key );
268
+ if (MP_OBJ_IS_STR_OR_BYTES (_value )) {
269
+ // not certain how to differentiate between string and bytes, here... TODO
270
+ return mod_pycom_nvs_setstring (_key , _value );
271
+ }
238
272
uint32_t value = mp_obj_get_int_truncated (_value );
239
273
240
274
esp_err_t esp_err = nvs_set_u32 (pycom_nvs_handle , key , value );
@@ -249,17 +283,53 @@ STATIC mp_obj_t mod_pycom_nvs_set (mp_obj_t _key, mp_obj_t _value) {
249
283
}
250
284
STATIC MP_DEFINE_CONST_FUN_OBJ_2 (mod_pycom_nvs_set_obj , mod_pycom_nvs_set );
251
285
286
+
287
+
288
+ STATIC mp_obj_t mod_pycom_nvs_getstring (mp_obj_t _key ) {
289
+ vstr_t vstr ;
290
+ const char * key = mp_obj_str_get_str (_key );
291
+ size_t required_size = 0 ;
292
+ if (ESP_ERR_NVS_NOT_FOUND == nvs_get_str (pycom_nvs_handle , key , NULL , & required_size )) {
293
+ return mp_const_none ;
294
+ }
295
+ vstr_init_len (& vstr , required_size );
296
+ if (ESP_OK != nvs_get_str (pycom_nvs_handle , key , vstr .buf , & required_size )) {
297
+ vstr_clear (& vstr );
298
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "can't get string" ));
299
+ return mp_const_none ;
300
+ }
301
+ if (vstr .len && vstr .buf [vstr .len - 1 ] == '\0' ) {
302
+ /* bit of a hack to get rid of trailing null terminator required by the
303
+ * nvs backend to figure out string length... must be a better way, TODO.
304
+ */
305
+ vstr .len = vstr .len - 1 ;
306
+ }
307
+ return mp_obj_new_str_from_vstr (& mp_type_str , & vstr );
308
+
309
+ }
310
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (mod_pycom_nvs_getstring_obj , mod_pycom_nvs_getstring );
311
+
312
+
252
313
STATIC mp_obj_t mod_pycom_nvs_get (mp_obj_t _key ) {
253
314
const char * key = mp_obj_str_get_str (_key );
254
315
uint32_t value ;
255
-
256
- if (ESP_ERR_NVS_NOT_FOUND == nvs_get_u32 ( pycom_nvs_handle , key , & value ) ) {
257
- return mp_const_none ;
316
+ esp_err_t esp_err = nvs_get_u32 ( pycom_nvs_handle , key , & value );
317
+ if (ESP_OK == esp_err ) {
318
+ return mp_obj_new_int ( value ) ;
258
319
}
259
- return mp_obj_new_int (value );
320
+ if (ESP_ERR_NVS_NOT_FOUND == esp_err || ESP_ERR_NVS_TYPE_MISMATCH == esp_err ) {
321
+ /* you would expect it to return TYPE_MISMATCH if it's been
322
+ stored as a string, but it's actually returning NOT_FOUND...
323
+ so: try string */
324
+ return mod_pycom_nvs_getstring (_key );
325
+ }
326
+ nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "Error doing nvs_get: %d" , esp_err ));
327
+ return mp_const_none ;
260
328
}
261
329
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (mod_pycom_nvs_get_obj , mod_pycom_nvs_get );
262
330
331
+
332
+
263
333
STATIC mp_obj_t mod_pycom_nvs_erase (mp_obj_t _key ) {
264
334
const char * key = mp_obj_str_get_str (_key );
265
335
@@ -478,7 +548,9 @@ STATIC const mp_map_elem_t pycom_module_globals_table[] = {
478
548
{ MP_OBJ_NEW_QSTR (MP_QSTR_ota_slot ), (mp_obj_t )& mod_pycom_ota_slot_obj },
479
549
{ MP_OBJ_NEW_QSTR (MP_QSTR_pulses_get ), (mp_obj_t )& mod_pycom_pulses_get_obj },
480
550
{ MP_OBJ_NEW_QSTR (MP_QSTR_nvs_set ), (mp_obj_t )& mod_pycom_nvs_set_obj },
551
+ { MP_OBJ_NEW_QSTR (MP_QSTR_nvs_setstring ), (mp_obj_t )& mod_pycom_nvs_setstring_obj },
481
552
{ MP_OBJ_NEW_QSTR (MP_QSTR_nvs_get ), (mp_obj_t )& mod_pycom_nvs_get_obj },
553
+ { MP_OBJ_NEW_QSTR (MP_QSTR_nvs_getstring ), (mp_obj_t )& mod_pycom_nvs_getstring_obj },
482
554
{ MP_OBJ_NEW_QSTR (MP_QSTR_nvs_erase ), (mp_obj_t )& mod_pycom_nvs_erase_obj },
483
555
{ MP_OBJ_NEW_QSTR (MP_QSTR_nvs_erase_all ), (mp_obj_t )& mod_pycom_nvs_erase_all_obj },
484
556
{ MP_OBJ_NEW_QSTR (MP_QSTR_wifi_on_boot ), (mp_obj_t )& mod_pycom_wifi_on_boot_obj },
0 commit comments