Skip to content

Doover Device Services

Doover Device Services (DDS) is the suite of containerized services that run on Doover devices to enable cloud connectivity, application management, and hardware abstraction. These services are pre-installed on Doover devices and start automatically on boot.

Service Overview

DDS consists of two categories of services: core services and bridge services.

Core Services

ServicePortDescription
Device Agent (DDA)50051Cloud connectivity and channel management
App Controller50052Application lifecycle and deployment management

Bridge Services

ServicePortDescription
platform_iface50053Hardware I/O abstraction
modbus_iface50054Modbus communication
camera_iface50050RTSP camera support

Management Services

ServiceDescription
Host ConfiguratorDevice configuration and system updates

Device Agent (DDA)

The Device Agent is the primary service for cloud connectivity. It maintains a persistent connection to the Doover cloud and handles all data synchronization.

Responsibilities

  • Cloud Connection - Establishes and maintains WebSocket connection to the Doover cloud
  • Channel Management - Manages subscriptions and publishes data to channels
  • Data Buffering - Queues data when offline and syncs when connection is restored
  • Authentication - Handles device authentication and token management
  • Configuration Sync - Receives deployment configurations from the cloud

Application Interaction

Your application interacts with DDA through the DeviceAgentInterface:

from pydoover.docker import Application, run_app
from pydoover.config import Schema

class MyApp(Application):
    def setup(self):
        # Check DDA status
        if self.device_agent.get_is_dda_available():
            print("DDA is running")

        if self.device_agent.get_is_dda_online():
            print("Connected to cloud")

        # Subscribe to channels
        self.device_agent.add_subscription(
            "deployment_config",
            self.on_config_update
        )

    async def on_config_update(self, channel_name, data):
        print(f"Config updated: {data}")

    def main_loop(self):
        # Publish telemetry
        self.device_agent.publish_to_channel("telemetry", {
            "temperature": self.platform_iface.get_system_temperature(),
            "voltage": self.platform_iface.get_system_voltage()
        })

if __name__ == "__main__":
    run_app(MyApp(config=Schema()))

Standard Channels

DDA manages several standard channels:

ChannelDirectionDescription
deployment_configCloud to DeviceApplication deployment configuration
tag_valuesBidirectionalShared tag values between applications
ui_stateBidirectionalUser interface state
cmdsCloud to DeviceCommands from the cloud

App Controller

The App Controller manages application lifecycle, including starting, stopping, and updating application containers.

Responsibilities

  • Container Management - Starts and stops application containers
  • Health Monitoring - Monitors application health and restarts failed containers
  • Deployment Scheduling - Schedules deployments based on cloud configuration
  • Resource Management - Manages container resources and limits

Deployment Scheduling

The App Controller supports scheduled deployments. Your application receives shutdown notifications and can request delays:

class SafeShutdownApp(Application):
    async def on_shutdown_at(self, shutdown_time):
        """Called when a shutdown is scheduled."""
        print(f"Shutdown scheduled for {shutdown_time}")
        # Prepare for shutdown
        await self.save_state()

    async def check_can_shutdown(self) -> bool:
        """Called to verify if shutdown can proceed."""
        # Return False to delay shutdown
        if self.is_critical_operation_running:
            return False
        return True

Platform Interface Bridge

The platform_iface bridge provides hardware abstraction for the device's built-in I/O.

Capabilities

  • Digital input reading with edge detection
  • Digital output control with scheduling
  • Analog input reading
  • Analog output control with scheduling
  • Pulse counting for flow meters and encoders
  • System metrics (voltage, power, temperature)
  • GPS location (on devices with 4G modems)

Container Configuration

The platform_iface container is configured based on the device type. Environment variables control which hardware drivers to load:

environment:
  - DEVICE_TYPE=doovit
  - PLT_IFACE_TYPE=platform_iface

Application Interaction

# Read all I/O
io_table = self.platform_iface.get_io_table()
print(f"Digital Inputs: {io_table.get('di')}")
print(f"Digital Outputs: {io_table.get('do')}")
print(f"Analog Inputs: {io_table.get('ai')}")
print(f"Analog Outputs: {io_table.get('ao')}")

# System monitoring
voltage = self.platform_iface.get_system_voltage()
temp = self.platform_iface.get_system_temperature()
power = self.platform_iface.get_system_power()

Modbus Interface Bridge

The modbus_iface bridge handles Modbus communication, supporting both RTU (serial) and TCP connections.

Capabilities

  • Modbus RTU over serial ports
  • Modbus TCP over Ethernet
  • Multiple simultaneous bus connections
  • Automatic reconnection
  • Polling subscriptions with callbacks

Container Configuration

environment:
  - MODBUS_DEFAULT_PORT=/dev/ttyAMA0
  - MODBUS_DEFAULT_BAUD=9600

Application Interaction

# Open a TCP bus to a Moxa slave
self.modbus_iface.open_bus(
    bus_type="tcp",
    name="remote_io",
    tcp_uri="192.168.1.10:502"
)

# Read registers
values = self.modbus_iface.read_registers(
    bus_id="remote_io",
    modbus_id=1,
    start_address=0,
    num_registers=10,
    register_type=3  # Input registers
)

Camera Interface Bridge

The camera_iface bridge manages RTSP camera connections for snapshot capture and streaming.

Capabilities

  • RTSP camera streaming
  • Snapshot capture
  • Dahua camera integration
  • Power management for PoE cameras

See Camera Interface for detailed documentation.

Host Configurator

The Host Configurator manages device-level configuration and system updates.

Responsibilities

  • Network Configuration - Manages network interfaces and connectivity
  • System Updates - Handles firmware and system package updates
  • Device Registration - Manages device identity and registration
  • Diagnostic Collection - Gathers system diagnostics for troubleshooting

Volume Mounts and Persistent Storage

DDS services use persistent storage for data that must survive container restarts.

Standard Paths

PathDescription
/var/lib/dds/Root directory for DDS persistent data
/var/lib/dds/dda/Device Agent data and queue storage
/var/lib/dds/config/Device configuration
/var/lib/dds/apps/Application data directories

Application Data

Applications can store persistent data in their designated directory:

import os

class MyApp(Application):
    def setup(self):
        # Get application data directory
        data_dir = os.environ.get("APP_DATA_DIR", "/var/lib/dds/apps/myapp")

        # Store persistent data
        self.state_file = os.path.join(data_dir, "state.json")

Service Dependencies

Services have dependencies that determine startup order:

Host Configurator (starts first)
    |
    +-- Device Agent (DDA)
    |       |
    |       +-- App Controller
    |               |
    |               +-- Application Containers
    |
    +-- Platform Interface
    +-- Modbus Interface
    +-- Camera Interface

Applications should handle cases where bridge services are not yet available:

def setup(self):
    # Wait for DDA to be available
    if not self.device_agent.await_dda_available(timeout=30):
        print("Warning: DDA not available, running in offline mode")

    # Test platform interface connection
    response = self.platform_iface.test_comms()
    if response is None:
        print("Warning: Platform interface not responding")

Monitoring and Troubleshooting

Checking Service Status

From a device shell:

# List running containers
docker ps

# Check DDA logs
docker logs dda

# Check platform interface logs
docker logs platform_iface

# Check application logs
docker logs my-app

Common Issues

DDA Not Connecting

  • Check network connectivity
  • Verify device registration
  • Check DDA logs for authentication errors

Platform Interface Not Responding

  • Verify the device type is correctly configured
  • Check for hardware driver issues
  • Review platform_iface container logs

Application Not Starting

  • Check App Controller logs
  • Verify container image is available
  • Check deployment configuration in the cloud

Next Steps