ODevice Recipes
Copy-paste patterns for common tasks.
Recipe 1: Basic read-only sensor
python
from odevice import App, Device, Number
app = App("Sensors")
sensor = Device(id="s1", name="Temp", properties={"temp": Number(unit="°C")})
app.add(sensor)
sensor.update(temp=22.5)
app.run()Recipe 2: Writable switch with backend
python
from odevice import App, Device, Boolean
app = App("Controls")
relay = Device(id="r1", name="Relay", properties={"on": Boolean(writable=True)})
app.add(relay)
@relay.on_write("on")
async def set_relay(value):
await your_backend.set_relay(value)
return value
app.run()Recipe 3: Gauge with deadband
python
pressure = Number(unit="bar", min=0, max=10, view="gauge", deadband=0.1, max_rate=2)Recipe 4: Enum mode selector
python
mode = Enum(options=["auto", "manual", "off"], writable=True)Recipe 5: Poll a REST backend
python
async def poll():
while True:
data = await httpx.get("http://api/status").json()
device.update(rpm=data["rpm"])
await asyncio.sleep(1)Recipe 6: MQTT bridge
python
def on_message(client, userdata, msg):
sensor.update(temperature=json.loads(msg.payload)["temperature"])Recipe 7: Multiple devices
python
for i in range(3):
app.add(Device(id=f"pump-{i}", name=f"Pump {i}", properties={...}))Recipe 8: Embed in existing FastAPI app
python
runtime = App("Embedded")
runtime.add(device)
fastapi_app = await runtime.run_async() # returns FastAPI appRecipe 9: Custom view override
python
Number(unit="kW", view="trend") # force trend chartRecipe 10: Viewer-only demo user
python
runtime = App("Demo")
# bootstrap creates 'admin'. Add a viewer:
runtime.auth.create_user("viewer", "password123", "viewer")
runtime.run()Recipe 11: Stateless action button
python
pump.action("reset", label="Reset Pump", severity="danger", confirm="Sure?")
@pump.on_action("reset")
async def do_reset():
await backend.reset()Recipe 12: Warning threshold
python
# property must allow it
pressure = Number(unit="bar", min=0, max=10, configurable={"warning": True})
app.add_warning("pump-01", "pressure", ">", 8.0, duration=5, severity="warning")Recipe 13: Automation (condition -> command)
python
power = Boolean(writable=True, automation={"allow_set": True})
app.add_automation("High Pressure Stop",
when={"entity": "pump-01", "property": "pressure", "operator": ">", "value": 9, "duration": 3},
then={"entity": "pump-01", "property": "power", "operation": "set", "value": False},
cooldown=30)Recipe 14: Daily schedule
python
app.add_schedule("Morning Start", "Asia/Bangkok",
schedule={"type": "daily", "time": "08:00"},
action={"entity": "pump-01", "property": "power", "operation": "set", "value": True})Recipe 15: Backend-declared page with grid
python
app.add_page(Page(id="reports", title="Reports", icon="chart",
columns=2, density="compact",
sections=[Section(title="Pump", entities=["pump-01"])]))Recipe 16: Map / location widget
python
from odevice import Location
tracker = Device(id="t1", name="Tracker",
properties={"pos": Location(lat=13.7, lng=100.5)})