diff --git a/esp32/frozen/Custom/README.md b/esp32/frozen/Custom/README.md new file mode 100644 index 0000000000..f6fae9f4b3 --- /dev/null +++ b/esp32/frozen/Custom/README.md @@ -0,0 +1,6 @@ +Custom distro modules +===================== + +Place any python packages/modules you want to have included as frozen .mpy and loaded on boot, here. + + diff --git a/esp32/mods/modpycom.c b/esp32/mods/modpycom.c index c85db88be0..0301356ca7 100644 --- a/esp32/mods/modpycom.c +++ b/esp32/mods/modpycom.c @@ -9,6 +9,7 @@ #include "py/mpconfig.h" #include "py/obj.h" +#include "py/objstr.h" #include "py/runtime.h" #include "mperror.h" #include "updater.h" @@ -162,8 +163,41 @@ STATIC mp_obj_t mod_pycom_pulses_get (mp_obj_t gpio, mp_obj_t timeout) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_pycom_pulses_get_obj, mod_pycom_pulses_get); + + +/* + * nvs_setstring/nvs_getstring: support for NVS string storage and, + * thanks to JSON/other serializers, pretty much any datastructure. + */ +STATIC mp_obj_t mod_pycom_nvs_setstring (mp_obj_t _key, mp_obj_t _value) { + const char *key = mp_obj_str_get_str(_key); + const char *value = mp_obj_str_get_str(_value); + if (strlen(value) >= 1984) { + // orwell error: maximum length (including null character) is 1984 bytes + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "value too long (max: 1984)")); + return mp_const_none; + } + esp_err_t esp_err = nvs_set_str(pycom_nvs_handle, key, value); + if (ESP_OK == esp_err) { + nvs_commit(pycom_nvs_handle); + } 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) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no space available")); + } else if (ESP_ERR_NVS_INVALID_NAME == esp_err || ESP_ERR_NVS_KEY_TOO_LONG == esp_err) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid key (or too long)")); + } else { + // not ESP_OK, but not reporting? TODO:check this... + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_pycom_nvs_setstring_obj, mod_pycom_nvs_setstring); + + STATIC mp_obj_t mod_pycom_nvs_set (mp_obj_t _key, mp_obj_t _value) { const char *key = mp_obj_str_get_str(_key); + if (MP_OBJ_IS_STR_OR_BYTES(_value)) { + // not certain how to differentiate between string and bytes, here... TODO + return mod_pycom_nvs_setstring(_key, _value); + } uint32_t value = mp_obj_get_int_truncated(_value); esp_err_t esp_err = nvs_set_u32(pycom_nvs_handle, key, value); @@ -178,17 +212,53 @@ STATIC mp_obj_t mod_pycom_nvs_set (mp_obj_t _key, mp_obj_t _value) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_pycom_nvs_set_obj, mod_pycom_nvs_set); + + +STATIC mp_obj_t mod_pycom_nvs_getstring (mp_obj_t _key) { + vstr_t vstr; + const char *key = mp_obj_str_get_str(_key); + size_t required_size = 0; + if (ESP_ERR_NVS_NOT_FOUND == nvs_get_str(pycom_nvs_handle, key, NULL, &required_size)) { + return mp_const_none; + } + vstr_init_len(&vstr, required_size); + if (ESP_OK != nvs_get_str(pycom_nvs_handle, key, vstr.buf, &required_size)) { + vstr_clear(&vstr); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't get string")); + return mp_const_none; + } + if (vstr.len && vstr.buf[vstr.len - 1] == '\0') { + /* bit of a hack to get rid of trailing null terminator required by the + * nvs backend to figure out string length... must be a better way, TODO. + */ + vstr.len = vstr.len - 1; + } + return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_pycom_nvs_getstring_obj, mod_pycom_nvs_getstring); + + STATIC mp_obj_t mod_pycom_nvs_get (mp_obj_t _key) { const char *key = mp_obj_str_get_str(_key); uint32_t value; - - if (ESP_ERR_NVS_NOT_FOUND == nvs_get_u32(pycom_nvs_handle, key, &value)) { - return mp_const_none; + esp_err_t esp_err = nvs_get_u32(pycom_nvs_handle, key, &value); + if (ESP_OK == esp_err) { + return mp_obj_new_int(value); } - return mp_obj_new_int(value); + if (ESP_ERR_NVS_NOT_FOUND == esp_err || ESP_ERR_NVS_TYPE_MISMATCH == esp_err) { + /* you would expect it to return TYPE_MISMATCH if it's been + stored as a string, but it's actually returning NOT_FOUND... + so: try string */ + return mod_pycom_nvs_getstring(_key); + } + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Error doing nvs_get: %d", esp_err)); + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_pycom_nvs_get_obj, mod_pycom_nvs_get); + + STATIC mp_obj_t mod_pycom_nvs_erase (mp_obj_t _key) { const char *key = mp_obj_str_get_str(_key); @@ -298,7 +368,9 @@ STATIC const mp_map_elem_t pycom_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_ota_slot), (mp_obj_t)&mod_pycom_ota_slot_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pulses_get), (mp_obj_t)&mod_pycom_pulses_get_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_set), (mp_obj_t)&mod_pycom_nvs_set_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_setstring), (mp_obj_t)&mod_pycom_nvs_setstring_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_get), (mp_obj_t)&mod_pycom_nvs_get_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_getstring), (mp_obj_t)&mod_pycom_nvs_getstring_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_erase), (mp_obj_t)&mod_pycom_nvs_erase_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_erase_all), (mp_obj_t)&mod_pycom_nvs_erase_all_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_wifi_on_boot), (mp_obj_t)&mod_pycom_wifi_on_boot_obj }, @@ -307,7 +379,7 @@ STATIC const mp_map_elem_t pycom_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_wifi_ssid), (mp_obj_t)&mod_pycom_wifi_ssid_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_wifi_pwd), (mp_obj_t)&mod_pycom_wifi_pwd_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_heartbeat_on_boot), (mp_obj_t)&mod_pycom_heartbeat_on_boot_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_lte_modem_en_on_boot), (mp_obj_t)&mod_pycom_lte_modem_on_boot_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_lte_modem_en_on_boot), (mp_obj_t)&mod_pycom_lte_modem_on_boot_obj }, }; STATIC MP_DEFINE_CONST_DICT(pycom_module_globals, pycom_module_globals_table); diff --git a/py/mkrules.mk b/py/mkrules.mk index 633b0dfab2..5e26225702 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -112,6 +112,7 @@ ifeq ($(OS_NAME), Linux) # make a list of all the .py files that need compiling and freezing FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR)/Base/ -type f -name '*.py' | $(SED) -e 's/$(FROZEN_MPY_DIR)\/Base\///') FROZEN_MPY_PY_FILES += $(shell find -L $(FROZEN_MPY_DIR)/Common/ -type f -name '*.py' | $(SED) -e 's/$(FROZEN_MPY_DIR)\/Common\///') +FROZEN_MPY_PY_FILES += $(shell find -L $(FROZEN_MPY_DIR)/Custom/ -type f -name '*.py' | $(SED) -e 's/$(FROZEN_MPY_DIR)\/Custom\///') ifeq ($(BOARD), $(filter $(BOARD), GPY FIPY)) FROZEN_MPY_PY_FILES += $(shell find -L $(FROZEN_MPY_DIR)/LTE/ -type f -name '*.py' | $(SED) -e 's/$(FROZEN_MPY_DIR)\/LTE\///') endif @@ -119,6 +120,7 @@ else # make a list of all the .py files that need compiling and freezing FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR)/Base/ -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)\/Base\//==') FROZEN_MPY_PY_FILES += $(shell find -L $(FROZEN_MPY_DIR)/Common/ -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)\/Common\//==') +FROZEN_MPY_PY_FILES += $(shell find -L $(FROZEN_MPY_DIR)/Custom/ -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)\/Custom\//==') ifeq ($(BOARD), $(filter $(BOARD), GPY FIPY)) FROZEN_MPY_PY_FILES += $(shell find -L $(FROZEN_MPY_DIR)/LTE/ -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)\/LTE\//==') endif @@ -138,6 +140,16 @@ $(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/Common/%.py $(Q)$(MKDIR) -p $(dir $@) $(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/Common/%=%) $(MPY_CROSS_FLAGS) $^ + +# to build custom .mpy files from .py files +$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/Custom/%.py + @$(ECHO) "MPY $<" + $(Q)$(MKDIR) -p $(dir $@) + $(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/Custom/%=%) $(MPY_CROSS_FLAGS) $^ + + + + ifeq ($(BOARD), $(filter $(BOARD), GPY FIPY)) # to build .mpy files from .py files $(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/LTE/%.py pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy