14 IoT and industrial communication libraries for Delphi — messaging, serialization,
discovery, telemetry, hardware protocols, and transport.
Each library is self-contained, has no external dependencies beyond Indy,
and ships with a console test suite that passes with no external infrastructure.
694 tests total, all passing.
| # | Library | Path | Tests | Category |
|---|---|---|---|---|
| 0 | MQTT | mqtt/ |
broker + client | Messaging |
| 1 | Modbus TCP/RTU | modbus/ |
63 | Hardware |
| 2 | CoAP | coap/ |
26 | Messaging |
| 3 | Serial / COM framing | serial/ |
25 | Transport |
| 4 | NMEA 0183 | nmea/ |
38 | Hardware |
| 5 | InfluxDB | influxdb/ |
33 | Telemetry |
| 6 | STOMP | stomp/ |
30 | Messaging |
| 7 | WebSocket | websocket/ |
27 | Transport |
| 8 | CBOR | cbor/ |
70 | Serialization |
| 9 | Prometheus | prometheus/ |
48 | Telemetry |
| 10 | JSON Helper | json/ |
62 | Serialization |
| 11 | MessagePack | msgpack/ |
97 | Serialization |
| 12 | mDNS / DNS-SD | mdns/ |
79 | Discovery |
| 13 | AMQP 1.0 | amqp/ |
96 | Messaging |
- Delphi 12 Athens (Studio 23.0) — Win32 / Win64 / Linux64 / Android
- Indy 10 — bundled with Delphi; used for TCP/UDP/UDP-multicast in MQTT, CoAP, Modbus TCP, STOMP, AMQP, WebSocket, InfluxDB, Prometheus, mDNS
- ESP32 (optional) — hardware target for Modbus RTU and CoAP integration tests
Full MQTT 3.1.1 broker and client, including a VCL/FMX component package.
Files
| File | Description |
|---|---|
MQTT.Types.pas |
Protocol types, packet constants |
MQTT.Packets.pas |
Frame encode / decode |
MQTT.Broker.pas |
In-process broker (QoS 0/1/2, retained, LWT, sessions) |
MQTT.Client.pas |
TCP client with reconnect and offline queue |
MQTT.SessionStore.pas |
Persistent session state |
MQTT.TopicTree.pas |
Wildcard topic matching (+, #) |
MQTT.TLS.pas |
TaurusTLS wrapper for TLS 1.2/1.3 |
MQTT.Components.pas |
VCL/FMX design-time components |
Projects
| Project | Description |
|---|---|
MQTTDemoFMX.dpr |
Full GUI demo (broker + client, FMX) |
MQTTDemo.dpr |
VCL demo |
MQTTClientConsole.dpr |
Headless client |
MQTTBrokerConsole.dpr |
Headless broker |
MQTTClientAndroid.dpr |
Android client (Bluetooth via BluePort) |
Feature highlights
- QoS 0, 1 and 2 with full handshake and duplicate detection
- Persistent sessions, offline message queue
NoLocal,RetainAsPublished,RetainHandlingflags- LWT (Last Will and Testament)
- TLS via TaurusTLS (optional)
- Broker and client in the same process for unit testing
Modbus TCP master/slave and Modbus RTU master, tested against a real ESP32.
Files
| File | Description |
|---|---|
Modbus.Types.pas |
Function codes, exception codes, data types |
Modbus.Codec.pas |
ADU/PDU encode-decode, CRC-16 |
Modbus.TCP.Master.pas |
TCP master (FC 01-06, 15-16) |
Modbus.TCP.Slave.pas |
TCP slave (register/coil callbacks) |
Modbus.RTU.Master.pas |
RTU master over serial / ISerialPort |
Projects
| Project | Description |
|---|---|
ModbusDemo.dpr |
25 TCP loopback tests (master ↔ slave in-process) |
ModbusRTUTest.dpr |
38 RTU tests against ESP32 sketch |
Supported function codes: FC01 ReadCoils, FC02 ReadDiscreteInputs, FC03 ReadHoldingRegisters, FC04 ReadInputRegisters, FC05 WriteSingleCoil, FC06 WriteSingleRegister, FC15 WriteMultipleCoils, FC16 WriteMultipleRegisters.
CoAP (RFC 7252) client and server over UDP, with an ESP32 integration sketch.
Files
| File | Description |
|---|---|
CoAP.Types.pas |
Message types, option numbers, response codes |
CoAP.Codec.pas |
Frame encode / decode |
CoAP.Client.pas |
UDP client (CON/NON, retransmission, token matching) |
CoAP.Server.pas |
UDP server (resource handler callbacks) |
Project: CoAPDemo.dpr — 26 loopback tests (client ↔ server in-process via TIdUDPServer).
Features: Confirmable (CON) and Non-confirmable (NON) messages, option encoding (Uri-Path, Content-Format, ETag, ...), piggy-backed and separate responses.
Cross-platform serial port abstraction with four framing modes.
Files
| File | Description |
|---|---|
Serial.Types.pas |
ISerialPort interface, framing mode enum |
Serial.Port.pas |
Windows COM implementation of ISerialPort |
Serial.Framer.pas |
TSerialFramer — frame detection over any ISerialPort |
Project: SerialDemo.dpr — 25 tests covering all four framing modes
using an in-process loopback.
Framing modes
| Mode | Description |
|---|---|
fmDelimiter |
Frames end with a configurable byte sequence |
fmFixedLength |
Every frame is exactly N bytes |
fmLengthPrefix |
Frame length carried in a 1/2/4-byte header |
fmTimeout |
Silence gap (inter-byte timeout) terminates a frame |
TSerialFramer depends only on ISerialPort, so it works on Windows COM ports,
Android Bluetooth (BluePort) or any byte-stream transport.
NMEA 0183 sentence parser for GPS receivers.
Files
| File | Description |
|---|---|
NMEA.Types.pas |
Record types for each sentence, status/fix enums |
NMEA.Parser.pas |
TNMEAParser with FeedBytes streaming API |
Project: NMEADemo.dpr — 38 tests.
Supported sentences: $xxRMC, $xxGGA, $xxGLL, $xxVTG
Talker prefixes: GP, GN, GL, GA (multi-constellation receivers)
Features: XOR checksum verification, coordinate conversion (DDMM.MMMMM → decimal degrees),
streaming FeedBytes(TBytes) API suitable for serial or UDP input.
InfluxDB line protocol builder and HTTP write client, compatible with v1 and v2.
Files
| File | Description |
|---|---|
InfluxDB.LineProtocol.pas |
TInfluxPoint (fluent) + TInfluxBatch |
InfluxDB.Client.pas |
TInfluxDBClient — HTTP write via TIdHTTP |
Project: InfluxDBDemo.dpr — 33 tests (no server required).
Usage
// Build a data point P := TInfluxPoint.Create('cpu') .Tag('host', 'server01') .FieldFloat('usage', 0.75) .FieldInt('cores', 4) .TimestampNow(ipSeconds); Writeln(P.Build); // → cpu,host=server01 usage=0.75,cores=4i 1716825600 // Write to InfluxDB 2.x C := TInfluxDBClient.CreateV2('localhost', 8086, 'myorg', 'mybucket', 'mytoken'); C.Write(P); C.Free;
Field types: float (no suffix), integer (i suffix), boolean (true/false),
string (double-quoted). Tags sorted alphabetically for InfluxDB series-key locality.
STOMP 1.1/1.2 client for RabbitMQ, ActiveMQ and any STOMP-compatible broker.
Files
| File | Description |
|---|---|
STOMP.Types.pas |
TSTOMPFrame — wire codec (Encode / TryDecode) |
STOMP.Client.pas |
TSTOMPClient — full client with background reader thread |
Project: STOMPDemo.dpr — 30 tests using an in-process mock broker (TIdTCPServer).
Usage
Client := TSTOMPClient.Create; Client.Connect('localhost', 61613, '/', 'guest', 'guest'); SubId := Client.Subscribe('/queue/sensor', procedure(const ADest, AMsgId: string; const ABody: TBytes; AFrame: TSTOMPFrame) begin Writeln(TEncoding.UTF8.GetString(ABody)); end); Client.SendText('/queue/sensor', '{"temp":23.5}'); // ... Client.Disconnect; Client.Free;
Features: Connect/Disconnect, Subscribe/Unsubscribe, Send/SendText,
Ack/Nack (for client / client-individual ack modes), binary body support
via content-length, heartbeat handling, thread-safe callbacks.
RFC 6455 WebSocket client over TCP (Indy), with an in-process echo-server test suite.
Files
| File | Description |
|---|---|
WebSocket.Types.pas |
Frame codec (ReadWSFrame / WriteWSFrame), WSComputeAccept |
WebSocket.Client.pas |
TWebSocketClient with background reader thread |
Project: WebSocketDemo.dpr — 27 tests (14 codec + 13 echo-server loopback).
Features: Full RFC 6455 frame codec (all three payload-length ranges, masking, FIN bit),
HTTP/1.1 Upgrade handshake with Sec-WebSocket-Accept verification, fragmented message
reassembly, Ping/Pong auto-response, clean Close handshake.
CBOR (RFC 7049 / RFC 8949) binary codec — used as payload format in CoAP and other IoT protocols.
Files
| File | Description |
|---|---|
CBOR.Types.pas |
TCBORValue + full encode/decode (all major types, Float16/32/64, tags, nested) |
Project: CBORDemo.dpr — 70 tests (28 encode RFC vectors + 21 decode + 10 roundtrip + 11 nested).
Usage
// Encode var B := CBOREncodeText('hello'); // 65 68 65 6c 6c 6f B := CBOREncodeUInt(1000); // 19 03 e8 B := CBOREncodeArray([CBOREncodeUInt(1), CBOREncodeUInt(2), CBOREncodeUInt(3)]); // → 83 01 02 03 // Decode var Offset := 0; var V := CBORDecode(B, Offset); // V.Kind = ckArray, V.ItemCount = 3, V.ArrayItems[0].UIntVal = 1 V.Free;
Supported major types: UInt (0), NInt (1), Bytes (2), Text (3), Array (4), Map (5), Tag (6), Float16/32/64 / Bool / Null / Undefined (7).
In-process Prometheus exposition endpoint — Counter, Gauge, Histogram + HTTP /metrics server.
Files
| File | Description |
|---|---|
Prometheus.Types.pas |
TLabelSet, TPrometheusCounter, TPrometheusGauge, TPrometheusHistogram, TPrometheusRegistry |
Prometheus.Exporter.pas |
TPrometheusExporter — TIdHTTPServer serving /metrics |
Project: PrometheusDemo.dpr — 48 tests (11 counter + 10 gauge + 14 histogram + 6 registry + 7 exporter).
Usage
// Create registry and metrics (registry owns the metrics) Reg := TPrometheusRegistry.Create; Reg.Register(TPrometheusCounter.Create('http_requests_total', 'HTTP requests')); Reg.Register(TPrometheusGauge.Create('temperature_celsius', 'Current temperature')); Reg.Register(TPrometheusHistogram.Create('req_latency_seconds', 'Latency', TPrometheusHistogram.DefaultBuckets)); // Instrument (Reg.Metric(0) as TPrometheusCounter).IncBy(Default(TLabelSet).Add('method','GET')); (Reg.Metric(1) as TPrometheusGauge).SetTo(23.5); (Reg.Metric(2) as TPrometheusHistogram).Observe(0.042); // Expose via HTTP Exp := TPrometheusExporter.Create(Reg); Exp.Start(9090); // curl http://localhost:9090/metrics
Metric types: Counter (monotone IncBy), Gauge (SetTo / IncBy / DecBy), Histogram (Observe,
LinearBuckets / ExponentialBuckets / DefaultBuckets, cumulative _bucket + _sum + _count).
Labels: fluent TLabelSet.Add(name, value) record; thread-safe (TCriticalSection per metric).
Fluent JSON builder and navigator wrapping Delphi's built-in System.JSON — no extra dependencies.
Files
| File | Description |
|---|---|
JSON.Helper.pas |
TJSONNav navigator, TJSONDoc owned document, TJSONBuilder fluent builder |
Project: JSONHelperDemo.dpr — 62 tests (25 nav + 9 doc + 17 builder + 11 roundtrip).
Usage
// Parse and navigate Doc := TJSONDoc.Create('{"device":"esp32","temp":23.5,"readings":[10,20,30]}'); Writeln(Doc.Root.Get('device').AsString); // esp32 Writeln(Doc.Root.Get('temp').AsFloat:0:1); // 23.5 Writeln(Doc.Root.Get('readings').Get(1).AsInt); // 20 Doc.Free; // Fluent build B := TJSONBuilder.Create; S := B.BeginObj .Key('device').Str('esp32') .Key('temp').Num(23.5) .Key('readings').BeginArr.Num(Int64(10)).Num(Int64(20)).EndArr .EndObj .Build; B.Free; // S = {"device":"esp32","temp":23.5,"readings":[10,20]}
TJSONNav — record wrapping TJSONValue (no ownership):
Get(key) / Get(index), AsString / AsFloat / AsInt / AsInt64 / AsBool,
IsValid / IsNull / IsObject / IsArray, Count, Keys, ToJSON.
MessagePack binary serialization codec — compact binary JSON replacement used in IoT, Redis, and MCU protocols.
Files
| File | Description |
|---|---|
MsgPack.Types.pas |
TMsgPackValue tree + full encode/decode (all format families, big-endian I/O) |
Project: MsgPackDemo.dpr — 97 tests (42 encode vectors + 25 decode + 14 roundtrip + 16 nested).
Usage
// Encode primitives var B := MPEncodeNil; // c0 B := MPEncodeBool(True); // c3 B := MPEncodeInt(-500); // d1 fe 0c B := MPEncodeStr('hello'); // a5 68 65 6c 6c 6f B := MPEncodeFloat64(3.14); // cb ... // Encode array [1, 2, 3] B := MPEncodeArray([MPEncodeUInt(1), MPEncodeUInt(2), MPEncodeUInt(3)]); // → 93 01 02 03 // Encode map {"id": 42} B := MPEncodeMap([MPEncodeStr('id'), MPEncodeUInt(42)]); // → 81 a2 69 64 2a // Decode var Offset := 0; var V := MPDecode(B, Offset); // V.Kind = mkMap, V.Keys[0].StrVal = 'id', V.Values[0].UIntVal = 42 V.Free; // High-level via TMsgPackValue tree var Root := TMsgPackValue.Create; Root.Kind := mkMap; Root.Keys := TObjectList<TMsgPackValue>.Create(True); Root.Values := TObjectList<TMsgPackValue>.Create(True); var K := TMsgPackValue.Create; K.Kind := mkStr; K.StrVal := 'temp'; Root.Keys.Add(K); var Vl := TMsgPackValue.Create; Vl.Kind := mkFloat64; Vl.F64Val := 23.5; Root.Values.Add(Vl); B := MPEncode(Root); Root.Free;
Supported format families: positive fixint (0-127), negative fixint (-32..-1), nil, bool, uint8/16/32/64, int8/16/32/64, float32/64, fixstr/str8/16/32, bin8/16/32, fixarray/array16/32, fixmap/map16/32, fixext1/2/4/8/16 + ext8/16/32.
mDNS (RFC 6762) + DNS-SD (RFC 6763) — zero-configuration service discovery on the local network.
Devices advertise services like _mqtt._tcp.local without a central DNS server.
Files
| File | Description |
|---|---|
mDNS.Types.pas |
DNS wire codec (name labels + compression, A/PTR/SRV/TXT records, messages), BuildBrowseQuery, BuildAnnounce, ParseServiceFromMsg |
mDNS.Client.pas |
TmDNSResponder (advertise), TmDNSBrowser (discover) via TIdUDPServer |
Project: mDNSDemo.dpr — 79 tests (15 name codec + 14 record codec + 15 message codec + 29 DNS-SD helpers + 6 functional loopback).
Usage
// Advertise a service var Svc: TServiceInfo; Svc.InstanceName := 'My Broker'; Svc.ServiceType := '_mqtt._tcp'; Svc.Domain := 'local'; Svc.HostName := 'broker.local'; Svc.Port := 1883; Svc.TXTEntries := TArray<string>.Create('version=3.1.1'); Svc.IPv4 := '192.168.1.10'; var R := TmDNSResponder.Create(Svc); R.Start; // listens on 224.0.0.251:5353 // Discover services var B := TmDNSBrowser.Create; var Found := B.Browse('_mqtt._tcp', 1000); // 1 second window for var S in Found do Writeln(S.InstanceName, ' at ', S.IPv4, ':', S.Port); B.Free; R.Stop; R.Free;
TServiceInfo record: InstanceName, ServiceType, Domain, HostName, Port, TXTEntries, IPv4.
Low-level codec: AppendDNSName / ReadDNSName (with compression pointer support),
EncodeDNSMessage / DecodeDNSMessage, BuildBrowseQuery, BuildAnnounce,
ParseServiceFromMsg.
AMQP 1.0 (ISO/IEC 19464) client — compatible with Azure Service Bus, RabbitMQ (with the
rabbitmq_amqp1_0 plugin), ActiveMQ and any AMQP 1.0 broker.
Files
| File | Description |
|---|---|
AMQP.Types.pas |
Type codec — all 22 AMQP primitives, big-endian I/O, described types |
AMQP.Frames.pas |
Frame codec — header, performatives, SASL, message sections |
AMQP.Client.pas |
TAMQPClient — full client with reader thread and event synchronisation |
Project: AMQPDemo.dpr — 96 tests (27 type codec + 16 frame codec + 34 performatives + 8 SASL + 11 functional loopback).
Usage
Client := TAMQPClient.Create; // Connect with PLAIN SASL (omit ASaslMech for no auth) Client.Connect('localhost', 5672, 'PLAIN', 'user', 'password'); Client.Open('my-container'); Client.Begin_; // Send a message Client.AttachSender('myqueue'); Client.Send(0, TEncoding.UTF8.GetBytes('{"temp":23.5}')); // Receive messages Client.OnMessage := procedure(AHandle: Cardinal; const APayload: TBytes) begin Writeln(TEncoding.UTF8.GetString(APayload)); end; Client.AttachReceiver('myqueue', 1, 100); // handle=1, credit=100 // Clean shutdown Client.Detach(0); Client.Detach(1); Client.End_; Client.Close; Client.Disconnect; Client.Free;
Performatives: Open, Begin, Attach (sender + receiver), Flow, Transfer, Disposition,
Detach, End, Close.
SASL: ANONYMOUS and PLAIN (user/password).
Message sections: Data (75ドル), AmqpValue (77ドル). Accepts multi-section messages.
Settled / unsettled sends: ASettled=True fire-and-forget; ASettled=False waits
for Disposition (at-least-once delivery).
- No external dependencies beyond Indy (bundled with Delphi).
- Cross-platform — Win32/Win64/Linux64/Android where applicable. Platform-specific code (Windows COM, Android JNI) is isolated behind interfaces.
- Self-contained tests — every library ships a console program that passes with zero external infrastructure (loopback sockets, in-process mock servers).
- Consistent style — fluent builders,
TBytesbodies, reference-to-procedure callbacks,TIdIOHandler-based I/O, background reader threads with event sync. - Hardware-tested — Modbus RTU and CoAP verified against a real ESP32.
- Production-grade — each codec implements the full wire spec (no partial frames, proper big-endian I/O, all compact forms, thread safety via critical sections).