New TIN Protocol
Overview
The New TIN protocol is used by modern Truma heating devices (TIN 4.0, mid-2018 onwards). Unlike the Legacy TIN protocol with separate command frames, New TIN features a unified command structure where all heating parameters are sent in a single frame.
This protocol is used by:
- Modern Truma Combi heaters (2018+)
- InetX control panels
- iNet X Connect remote modules
- Modern Aventa air conditioning units
Signal Frame Types
| Signal ID | Frame Type | Direction | Purpose |
|---|---|---|---|
| 0x20 | Heater Command | Master → Slave | Unified heater control |
| 0x21 | Heater Info 1 | Slave → Master | Temperature telemetry |
| 0x22 | Heater Info 2 | Slave → Master | Power and system status |
| 0x17 | Aircon Command | Master → Slave | Air conditioning control |
Heater Command (0x20)
The unified command frame controlling all heater functions.
Frame Structure
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| Content | Room Temp Code | Control Flags | Water Temp | Fuel Control | Electro Power | Vent + Energy | 0xE0 | 0x0F |
| Function | Target temp | Boiler/Heat | Water level | Gas enable | Electric power | Fan + bitmap | Fixed | Fixed |
Byte 0: Room Temperature Code
Temperature is encoded using the following formula:
code = (220 + (temp - 5) * 10) % 256
temp = ((code - 220) % 256) / 10 + 5
Special case: 0xAA = Off
Temperature Range: 5-30°C (in 1°C steps)
Byte 1: Control Flags
| Bit | Function | Values |
|---|---|---|
| 7 | Boiler enable | 0 = On, 1 = Off (inverted!) |
| 0 | Heating enable | 0 = Off, 1 = On |
| 1-6 | Base pattern | Always 0x2A (binary: 0010 1010) |
Common Values:
0x2A(0010 1010): Boiler ON, Heating OFF0x2B(0010 1011): Boiler ON, Heating ON0xAA(1010 1010): Boiler OFF, Heating OFF0xAB(1010 1011): Boiler OFF, Heating ON
Byte 2: Water Temperature Level
| Code | Level | Temperature | Description |
|---|---|---|---|
0xAA | Off | - | Water heating disabled |
0xC3 | Eco | ~40°C | Energy-saving hot water |
0xD0 | Hot | ~60°C | Maximum hot water |
Byte 3: Fuel Control
| Value | Function |
|---|---|
0x00 | Fuel disabled |
0xFA | Fuel enabled (gas/diesel heating active) |
Byte 4: Electric Power Level
| Code | Power Level | Watts |
|---|---|---|
0x00 | Off | 0W |
0x09 | Low | 900W |
0x12 | High | 1800W |
Byte 5: Ventilation + Energy Bitmap
Upper Nibble (bits 4-7): Ventilation Level
| Nibble | Level | Description |
|---|---|---|
0x0 | Off | Ventilation disabled |
0x1 | Level 1 | Manual minimum |
0x2 | Level 2 | Manual low |
0x3-0x9 | Levels 3-9 | Manual intermediate levels |
0xA | Level 10 | Manual maximum |
0xB | Comfort | Automatic comfort mode |
0xD | Boost | Maximum boost mode |
Lower Nibble (bits 0-3): Energy Bitmap
| Bit | Function |
|---|---|
| 0 | Fuel enabled (mirrors byte 3) |
| 1 | Electro enabled (derived from byte 4) |
| 2-3 | Reserved |
Common Patterns:
0xB0= Comfort mode, no energy0xB1= Comfort mode, fuel only0xB2= Comfort mode, electric only0xB3= Comfort mode, fuel + electric (mix)
Bytes 6-7: Fixed Values
- Byte 6: Always
0xE0 - Byte 7: Always
0x0F
Example Frames
Everything off:
[0xAA] [0xAA] [0xAA] [0x00] [0x00] [0x00] [0xE0] [0x0F]
Heat room to 22°C, water Eco, fuel only, comfort fan:
[0x86] [0x2B] [0xC3] [0xFA] [0x00] [0xB1] [0xE0] [0x0F]
│ │ │ │ │ │
│ │ │ │ │ └─ Comfort mode (0xB), fuel bit set (0x1)
│ │ │ │ └─ Electric off
│ │ │ └─ Fuel enabled
│ │ └─ Water Eco (40°C)
│ └─ Boiler on (bit 7=0), heating on (bit 0=1), pattern 0x2A
└─ Room 22°C
Heat room to 28°C, water Hot, mix mode (fuel + 900W), boost fan:
[0xC2] [0x2B] [0xD0] [0xFA] [0x09] [0xD3] [0xE0] [0x0F]
│ │ │ │ │ │
│ │ │ │ │ └─ Boost mode (0xD), fuel + electro bits (0x3)
│ │ │ │ └─ Electric 900W
│ │ │ └─ Fuel enabled
│ │ └─ Water Hot (60°C)
│ └─ Boiler on, heating on
└─ Room 28°C
Water heating only (no room heating), Hot water, fuel:
[0xAA] [0x2A] [0xD0] [0xFA] [0x00] [0x01] [0xE0] [0x0F]
│ │ │ │ │ │
│ │ │ │ │ └─ Fan off, fuel bit set
│ │ │ │ └─ Electric off
│ │ │ └─ Fuel enabled
│ │ └─ Water Hot
│ └─ Boiler on, heating off
└─ Room heating off
Manual ventilation level 5, no heating:
[0xAA] [0xAA] [0xAA] [0x00] [0x00] [0x50] [0xE0] [0x0F]
│
└─ Level 5 (0x5), no energy
Heater Info 1 (0x21)
Reports current room and water temperatures.
Frame Structure
| Byte | 0 | 1 | 2 | 3-7 |
|---|---|---|---|---|
| Content | Room Temp (low 8 bits) | Room (high 4 bits) + Water (low 4 bits) | Water Temp (high 8 bits) | Reserved |
| Encoding | 12-bit packed | Shared byte | 12-bit packed | Padding |
Temperature Encoding
Temperatures are encoded as 12-bit values representing Kelvin × 10, packed into 3 bytes.
Room Temperature:
room_encoded = (byte1 & 0x0F) << 8 | byte0
room_celsius = (room_encoded / 10.0) - 273.0
Water Temperature:
water_encoded = byte2 << 4 | (byte1 & 0xF0) >> 4
water_celsius = (water_encoded / 10.0) - 273.0
Example Frame
Room at 22.5°C, water at 45.3°C:
Step 1: Encode temperatures
room_kelvin_x10 = (22.5 + 273.0) × 10 = 2955
water_kelvin_x10 = (45.3 + 273.0) × 10 = 3183
Step 2: Pack into bytes
room_encoded = 2955 = 0x0B8B (12-bit)
byte0 = 0x8B (low 8 bits)
byte1_low = 0x0B (high 4 bits)
water_encoded = 3183 = 0xC6F (12-bit)
byte2 = 0xC6 (high 8 bits)
byte1_high = 0x0F (low 4 bits)
byte1 = (0x0F << 4) | 0x0B = 0xFB
Frame:
[0x8B] [0xFB] [0xC6] [0x00] [0x00] [0x00] [0x00] [0x00]
│ │ │
│ │ └─ Water high 8 bits (0xC6)
│ └─ Room high 4 bits (0x0B) + Water low 4 bits (0x0F)
└─ Room low 8 bits (0x8B)
Decoding Example
Given frame: [0x9F] [0xBB] [0xB7] [0x28] [0x12] [0x02] [0xF0] [0x0F]
Room Temperature:
room_encoded = ((0xBB & 0x0F) << 8) | 0x9F
= (0x0B << 8) | 0x9F
= 0x0B9F = 2975
room_celsius = 2975 / 10.0 - 273.0 = 24.5°C
Water Temperature:
water_encoded = (0xB7 << 4) | ((0xBB & 0xF0) >> 4)
= (0xB7 << 4) | 0x0B
= 0xB7B = 2939
water_celsius = 2939 / 10.0 - 273.0 = 20.9°C
Heater Info 2 (0x22)
Reports power supply status and boiler state.
Frame Structure
| Byte | 0 | 1 | 2 | 3-7 |
|---|---|---|---|---|
| Content | Voltage | System Flags | Boiler State | Reserved |
Byte 0: Voltage
Encoding: Voltage × 100mV
Example:
0x84= 132 → 13.2V0x85= 133 → 13.3V0x77= 119 → 11.9V
Byte 1: System Flags
| Bit | Function | Values |
|---|---|---|
| 5 | 230V AC supply | 0 = Not present, 1 = Present |
| 6 | AC auto mode | Status indicator |
| 7 | Pump running | 0 = Off, 1 = Running |
| 0-4 | Reserved | Various status bits |
Common Values:
0x20: 230V present, pump off0x60: 230V present, additional flag set0x70: 230V present, pump running0x30: 230V present, different status
Byte 2: Boiler State
| Code | State | Description |
|---|---|---|
0x10 | Eco reached | Water at Eco temperature (~40°C) |
0x11 | Eco heating | Actively heating to Eco |
0x30 | Hot reached | Water at Hot temperature (~60°C) |
0x31 | Hot heating | Actively heating to Hot |
0x04 | Error/Other | Alternative status code |
0x05 | Error/Other | Alternative status code |
Example Frames
13.2V, 230V present, Eco temperature reached:
[0x84] [0x60] [0x10] [0x05] [0xFF] [0xFF] [0xFF] [0xFF]
11.9V, 230V present, pump running, Hot water active:
[0x77] [0x70] [0x31] [0x05] [0xFF] [0xFF] [0xFF] [0xFF]
13.3V, 230V present, heating inactive:
[0x85] [0x20] [0x10] [0x05] [0xFF] [0xFF] [0xFF] [0xFF]
Aircon Command (0x17)
Controls air conditioning units on the TIN bus.
Frame Structure
| Byte | 0-7 |
|---|---|
| Content | AC control data |
Note: The exact format for AC control requires further analysis. The signal is used for Truma Aventa and Saphir air conditioning units.
Complete Control Sequence Example
Scenario: Cold morning startup
Step 1: Master sends Heater Command (0x20)
Target: Room 22°C, Water Eco, Fuel only, Comfort fan
[0x86] [0x2B] [0xC3] [0xFA] [0x00] [0xB1] [0xE0] [0x0F]
Step 2: Heater responds with Info 1 (0x21)
Current: Room 15.5°C, Water 12.0°C (cold start)
[0x5A] [0xAB] [0xBC] [0x3C] [0x12] [0x01] [0xF0] [0x0F]
Step 3: Heater responds with Info 2 (0x22)
Voltage: 13.2V, 230V present, Eco heating active
[0x84] [0x60] [0x11] [0x05] [0xFF] [0xFF] [0xFF] [0xFF]
Step 4: After 30 minutes, Info 1 update
Current: Room 21.5°C, Water 39.5°C (approaching target)
[0x7A] [0xBB] [0xC3] [0x3C] [0x12] [0x01] [0xF0] [0x0F]
Step 5: Target reached, Info 2 update
Voltage: 13.2V, 230V present, Eco temperature reached
[0x84] [0x60] [0x10] [0x05] [0xFF] [0xFF] [0xFF] [0xFF]
Implementation Notes
Temperature Encoding
Room Temperature (Byte 0): Uses the formula (220 + (temp - 5) * 10) % 256 where temp is in Celsius (5-30°C). Special case: 0xAA = Off.
Telemetry Temperatures (Frame 0x21): Encoded as 12-bit values representing Kelvin × 10, packed into bytes.
Advantages over Legacy TIN
- Single Frame: All parameters in one frame (0x20) vs. 5 separate frames
- Efficient: Reduced bus traffic and simpler state management
- Atomic Updates: All parameters updated simultaneously
- Modern Features: Better support for mix mode, detailed status reporting
Migration from Legacy TIN
When supporting both protocols:
Detection: Use product identification to determine device generation
- Function ID
0x0301or0x0310→ Legacy TIN - Function ID
0x0340or0x0320→ New TIN
- Function ID
Abstraction Layer: Create unified API that maps to appropriate protocol:
trait HeaterControl { fn set_room_temp(&mut self, celsius: u8); fn set_water_temp(&mut self, level: WaterLevel); fn set_fuel_enabled(&mut self, enabled: bool); fn set_electro_power(&mut self, watts: u16); fn set_fan_level(&mut self, level: FanLevel); }Frame Generation: Convert high-level commands to protocol-specific frames
References
- TIN Protocol Overview - General TIN protocol information
- Legacy TIN Protocol - Legacy protocol specification
- Implementation:
womonet-drivers/src/tin/protocol/tinnew/ - Test Data:
truma-driver/logs_new.md
