TCP / UDP
For equipment that has no industrial protocol at all: bench scales, barcode and RFID readers, weather stations, laboratory instruments, serial devices behind an Ethernet gateway, and in-house protocols. QUBIQ opens the socket, splits the byte stream into messages, and lets you map fields to tags.
Configuration
| Field | Description |
|---|---|
| Name | Connection identifier. |
| Host | Device IP or hostname (for client role). |
| Port | Device port, or the port to listen on in server role. |
| Transport | tcp or udp. |
| Role | client — QUBIQ connects out. server — QUBIQ listens and the device connects in. |
| Frame mode | How the byte stream is split into messages. See below. |
| Delimiter | For delimiter framing: the terminator, e.g. \r\n, \n, \x03. |
| Frame size | For fixed-length framing: bytes per message. |
| Max message bytes | Hard cap; a message larger than this is not buffered indefinitely. It ends that stream and is reported. |
| Field delimiter | Splits a message into fields, e.g. , for CSV, \t, ;. |
| Field count | Expected number of fields. A message with a different count turns its tags Bad. |
| Writeable | Allows tags on this connection to send data to the device. |
| Connect timeout (ms) | Socket connect timeout. |
| Inactivity timeout (ms) | Reconnect if nothing is received for this long. |
Framing
A TCP stream has no message boundaries — framing is how you recover them. Getting this wrong is the usual cause of "half a reading" or "two readings stuck together".
| Frame mode | Use when | Notes |
|---|---|---|
| Delimiter | The device terminates each message (\r\n, \n, ETX) | The most common case. |
| Fixed length | Every message is exactly N bytes | Binary protocols with a fixed record. |
| None | UDP, where each datagram is already a message | Do not use for TCP. |
UDP preserves datagram boundaries, so framing is usually unnecessary — but UDP also loses datagrams silently and may reorder them. Do not use it for anything you must not miss.
A message cut short is refused, not published Changed in 1.0.7
When a TCP stream ended in the middle of a message — the device dropped, or closed the socket — the bytes received so far used to be handed on as if they were a whole message, and published as a tag value with Good quality. A short reading looked exactly like a real one.
The fragment is now discarded and the reason reported:
| Frame mode | Refused at the end of a stream |
|---|---|
| Fixed length | Fewer bytes than the frame size. |
| Delimiter | Any bytes after the last delimiter. |
The delimiter case has a consequence worth checking. A complete message with no terminator cannot be told apart from a truncated one, so a device that sends its last message without the delimiter and then closes the connection now loses that message, where it used to arrive. If a device does that, it is not terminating its messages the way its framing says — confirm the delimiter against a raw capture.
Framing faults are reported Changed in 1.0.7
A message longer than Max message bytes, a stream cut mid-message and a read error all stop the stream, and until 1.0.7 none of them said so: the connection simply went quiet, or one peer of a server silently disappeared. Now:
- In client role the connection is marked down with the reason —
framing: …rather than a bare disconnected — and reconnects. - In server role only the offending peer is dropped. The fault is logged and counted as a failure on the connection, but the listener stays up and the other peers' tags stay Good: one device sending a malformed stream must not mark every tag on the listener Bad.
Field mapping
Every connection gets a fixed set of generated tags, and a binding's address picks one of them by name:
| Generated tag | Holds |
|---|---|
message | The whole message, as text. |
messageBytes | The whole message, as hexadecimal. |
lastReceiveTime | When the message arrived. |
field0 … fieldN | One per field, counted from 0, when a field delimiter and field count are set. |
writeable, writeableBytes | Write-only: what a write sends to the device. TCP with Writeable on only. |
Message: "ST,GS,+ 12.345,kg
"
Fields: field0="ST" field1="GS" field2="+ 12.345" field3="kg"
Tag Scale/Status → field0
Tag Scale/Weight → field2 (data type float)
Tag Scale/Unit → field3
Field count is a cheap integrity check: a truncated or concatenated message has the wrong number
of fields. It is not parsed into wrong tags: every tag of that message goes Bad, with the counts in
the status (field count 3 does not match expected 4).
Binding tags
| Field | Notes |
|---|---|
| Tag | One of the generated tags, chosen from a list. The field tags appear once the connection has a field count. |
| Data type | Set it — text "12.345" becomes a number only if the tag says float. |
There is no poll rate: every message the device sends updates the tags.
Writing to the device
With Writeable enabled on a TCP connection, writing a tag bound to writeable (text) or
writeableBytes (hexadecimal) transmits the value on the socket; any other generated tag refuses a
write. The tag then shows the last value sent, since nothing reads it back. The framing
configuration is applied on the way out: the delimiter is appended, or the payload is padded to the
fixed length.
Use this for command protocols — tare a scale, trigger a reader, request a measurement.
In server role a write goes to the most recently connected peer that is still connected. 1.0.7 It used to go to the most recent peer ever — so once that peer left, every write failed until another connected, even with other peers live on the listener.
Reconnecting Changed in 1.0.7
In client role a dropped connection is redialled with backoff, from half a second up to fifteen seconds between attempts, and there is always a wait before a redial.
The backoff now resets only after a connection has lasted five seconds. It used to reset on any successful dial, so a peer that accepted and immediately hung up — the wrong port, the wrong protocol, a device at its connection limit — was redialled with no delay at all: thousands of connection attempts a second at one end, a pegged CPU at the other.
Requests to the worker — a connection check, a write — are also handled side by side across connections now, so one unreachable device no longer holds up the others.
Quality and liveness
A raw socket gives no quality information, so QUBIQ infers it:
| Condition | Quality |
|---|---|
| Message parsed, field present | Good |
| Socket down or reconnecting | Bad |
| Field count does not match | Bad on every tag of the message, with the counts |
| Message over Max message bytes | Stream ended and reported |
| Stream ended mid-message | Fragment discarded, never published |
| Nothing received within the tag's stale after 1.0.8 | Uncertain, last value kept |
For a device that sends on a cycle, set stale after on its tags. Without it, a dead device is indistinguishable from a quiet one.
Security
Raw TCP/UDP has no authentication and no encryption. Anyone who can reach the port can send data that QUBIQ will parse into tags.
- Keep these devices on an isolated segment.
- In
serverrole, bind to a specific interface and firewall the port. - Never expose a
server-role TCP/UDP connection to an untrusted network. - Treat values from it as untrusted input: validate ranges on the tag, not just in the display.
Troubleshooting
| Symptom | Check |
|---|---|
| Values are truncated or concatenated | Wrong frame mode or delimiter. Capture the raw stream and look at the actual terminator. |
| Some messages ignored | Field count mismatch — the device emits a status message with a different shape. |
| Data stops after a while | Device closed the socket; set inactivity timeout so QUBIQ reconnects. |
Nothing at all, client role | The device may be a server-only device expecting QUBIQ to listen — switch roles. |
| Numbers arrive as strings | Set the tag's data type; leading spaces and + signs are handled on conversion. |
| Works then breaks after a firmware update | Vendors change delimiters and field order between versions. Re-capture. |
Connection status reads framing: … | A message over Max message bytes, or a stream that ended mid-message. See framing faults. |
| A device's last message before it disconnects no longer arrives | It is sent without the delimiter, and is now refused as a partial frame. |
Writes fail in server role while a peer is connected | Fixed in 1.0.7 — writes follow the most recent live peer. |