The Integration Gap

Factory floors run on PLCs, RFID readers, sensors, and industrial protocols. Business applications run on .NET, SQL Server, and REST APIs. Bridging these two worlds is not a standard software engineering problem — it requires understanding both the industrial and the enterprise domains.

Common Industrial Devices and Protocols

RFID Readers (Zebra, Motorola, Impinj)

RFID readers connect via:

  • LLRP (Low-Level Reader Protocol): Binary protocol over TCP. Low latency, complex.
  • REST APIs: Newer readers expose HTTP endpoints for tag reads.
  • Proprietary SDKs: Usually .NET-compatible, but often .NET Framework only.

A typical integration pattern:

RFID Reader → LLRP Client (C#) → Message Queue (RabbitMQ) → Business Logic → SQL Server

The LLRP client reads tag events, normalizes them into business objects, and publishes them for downstream processing.

PLC (Programmable Logic Controllers)

Common PLC brands: Siemens, Allen-Bradley, Schneider Electric, Mitsubishi.

Communication options:

  • Modbus TCP: Simple, widely supported. Read/write coils and registers.
  • OPC UA: Modern, secure, structured data model.
  • Vendor-specific protocols: Siemens S7, Allen-Bradley EtherNet/IP.

For .NET, NModbus4 and OPC UA .NET Standard are reliable open-source libraries.

Modbus Integration Example

using (var client = new ModbusTcpClient("192.168.1.100", 502))
{
    client.Connect();
    // Read 10 holding registers starting at address 0
    ushort[] registers = client.ReadHoldingRegisters(1, 0, 10);
    var temperature = registers[0] / 10.0; // Scale factor depends on device
}

OPC UA Integration Pattern

OPC UA is the recommended protocol for new industrial integrations. It supports:

  • Structured data model (not just raw registers)
  • Security (authentication, encryption, auditing)
  • Publish/subscribe pattern
  • Historical data access

Architecture Patterns

Pattern 1: Direct Connection (Simple, Low Volume)

.NET Worker Service → Modbus/OPC → Device

Best for: Single device, low data volume, non-critical.

Pattern 2: Gateway + Queue (Production Grade)

Device → Gateway Service → RabbitMQ/Redis → Worker Service → Database

Best for: Multiple devices, high throughput, decoupled processing.

The gateway isolates protocol specifics. Downstream services work with normalized business events.

Pattern 3: Edge + Cloud (SCADA-Style Telemetry)

Device → Edge Gateway (on-prem) → Message Queue → Cloud Processing → Dashboard

Best for: Remote monitoring, multi-site, historical analytics.

Data Normalization

Industrial data is messy:

  • Unit conversions: Raw register values need scaling (e.g., 0-4095 → 0-10V → 0-100 degrees C).
  • Timestamp alignment: Devices may have different clocks or no clocks at all.
  • Data quality flags: Values may be stale, out-of-range, or unreliable.
  • Bit-packed data: Modbus registers often pack multiple boolean values into one 16-bit word.

Always add metadata to every reading:

public class TelemetryPoint
{
    public string DeviceId { get; set; }
    public string PointId { get; set; }
    public double Value { get; set; }
    public string Unit { get; set; }
    public DateTime Timestamp { get; set; }
    public DataQuality Quality { get; set; }
}

Error Handling and Resilience

Industrial networks are unreliable. Devices go offline, cables get disconnected, power cycles happen.

Retry with Polly

var retryPolicy = Policy
    .Handle<IOException>()
    .Or<TimeoutException>()
    .WaitAndRetryAsync(
        3,
        retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
        onRetry: (exception, timeSpan, retryCount, context) =>
        {
            logger.Warning("Retry {RetryCount} after {Delay}ms: {Message}",
                retryCount, timeSpan.TotalMilliseconds, exception.Message);
        });

Circuit Breaker

If a device is consistently unreachable, stop trying and alert operations. Use a circuit breaker pattern to avoid flooding logs and network traffic.

Dead Letter Queue

Failed readings go to a dead letter queue for manual inspection. Some data (safety-critical) cannot be silently dropped.

Database Design for Telemetry

Time-Series Considerations

  • Partition tables by time (month or week)
  • Use clustered columnstore indexes for large telemetry tables
  • Consider sliding window partitioning for data retention
  • Archive old data to cheaper storage

Example Schema

CREATE TABLE TelemetryReadings (
    Id BIGINT IDENTITY,
    DeviceId VARCHAR(50) NOT NULL,
    PointId VARCHAR(100) NOT NULL,
    Value FLOAT NOT NULL,
    Timestamp DATETIME2(3) NOT NULL,
    Quality TINYINT NOT NULL DEFAULT 0,
    CONSTRAINT PK_TelemetryReadings PRIMARY KEY CLUSTERED (Timestamp, Id)
) ON PS_Telemetry_Monthly(Timestamp);

Testing Industrial Integrations

Simulators

Use device simulators for development and testing:

  • Modbus Slave simulators (free tools available)
  • OPC UA server simulators
  • RFID tag simulators (generate synthetic tag reads)

Integration Tests

Write integration tests that:

  1. Start a simulator
  2. Run the integration service
  3. Assert that readings are correctly parsed, normalized, and stored
  4. Test error scenarios (disconnect simulator, send invalid data, timeout)

Summary

Industrial integration is not just about reading data from a device. It requires:

  • Understanding the physical device and its protocol
  • Normalizing data into business-meaningful objects
  • Handling unreliable networks gracefully
  • Designing database schemas for time-series data
  • Testing with simulators before touching real hardware

The skills overlap between industrial engineering and enterprise software development is rare and valuable. Developers who can bridge this gap are critical for any organization running physical operations.