Created
October 12, 2025 17:02
-
-
Save ncolomer/9c24617677f3ceea465b622141396fd6 to your computer and use it in GitHub Desktop.
Sonoff TRVZB External Setpoint
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| blueprint: | |
| name: Sonoff TRVZB External Setpoint | |
| description: | | |
| Control multiple TRV (Thermostatic Radiator Valve) valves using a single external temperature sensor. | |
| Compatible with both Zigbee2MQTT and ZHA integrations. | |
| Features: | |
| - Directly sets external temperature on TRV (no offset calculation) | |
| - Automatically switches TRV to external sensor mode if needed | |
| - Automatic 2-hour update to prevent TRV fail-safe mode | |
| - Rate limiting to preserve battery life and reduce Zigbee traffic | |
| domain: automation | |
| input: | |
| external_temperature_sensor: | |
| name: External Temperature Sensor | |
| description: The external temperature sensor (e.g., SNZB-02) to use as the reference | |
| selector: | |
| entity: | |
| filter: | |
| - domain: sensor | |
| device_class: temperature | |
| target_trvs: | |
| name: Target TRV Valves (Sonoff TRVZB) | |
| description: Select one or more Sonoff TRVZB valves to control with the external sensor | |
| selector: | |
| target: | |
| entity: | |
| - domain: climate | |
| device: | |
| - manufacturer: SONOFF | |
| model: TRVZB | |
| update_interval: | |
| name: Minimum Update Interval | |
| description: Minimum time between updates on sensor changes to avoid battery drain (in seconds) | |
| default: 300 | |
| selector: | |
| number: | |
| min: 60 | |
| max: 3600 | |
| unit_of_measurement: seconds | |
| mode: slider | |
| mode: restart | |
| trigger: | |
| - platform: state | |
| entity_id: !input external_temperature_sensor | |
| id: sensor_change | |
| - platform: time_pattern | |
| hours: "/2" | |
| id: failsafe_prevention | |
| variables: | |
| external_sensor: !input external_temperature_sensor | |
| target_valves: !input target_trvs | |
| min_interval: !input update_interval | |
| condition: | |
| - alias: Check external sensor is available | |
| condition: template | |
| value_template: "{{ states(external_sensor) not in ['unknown', 'unavailable'] }}" | |
| - alias: Determine if update should proceed | |
| condition: or | |
| conditions: | |
| # Always update every 2 hours to prevent fail-safe mode | |
| - alias: 2-hour failsafe update (bypass rate limiter) | |
| condition: trigger | |
| id: failsafe_prevention | |
| # For sensor changes, respect the rate limiter | |
| - alias: Sensor change with rate limiting | |
| condition: and | |
| conditions: | |
| - alias: Triggered by sensor change | |
| condition: trigger | |
| id: sensor_change | |
| - alias: Rate limiter check (minimum interval elapsed) | |
| condition: template | |
| value_template: > | |
| {{ this.attributes.last_triggered is none or | |
| (now() - this.attributes.last_triggered).total_seconds() >= min_interval }} | |
| action: | |
| - alias: Process each TRV valve | |
| repeat: | |
| for_each: "{{ target_valves.entity_id }}" | |
| sequence: | |
| - variables: | |
| trv_entity: "{{ repeat.item }}" | |
| trv_device_id: "{{ device_id(trv_entity) }}" | |
| trv_external_temperature_input: > | |
| {{ expand(device_entities(trv_device_id)) | |
| | selectattr('entity_id', 'search', 'external_temperature_input') | |
| | map(attribute='entity_id') | |
| | list | |
| | first | default('') }} | |
| trv_sensor_select: > | |
| {{ expand(device_entities(trv_device_id)) | |
| | selectattr('entity_id', 'search', 'temperature_sensor_select') | |
| | map(attribute='entity_id') | |
| | list | |
| | first | default('') }} | |
| # Step 1: Ensure TRV is set to use "external" temperature sensor (slot 1) | |
| - alias: Switch TRV to external mode if needed | |
| choose: | |
| - conditions: | |
| - alias: Check if sensor select exists and is not set to external | |
| condition: template | |
| value_template: > | |
| {{ trv_sensor_select != '' and | |
| states(trv_sensor_select) != 'external' }} | |
| sequence: | |
| - alias: Set TRV temperature sensor to external (slot 1) | |
| service: select.select_option | |
| target: | |
| entity_id: "{{ trv_sensor_select }}" | |
| data: | |
| option: external | |
| # Step 2: Set the external temperature value | |
| - alias: Check if external temperature input entity exists | |
| condition: template | |
| value_template: "{{ trv_external_temperature_input != '' }}" | |
| - alias: Write external temperature value to TRV | |
| service: number.set_value | |
| target: | |
| entity_id: "{{ trv_external_temperature_input }}" | |
| data: | |
| value: "{{ states(external_sensor) | float }}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment