diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ad7e50..3d1e574 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,23 +1,16 @@ name: Build on: - push: - branches: [ main ] - paths: - - "**.py" - - "requirements.txt" - - ".github/workflows/ci.yml" - - "Makefile" - - "external/**" - pull_request: branches: [ main ] paths: - - "**.py" + - "src/**" + - "tests/**" + - "external/**" - "requirements.txt" - ".github/workflows/ci.yml" - "Makefile" - - "external/**" + - ".pylintrc" jobs: test: diff --git a/Makefile b/Makefile index a1460f3..5da1e69 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PYROBUSTA_VERSION := v0.4.0 +PYROBUSTA_VERSION := v0.5.0 DEVICE ?= u0 SRC_DIR := src diff --git a/README.md b/README.md index 3acb293..aef49b6 100644 --- a/README.md +++ b/README.md @@ -13,76 +13,73 @@ A lightweight HTTP server library for MicroPython designed for constrained embed - Query parameter parsing with percent encoding support - TLS support -# Prerequisites - -## Setup virtual environment -```bash -python3 -m venv venv -source venv/bin/activate -python3 -m pip install -r requirements.txt -``` - -## Create pyrobusta.env in the project root (optional) - -```bash -# pyrobusta.env -wifi_ssid="" -wifi_password="" -tls="true" -socket_max_con=2 -http_mem_cap=0.05 -... +# Installation + +Use the mip package manager to install PyRobusta on your MicroPython-installed device.\ +The bare minimum requirement is 40KB of free heap, however, it is recommended to select\ +boards with more SRAM for usability and stability. The ESP32-C3 is a recommended entry-level\ +board leaving a user-friendly amount of memory after installing PyRobusta. + +If required, use the below script to connect to a Wi-Fi station in advance. +```python +from network import WLAN, STA_IF +from time import sleep + +ssid = "" +password = "" + +sta_if = WLAN(STA_IF) +sta_if.active(True) +sta_if.connect(ssid, password) + +timeout = 30 +while timeout > 0: + if sta_if.isconnected(): + ip = sta_if.ifconfig()[0] + print(f"connected, IP={ip}") + break + sleep(1) + timeout -= 1 + +if sta_if.isconnected(): + print(sta_if.ifconfig()[0]) +else: + print("connection failed") ``` -pyrobusta.env contains runtime configuration, deployed to the device. This allows the user to override default behavior and configure optional settings. -- rules such as ```make run-unix``` or ```make run-device``` also rely on pyrobusta.env, allowing the user to experiment with different settings -- pyrobusta.env is ignored when running functional tests (```make test-unix```, ```make test-device```) +Install and start PyRobusta by following the below steps. For more advanced usage,\ +check the included documentation reachable from the home page served by your device. -Check [configuration.md](https://github.com/szeka9/PyRobusta/blob/main/docs/configuration.md) for all configuration options. +```python +# Download latest version of PyRobusta +import mip +mip.install("github:szeka9/PyRobusta") +# Install assets +from pyrobusta.utils.assets import install_www +install_www() -# Build and run example application +# Start the server +import asyncio +from pyrobusta.server.http_server import HttpServer -## Run on unix port +async def main(): + server = HttpServer() + asyncio.create_task(server.start_socket_server()) + while True: + await asyncio.sleep(1) -```bash -make toolchain # Setup mpy-cross and micropython -make build # Cross-compile, create build artifacts -make stage-example # Create runtime directory for unix port -make run-unix # Run example application on the unix port of micropython +asyncio.run(main()) ``` +Open a browser and type your device's IP in the address bar. You should be greeted\ +by the default home page. -## Deploy to a device - -```bash -make toolchain # Setup mpy-cross and micropython -make build # Cross-compile, create build artifacts -make deploy # Upload build artifacts to device using mpremote -make tls-cert # Optional: generate self-signed certificate for the device -make deploy-cert # Optional: upload generated certificate to the device -make deploy-example # Deploy the selected example app using mpremote -make run-device # Optional: Reset the device and connect through REPL -``` -```deploy-example``` and ```run-device``` uses the DEVICE argument -set to ```u0``` (/dev/ttyUSB0) by default, passed to mpremote. +![image info](./docs/img/home_page.png) -Override the DEVICE argument to select a different device, e.g. -```make DEVICE=a0 run-device``` for /dev/ttyACM0. Check mpremote --help -for additional shortcuts. +For fine-tuning heap usage, check the [dimensioning guide](./docs/dimensioning/http_dimensioning.md)\ +and [configuration settings](./docs/configuration.md). -## Redeploy +# Development -When changing the source code, run the below rule for redeploying to the device. - -```bash -make redeploy # Will run the following rules: clean build clean-device deploy -``` - -## Unit tests, pylint, functional tests - -```bash -make static-checkers # Run static checkers (Pylint, black formatter) -make unit-test # Run unit tests -make test-unix # Run functional tests on the unix port -make test-device # Run functional tests on a device -``` +Check the provided development guide to create and deploy custom builds\ +to your device: [development guide](./docs/development.md) diff --git a/assets/www/examples.html b/assets/www/examples.html index bce9539..e1a2ca6 100644 --- a/assets/www/examples.html +++ b/assets/www/examples.html @@ -55,10 +55,10 @@

Server configuration

# /pyrobusta.env socket_max_con=2 # max number of socket connections, reduce it to lower memory usage -http_multipart="false" # turn on/off multipart parser, increases memory usage when turned on -http_mem_cap="0.05" # memory cap (% × 0.01) of usable heap for stream buffers +http_multipart=False # turn on/off multipart parser, increases memory usage when turned on +http_mem_cap=0.05 # memory cap (% × 0.01) of usable heap for stream buffers http_served_paths="/www /lib/pyrobusta" # space delimited list of filesystem paths allowed to be served -tls="false" # key.der and cert.der needs to be installed at / when set to true +tls=False # key.der and cert.der needs to be installed at / when set to true

@@ -72,7 +72,7 @@

Simple Server Application

import asyncio from gc import mem_free, mem_alloc -from pyrobusta.server import http_server +from pyrobusta.server.http_server import HttpServer from pyrobusta.protocol.http import HttpEngine from pyrobusta.utils import logging @@ -94,14 +94,14 @@

Simple Server Application

return "text/plain", (f"Free memory [{value_format}]: {free}\n") +async def run_server(): + server = HttpServer() + asyncio.create_task(server.start_socket_server()) + while True: + await asyncio.sleep(1) def main(): - http_server.main() - try: - asyncio.get_event_loop().run_forever() - except Exception as e: - logging.warning(f"loop stopped: {e}") - asyncio.get_event_loop().close() + asyncio.run(run_server())

@@ -72,7 +72,7 @@

Simple Server Application

import asyncio from gc import mem_free, mem_alloc -from pyrobusta.server import http_server +from pyrobusta.server.http_server import HttpServer from pyrobusta.protocol.http import HttpEngine from pyrobusta.utils import logging @@ -94,16 +94,18 @@

Simple Server Application

return "text/plain", (f"Free memory [{value_format}]: {free}\n") +async def run_server(): + server = HttpServer() + asyncio.create_task(server.start_socket_server()) + while True: + await asyncio.sleep(1) def main(): - http_server.main() - try: - asyncio.get_event_loop().run_forever() - except Exception as e: - logging.warning(f"loop stopped: {e}") - asyncio.get_event_loop().close() + asyncio.run(run_server()) -

Use curl to test your application.

\ No newline at end of file diff --git a/dist/pyrobusta/assets/www/index.html b/dist/pyrobusta/assets/www/index.html index 2f49452..f5d4cf2 100644 --- a/dist/pyrobusta/assets/www/index.html +++ b/dist/pyrobusta/assets/www/index.html @@ -48,7 +48,7 @@

Available Resources

diff --git a/dist/pyrobusta/bindings/http_connection.mpy b/dist/pyrobusta/bindings/http_connection.mpy new file mode 100644 index 0000000..0b1a36a Binary files /dev/null and b/dist/pyrobusta/bindings/http_connection.mpy differ diff --git a/dist/pyrobusta/bindings/socket_http.mpy b/dist/pyrobusta/bindings/socket_http.mpy deleted file mode 100644 index 6ee7b49..0000000 Binary files a/dist/pyrobusta/bindings/socket_http.mpy and /dev/null differ diff --git a/dist/pyrobusta/con/wifi.mpy b/dist/pyrobusta/con/wifi.mpy deleted file mode 100644 index 5e82314..0000000 Binary files a/dist/pyrobusta/con/wifi.mpy and /dev/null differ diff --git a/dist/pyrobusta/con/__init__.py b/dist/pyrobusta/connectivity/__init__.py similarity index 100% rename from dist/pyrobusta/con/__init__.py rename to dist/pyrobusta/connectivity/__init__.py diff --git a/dist/pyrobusta/connectivity/wifi.mpy b/dist/pyrobusta/connectivity/wifi.mpy new file mode 100644 index 0000000..d89dfb2 Binary files /dev/null and b/dist/pyrobusta/connectivity/wifi.mpy differ diff --git a/dist/pyrobusta/transport/connection.mpy b/dist/pyrobusta/transport/connection.mpy new file mode 100644 index 0000000..e74282a Binary files /dev/null and b/dist/pyrobusta/transport/connection.mpy differ diff --git a/dist/pyrobusta/transport/socket.mpy b/dist/pyrobusta/transport/socket.mpy deleted file mode 100644 index 3389bfc..0000000 Binary files a/dist/pyrobusta/transport/socket.mpy and /dev/null differ diff --git a/dist/pyrobusta/utils/config.mpy b/dist/pyrobusta/utils/config.mpy index 671b920..f10be66 100644 Binary files a/dist/pyrobusta/utils/config.mpy and b/dist/pyrobusta/utils/config.mpy differ diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..07c41ad --- /dev/null +++ b/docs/development.md @@ -0,0 +1,74 @@ + +# Prerequisites + +## Setup virtual environment +```bash +python3 -m venv venv +source venv/bin/activate +python3 -m pip install -r requirements.txt +``` + +## Create pyrobusta.env in the project root (optional) + +```bash +# pyrobusta.env +wifi_ssid="" +wifi_password="" +tls="true" +socket_max_con=2 +http_mem_cap=0.05 +... +``` +pyrobusta.env contains runtime configuration, deployed to the device. This allows the user to override default behavior and configure optional settings. + +- rules such as ```make run-unix``` or ```make run-device``` also rely on pyrobusta.env, allowing the user to experiment with different settings +- pyrobusta.env is ignored when running functional tests (```make test-unix```, ```make test-device```) + +Check [configuration.md](./configuration.md) for all configuration options. + + +# Build and run example application + +## Run on unix port + +```bash +make toolchain # Setup mpy-cross and micropython +make build # Cross-compile, create build artifacts +make stage-example # Create runtime directory for unix port +make run-unix # Run example application on the unix port of micropython +``` + +## Deploy to a device + +```bash +make toolchain # Setup mpy-cross and micropython +make build # Cross-compile, create build artifacts +make deploy # Upload build artifacts to device using mpremote +make tls-cert # Optional: generate self-signed certificate for the device +make deploy-cert # Optional: upload generated certificate to the device +make deploy-example # Deploy the selected example app using mpremote +make run-device # Optional: Reset the device and connect through REPL +``` +```deploy-example``` and ```run-device``` uses the DEVICE argument +set to ```u0``` (/dev/ttyUSB0) by default, passed to mpremote. + +Override the DEVICE argument to select a different device, e.g. +```make DEVICE=a0 run-device``` for /dev/ttyACM0. Check mpremote --help +for additional shortcuts. + +## Redeploy + +When changing the source code, run the below rule for redeploying to the device. + +```bash +make redeploy # Will run the following rules: clean build clean-device deploy +``` + +## Unit tests, pylint, functional tests + +```bash +make static-checkers # Run static checkers (Pylint, black formatter) +make unit-test # Run unit tests +make test-unix # Run functional tests on the unix port +make test-device # Run functional tests on a device +``` diff --git a/docs/img/home_page.png b/docs/img/home_page.png new file mode 100644 index 0000000..95b02ba Binary files /dev/null and b/docs/img/home_page.png differ diff --git a/package.json b/package.json index ad11182..e0b9b0f 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,22 @@ { - "version": "v0.4.0", + "version": "v0.5.0", "urls": [ [ - "pyrobusta/transport/socket.mpy", - "github:szeka9/PyRobusta/dist/pyrobusta/transport/socket.mpy" + "pyrobusta/connectivity/wifi.mpy", + "github:szeka9/PyRobusta/dist/pyrobusta/connectivity/wifi.mpy" + ], + [ + "pyrobusta/connectivity/__init__.py", + "github:szeka9/PyRobusta/dist/pyrobusta/connectivity/__init__.py" ], [ "pyrobusta/transport/__init__.py", "github:szeka9/PyRobusta/dist/pyrobusta/transport/__init__.py" ], + [ + "pyrobusta/transport/connection.mpy", + "github:szeka9/PyRobusta/dist/pyrobusta/transport/connection.mpy" + ], [ "pyrobusta/assets/www/index.html", "github:szeka9/PyRobusta/dist/pyrobusta/assets/www/index.html" @@ -66,21 +74,13 @@ "github:szeka9/PyRobusta/dist/pyrobusta/__init__.py" ], [ - "pyrobusta/bindings/socket_http.mpy", - "github:szeka9/PyRobusta/dist/pyrobusta/bindings/socket_http.mpy" + "pyrobusta/bindings/http_connection.mpy", + "github:szeka9/PyRobusta/dist/pyrobusta/bindings/http_connection.mpy" ], [ "pyrobusta/bindings/__init__.py", "github:szeka9/PyRobusta/dist/pyrobusta/bindings/__init__.py" ], - [ - "pyrobusta/con/wifi.mpy", - "github:szeka9/PyRobusta/dist/pyrobusta/con/wifi.mpy" - ], - [ - "pyrobusta/con/__init__.py", - "github:szeka9/PyRobusta/dist/pyrobusta/con/__init__.py" - ], [ "pyrobusta/server/__init__.py", "github:szeka9/PyRobusta/dist/pyrobusta/server/__init__.py" diff --git a/src/pyrobusta/utils/config.py b/src/pyrobusta/utils/config.py index 4632640..c7e88c3 100644 --- a/src/pyrobusta/utils/config.py +++ b/src/pyrobusta/utils/config.py @@ -14,7 +14,7 @@ def const(n): # pylint: disable=C0116 from .helpers import normalize_path -PYROBUSTA_VERSION = "v0.4.0" +PYROBUSTA_VERSION = "v0.5.0" CONFIG_LOCATION = "pyrobusta.env" # -------------------------------------------