Skip to content

Infinity Framing Protocol

John Lifsey edited this page Apr 7, 2026 · 3 revisions

RS-485 is a half duplex, multi-master bus. Nothing prevents two devices from sending data at the same time. Collisions happen, and the framing protocol detects and responds to them.

Frames consist of an 8 byte header, variable length data, and finally a CRC16 checksum over the header and data.

All devices receive all data and ignore frames not addressed to them. When a device receives a frame with a valid checksum and its own address as destination, it responds with a positive acknowledgement (ACK02 or ACK06) or a negative acknowledgement (NAK). The sending device resends the frame if it does not receive an acknowledgement, as a collision or other data corruption may have occurred.

The thermostat (address 2001) is usually the master, with other devices responding to its requests. The SAM (address 9201, if present) is sometimes the master, usually sending frames to the thermostat. The small number of masters means there are relatively few collisions.

Katai Struct frame definition

Frame
Header Data Checksum
1 byte 1 byte 1 byte 1 byte 1 byte 1 byte 1 byte 1 byte
Destination Address Destination Bus Source Address Source Bus Length PID EXT Function 0-255 bytes 2 bytes

In practice for home use, the bus byte is always 0x01 and PID/EXT bytes are always 0x00.

  • See Infinity - Known Devices for possible addresses; 0xf1f1 is the broadcast destination address
  • The source address of a READ or WRITE frame is where the acknowledgement will be sent
  • The length is the length in bytes of the data, excluding header and checksum
  • The function is READ, WRITE, ACK06, etc. -- see below
  • The checksum is CRC16 over header and data

Typical function codes:

0x02 ACK02 -> "ACK02"
0x06 ACK06 -> "ACK06"
     if length = 1 and data = 0x00 -– acknowledges a WRITE frame
     if length > 3 bytes -– a response to a READ frame; the first three data bytes are the register number and the remaining bytes are the contents of the register
0x0B READ_TABLE_BLOCK -> "READ"
     length = 3 -- the register number to read
0x0C WRITE_TABLE_BLOCK -> "WRITE"
     length > 3 bytes -- the first three data bytes are the register number and the remaining bytes are the new contents of the register
0x15 NACK -> "NACK" (also called "exception")
     Known exception codes (single data byte):
       0x04 - Register not served (no device responds to this register address)
       0x0A - Negative acknowledgement: no such table, table not writable, invalid data, function not supported

Other function codes:

0x10 CHANGE_TABLE_NAME -> "CHGTBN"
0x1E ALARM_PACKET -> "ALARM"
0x22 READ_OBJECT_DATA -> "OBJRD"
0x62 READ_VARIABLE -> "RDVAR"
0x63 WRITE_VARIABLE -> "FORCE"
0x64 AUTO_VARIABLE -> "AUTO"
0x75 READ_LIST -> "LIST"

In observation, the thermostat (device 2001 or 1F01) always initiates a READ(0x0B) or WRITE(0x0C), and the response is always ACK06(0x06) or NAK(0x15). There is an instance of Device 0x4001 sending a READ(0x0B) frame to 0x4101, but it is unknown what this is for, as there is no response.

The SAM (0x92) also initiates reads and writes when present. The SAM writes register 3B03 (sam_zones) to the thermostat after processing ASCII commands, and the thermostat responds with 3B0E writes (acknowledgment). The SAM continuously reads registers 3C14, 3C0C, 3C0D, 3003, 3005 from the thermostat, which consistently respond with exception 0x04 (register not served). These may be SAM-internal registers.

During a 10.5-hour passive capture, all 54,076 exception frames were thermostat->SAM with data byte 0x04. These correlate 1:1 with SAM reads of registers the thermostat does not serve (3C14, 3C0D, 3C0C, 3005, 3003, 3104, 0104, 0420, 0202).

The thermostat regularly broadcasts (destination address F1F1) the date and time (registers 0202/0203) approximately every 60-90 seconds. A touch thermostat with source address 1F01 was reported to make additional broadcasts at startup time.

Clone this wiki locally