Supported Hardware
The Doover platform supports multiple hardware platforms, from industrial-grade devices to development boards. This page documents the supported devices and their capabilities.
Primary Devices
Primary devices are the main compute units that run your pydoover applications. They host the Docker containers for your application and the device bridges.
Doovit
The Doovit is the primary Doover edge computing device. It provides a complete industrial IoT solution with built-in I/O, cellular connectivity, and GPS.
| Capability | Support |
|---|---|
| Digital Inputs | Yes |
| Digital Outputs | Yes |
| Analog Inputs | Yes |
| Analog Outputs | Yes |
| System Voltage Monitoring | Yes |
| System Temperature | Yes |
| GPS Location | Yes (with 4G modem) |
| Pulse Counting | Yes |
IGT Series
The IGT series are industrial gateway devices with varying I/O capabilities.
IGT34 - The most advanced IGT model with full I/O support.
| Capability | Support |
|---|---|
| Digital Inputs | Yes |
| Digital Outputs | Yes |
| Analog Inputs | Yes |
| Analog Outputs | Yes |
IGT33 - Mid-range industrial gateway.
| Capability | Support |
|---|---|
| Digital Inputs | Yes |
| Digital Outputs | Yes |
| Analog Inputs | Yes |
| Analog Outputs | Yes |
IGT22 - Entry-level industrial gateway.
| Capability | Support |
|---|---|
| Digital Inputs | Yes |
| Digital Outputs | Yes |
| Analog Inputs | Yes |
| Analog Outputs | No |
Raspberry Pi 4
The Raspberry Pi 4 is supported for development and light industrial applications. I/O is provided through GPIO pins and requires appropriate HATs for industrial use.
| Capability | Support |
|---|---|
| Digital Inputs | GPIO (with appropriate HAT) |
| Digital Outputs | GPIO (with appropriate HAT) |
| Analog Inputs | No (requires ADC HAT) |
| Analog Outputs | No (requires DAC HAT) |
Capabilities Matrix
| Platform | DI | DO | AI | AO | System Metrics | Notes |
|---|---|---|---|---|---|---|
| Doovit | Yes | Yes | Yes | Yes | Yes | Primary Doover device |
| IGT34 | Yes | Yes | Yes | Yes | Limited | Most advanced IGT |
| IGT33 | Yes | Yes | Yes | Yes | Limited | Mid-range IGT |
| IGT22 | Yes | Yes | Yes | No | Limited | Entry-level IGT |
| RPi4 | GPIO | GPIO | No | No | CPU Temp | Requires HATs for industrial I/O |
Slave Devices via Modbus
The Doover platform supports distributed I/O through Modbus slave devices. These devices connect to a primary device via Modbus RTU (serial) or Modbus TCP and provide additional I/O points.
Moxa ioLogik E1200 Series
Moxa ioLogik devices are industrial Ethernet remote I/O modules that connect via Modbus TCP.
Moxa 1212 - Mixed digital I/O module.
| I/O Type | Count |
|---|---|
| Digital I/O | 12 (configurable as input or output) |
| Connection | Modbus TCP |
Moxa 1241 - Digital input and output module.
| I/O Type | Count |
|---|---|
| Digital Inputs | 12 |
| Digital Outputs | 8 |
| Connection | Modbus TCP |
Moxa 1242 - Extended digital I/O module.
| I/O Type | Count |
|---|---|
| Digital Inputs | 12 |
| Digital Outputs | 12 |
| Connection | Modbus TCP |
Master-Slave Architecture
The Doover platform uses a master-slave architecture for distributed I/O:
Primary Device (Master)
|
+-- Local I/O (platform_iface)
|
+-- Modbus Bus (modbus_iface)
|
+-- Slave 1: Moxa 1242 @ 192.168.1.10:502
+-- Slave 2: Moxa 1241 @ 192.168.1.11:502
+-- Slave 3: RTU Device @ /dev/ttyUSB0, ID 1
Your application accesses slave I/O through the ModbusInterface:
# Configure slaves in your application config
class MyConfig(Schema):
def __init__(self):
self.modbus_config = ModbusConfig("Modbus")
self.modbus_config.type.default = "tcp"
self.modbus_config.name.default = "io_bus"
self.modbus_config.tcp_uri.default = "192.168.1.10:502"
# Read from a Moxa slave
class MyApp(Application):
def main_loop(self):
# Read digital inputs from Moxa 1242
di_values = self.modbus_iface.read_registers(
bus_id="io_bus",
modbus_id=1,
start_address=0,
num_registers=12,
register_type=2 # Discrete inputs
)
# Write digital outputs
self.modbus_iface.write_registers(
bus_id="io_bus",
modbus_id=1,
start_address=0,
values=[1, 0, 1, 1], # Set outputs 0-3
register_type=1 # Coils
)
Hardware Selection Guidance
When selecting hardware for your project, consider these factors:
For Industrial Deployments
- Doovit - Best choice for new deployments requiring full I/O, cellular, and GPS
- IGT34/33 - Good choice when you need robust industrial I/O without cellular
- IGT22 - Budget option when analog outputs are not required
For Development and Prototyping
- Raspberry Pi 4 - Good for development and testing
- Doovit - Recommended if you need to test with real hardware I/O
For Distributed I/O
- Moxa 1242 - When you need many digital I/O points in a remote location
- Moxa 1241 - When you need more outputs than inputs
- Moxa 1212 - When I/O requirements are flexible
For High-Reliability Applications
- Doovit or IGT Series - Industrial-grade devices with appropriate certifications
- Add Moxa slaves - For redundant I/O paths or geographically distributed I/O
Configuration Example
Here is an example configuration for a Doovit master with two Moxa slaves:
from pydoover.docker import Application, run_app, ManyModbusConfig
from pydoover.config import Schema
class DistributedIOConfig(Schema):
def __init__(self):
# Configure multiple Modbus buses for slave devices
self.modbus_config = ManyModbusConfig("Modbus Buses")
class DistributedIOApp(Application):
config: DistributedIOConfig
def setup(self):
# Open connection to first Moxa slave
self.modbus_iface.open_bus(
bus_type="tcp",
name="moxa_1",
tcp_uri="192.168.1.10:502"
)
# Open connection to second Moxa slave
self.modbus_iface.open_bus(
bus_type="tcp",
name="moxa_2",
tcp_uri="192.168.1.11:502"
)
def main_loop(self):
# Read from local Doovit I/O
local_di = self.platform_iface.get_di(0)
# Read from first Moxa slave
remote_di_1 = self.modbus_iface.read_registers(
bus_id="moxa_1",
modbus_id=1,
start_address=0,
num_registers=1,
register_type=2
)
# Read from second Moxa slave
remote_di_2 = self.modbus_iface.read_registers(
bus_id="moxa_2",
modbus_id=1,
start_address=0,
num_registers=1,
register_type=2
)
# Use combined I/O data
print(f"Local: {local_di}, Remote 1: {remote_di_1}, Remote 2: {remote_di_2}")
if __name__ == "__main__":
run_app(DistributedIOApp(config=DistributedIOConfig()))
Next Steps
- Device Services - Core Doover services
- Device Bridges Overview - Bridge architecture
- PlatformInterface - Local I/O API
- ModbusInterface - Modbus communication API