This is an old revision of the document!
JRBusTCP Protocol v1 Specification
1. Overview
JRBusTCP is a proprietary binary communication protocol designed for efficient, deterministic data exchange between JRobo / JRoboPLC instances and client applications. The protocol operates over TCP/IP and is optimized for:
* High-frequency data exchange * Minimal bandwidth usage * Deterministic behavior suitable for automation and PLC-like systems * Explicit control over data serialization and transport
The protocol follows a request/response model with client-initiated communication. All messages are framed, version-agnostic at transport level, and protected by CRC32 checksums.
Maximum supported message size is 16384 bytes.
—
2. Transport Layer
* Transport protocol: TCP * Connection model: persistent TCP connection * Byte order: Big Endian (network byte order) * Encoding for strings: UTF-8
JRBusTCP does not define connection establishment beyond TCP. Session state (authentication, tag list, update state) is maintained per TCP connection.
—
3. Message Framing
3.1 General Message Format
+--------+--------+----------------------------+--------+ | size | header | payload | crc | | 2 B | 2 B | (size - 4 - 4 bytes) | 4 B | +--------+--------+----------------------------+--------+
Where payload has the following structure:
+---------+------+---------------------------+ | reqId | cmd | body | | 4 B | 1 B | variable length | +---------+------+---------------------------+
3.2 Field Description
* size (2 bytes): Total message size in bytes, from `header` through `crc` inclusive * header (2 bytes): Constant magic value `0xABCD` * reqId (4 bytes): Request identifier (int32, signed). Generated by client * cmd (1 byte): Command code * body (variable): Command-specific payload * crc (4 bytes): CRC32 calculated over `[reqId..body]`
3.3 Request Identifier (reqId)
* Generated by the client * Initial value SHOULD be random * Incremented by 1 for each subsequent request * Server MUST return the same `reqId` value unchanged * Client MUST verify response `reqId` matches request
Server does not validate or interpret `reqId`.
—
4. Command Set
4.1 Command Code Summary
| Code | Name |
|---|---|
| 0x01 | INIT |
| 0x02 | LIST |
| 0x03 | UPDATE |
| 0x04 | READ |
| 0x05 | WRITE |
| 0x06 | CRC |
| 0x07 | AUTH_INIT |
| 0x08 | AUTH_SUBMIT |
| 0xFE | UNAUTHENTICATED |
| 0xFF | UNKNOWN |
Response commands are formed by setting the highest bit (`cmd | 0x80`).
—
5. INIT (0x01)
Initializes tag list and session parameters.
==== Request ====
cmd : 0x01 flen : 1 byte filter : flen bytes (UTF-8 regex) clen : 1 byte client : clen bytes (UTF-8) flags : 2 bytes
Flags Bitmask
* b0: Client supports tag descriptions * b1: Client supports tag status in READ * b2: Exclude tags with `external` flag * b3: Include tags with `hidden` flag
==== Response ====
cmd : 0x81 listsize : 3 bytes (uint24)
`listsize` indicates total number of tags selected.
—
6. LIST (0x02)
Retrieves tag metadata in chunks.
==== Request ====
cmd : 0x02 index : 3 bytes (uint24)
==== Response ====
cmd : 0x82 index : 3 bytes quantity : 3 bytes next : 3 bytes [tag entries]
==== Tag Entry Format ====
type : 1 byte nlen : 1 byte tagname : nlen bytes (UTF-8) dlen : 1 byte descr : dlen bytes (UTF-8)
Data Types
| Code | Type |
|---|---|
| 1 | BOOL |
| 2 | INT32 |
| 3 | INT64 |
| 4 | DOUBLE |
| 5 | STRING |
—
7. UPDATE (0x03)
Checks for tag value changes.
==== Request ====
cmd : 0x03
==== Response ====
cmd : 0x83 quantity : 3 bytes next : 3 bytes liststate : 1 byte
* 0x00: tag list unchanged * 0xFF: tag list changed; client MUST re-run INIT + LIST
—
8. READ (0x04)
Reads tag values.
==== Request ====
cmd : 0x04 index : 3 bytes
==== Response ====
cmd : 0x84 index : 3 bytes quantity : 3 bytes next : 3 bytes [data blocks]
Index Blocks
* 0xFE: Next tag index, uint16 * 0xFF: Next tag index, uint24
Value Encodings (Compact)
* 0xF0: false / zero * 0xF1: true / one * 0xF2: 1-byte integer * 0xF3: 2-byte integer
Value Encodings (Full)
* 0xF8: int32 (4 bytes) * 0xF9: int64 (8 bytes) * 0xFA: double (8 bytes) * 0xFB: string (2-byte length + UTF-8 bytes)
Status bit: b4 of first value byte (if INIT.flags.b1 = 1)
* 1 = Good * 0 = Bad
—
9. WRITE (0x05)
Writes tag values.
==== Request ====
cmd : 0x05 index : 3 bytes quantity : 3 bytes [data blocks]
==== Response ====
cmd : 0x85
—
10. CRC (0x06)
Returns CRC32 checksum of all tag values after last UPDATE.
==== Request ====
cmd : 0x06
==== Response ====
cmd : 0x86 crc : 4 bytes
—
11. Authentication
==== AUTH_INIT (0x07) ====
request: cmd : 0x07 klen : 2 bytes keyname : klen bytes response: cmd : 0x87 status : 1 byte nlen : 2 bytes nonce : nlen bytes
Status:
* 0x00 OK * 0x01 FAILED * 0x02 DISABLED
==== AUTH_SUBMIT (0x08) ====
request: cmd : 0x08 nlen : 2 bytes nonce : nlen bytes response: cmd : 0x88 status : 1 byte
Status:
* 0x00 ACCEPTED * 0xFF DENIED
—
12. Error Responses
* 0xFE: UNAUTHENTICATED * 0xFF: UNKNOWN
—
13. Session Lifecycle
1. TCP connect 2. AUTH_INIT / AUTH_SUBMIT (optional) 3. INIT 4. LIST (paged) 5. UPDATE 6. READ / WRITE 7. CRC (optional) 8. TCP disconnect
—
14. Design Notes
* Protocol favors deterministic binary layout * Compact encodings reduce bandwidth * Explicit pagination avoids oversized frames * reqId enables async request matching
—
15. Versioning
This document defines JRBusTCP Protocol v1. Any incompatible changes MUST increment protocol version and be negotiated out-of-band.
—
16. Diagrams
==== 16.1 Typical Session Sequence ====
Client Server | | |--- TCP CONNECT ---------------->| | | |--- INIT ----------------------->| |<-- INIT RESPONSE (listsize) ----| | | |--- LIST (index=0) ------------->| |<-- LIST (chunk 1) --------------| |--- LIST (next) ---------------->| |<-- LIST (last chunk) -----------| | | |--- UPDATE --------------------->| |<-- UPDATE (quantity,next) ------| | | |--- READ (index=first changed) ->| |<-- READ (values) ---------------| | | |--- UPDATE / READ (loop) --------| | |
==== 16.2 Binary Layout: READ Response ====
+---------+------+---------+-----------+-----------+----------------+ | reqId | cmd | index | quantity | next | data blocks | | 4 B | 1 B | 3 B | 3 B | 3 B | variable | +---------+------+---------+-----------+-----------+----------------+
==== 16.3 Binary Layout: WRITE Request ====
+---------+------+---------+-----------+----------------+ | reqId | cmd | index | quantity | data blocks | | 4 B | 1 B | 3 B | 3 B | variable | +---------+------+---------+-----------+----------------+
—
17. Rationale
17.1 Why Not JSON / Protobuf
* Determinism: binary layouts provide predictable parsing cost * Zero allocations: no intermediate object trees required * Bandwidth efficiency: compact numeric encodings outperform JSON * Schema stability: no dependency on external IDL or runtime reflection
17.2 Why TCP and Not UDP
* Guaranteed delivery and ordering * Built-in congestion control * Simplified client/server implementations * NAT/firewall friendly
—
Appendix A: Examples
==== A.1 INIT Request (hex dump) ====
00 1A AB CD 00 00 00 01 01 05 2E 2A 00 06 4A 52 6F 62 6F 00 03 A1 B2 C3 D4
==== A.2 READ Response (single INT32 value) ====
00 14 AB CD 00 00 00 05 84 00 00 01 00 00 01 00 00 00 F8 00 00 00 2A DE AD BE EF
—
Appendix B: Performance Considerations
B.1 Latency
* Typical RTT dominated by TCP latency * Binary parsing cost negligible * Suitable for polling rates up to several kHz on LAN
B.2 Batching
* READ/WRITE support bulk operations * Clients SHOULD batch contiguous tag indices * Server SHOULD maximize quantity per response until size limit reached
B.3 UPDATE Polling Strategy
* Poll UPDATE at fixed interval (e.g., 10–100 ms) * Issue READ only when quantity > 0 * Use CRC command to validate full state synchronization when needed