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