Skip to content

Device Bridges Architecture

Device bridges are containerized microservices that provide hardware abstraction for the Doover platform. They enable pydoover applications to interact with hardware through consistent APIs, regardless of the underlying device type.

What Are Device Bridges

Device bridges are Docker containers that run alongside your pydoover applications on Doover devices. Each bridge exposes a gRPC service that handles a specific aspect of hardware interaction:

  • platform_iface - Provides access to digital and analog I/O on the device
  • modbus_iface - Handles Modbus RTU and TCP communication
  • camera_iface - Manages RTSP camera streaming and snapshots

The bridges abstract away hardware-specific details, allowing your application code to work across different hardware platforms without modification.

Why Device Bridges Exist

The bridge architecture serves several important purposes:

Separation of Concerns - Hardware-specific driver code is isolated from application logic. Your application interacts with clean APIs rather than dealing with hardware registers, GPIO libraries, or serial protocols directly.

Hardware Portability - The same application code can run on different hardware platforms (Doovit, IGT34, Raspberry Pi) because the bridges present a consistent interface regardless of the underlying hardware.

Independent Updates - Hardware drivers and application code can be updated separately. A fix to a platform driver does not require rebuilding your application.

Simplified Development - Developers can focus on application logic without needing deep knowledge of hardware interfaces. The bridges handle timing, error recovery, and hardware-specific quirks.

Bridge Services and Ports

Each bridge service runs in its own container and listens on a designated gRPC port:

ServicePortDescription
platform_iface50053Digital/analog I/O, system monitoring, pulse counting
modbus_iface50054Modbus RTU (serial) and TCP communication
camera_iface50050RTSP camera streaming and snapshot capture

Doover Device Services

In addition to the hardware bridges, two core services manage the device:

ServicePortDescription
Device Agent (DDA)50051Cloud connectivity, channel subscriptions, data sync
App Controller50052Application lifecycle management, deployment scheduling

These services are part of Doover Device Services (DDS) and run automatically on all Doover devices. See Device Services for details.

How Applications Interact with Bridges

Your pydoover application communicates with bridges through gRPC interfaces provided by the pydoover library:

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

class MyApp(Application):
    def main_loop(self):
        # Read digital input via platform_iface (port 50053)
        button_pressed = self.platform_iface.get_di(0)

        # Control digital output via platform_iface
        self.platform_iface.set_do(0, button_pressed)

        # Read Modbus register via modbus_iface (port 50054)
        temperature = self.modbus_iface.read_registers(
            bus_id="sensor_bus",
            modbus_id=1,
            start_address=0,
            num_registers=1,
            register_type=3
        )

        # Publish data via DDA (port 50051)
        self.device_agent.publish_to_channel("telemetry", {
            "button": button_pressed,
            "temperature": temperature
        })

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

The Application class automatically initializes connections to all bridges. The interface URIs default to localhost with the standard ports, but can be configured through environment variables or command-line arguments.

Communication Flow

When your application calls a bridge method:

  1. The pydoover interface serializes the request as a gRPC message
  2. The message is sent to the bridge container over the local network
  3. The bridge translates the request to hardware-specific operations
  4. Results are returned through the gRPC response
  5. The pydoover interface deserializes the response for your application

This happens transparently. From your application's perspective, you are simply calling Python methods.

Container Network

All services communicate over a Docker bridge network. Each container can reach others by their service name or localhost when running on the same device:

Application Container
    |
    +-- localhost:50051 --> Device Agent (DDA)
    +-- localhost:50052 --> App Controller
    +-- localhost:50053 --> Platform Interface
    +-- localhost:50054 --> Modbus Interface
    +-- localhost:50050 --> Camera Interface

Configuration

Bridge services are configured through environment variables and volume mounts. The host_configurator service manages device-level configuration and updates. See Device Services for configuration details.

Next Steps