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:
- Start a simulator
- Run the integration service
- Assert that readings are correctly parsed, normalized, and stored
- 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.