This library is still under active development.
- BLE UART Setup
A simple to install setup and use WiFi Setup Portal for micropython based ESP32 boards.
Inspired by https://github.com/george-hawkins/micropython-wifi-setup
- Reliable and Simple
- Low Memory Overhead
- ASYNC processing
- Very simple web-browser requirements. Minimal Javascript.
- No separate web-app build step. Just simple html template files. Not Fancy, Just Functional.
- Easy to integrate into your existing projects.
- Easy to build your project upon if desired.
- Easy to modify to make it your own.
- (new) Bluetooth LE UART Setup Support
- Self-Installing templates and assets into data directory on device.
- Unit Tests!
- Easier Theming
- SEEED Xaio ESP32-S3
- SEEED Xaio ESP32-C3
The following 3 libraries are required dependencies. Recommended you drop these into your /lib directory on your device
- utemplate
- copy the directory
utemplatein the repo to/lib/utemplateon your device
- copy the directory
- microdot
- copy the directory
src/microdotto/lib/microdoton your device - note, Not all microdot files are needed, you can skip the ones you don't want to use yourself. the only required files for this library are:
__init__.pymicrodot.pyutemplate.py
- copy the directory
- aioble - If you intend to use the
blesetupmodule.mpremote mip install aioble
Made up of 2 main parts. The .py source files, and the assets. They are kept separate to simplify customizing this library.
This is the library python files. These files need to be in the /lib or the / root of your device. Or, pre-frozen in the modules directory of a custom micropython firmware.
This is the assets directory. Contains the .html template files, and a handfull of image and css assets.
These files by default are loaded from /lib/uwifisetup/www from your device. That is the default install location using the mip install method below.
If you happen to be building an IOT web-app, then you might wish to modify the portal template and css files to match your desired look-and-feel. You might also then want to use the same template and asset structure in your main web-app. Moving the www directory and contents to a common location on your device allows you full access and control of the files.
To move these to a different install location on your deivce, you need only specify a different templateFileRoot parameter to setup.setupWifi(...). The simplest thing to do is to move the www folder to the root of your micropython filesystem, and pass just wwww to the setupWifi function.
await setup.setupWifi(templateFileRoot='www'...)You can now setup your own microdot web-server, with your own template files within the www directory, and include the _top.html and _bottom.html and _start.html wrapper template files to mimic the look and feel and functionality. Reference the welcome.html and list_networks.html for example use.
Simply put, you need to reference any common assets offered up by this wifi setup with the relative path of uwifisetup/<file> .
{% include "_uwifisetup/_bottom.html" %}
or
<img class="f-right" src="/_uwifisetup/assets/network_wifi_{{ numBars }}_bar{{ showLock }}_48px.svg"/>
You'll need mpremote installed on your system. There are a number of ways to do the install, all platform dependant. Linux/Mac
pip install mpremoteInstall upython-wifi-setup into /lib/uwifisetup on the device.
This installs the .mpy pre-compiled versions of this library, but still uses the *.py of the dependencies. For now...
mpremote mip install aioble
mpremote mip install github:shaneapowell/upython-wifi-setup/package-deps.json
mpremote mip install github:shaneapowell/upython-wifi-setup/package.jsonYou can optionally install the non .mpy original source.
mpremote mip install aioble --no-mpy
mpremote mip install github:shaneapowell/upython-wifi-setup/package-deps.json
mpremote mip install github:shaneapowell/upython-wifi-setup/package-raw.jsonAfter doing one of the above install steps.. you can give it a try it out with the following.
Copy the example.py file to your local system on your computer, and run it with mpremote. Follow the steps to connect to your wifi.
wget https://raw.githubusercontent.com/shaneapowell/upython-wifi-setup/main/examples/example.py
mpremote run example.py- Re-Run the above example.py file again to then see it connect to your wifi.
- you can reset/clear the
creds.jsonfile to try it all again.
mpremote rm /creds.json-
Clone this repo
git clone https://github.com/shaneapowell/upython-wifi-setup.git git submodule init git submodule update
-
install pipenv.
pip3 install pipenv
-
Plug in your micropython esp32 device usb to your computer.
-
Update the
.envfile, set theRSHELL_PORTwith the TTY path to your device. -
Sync the pipenv venv packages. This is only needed once, or with any new updates to the
Pipfile.pipenv sync
-
Install the microdot and utemplate package dependencies into
/libon the devicepipenv run deploy_deps
-
Install the aioble if using the blesetup feature.
mpremote mip install aioble
-
Optional build the pre-compiled parts. Optional because the
distfolder should already have the most recent-pre-compiled. Note: YOu'll see some likeModulenotFoundError: No Module named_uwifisetup/complete_html`. You can safely ignore those.pipenv run compile
-
Deploy the code and assets into the
/libdirectory.pipenv run deploy
-
Try it Out. Run the example
pipenv run example -
Connect your phone to the wifi access point named
MyPyDevice -
After the setup is complete, the device should reset itself.
-
Re-Run the above example, and the command should finish with a message
Connected to wifi Success -
Re-Run the example now, to see the wifi connect using your new creds
pipenv run example
-
Re-Set your creds to try all over again
pipenv run example_reset
Because you're the type of person who needs to do things manually. You can inspect the Pipfile for commands to reference.
- Manually Install the
microdotandutemplatedependencies. - Manually copy over the
dist/uwifisetup(pre-compiled) orsrc/uwifisetup(source) files to/lib/uwifisetup. - Manually copy over the
dist/www(pre-compiled) orsrc/www(source) files to/lib/uwifisetup/www - if you copied the pre-compiled
dist/wwwfiles, you'll also need to copy over thesrc/www/_uwifisetup/assetsfiles into/lib/uwifisetup/www/_uwifisetup/assets
You can pre-compile the source and template files into .mpy files to reduce the load and overhead on your hardware. The following will compile and move all distribution files into the /dist directory. You can then deploy the contents of the /dist directory, or manually move than as you see fit.
pipenv run compile
pipenv run deployDoing this is a little beyond the scope of this readme. This is however, what I have done for my projects. It's a little tricky getting the correct files into the correct directory for a clean deployment. In short, you want to get all the .py files into the modules directory. And all the non .py asset files into the filesystem of your device.
The .py files are more than just what is in the src/uwifisetup directory. There is also the .py files generated by the conversion of the .html template files. These are generated with the pipenv compile command, and left in the src/_uwifisetup/ directory.
I copied the src/uwifisetup into the micropython firmware modules directory. I also copied over the src/www/_uwifisetup/*.py files. Finally, the non .py files found in the src/www/_uwifisetup directory must be placed into the main filesystem of your device. They cannot be pre-frozen as they are not source files.
The access point name, and wifi password are stored in a plain text json file creds.json in the root of the data partition.
The ability to configure your wifi over BLE Nordic UART has been added. This feature doesn't include a full UI, but rather a simple json based TX/RX protocol that can be used with your own custom BlueTooth application.
see the example_ble.py. A very basic json based async protocol is implemented with a few very specific request
commands to handle setting up your wifi.
An important limitation to note is that the messages are limited to 256 characters max. This should not pose a problem for a typical use-case of this protocol.
To play with BLE Uart mode, the mobile app nRF Toolbox in the App Store / Play Store can be used to send and receive messages.
A request json must include at a minimum a req field with a known request command code. Each request code has it's own set of optional and required additional fields.
A response for a request will have the request code echoed back, as well as a response code to indicate the outcome of the request, and any additional information specific to the request.
While the module is async, a request will return a response before another request is accepted. With the echo-back field of the response model, this protocol has the appearance of being totally async, but it is not. It is semi-blocking sequential. Semi-Blocking since the network calls themselves are blocking.
ok: You expect a valid set of fields in the json for the given request.error: An error was triggered. see the includedmsgfield for more info.done: A response code unique to theget_available_wificommand. These are returned one at a time. The last one is empty with this response code.
{"req": "get_device_info"}Will include the deviceName provided to the blesetup.setupWifi() function, and the deviceInfo dict values.
{"resp": "get_device_info", "resp_code": "ok", "device_name": "MyPyDevice", "uuid": "123456"}Due to the 256 character limit of the UART characteristic, the request will return a series of wifi response models until a status code of done is returned. You'll need to loop on the responses until the done status code. The wifi responses are returned in order from strongest to weakest by default.
{"req": "get_available_wifi"}Expected Response Fields:
ssid- The STRING SSID of wifirssi- The INT RSSI strength of the wifisecure- The INT code of the type of security of this wifi. see the ESP32 WLANscanfunction for expected values.- 0 = Open
- 1 = WEP
- 2 = WPA-PSK
- 3 = WPA2-PSK
- 4 = WPA/WPA2-PSK
{"resp": "get_available_wifi", "resp_code": "ok", "ssid": "My Wifi", "rssi": -71, "secure": 4}{"resp": "get_available_wifi", "resp_code": "ok", "ssid": "Bobs Wifi", "rssi": -56, "secure": 4}{"resp": "get_available_wifi", "resp_code": "ok", "ssid": "Janes Public", "rssi": -46, "secure": 0}{"resp": "get_available_wifi", "resp_code": "done"}Request to connect to a wifi.
The ssid and password fields are both required, even for an open wifi. If you are connecting to an unsecure open wifi, just pass a null password value.
{"req": "connect_to_wifi", "ssid": "My Wifi", "password": "abc123"}{"req": "connect_to_wifi", "ssid": "My Wifi", "password": null}A success response will include your assigned IP address.
{"resp": "connect_to_wifi", "resp_code": "ok", "ip_addr": "192.168.0.142"}Connection Failures will look like
{"resp": "connect_to_wifi", "resp_code": "error", "msg": "Incorrect Password"}Send the complete request, to tell the blesetup system to shutdown and fall out of the await. If the blesetup function included resetDeviceWhenSetupComplete=True, then this call will result in the device being reset.
{"req": "complete"}{"resp": "complete", "resp_code": "ok"}pipenv run example_ble
Plug in the values to match your local wifi, but you can try this sequence with the uRF toolbox mobile app.
TX:{"req": "get_device_info"}
RX:{"resp": "get_device_info", "resp_code": "ok", "device_name": "MyPyDevice", "uuid": "123456"}
TX:{"req": "get_available_wifi"}
RX:{"resp": "get_available_wifi", "resp_code": "ok", "ssid": "My Wifi", "rssi": -71, "secure": 4}
RX:{"resp": "get_available_wifi", "resp_code": "ok", "ssid": "Bobs Wifi", "rssi": -56, "secure": 4}
RX:{"resp": "get_available_wifi", "resp_code": "ok", "ssid": "Janes Public", "rssi": -46, "secure": 0}
RX:{"resp": "get_available_wifi", "resp_code": "done"}
TX:{"req": "connect_to_wifi", "ssid": "My Wifi", "password": "Bad Password"}
RX:{"resp": "connect_to_wifi", "resp_code": "error", "msg": "Timed Out"}
TX:{"req": "connect_to_wifi", "ssid": "My Wifi", "password": null}
RX:{"resp": "connect_to_wifi", "resp_code": "error", "msg": "Unable to Connect"}
TX:{"req": "connect_to_wifi", "ssid": "My Wifi", "password": "abc123"}
RX:{"resp": "connect_to_wifi", "resp_code": "ok", "ip_addr": "192.168.0.142"}
TX:{"req": "complete"}
RX:{"resp": "complete", "resp_code": "ok"}
Functions and Use Reference
- setupWifi()
- shutdown()
- hasCredentials()
- factoryReset()
- saveCredentials()
- loadCredentials()
- connectWifi()
If you are like me, you will want to use this library, but, make it look like your project/theme.
In that case, it'll be simply up to you to modify the .css and .html files to your needs. If you wish to just leverage what this library already provides, you can keep the .css and .html files unmodified, and include them in your own app.
Look at how the examples/example.py file runs this wifi setup library.
It only creates the microdot webserver instance if it needs to during the setup stage. If you have no need for a webserver in your project, you don't need to do anything. If however, you wish to also serve up your own content, but use the templates and css provided by this library. You'll have to do a little work. But, not as much as you think.
- Move the
wwwtemplates and assets to the device root/ - Modify the
setup(...)function, passing in a newtemplateFileRoot='www'value. - Add your own html, template and assets to the
wwwdirectory. - Setup your own microdot web-server to provide access to the html and assets files.
- Include the already, ready-to-go,
_start.html,_top.htmland_bottom.htmltemplate
- Clone repo
git clone https://github.com/shaneapowell/upython-wifi-setup.git git submodule update
- Modify
setup.py. Near the top, Comment out theDEFAULT_TEMPLATE_LOADER_CLASS=utemplate.compiled.Loader. Uncomment the#DEFAULT_TEMPLATE_LOADER_CLASS=utemplate.recompile.Loaderline. - Deploy dependencies as normal
pipenv run deploy_dependencies
- Deploy raw source files
pipenv run deploy_raw
- Try it out
pipenv run example pipenv run example_reset
pipenv sync
pipenv run linter
pipenv run typechecker
