Generic serial and TCP

Equipment that speaks a text or byte protocol of its own, such as weighing indicators and barcode readers, over a serial line, TCP or UDP: how its messages end and are checked, and how each tag takes its value from them.

View as Markdown

The Generic serial and TCP driver reads and writes equipment that speaks a protocol of its own, made of text or of simple bytes, where no standard protocol applies: a weighing indicator, a barcode or RFID reader, an older instrument, a label printer. Such equipment cannot be asked what it is, so nothing is discovered. You tell the device how a message it sends ends and how its checksum is checked, and you tell each tag how it gets its value, which messages are its own and which characters of a message are the value.

A device reaches its equipment in one of three ways, chosen when it is created:

Transport How the device is reached What its tags may do
On a serial line A serial line of this driver, shared with the other devices on it, one request at a time. Request and response, listening, writes.
TCP client Its own connection to the equipment's host and port. Request and response, listening, writes.
UDP listener A port of this station that the equipment sends datagrams to. The station sends nothing. Listening only, read only.

A device on a serial line hangs under its line, so that part of the tree reads Driver → Line → Device → Tag, as under Modbus RTU. A network device sits under the driver and may be filed in folders like any other driver's device, Driver → Folder → Device → Tag. A device stays on the side it was created on: TCP and UDP can be switched, but a device never moves between a line and the network.

The driver's page

The line under the header reads "Serial lines carry the instruments that share a bus, and network devices sit under the driver. Add a line or a device, then open it to describe its messages." and the page holds two tables, one under the other:

Table What grows it What it lists
Serial lines Add line, at the right of its title. The driver's lines: Line, Physical tuple (port · baud · format, with no timeout, since a line of this driver has none), Devices, State, and the actions Open, Enable, Disable and Delete. Empty, it reads "No serial lines yet."
Devices Add device, at the right of its title. It creates a network device, a TCP client. Every device of the driver, those on a line included, with the columns of any driver's device table. Empty, it reads "No devices yet."

The header counts the devices in parentheses, and the driver row in the tree counts both levels once a line exists ("1 line · 2 devices"). The driver's bar has no Discover. Right-clicking the driver row offers Add device, Add line, New folder and Refresh, then, after a separator, Remove driver; in the column's New… menu the driver's entry offers New device, New serial line and New folder, then its lines, folders and devices. Once added, the driver stands under the Drivers folder of the tree, with or without a line or a device.

Serial line

A line of this driver is the line described on Serial lines, with fewer fields. Its page says "One physical serial bus: the port settings its instruments share, one request at a time." and its Physical line card holds:

Field Meaning Default
Name The friendly name of the bus, shown in the tree and on every device on it. "New line"
Serial port The Windows COM port, physical, virtual or redirected, typed or picked from the ports Windows reports (Refresh reads them again). One port belongs to one line, whatever driver the line belongs to. the first free port
Baud The bus speed, shared by every device on the line. 9600
Serial format Data bits, parity and stop bits: 8N1, 8N2, 8E1, 8E2, 8O1, 8O2, 7N2, 7E1, 7E2 or 7O1. All ten are offered, because this driver does not need 8 data bits. 8E1

A line created here starts disabled, so the port settings are typed before the port opens. The port, the baud and the format change only while the line is disabled; the name changes at any time. A line of this driver has no transmission mode, no response timeout, no minimum transaction interval and no automatic silence: each device on it says on its own panel how its messages end and how long it waits for an answer, as the Devices card under the line says: "Every device on this line shares its port settings. Each one says on its own panel how its messages end and how long it waits for an answer." It has no Discover units card and its Devices table has no Unit ID column, because an instrument is told apart by what its requests say, not by an address.

Add device on the line, or on its right-click menu, creates a device of this driver on that line. A line belongs to the driver it was created under, for good: a Modbus RTU device and a device of this driver never share a line, and an agent that points a device at a line of the other driver is refused. The line's states (Off, Idle, Connecting…, Online, Port failure) are those of every serial line, on Enabling and health.

On the line, the driver opens the port once for every device on it and sends one request at a time, waiting for its answer before the next. Between requests, whatever arrives is offered to every device on the line, each one cutting it into messages by its own rules. A port that fails is reopened by the line for all its devices, waiting longer between attempts while it keeps failing.

Device

Connection

Field Meaning Default
Transport A network device only. TCP client: "The station connects to the device's host and port." UDP listener: "The station listens on a local port for what the device sends, and sends nothing." The two can be switched; a device on a line shows its line instead. TCP client
Host TCP: the equipment's host name or IP address. A whole address can be pasted, with tcp:// in front and the port after the host. empty
Port TCP: the port the equipment answers on, 1 to 65535. No port is standard for such equipment, so a new device has none. empty
Accept from UDP, in place of Host: "Only datagrams from this address are read. Empty: any sender." empty
Local port UDP, in place of Port: "The port on this station that the device sends to. The Windows firewall has to let it in." empty
Serial line · fixed A device on a line: the line's name over its port, baud and format, read only. the line it is added under

A new TCP device reads "Host not entered yet" and is not connected until it has a host and a port. A device with a host and no port, and a UDP device without its local port, cannot be saved: "Give the port: the device's port over TCP, the local port to listen on over UDP." A device on a line has no host, port or folder, and no unit id.

The Base URI the header shows is the runtime address: generic://tcp/<host>:<port>, generic://udp/<local port> (with from=<sender> when Accept from is filled in) or generic://serial/<line id>/<port>/<baud>/<format>, followed by how messages end and are checked (end, start, terminator, length, gap, timeout, checksum and the rest). The bytes it carries are bytes, never the notation the device is typed in. A copy of a device on a line stays on that line; a copy of a network device lands at the driver's own level.

The Messages card

Under the Connection card, the Messages card says how the bytes are typed and how a message ends.

Field Meaning Default
Typed as How the start marker, the terminator and each tag's request, filter, separator, write message and expected reply are written. Text with escapes: printable characters as themselves, \r, \n, \t, \\ and \xNN for any other byte. Hex bytes: two digits per byte, such as 02 30 31 0D. Switching rewrites every byte field of the device and of its tags, so each keeps sending the same bytes; while one of them is not valid bytes the switch is refused: "The notation was not changed: a byte field of this device or of its tags is not valid in the notation in use. Correct it first." Text with escapes
Message ends with Terminator, Fixed length or Silence. Over UDP each datagram is one message whatever this says. Terminator
Terminator With Terminator: the bytes that close every message. They are not part of what the tags read. \r\n
Message length (bytes) With Fixed length, 1 to 1024: "Every message is this many bytes, the start marker and the checksum included."
Silence (ms) With Silence, 5 to 10000: "A message ends when nothing arrives for this long." 50
Start marker Optional. The bytes every message starts with, such as \x02. Bytes before it are dropped, which also puts a stream joined in the middle of a message back in step, and it counts as the first characters of the message. empty
Response timeout (ms) 50 to 60000: "How long a request waits for its answer, and a write for its expected reply." 1000
Maximum time without a message (s) 0 to 86400, 0 meaning never: "Listening tags stop counting as readings when nothing arrives for this long. 0: never, for a device that sends only now and then, like a barcode reader. Set it for a device that sends all the time, like a weighing indicator." 0

A field the chosen ending does not read is not drawn and keeps its value for when that ending comes back. A value the device cannot work with is not saved, and the feed says why, for example "Give the terminator the messages end with, such as \r\n." or "The message length must be from 1 to 1024 bytes."

The Checksum card

Field Meaning Default
Algorithm The checksum every message carries: None, Sum (8-bit), Two's complement of the sum (LRC), Two's complement of the 7-bit sum (Toledo), XOR (8-bit), CRC-16/MODBUS or CRC-16/CCITT. "A message whose checksum does not match is dropped and counted in the journal, never read as a value." None
Written as Hex text, the checksum written as hex digits, or Raw bytes, the checksum's own bytes. Hex text
Placement Before the end: the last bytes before the terminator, or the last bytes of the message. After the terminator: right after it, which it then covers; offered only when messages end with a terminator. Before the end
Bytes left out at the start 0 to 255: "Bytes at the start of the message that the checksum does not cover, such as an STX or a $." 0
Bytes left out before it 0 to 255: "Bytes just before the checksum that it does not cover, such as the * of an NMEA sentence. The tags do not read them either." 0

Every field but the algorithm is drawn only once a checksum is chosen. The checksum covers the message from its first byte to the byte before the checksum, except the bytes left out. A message whose checksum does not match is never read as a value: it is dropped, and the journal says so under the device at most once a minute. The checksum is only checked: requests and writes are sent exactly as typed, so a request that needs a checksum carries it in its own bytes.

Algorithm Common use
Sum (8-bit) Indicators.
Two's complement of the sum (LRC) Indicators, frames in the style of Modbus ASCII.
Two's complement of the 7-bit sum (Toledo) The continuous output of a Toledo indicator, as a raw byte after the CR.
XOR (8-bit) NMEA 0183 sentences ($…*hh), indicators, RFID readers.
CRC-16/MODBUS Binary frames; the low byte first as raw bytes.
CRC-16/CCITT Binary frames (the CCITT-FALSE variant); the high byte first as raw bytes.

Tag addressing

A tag of this driver has no address to type: its Source card asks how it gets its value, in the fields below. Bytes are typed in the device's notation.

Field Meaning Default
Read mode Request and response: "The station sends the request at the tag's poll interval and reads the value from the answer." Listen: "The device sends by itself, and the tag keeps the last message its filter accepts." A UDP device offers Listen alone: "This device listens on UDP and sends nothing: its tags only listen and are read only." Request and response
Request Request and response only: "What the station sends at the tag's poll interval, typed as the device says. The first message the filter accepts within the response timeout is the answer." required
Message filter Which messages belong to the tag: Every message, Starts with (the bytes they start with) or Matches a regular expression (the Regular expression they match). For a request, "Which message answers the request. The others go on to the listening tags." Every message
Value is How the value is cut out of the message: The whole message, Fixed position (First character and Length), Field between separators (Separator and Field number) or Capture group of a pattern (Pattern). "Positions and fields count from 1. The pattern needs exactly one capture group, the value. Numbers are read with a decimal point." The whole message
The device writes a comma for the decimal point Float and Double tags only. The comma is the decimal point when reading and when writing. off
Write message Tags that are written, not on UDP: "What a write sends, with where the value goes, such as SP \r, or to format it. On a Boolean tag a write message without is a command, sent when true is written." empty
Expected reply "Optional. What the device's reply to a write starts with. The write succeeds only when that reply arrives within the response timeout." empty

Characters are counted from the start of the message, the start marker included; the terminator, the checksum and the bytes the checksum leaves out before it are not part of what a tag reads. A pattern is a .NET regular expression, and a message it takes longer than 250 ms to read is not read. A Write only tag has no request, filter or value fields; a tag with no write message is read only.

The data types are Boolean, Int32, Int64, Float, Double and String. The text taken is read as the tag's type before the tag's own stages convert it, as for every driver (see The value pipeline): a Boolean reads 1, true, on or yes and 0, false, off or no; an integer reads a whole number (12.0 reads as 12, 12.5 is refused); a Float or a Double reads a decimal number; a String takes the characters as they are. Spaces around a number, and between its sign and its digits, are ignored, because indicators pad their numbers. A tag whose fields cannot work is not saved, and the tag's page says what it lacks, for example "Give the request this tag sends." or "The pattern needs exactly one capture group, around the value."

The read-only preview of the wire address reads ask or listen followed by what applies, for example listen?extract=position&start=5&length=6, or ask?send=01RD%0D&extract=field&separator=,&field=3 for a tag that sends 01RD and a CR and reads the third comma-separated field of the answer.

Reading

Situation Request and response tag Listening tag
The value From the first checked message the filter accepts within the response timeout after the request. From the last checked message the filter accepts, dated by its arrival.
When it is read At the tag's poll interval. Whenever the equipment sends; the tag shows the last message at its poll interval.
Before the first message Not applicable. The tag waits: no value and no error, as any tag before its first answer.
No answer, or a silent equipment No answer within the response timeout is a failed read, and the tag's policy for a device that did not answer decides what it shows. Past the device's Maximum time without a message (s), every listening tag fails its read and its policy decides what it shows. A TCP connection that drops fails them whatever that time says.
A message the tag cannot read A failed read, with the reason: a field missing, the value reaching past the end of the message, or text the type cannot hold. The same.

Messages that answer no request go on to the listening tags of the same device, so a device may have both kinds of tags. Listening tags whose filters are the same share what was heard, and may take different fields out of the same message.

Writing

A write goes through the same funnel as any other driver's: the write box takes the engineering value, and the conversion stages are reversed before the raw value is sent (see Connector).

Write message What is sent What the write reports
With {value} The bytes typed, with the value where {value} stands: a number in invariant culture (with a comma for the decimal point when the tag says so), or formatted by {value:FORMAT} with a .NET number format (W{value:000.0}\r sends 12.5 as W012.5 and a CR); a Boolean as 1 or 0; a text as it is. Done once sent. With an Expected reply, done only when a reply starting with it arrives within the response timeout; another reply refuses the write with that reply as the reason, and silence is no response.
Without {value}, on a Boolean tag A command, such as a tare or a print: writing true sends it, writing false is refused. The same.
None Nothing: the tag is read only.

Writes wait their turn on the device's queue like every driver's: on a line they share the line's one request at a time, on TCP the device's own connection. A UDP device sends nothing, so its tags cannot be written.

Example: a weighing indicator on RS-232

An indicator in the style of Toledo's continuous output sends, many times a second, an STX, three status bytes, six digits of weight, six of tare, a CR and a checksum byte. On the station:

  1. Add line on the driver's page; name it Scale line, pick COM3, keep Baud 9600 and choose 7E1 as Serial format, then Enable the line.
  2. Add device on the line; name it Scale. On the Messages card keep Text with escapes and Terminator, set the Terminator to \r, the Start marker to \x02 and Maximum time without a message (s) to 10, so a pulled cable shows as lost communication.
  3. On the Checksum card choose Two's complement of the 7-bit sum (Toledo), Raw bytes and After the terminator, with both counts of bytes left out at 0.
  4. Add tag; name it Weight, Double, Read only. On the Source card choose Listen, Every message and Fixed position, with First character 5 and Length 6: the STX is character 1, the three status bytes are 2 to 4, the weight 5 to 10.
  5. The digits carry no decimal point, so the tag's Scale stage places it, for example a factor of 0.01 for an indicator set to two decimals.

An agent does the same with three tool calls:

serial_line_upsert driver=GenericSerialTcp name="Scale line" serialPort=COM3 baudRate=9600 serialFormat=7E1
device_upsert driver=GenericSerialTcp name=Scale transport=SerialLine serialLineId=<id> messageEnd=Terminator terminator=\r startMarker=\x02 checksum=SumTwosComplement7Bit checksumFormat=Raw checksumPlacement=AfterEnd silenceTimeoutSeconds=10
tag_upsert device=Scale name=Weight opcUaType=Double tagMode=Listen valueExtraction=FixedPosition valueStart=5 valueLength=6

Example: a barcode reader on TCP

A barcode reader with an Ethernet port sends one code per line, and only when it reads one:

  1. Add device on the driver's page; name it Reader, keep TCP client, and enter Host 192.168.0.40 and Port 2001.
  2. On the Messages card keep Text with escapes, Terminator \r\n and Maximum time without a message (s) 0: a reader that sends nothing for an hour is not failing. Keep None on the Checksum card.
  3. Add tag; name it Code, String, Read only. On the Source card choose Listen, Every message and The whole message.

The same with the agent's tools:

device_upsert driver=GenericSerialTcp name=Reader transport=TcpClient host=192.168.0.40 port=2001 messageEnd=Terminator terminator=\r\n
tag_upsert device=Reader name=Code opcUaType=String tagMode=Listen valueExtraction=WholeMessage

driver_capabilities describes this driver under genericSerialTcp, with these two examples, and serial_line_upsert creates a line of this driver with driver=GenericSerialTcp; the other tools are on Agent tools.

Limits worth knowing

  • Nothing is discovered: there is no protocol to ask such equipment what it is or what it holds.
  • A binary frame that announces its own length in a header is not read; a message ends with a terminator, a fixed length, a silence, or a datagram.
  • The checksum is only checked: no checksum is added to what the station sends.
  • A tag takes one value out of a message, as text read as its type; numbers packed as binary integers or floats inside the message are not decoded.
  • A UDP device only listens: it sends no request and accepts no write.
  • A device cannot be moved between a serial line and the network, nor to another line: create it where it belongs and delete the old one.