Administration guide for the Doover platform
This skill covers administration topics for the Doover platform, including organization setup, device types, and deployment configuration.
Organizations are the top-level entity in Doover, containing users, devices, and applications.
Organization
├── Users (members with roles)
├── Device Types (templates for devices)
├── Devices (physical/virtual devices)
├── Applications (apps deployed to devices)
└── API Keys (for programmatic access)
| Role | Permissions |
|---|---|
| Owner | Full access, billing, can delete org |
| Admin | Manage users, devices, apps |
| Developer |
| Deploy apps, view devices |
| Viewer | Read-only access to dashboards |
Device types define templates for devices with pre-configured applications.
Device types specify:
Key fields for device type integration:
{
"my_app": {
"key": "uuid-goes-here",
"name": "my_app",
"display_name": "My Application",
"type": "DEV",
"visibility": "PUB",
"allow_many": true,
"description": "Short description",
"long_description": "README.md",
"depends_on": ["platform_interface"],
"owner_org_key": "org-uuid",
"image_name": "ghcr.io/getdoover/my_app",
"container_registry_profile_key": "",
"build_args": "--platform linux/amd64,linux/arm64"
}
}
| Field | Type | Description |
|---|---|---|
key | UUID | Unique identifier for the app |
name | string | Internal name (snake_case) |
display_name | string | Human-readable name |
type | enum | DEV (development) or PROD (production) |
visibility | enum | PUB (public) or PRI (private) |
allow_many | boolean | Allow multiple instances on one device |
description | string | Short description |
long_description | string | Path to README or long description |
depends_on | array | Required system apps |
owner_org_key | UUID | Owning organization |
image_name | string | Docker image registry path |
container_registry_profile_key | UUID | Registry credentials profile |
build_args | string | Docker build arguments |
Applications can depend on system services:
{
"depends_on": [
"platform_interface",
"device_agent",
"modbus_interface"
]
}
| Dependency | Purpose |
|---|---|
platform_interface | GPIO, hardware I/O access |
device_agent | Channel publishing, tag management |
modbus_interface | Modbus RTU/TCP communication |
Provides access to device hardware:
class MyApplication(Application):
async def main_loop(self):
# Digital input
values = await self.platform_iface.get_di_async([1, 2, 3])
# Digital output
await self.platform_iface.set_do_async(pin=4, value=True)
# Analog input (if supported)
analog = await self.platform_iface.get_ai_async([1])
Provides data management services:
class MyApplication(Application):
async def main_loop(self):
# Publish to channel
await self.device_agent.publish_to_channel_async(
"sensor_data",
json.dumps({"temperature": 25.5})
)
For Modbus communication:
class MyApplication(Application):
async def main_loop(self):
# Read holding registers
registers = await self.modbus_iface.read_registers_async(
start_address=100,
count=10,
register_type=3 # Holding registers
)
# Write register
await self.modbus_iface.write_register_async(
address=200,
value=1
)
Configure container registry access in doover_config.json:
{
"my_app": {
"image_name": "ghcr.io/getdoover/my_app",
"container_registry_profile_key": "registry-profile-uuid"
}
}
Supported registries:
Multi-platform builds for ARM and x86 devices:
{
"my_app": {
"build_args": "--platform linux/amd64,linux/arm64"
}
}
Common build arguments:
--platform linux/amd64 - Intel/AMD 64-bit--platform linux/arm64 - ARM 64-bit (Raspberry Pi 4, etc.)--platform linux/arm/v7 - ARM 32-bit (older Pi models)# 1. Ensure you're authenticated
doover auth login
# 2. Build for target platforms
doover app build
# 3. Publish to platform
doover app publish
# For staging/testing
doover app publish --staging
# Production with specific profile
doover app publish --profile production
Applications receive configuration via environment variables:
| Variable | Description |
|---|---|
APP_KEY | Unique key for this app instance |
CONFIG_FP | Path to configuration JSON file |
HEALTHCHECK_PORT | Port for health check endpoint |
import os
class MyApplication(Application):
async def setup(self):
app_key = os.environ.get("APP_KEY")
config_path = os.environ.get("CONFIG_FP")
log.info(f"Starting app {app_key}")
log.info(f"Config from {config_path}")
For local development: