rise-l-net
Lightweight IoT device management toolkit. Pair a small MicroPython client with a Python server and you have heartbeats, telemetry, and device lifecycle events on tap. Pure stdlib by default; aiohttp/aiosqlite are opt-in for the async track.
-
Homepage: https://lyuxc.cn/risel
-
Two-way library: ships both a device-side client and a server-side manager.
-
Sync and async:
RISELDevice/RISELServerfor stdlib,AsyncRISELDevice/AsyncRISELServerfor asyncio. -
MicroPython-friendly: the sync client runs on ESP32-class boards (no extra deps).
-
Pluggable: middleware, plugins, custom routes, swappable storage and transport.
Install
pip install rise-l-net # client + sync server (stdlib only)
pip install "rise-l-net[async]" # adds aiohttp + aiosqlite
pip install "rise-l-net[dev]" # for contributors
macOS / zsh 用户:
[...]是 zsh 的 glob 字符,所以带 extras 的命令必须加引号(或单引号)。bash 不需要。
Python 3.10+ on the server side. The sync client is also designed to import on MicroPython.
Quick start
Server (sync)
from rise_l_net import RISELServer
server = RISELServer(port=8080)
server.on_report(lambda device_id, payload: print(device_id, payload["event_type"]))
server.start()
Server (async)
import asyncio
from rise_l_net import AsyncRISELServer
async def main() -> None:
async with AsyncRISELServer(port=8080) as server:
await server.wait_closed()
asyncio.run(main())
Client (sync, runs on MicroPython too)
from rise_l_net import RISELDevice
device = RISELDevice(
"http://server.local:8080",
wifi_ssid="MyWiFi",
wifi_password="secret",
)
device.start()
device.report("temperature", {"value": 23.5})
Client (async)
import asyncio
from rise_l_net import AsyncRISELDevice
async def main() -> None:
async with AsyncRISELDevice("http://server.local:8080") as device:
await device.report("ping", {"v": 1})
await device.wait_closed()
asyncio.run(main())
Extending
Both client and server expose three extension points: middleware, plugins (server only), and a swappable storage/transport layer.
from rise_l_net import RISELServer
from rise_l_net.server import AuthMiddleware, RateLimitMiddleware, AlertPlugin
server = (
RISELServer(port=8080)
.use(AuthMiddleware(api_key="secret"))
.use(RateLimitMiddleware(max_requests_per_minute=120))
.plugin(AlertPlugin({"temperature": {"warning": 30, "critical": 40}}))
)
server.start()
from rise_l_net import RISELDevice
from rise_l_net.client import RetryMiddleware, ThrottleMiddleware, CacheMiddleware
device = (
RISELDevice("http://server:8080")
.use(RetryMiddleware(max_retries=5))
.use(ThrottleMiddleware(max_requests_per_second=2))
.use(CacheMiddleware(cache_path="/data/cache.json"))
)
device.start()
API surface
| Endpoint | Direction | Body |
|---|---|---|
POST /api/heartbeat |
client → server | {device_id, ip, uptime, version, metadata} |
POST /api/report |
client → server | {device_id, event_type, data, severity, timestamp} |
POST /<custom> |
client → server | Anything you handle in server.route(...) |
Authentication is opt-in via AuthMiddleware. The middleware uses a constant-time comparison and the header lookup is case-insensitive.
Logging
Library logs go through the rise_l_net logger. To enable a default stderr handler:
from rise_l_net import configure_logging
configure_logging("INFO")
If your application already configures logging, do not call configure_logging and the library will respect your handlers.
Development
git clone https://github.com/LXC-TRU/RISE.L.net.git
cd RISE.L.net
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
ruff check src tests
mypy src
pytest
License
MIT — see LICENSE.
Metadata
Release files for rise-l-net 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rise_l_net-0.1.1.tar.gz | 57.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rise_l_net-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 122.3 kB
Release files / rise_l_net-0.1.1.tar.gz
| Download URL | rise_l_net-0.1.1.tar.gz |
|---|---|
| Size | 57.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0b8f167e1350ea749053ff38b607286fc77708b12122c685002533b591c80eb1
|
|
BLAKE2b-256 checksum How to use checksums |
0c2f910fd6e29841a45d0d38eae093c79056a957028ab04e0fb507aeab02e72c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 30, 2026.
Transparency logRelease files / rise_l_net-0.1.1-py3-none-any.whl
| Download URL | rise_l_net-0.1.1-py3-none-any.whl |
|---|---|
| Size | 64.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a7c98155da3f9ef5d1c876a85caaf7150995888f60b86af29199480321dc8cdb
|
|
BLAKE2b-256 checksum How to use checksums |
e9b0f166bdbe4a149e80023d4e654d75827b98c7616edbce13b5e44b04a3916d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 30, 2026.
Transparency log