Quick Start
This guide walks you through creating and running a Doover application using the doover-cli wizard. By the end, you'll have a working application running locally that you can customize and deploy to the Doover platform.
Prerequisites
Before starting, ensure you have:
- Python 3.11 or higher
- Docker installed and running
- A Doover account (sign up at my.doover.com)
Step 1: Install the Doover CLI
Install the Doover CLI using one of these methods:
# Using uv (Recommended) uv tool install doover-cli # Using pipx pipx install doover-cli # Using pip pip install doover-cli
Verify the installation:
doover --version
Step 2: Authenticate
Log in to your Doover account:
doover login
This opens a browser window for authentication. Once complete, your credentials are stored locally for future use.
Step 3: Create Your Application
Run the application creation wizard:
doover app create
The wizard guides you through the setup:
What is the name of your app? my-sensor-app Description: Monitors temperature sensors and sends alerts Would you like me to initiate a git repository? [Y/n] y What is the container registry for your app? ghcr.io/getdoover What is the owner organisation's key (on Doover)? my-org What is the container registry profile key on Doover? my-registry Fetching template repository... Renaming template files... Updating config... Done!
The wizard creates a complete project with this structure:
my-sensor-app/ ├── src/ │ └── my_sensor_app/ │ ├── __init__.py # Entry point │ ├── application.py # Main application logic │ ├── app_config.py # Configuration schema │ ├── app_ui.py # UI elements │ └── app_state.py # State machine (optional) ├── simulators/ │ ├── sample/ │ │ └── main.py # Simulator for local testing │ └── docker-compose.yml # Local development setup ├── tests/ │ └── test_imports.py ├── doover_config.json # Application metadata ├── pyproject.toml ├── Dockerfile └── README.md
Step 4: Run Locally
Navigate to your application directory and start it:
cd my-sensor-app doover app run
This starts three Docker containers:
- device_agent - Simulates the Doover device agent
- simulator - Provides mock data via tags
- your application - The application you just created
You'll see logs from all three containers in your terminal.
Step 5: View in Browser
While your app is running, open the channel viewer to see your application's data:
doover app channels
This opens the Doover web interface connected to your local instance, where you can see UI elements, variables, and interact with your application.
Understanding the Generated Code
The wizard generates a working application based on the app-template. Here's what each file does:
application.py
The main application class with lifecycle methods:
from pydoover.docker import Application
from pydoover import ui
class SampleApplication(Application):
async def setup(self):
"""Called once when the application starts."""
self.ui = SampleUI()
self.ui_manager.add_children(*self.ui.fetch())
async def main_loop(self):
"""Called repeatedly (default: every 1 second)."""
# Update UI, read sensors, process logic
self.ui.is_working.update(True)
@ui.callback("send_alert")
async def on_send_alert(self, new_value):
"""Called when user presses the send_alert button."""
await self.publish_to_channel("significantAlerts", "Alert!")
app_config.py
Defines configurable parameters for your application:
from pydoover import config
class SampleConfig(config.Schema):
def __init__(self):
self.outputs_enabled = config.Boolean("Digital Outputs Enabled", default=True)
self.funny_message = config.String("A Funny Message")
app_ui.py
Defines the UI elements users see in the Doover dashboard:
from pydoover import ui
class SampleUI:
def __init__(self):
self.is_working = ui.BooleanVariable("is_working", "We Working?")
self.send_alert = ui.Action("send_alert", "Send Alert")
self.battery = ui.Submodule("battery", "Battery Module")
# ... more UI elements
Customizing Your Application
Modify the Main Loop
Edit application.py to add your logic:
async def main_loop(self):
# Read from simulator or real hardware
sensor_value = self.get_tag("random_value", self.config.sim_app_key.value)
# Update UI
self.ui.sensor_reading.update(sensor_value)
# React to thresholds
if sensor_value > 80:
await self.publish_to_channel("alerts", f"High value: {sensor_value}")
Add UI Elements
Edit app_ui.py to add variables and controls:
# Add a numeric variable with color ranges
self.temperature = ui.NumericVariable(
"temperature",
"Temperature (°C)",
precision=1,
ranges=[
ui.Range("Cold", 0, 15, ui.Colour.blue),
ui.Range("Normal", 15, 28, ui.Colour.green),
ui.Range("Hot", 28, 50, ui.Colour.red),
]
)
Add Configuration Options
Edit app_config.py to add user-configurable settings:
self.alert_threshold = config.Number(
"Alert Threshold",
default=80.0,
description="Value above which alerts are triggered"
)
Development Workflow
# Make code changes, then: # Check code quality doover app lint --fix doover app format --fix # Run tests doover app test # Rebuild and run doover app build doover app run # When ready, publish to Doover doover app publish
Next Steps
Now that you have a running application, explore these topics:
- Application Class - Deep dive into the Application lifecycle
- UI Components - Build rich user interfaces
- Configuration - Create flexible, configurable apps
- State Machine - Manage complex application states
- Doover CLI - Master the development workflow