Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
PYROBUSTA_VERSION := 0.3.0
PYROBUSTA_VERSION := v0.4.0
DEVICE ?= u0

SRC_DIR := src
TEST_DIR := tests
EXAMPLE_DIR := example/mem_usage
EXAMPLE_DIR := example/mip_repo
BUILD_DIR := build
DIST_DIR := dist
PKG := pyrobusta
TLS_DIR := tls
ASSETS_DIR := assets

PKG := pyrobusta

MICROPY_ROOT := external/micropython
MPY_CROSS := $(MICROPY_ROOT)/mpy-cross/build/mpy-cross
Expand Down Expand Up @@ -47,6 +49,11 @@ toolchain:
# -----------------------------
.PHONY: build
build: $(MPY_TARGETS) $(INIT_TARGETS)
@mkdir -p $(BUILD_DIR)
@if [ -d assets ]; then \
echo "Copying assets/ -> $(BUILD_DIR)"; \
cp -r assets $(BUILD_DIR)/${PKG}/; \
fi

# Compile .py -> .mpy
$(BUILD_DIR)/%.mpy: $(SRC_DIR)/%.py
Expand All @@ -66,6 +73,7 @@ $(BUILD_DIR)/%.py: $(SRC_DIR)/%.py
.PHONY: deploy
deploy:
@echo "Uploading build/$(PKG) to device $(DEVICE)"
@mpremote $(DEVICE) soft-reset
@mpremote $(DEVICE) mkdir :/lib || true
@find $(BUILD_DIR)/$(PKG) | while read source; do \
rel=$${source#$(BUILD_DIR)/}; \
Expand All @@ -79,14 +87,28 @@ deploy:
fi; \
sleep 1; \
done
@mpremote $(DEVICE) reset

# -----------------------------
# Deploy custom configuration
# -----------------------------
.PHONY: deploy-config
deploy-config:
@echo "Uploading pyrobusta.env"
@mpremote $(DEVICE) soft-reset
@if [ -f pyrobusta.env ]; then mpremote $(DEVICE) cp pyrobusta.env :pyrobusta.env; fi
@mpremote $(DEVICE) reset


# -----------------------------
# Deploy index page # TODO use install_www from assets module
# -----------------------------
.PHONY: deploy-www
deploy-www:
@echo "Deploying /www"
@mpremote $(DEVICE) soft-reset
@mpremote $(DEVICE) run scripts/install_www.py
@mpremote $(DEVICE) reset

# -----------------------------
# Full redeploy
Expand All @@ -107,6 +129,9 @@ publish:
@sed -E -i.bak 's/(PYROBUSTA_VERSION[[:space:]]*=[[:space:]]*)"[^"]*"/\1"$(PYROBUSTA_VERSION)"/' \
$(SRC_DIR)/pyrobusta/utils/config.py \
&& rm -f $(SRC_DIR)/pyrobusta/utils/config.py.bak
@sed -E -i.bak 's/(PyRobusta[[:space:]]).+([[:space:]]Web Server)/\1$(PYROBUSTA_VERSION)\2/' \
$(ASSETS_DIR)/www/*.html \
&& rm -f $(ASSETS_DIR)/www/*.html.bak
$(MAKE) clean
$(MAKE) build BUILD_DIR=$(DIST_DIR)
scripts/update_package.bash $(DIST_DIR) package.json $(PYROBUSTA_VERSION)
Expand All @@ -128,7 +153,7 @@ stage-example:
@echo "Copying built package"
@cp -r build/pyrobusta $(RUNTIME_DIR)/lib

@echo "Copying example files"
@echo "Copying example app"
@cp $(EXAMPLE_DIR)/app.py $(RUNTIME_DIR)/
@cp $(EXAMPLE_DIR)/boot.py $(RUNTIME_DIR)/

Expand All @@ -152,16 +177,20 @@ run-unix: stage-example
.PHONY: deploy-example
deploy-example:
@echo "Uploading boot.py"
@mpremote $(DEVICE) soft-reset
mpremote $(DEVICE) cp $(EXAMPLE_DIR)/boot.py :boot.py
mpremote $(DEVICE) cp $(EXAMPLE_DIR)/app.py :app.py

@echo "Uploading pyrobusta.env"
@if [ -f pyrobusta.env ]; then mpremote $(DEVICE) cp pyrobusta.env :pyrobusta.env; fi
@mpremote $(DEVICE) reset

# -----------------------------
# Run example directly
# -----------------------------
.PHONY: run-device
run-device:
@mpremote $(DEVICE) soft-reset
mpremote $(DEVICE) run $(EXAMPLE_DIR)/app.py


Expand Down Expand Up @@ -226,20 +255,26 @@ test-unix: TLS_DIR=$(TEST_RUNTIME)
test-unix: stage-test tls-cert
@cd $(TEST_RUNTIME); \
for test in test_*.py; do \
echo "\n==================================="; \
echo "Running $$test"; \
echo "==================================="; \
MICROPYPATH=":.frozen:lib" ../$(MICROPYTHON) $$(basename $$test) || exit 1; \
done

# -----------------------------
# Run functional tests on device
# -----------------------------
.PHONY: test-device
test-device: #clean-device upload
test-device: stage-test #clean-device upload
@mpremote $(DEVICE) soft-reset
@cd $(TEST_RUNTIME); \
for test in test_*.py; do \
echo "\n==================================="; \
echo "Running $$test"; \
echo "==================================="; \
mpremote $(DEVICE) run $$(basename $$test) || exit 1; \
done
@mpremote $(DEVICE) reset

# ================================================
# Utilities for TLS
Expand Down Expand Up @@ -272,8 +307,10 @@ tls-cert:
# -----------------------------
.PHONY: deploy-cert
deploy-cert:
@mpremote $(DEVICE) soft-reset
@mpremote $(DEVICE) cp $(TLS_DIR)/key.der :key.der
@mpremote $(DEVICE) cp $(TLS_DIR)/cert.der :cert.der
@mpremote $(DEVICE) reset

# ================================================
# Cleanup
Expand Down Expand Up @@ -305,4 +342,6 @@ clean: clean-build clean-runtime
# -----------------------------
.PHONY: clean-device
clean-device:
@mpremote $(DEVICE) soft-reset
mpremote $(DEVICE) run scripts/clean_device.py
@mpremote $(DEVICE) reset
157 changes: 157 additions & 0 deletions assets/www/examples.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PyRobusta Home</title>
<style>
body {
font-family: serif;
margin: 40px;
background: white;
color: black;
}
h1 {
border-bottom: 1px solid #999;
padding-bottom: 10px;
}
hr {
margin: 20px 0;
}
a {
color: blue;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
textarea {
resize: none;
background-color: rgb(37, 37, 37);
color: white;
box-sizing: border-box;
width: 100%;
padding-left: 10px;
}
.footer {
font-size: 0.9em;
color: #555;
margin-top: 30px;
}
</style>
</head>
<body>

<h1>Getting Started</h1>

<a href="index.html">← Back</a>

<p>This page presents useful examples to configure your server.</p>

<hr>

<h2>Server configuration</h2>
<textarea readonly="true" rows="8">
# /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_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
</textarea>
<p></p>

<hr>

<h2>Simple Server Application</h2>
<p>The below example demonstrates how to set up a simple application, exposed at /app.</p>
<textarea readonly="true" rows="37">
# /app.py

import asyncio
from gc import mem_free, mem_alloc

from pyrobusta.server import http_server
from pyrobusta.protocol.http import HttpEngine
from pyrobusta.utils import logging


@HttpEngine.route("/app", "GET")
def app(http_ctx, payload):
free = mem_free()
value_format = "bytes"

if http_ctx.query:
value_format = http_ctx.get_url_encoded_query_param(
http_ctx.query, "format", default="bytes"
)
if value_format not in ("%", "bytes"):
raise ValueError("invalid format")

if value_format == "%":
free = round(100 * free / (free + mem_alloc()), 2)

return "text/plain", (f"Free memory [{value_format}]: {free}\n")


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()
</textarea>
<textarea readonly="true" rows="13">
# This file is executed on every boot (including wake-boot from deepsleep)
import machine
from os import listdir

from pyrobusta.con import wifi

connected = wifi.initialize()
if connected and not machine.reset_cause() == machine.SOFT_RESET:
if "app.py" in listdir():
import app

app.main()
</textarea>

<p>Soft reset the device and upload app.py and boot.py with mpremote.</p>
<textarea readonly="true" rows="4">
$ mpremote a0 soft-reset
$ mpremote a0 cp app.py :/app.py
$ mpremote a0 cp boot.py :/boot.py
</textarea>

<p>Hard reset the device to start the application and connect over REPL.</p>
<textarea readonly="true" rows="12">
$ mpremote a0 reset repl
Connected to MicroPython at /dev/ttyACM0
...
[INFO] pyrobusta.con.wifi: network b'Home-Wi-Fi' found!
[INFO] pyrobusta.con.wifi: connected, available at 192.168.1.101
[WARN] pyrobusta.server.http_server.init_pools: low-memory mode with reduced buffer size
[INFO] pyrobusta.server.http_server.init_pools: 2 connection(s) allowed
[INFO] pyrobusta.server.http_server: started

# You can now reach the device at 192.168.1.101:8080 (replace with your IP)
# Press Ctrl-x to exit
</textarea>

<p>Use curl to test your application.</p>
<textarea readonly="true" rows="6">
$ curl "http://192.168.1.101:8080/app"
Free memory [bytes]: 115456

$ curl "http://192.168.1.101:8080/app?format=%"
Free memory [%]: 71.76
</textarea>

<div class="footer">
<hr>
<address>PyRobusta v0.4.0 Web Server</address>
</div>
</body>
</html>
55 changes: 55 additions & 0 deletions assets/www/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PyRobusta Home</title>
<style>
body {
font-family: serif;
margin: 40px;
background: white;
color: black;
}
h1 {
border-bottom: 1px solid #999;
padding-bottom: 10px;
}
hr {
margin: 20px 0;
}
a {
color: blue;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.footer {
font-size: 0.9em;
color: #555;
margin-top: 30px;
}
</style>
</head>
<body>

<h1>PyRobusta Home</h1>

<p>The server is running correctly and is ready to serve content.</p>

<hr>

<h2>Available Resources</h2>
<ul>
<li><a href="examples.html">Getting Started</a></li>
<li><a href="https://github.com/szeka9/PyRobusta">Source Code</a></li>
</ul>

<div class="footer">
<hr>
<address>PyRobusta v0.4.0 Web Server</address>
</div>

</body>
</html>
Loading
Loading