Skip to content

4.4 IoT DC3's Driver-Module Architecture and Driver SDK

4.4.1 IoT DC3 Platform Overview and Driver-Module Architecture

The preceding sections dissected protocol adapters and the driver framework in principle, but landing them in a maintainable engineering platform still requires solving a few practical problems: Drivers must be independently deployable and decoupled from business logic, and different members of a team must be able to develop protocol Drivers in parallel without interfering with one another. IoT DC3 separates the Driver layer into a set of independent microservice processes. In the 2026-08 code snapshot checked for this book, the repository contains 36 dc3-driver-* modules. That count includes field protocols, database/data-source adapters, and virtual test modules, so it is neither equivalent to "36 standard protocols" nor a fixed capability promise for future releases. The stable design assets are the unified Driver SDK and the independent deployment boundary.

Platform Overview: Frontend-Backend Separation and Microservices

IoT DC3 adopts a frontend-backend-separated microservice architecture. The frontend uses Vue.js to build the management console; the backend is split along business boundaries into centers such as Gateway, Auth, Manager, Data, and Agentic. The Gateway routes by fixed service names, its address can be overridden through environment variables, and it is resolved by DNS inside the Compose network — there is no Nacos registry. The driver layer is a set of independently running microservices, each of which can be packaged and deployed on its own; adding a protocol only requires adding a driver module that implements the Driver SDK SPI (Service Provider Interface) and completing business-metadata registration with the Manager over gRPC at startup.

Drivers and the platform use both gRPC and asynchronous messaging: gRPC handles Manager business registration and metadata queries, while the messaging port carries point commands, custom commands, execution receipts, point values, and status events. RabbitMQ is the current default broker, and the code also provides Kafka, RocketMQ, Pulsar, ActiveMQ, and MQTT 5 adapters. After replacement, acknowledgment, retry, ordering, and dead-letter semantics must be revalidated. A single Driver process failure should remain contained within the corresponding protocol module and consumption path.

What the Driver-Module Count Means and Covers

The number "36" is a module count in one code snapshot, not a ceiling on protocol count. Developers can add custom Drivers on the Driver SDK and connect them through the platform's registration and messaging contracts. Existing modules cover field protocols such as Modbus, selected PLC protocols, and OPC UA, but also non-field-protocol modules such as database inputs and virtual tests. NB-IoT is an access technology; terminals still connect through the MQTT, CoAP/LwM2M, or vendor protocol that it carries, and a module name does not prove that the platform automatically provides a cellular capability. Set against the protocol fragmentation discussed in Section 4.2, IoT DC3's strategy is not to "invent a new standard that wipes out fragmentation" but to absorb differences behind a unified Driver boundary.

The Driver Process Communication Model

The driver process maintains the connection channel to the physical devices while acting as a producer and consumer on the message queue. Consider an NB-IoT driver scenario: after startup, the driver connects to the operator network or an NB-IoT cloud platform and receives the readings reported by water-meter devices; the driver parses the raw bytes into structured data and sends it to the data service through the message queue. When a platform user issues an open-valve command, the command is wrapped into an MQ message and delivered to the driver process, which then repackages it in NB-IoT protocol format, fills in AT commands or a CoAP request, and sends it to the device.

A single driver process can manage hundreds or thousands of devices of the same type at once — internally, the driver maintains a device connection pool or session manager and routes messages by device ID. This architecture lets the driver layer focus only on protocol translation and device lifecycle management, without concerning itself with data storage, business alarms, or UI presentation. The message queue guarantees that cascading failures do not spread across layers.

The Complete Workflow for Adding a New Protocol Driver

From the developer's perspective, adding a driver breaks down into roughly four steps:

  1. Write the protocol implementation: construct requests and parse responses according to the target protocol, and return standardized results. This is the only part tied to the specific protocol, and its effort depends on the protocol's complexity.

  2. Declare the driver metadata: configure the driver name and the attribute model of the supported protocol (points, commands, events), so that the platform knows what it can connect to.

  3. Package, start up, and complete business registration: package the driver as an independent process, start it, and complete business-metadata registration with the platform. The registration here is the business registration that "lets the platform know this driver" — not registering an instance with a service registry.

  4. Bind devices: when creating a device in the platform console, select that driver type and fill in the device connection parameters (such as IP, port, and device address); the platform automatically associates the device with the driver instance, and the driver immediately starts periodic collection.

Of the first three steps, the time for step 1 depends on the target protocol's complexity, while steps 2–4 are configuration work. The whole workflow requires no changes to the platform's core code and involves no database schema changes. Teams can divide the work by protocol and develop in parallel — group A focusing on LoRa driver optimization, group B developing a proprietary communication protocol — with the unified driver SDK interfaces guaranteeing interoperability. (Specific SDK interface signatures appear in the hands-on project in Chapter 14.)

Independent deployment of the driver layer brings higher operational complexity — more processes, and higher monitoring and logging costs. In practice, for resource-constrained gateway devices, multiple lightweight drivers can be packaged into a single process, lowering resource overhead through thread isolation rather than process isolation. IoT DC3 supports this hybrid deployment model, and engineering teams need to weigh device scale, the resources of the deployment environment, and the frequency of protocol changes.

Figure 4-10 IoT DC3 Overall Architecture and the Driver LayerThe driver layer runs standalone JVM processes with the Driver SDK, decoupled from core services via MQ; new drivers are just one more box, and a failure does not stop the platform.Figure 4-10 IoT DC3 Overall Architecture and the Driver LayerThe driver layer runs standalone JVM processes with the Driver SDK, decoupled from core services via MQ; new drivers are just one more box, and a failure does not stop the platform.Platform DomainDevice & Edge DomainCommands (MQ)Data Reports (MQ)Frontend App LayerVue.js Admin ConsoleCore Services LayerFixed Service Names + Container DNS + Env VarsGatewayAuthManagerDataAgenticDriver LayerStandalone JVM Process + Driver SDKModbus DriverLoRa DriverNB-IoT DriverBLE DriverZigbee DriverPLC S7 DriverMC Protocol DriverModbus TCPLoRaWANNB-IoTBLE GATTS7 TCPZigbeeMC ProtocolPhysical Device LayerPLCSensorsWater MeterActuatorIndustrial MeterSolid arrows: data flow (uplink/downlink)Dashed arrows: asynchronous decoupled communication via message queueThe yellow layer is the driver layer — the focus of the figureFigure 4-10 IoT DC3 overall architecture and the driver layer position. Driver processes are independent of each other, decoupled from core platform services via the message queue, so a driver failure does not interrupt the platform. Adding a driver only requires one more box in the driver layer; no other layer changes.
Figure 4-10 IoT DC3 Overall Architecture and the Driver Layer

4.4.2 Key Design Points of the Driver SDK

The Driver SDK's goal is to separate protocol implementation from the platform's shared capabilities. IoT DC3 does not provide a unified base-class skeleton; it adopts a compositional SPI instead: a protocol driver implements fine-grained interfaces as needed — connection lifecycle, read/write, health check, command, validation — implementing whichever interfaces its capabilities require rather than being forced to inherit an abstract class that contains every method. This is a trade-off worth borrowing: a unified base-class abstraction forces a driver to carry methods it never uses, while composing fine-grained interfaces lets each protocol take only what it needs.

The platform runtime invokes the protocol implementation through three service contracts: read (resolve the device and point configuration from the metadata cache, delegate the read to the protocol, and report the values), write (validate the device–point relationship, delegate the write to the protocol, and return the device's confirmation), and command (execute a custom command and return a receipt). At startup, the driver completes business registration and protocol initialization; at run time it sends and receives commands, receipts, and status events over the message queue. The business registration here serves to give the platform the driver and its attribute model — it is not registering an instance with a service registry such as Nacos or Eureka.

When developing a protocol driver, concentrate effort on three boundaries: first, the connection and reconnection strategy belongs to the individual driver — do not assume the SDK provides a unified connection manager; second, sticky packets, frame boundaries, byte order, and checksums should be tested inside the protocol implementation; third, exceptions must be expressed through domain exceptions and result receipts — never swallow them and let a message be falsely acknowledged. This reuses the SDK's metadata, command, and message contracts while preserving the implementation freedom that different protocols need. (Specific interface signatures and source code appear in the hands-on project in Chapter 14.)

4.4.3 Engineering Boundaries of Loading, Addressing, and Command Routing

Once drivers are deployed independently, the platform needs to know which protocol a driver supports, whether it is currently online, and to which queue its commands should be delivered. IoT DC3's answer: business-metadata registration, status events, and command queues bound by driver identifier — explicitly without relying on a service registry such as Nacos or Eureka. This is a conceptual boundary worth emphasizing: business registration gives the platform the driver and its attribute model, whereas the service registry handles instance discovery and load balancing — the two must not be conflated. Drivers are addressed by fixed service names (overridable through environment variables) and resolved by DNS in the container network, so the configuration boundary is clear.

When the same protocol needs multiple instances, the service names, client identifiers, device bindings, and queue-consumption relationships must be planned explicitly; round-robin load balancing from a registry cannot be applied by default. Driver upgrades follow container orchestration and message semantics: the new instance passes its health check, completes business registration, and starts consuming before the old instance is stopped; commands carry idempotency identifiers for deduplication, avoiding duplicate execution during the switchover.

The core of driver loading and management is not "registry hot-plugging" but four verifiable contracts: business registration succeeds at startup, status messages are observable at run time, command-queue routing is explicit, and commands are idempotent during upgrades. Only when these four points hold can independent drivers scale safely without modifying the center services. (If dynamic cross-cluster instance discovery is genuinely required, a service registry can be evaluated separately — but that is a general architecture option and must not be written back as DC3's current implementation.)

From Industrial Software to AI Agents · Building a multi-protocol, cloud-native, open-source industrial IoT platform ready to evolve toward AI agents