Aqotec RM360 over Modbus, Part 3: Safe Writes and Automations
Safe RM360 write automations for Home Assistant: mode selection, float32 offsets, value bounds, and no startup write storms.
After read-only sensors and a safe energy counter, the next step is controlled writes.
The important rule: write only when the user changes something. Do not write on every Home Assistant start and do not mirror sensors back into registers.
This part covers regular setpoints and operating-mode writes. External room temperature is slightly different because it is intentionally periodic; I split that into Part 4.
Heating circuit 2 mode
For my RM360, heating circuit 2 uses register 41197.
The mode mapping is:
| Mode | Register value |
|---|---|
| Auto | 0 |
| Day | 1 |
| Night setback | 2 |
| Party | 3 |
| Off / frost protection | 4 |
A small input_select is enough for the UI:
input_select:
rm360_hc2_mode_set:
name: "RM360 HC2 Mode"
options:
- "Auto"
- "Day"
- "Night"
- "Party"
- "Off"
And the automation writes only after a real user-side state change:
- id: rm360_hc2_mode_write
alias: RM360 HC2 Mode Write
mode: restart
triggers:
- trigger: state
entity_id: input_select.rm360_hc2_mode_set
conditions:
- condition: template
value_template: >
{{
trigger.from_state is not none
and trigger.from_state.state not in ['unknown', 'unavailable']
and trigger.to_state is not none
and trigger.to_state.state != trigger.from_state.state
}}
actions:
- delay: "00:00:01"
- action: modbus.write_register
data:
hub: rm360
slave: 1
address: 41197
value: >
{% set m = {
'Auto': 0,
'Day': 1,
'Night': 2,
'Party': 3,
'Off': 4
} %}
{{ m[states('input_select.rm360_hc2_mode_set')] | int }}
Float32 correction values
Some RM360 values are float32, which means two 16-bit registers must be written as one Modbus FC16 operation.
Example for a day correction value:
- id: rm360_day_offset_write
alias: RM360 Day Offset Write
mode: restart
triggers:
- trigger: state
entity_id: input_number.rm360_day_offset_set
conditions:
- condition: template
value_template: >
{% set value = trigger.to_state.state | float(none) %}
{{
trigger.from_state is not none
and trigger.from_state.state not in ['unknown', 'unavailable', 'none', '']
and value is not none
and -4.0 <= value <= 4.0
and trigger.to_state.state != trigger.from_state.state
}}
actions:
- delay: "00:00:02"
- action: modbus.write_register
data:
hub: rm360
slave: 1
address: 41214
value: >
{% set value = states('input_number.rm360_day_offset_set') | float %}
{% set raw = value | pack(">f") %}
{{ [unpack(raw, ">H", offset=0), unpack(raw, ">H", offset=2)] }}
The same pattern works for the night correction and for heating-circuit-specific offsets. Adjust the register and value range, but keep the guardrails.
Final checks before regular write automations
Before enabling write automations:
- verify every register against the controller documentation
- keep the first write small and reversible
- check the RM360 display after each first write
- avoid writing during Home Assistant startup
- keep read sensors and write helpers separate
The remaining special case is the external room temperature for heating circuit 2. That needs both Home Assistant automation and manual RM360 service-menu configuration, so it gets its own Part 4.
Series navigation
Previous step: Aqotec RM360 over Modbus, Part 2: The Energy Counter Workaround
Next step: Aqotec RM360 over Modbus, Part 4: External Room Temperature for HC2