Skip to main content

Python app-server framework for the io7 IoT platform

Project description

io7app

PyPI Python License

A small, intuitive Python framework for writing app servers on the io7 IoT platform.

You decorate Python functions with the device events they react to and the schedules they fire on. The programming model is one small function per concern: any number of functions can subscribe to the same event — the runtime stacks them and fires each independently — and a report-by-exception filter (@app.filter) lets each function wake only when its element of the event actually changes. A dimmer's power flips, its brightness moves, and an audit log each live in their own three-line function instead of one entangled handler.

The framework owns the MQTT connection, topic routing, JSON envelope handling, the filters, scheduling, and dynamic register/unregister. Your code stays focused on business logic.

Demo: YouTube walkthrough

The io7 platform — where this library fits

┌──────────┐                  ┌───────────┐                  ┌─────────────────┐
│  Devices │  ── events ──▶   │  Broker   │  ── events ──▶   │       App       │
│ (sensors,│                  │(Mosquitto)│                  │  (this library, │
│actuators)│ ◀── commands ──  │           │ ◀── commands ──  │   one process)  │
└──────────┘                  └───────────┘                  └─────────────────┘
   (many)                                                        

io7 separates the world into two roles. Devices publish events (sensor readings, status changes) and receive commands (actuation requests). Apps subscribe to events from any device and publish commands to any device — they are where the IoT business logic lives ("if temperature drops, turn the valve on", "when the switch flips, mirror it on the lamp").

This library implements only the App side. Device firmware lives in the io7 device libraries (ESP32, ESP8266, MicroPython).

Quick start

You have two ways to run an io7app: as a normal pip package on your machine, or inside a self-contained Docker image. Both expect the same two files in your working directory:

  • app.py — your application (decorators + App().run()).
  • .env — broker credentials. Copy from .env.example:
    IO7_SERVER=iot201.ddns.net
    IO7_APP_ID=app3
    IO7_TOKEN=app3
    
    TLS, port overrides, and log levels are documented in the user guide.

A minimal app.py:

from io7app import App

app = App()

@app.on_event("sw1", "status")
def on_switch(data):
    print("sw1 ->", data)

app.run()

Option 1 — Local install (pip)

Available on PyPI. Requires Python ≥ 3.10:

pip install io7app
# Optional, only if you use @inject(cron=...)
pip install io7app[cron]

Then in the directory containing app.py and .env:

python app.py

Talks to any standard MQTT broker (Mosquitto, EMQX, HiveMQ, the io7 platform itself).

Option 2 — Docker

Useful when you don't want to manage a Python environment on the host, and the natural choice when the rest of your io7 stack (broker, io7api, etc.) already runs in containers. The image is published on Docker Hub as io7lab/io7-app — no local build needed.

1. Find the network your io7 stack is on.

So the app can reach the broker / io7api by container name rather than over the public internet:

docker network ls
# or look it up from a known container:
docker inspect io7api \
  --format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}'

You'll see something like io7_default or io7-net. Use that below.

2. Run the container from any directory containing app.py and .env:

docker run -d --restart always \
  --name io7app \
  --network io7_default \
  -v "$PWD":/app \
  io7lab/io7-app

When the broker runs on the same docker network, point IO7_SERVER in .env at the broker's service/container name rather than its public DNS:

IO7_SERVER=mqtt        # or whatever your broker container is named
IO7_APP_ID=app3
IO7_TOKEN=app3

The container watches /app/app.py and /app/.env and auto-restarts the Python process when either changes — edit a file, save, and the new code is live within ~2 seconds. No need to bounce the container yourself. If you split your app across helper modules, run touch app.py to force a reload after editing them.

If app.py raises an exception, the traceback shows up in docker logs -f io7app and the container keeps watching; fix the file and it restarts automatically.

Tunables (set with -e):

  • IO7_POLL_INTERVAL=1 — poll period in seconds (default 2).

Docker Compose

If you already maintain a docker-compose.yml for the io7 stack, add this service alongside io7api / mqtt so it shares the same network and lifecycle:

services:
  io7-app:
    image: io7lab/io7-app
    container_name: io7app
    restart: always
    volumes:
      - ./myapp:/app          # folder with app.py and .env
    # environment:
    #   - IO7_POLL_INTERVAL=1
    # networks:               # only needed if your compose file
    #   - io7-net              # uses a non-default network name

Then docker compose up -d io7-app. Compose places the service on the project's default network automatically, so it can reach mqtt / io7api by service name.

Status

  • Version 0.2.0
  • Under 900 lines of Python across four small modules (router, scheduler, filter, app)
  • 97 tests, all green
  • Runtime deps: paho-mqtt (MQTT) and python-dotenv (config). Optional: croniter for cron schedules.

Where to go next

  • USER_GUIDE.md — write your first app, decorator reference, scheduling, dynamic register/unregister, debug logging. Every claim in the guide is exercised by a test.
  • examples/ — six runnable apps: switch/lamp, lux/lamp, lux auto-lamp triangle (lux + switch ↔ lamp, filtered), thermostat/valve, scheduled inject, wildcard tracing.
  • docs/superpowers/specs/ — design document.
  • docs/superpowers/plans/ — implementation plan.

Develop

git clone <this-repo>
cd io7app
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

Design principles

  • Small. Four modules, two classes, four decorators.
  • Intuitive. A working app is 3-5 lines of business logic.
  • Honest. No magic — handler signatures are inspected, not assumed; dropped messages are silent only when the spec says so; warnings spell out exactly what was deduplicated and why.
  • Optimal where it counts. Static topics dispatch in O(1); wildcards compile to a regex once; overlapping decorators are consolidated at registration time so handlers never double-fire.

License

MIT — see LICENSE. Same as the rest of the io7lab packages.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

io7app-0.2.0.tar.gz (34.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

io7app-0.2.0-py3-none-any.whl (17.3 kB view details)

Uploaded Python 3

File details

Details for the file io7app-0.2.0.tar.gz.

File metadata

  • Download URL: io7app-0.2.0.tar.gz
  • Upload date:
  • Size: 34.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for io7app-0.2.0.tar.gz
Algorithm Hash digest
SHA256 b70a0ff118762b5492a772628de694b6228834db7fd9e4cff433dd1eb2ff09fa
MD5 55817fe1ecb65933650a3cd9c3faab1e
BLAKE2b-256 beeb129194e007b87b3e367afe0f274622db6524e05c2529a5bd5d4c900849fe

See more details on using hashes here.

File details

Details for the file io7app-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: io7app-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 17.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for io7app-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d5bd9fc9b384a90aa1a191b4c71a9567c26bb6271e3a4a973e88d22418beb807
MD5 2bbbd743bd15bfaa3ee00d37560f03ae
BLAKE2b-256 c04d0f2708901bc58db6680b7b85fa73311a5e28c1a51770f05633b55cb1058c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page