Skip to content

Configuration

Every Doover application -- whether a Docker app on an edge device or a cloud processor -- defines its configuration as a Schema subclass with typed elements. The schema serves three purposes:

  1. Generates JSON Schema for validation (draft 2020-12)
  2. Renders a configuration form in the Doover web portal automatically
  3. Provides typed access to configuration values in application code

Configuration is defined once in code, delivered to the application at deployment time, and can be edited at runtime through the portal's auto-generated form.

Defining a Schema

Subclass Schema from pydoover.config and declare typed elements as class attributes.

from pydoover.config import Schema, Number, String, Boolean

class MyConfig(Schema):
    poll_interval = Number(
        "Poll Interval",
        default=30.0,
        description="Seconds between sensor readings",
    )
    site_name = String(
        "Site Name",
        default="Unnamed Site",
        description="Display name for this installation",
    )
    alerts_enabled = Boolean(
        "Enable Alerts",
        default=True,
        description="Whether to send temperature alerts",
    )

Each element has a display name (shown in the UI), an optional default value, and an optional description. Elements without a default are required -- the deployment will fail if the operator does not provide a value.

Using Configuration in an Application

In both Docker applications and processors, the config is accessible as self.config. Access individual values through the .value property on each element.

from pydoover.processor import Application
from pydoover.models import ScheduleEvent


class MyProcessor(Application):
    config_cls = MyConfig

    async def setup(self):
        # Access config values via the .value property
        self.interval = self.config.poll_interval.value
        self.site = self.config.site_name.value

    async def on_schedule(self, event: ScheduleEvent):
        if self.config.alerts_enabled.value:
            await self.check_and_alert()

The .value property returns the value that was set during deployment. If the config has not been loaded yet (e.g., accessing it before setup), it raises a ValueError.

How Configuration Flows

  1. Define: You declare a Schema subclass in your application code.
  2. Export: The schema is exported to doover_config.json (via doover config-schema export or Schema.export()). This file is included in the application package.
  3. Deploy: When the application is installed on an agent, the operator fills in configuration values through the portal form (generated from the JSON Schema).
  4. Deliver: At runtime, the platform delivers the configuration as a dictionary. The framework calls _inject_deployment_config() to populate each element's value.
  5. Access: Your application reads values via self.config.element_name.value.
Information Circle

Configuration values can be changed at any time through the Doover portal. For processors, the new values take effect on the next invocation. For Docker applications, a redeployment or restart is typically required.

Element Types at a Glance

pydoover provides primitive, complex, and Doover-specific element types:

CategoryTypesDescription
PrimitiveInteger, Number, Boolean, String, DateTimeSingle-value fields
ComplexEnum, Array, ObjectMulti-value or nested fields
Doover-specificApplication, ApplicationInstall, Device, Group, DevicesConfig, GroupsConfig, TagRef, ApplicationPosition, ApplicationDefaultOpen, LLMAPIKeyPlatform resource references and internal settings

See Configuration Elements for detailed documentation of each type.

Simple Example

Here is a complete example showing a schema used in a processor.

from pydoover.config import Schema, Number, String, Enum, Boolean
from pydoover.processor import Application, run_app, ScheduleConfig


class ReportConfig(Schema):
    schedule = ScheduleConfig("Report Schedule")
    report_name = String("Report Name", default="Daily Summary")
    temperature_unit = Enum(
        "Temperature Unit",
        choices=["Celsius", "Fahrenheit"],
        default="Celsius",
    )
    include_humidity = Boolean("Include Humidity", default=True)
    decimal_places = Number("Decimal Places", default=2.0)


class ReportProcessor(Application):
    config_cls = ReportConfig

    async def on_schedule(self, event):
        unit = self.config.temperature_unit.value
        decimals = int(self.config.decimal_places.value)
        # Generate report using the configured settings

Next Steps