The btree module is well suited for storing key-value pair data in a file on the file system.
I wrapped it in a module called "storage" with get and put methods that take ascii values, like this:
Code: Select all
import btree
CORE_STORAGE = "data"
# Do this only once, it will overwite a previous file with a new one if it exists
def init():
with open(CORE_STORAGE, 'w+b') as f:
db = btree.open(f)
db[b"MODE"] = b"INIT"
db.close()
def get(item):
value = None
with open(CORE_STORAGE, 'r+b') as f:
db = btree.open(f)
b_item = item.encode('ascii')
value = db.get(b_item)
if value:
value = value.decode('ascii')
db.close()
return value
def put(item, value):
b_item = None
b_value = None
try:
b_item = item.encode('ascii')
b_value = value.encode('ascii')
except AttributeError:
print("storage items and values must be ascii strings")
return False
if b_item and b_value:
with open(CORE_STORAGE, 'r+b') as f:
db = btree.open(f)
db[b_item] = b_value
db.flush()
db.close()
return True
For things which need to be written a relatively small number of times, this works fine.
Code: Select all
>>> import storage
>>> storage.put("SSID", "My AP ESSID")
>>> ssid = storage.get("SSID")
You scan run an access point at the same time as the station, giving you the ability to access the device if you are in the proximity to add settings. For example, I created a small page which accepts config values and stores them so I can update device credentials from my phone, so I can boot it up and connect it to any network.
When you scan for networks, it returns a list of tuples for each network.
Code: Select all
(b'titopuente', b'\x08\x11\x96\xc1\xc9\xdc', 6, -38, 3, False)
(b'ATTPm5PQgs', b'\x88\x96N>s0', 11, -59, 3, False)
(b'Sonic.net-209', b'\x94\xc1P\x00[:', 6, -73, 3, False)
(b'ATT5veM6wF', b'\x0c|(w?\x04', 6, -89, 3, False)
(b'Leslie Riley', b'T\xbe\xf7\xfeC\xc0', 11, -90, 3, False)
(b'DIRECT-94-HP DeskJet 3630 series', b'\xc4e\x16[=\x95', 6, -92, 3, False)
(b'xfinitywifi', b'^\xbe\xf7\xfeC\xc0', 11, -92, 0, False)
(b'ATT2UyA68M', b'8;\xc8>9\x81', 11, -94, 3, False)
(b'Wemo.Mini.1F7', b'$\xf5\xa2\x1a\xa0j', 11, -94, 0, False)
Looking at ports/esp32/modnetwork.c in the scan function:
Code: Select all
t->items[0] = mp_obj_new_bytes(wifi_ap_records[i].ssid, ssid_len);
t->items[1] = mp_obj_new_bytes(wifi_ap_records[i].bssid, sizeof(wifi_ap_records[i].bssid));
t->items[2] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].primary);
t->items[3] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].rssi);
t->items[4] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].authmode);
t->items[5] = mp_const_false; // XXX hidden?
so the 5th item is the auth mode. (This is also noted in the docs).
These objects are wifi_ap_record_t structs, and the 5th item is a wifi_auth_mode_t enum, both of which are defined in esp_wifi_types.h in esp-idf:
Code: Select all
typedef enum {
WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */
WIFI_AUTH_WEP, /**< authenticate mode : WEP */
WIFI_AUTH_WPA_PSK, /**< authenticate mode : WPA_PSK */
WIFI_AUTH_WPA2_PSK, /**< authenticate mode : WPA2_PSK */
WIFI_AUTH_WPA_WPA2_PSK, /**< authenticate mode : WPA_WPA2_PSK */
WIFI_AUTH_WPA2_ENTERPRISE, /**< authenticate mode : WPA2_ENTERPRISE */
WIFI_AUTH_MAX
} wifi_auth_mode_t;
so iterating over the scan results and trying the AP's where the auth mode is 0 should work.
Remember that you may not get access to the network even if you can associate with the AP. An open access point may still require a login (like on public wifi with a captive portal).
If you successfully associate, you should check to see if you can access something known.