Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save arstorey/d8cb99cf46bb482b30c78e7f63498b34 to your computer and use it in GitHub Desktop.

Select an option

Save arstorey/d8cb99cf46bb482b30c78e7f63498b34 to your computer and use it in GitHub Desktop.
Home Assistant automation blueprint for firmware-level soil moisture and temperature calibration for THIRDREALITY Smart Soil Moisture Sensor Gen2 (3RSM0347Z).
blueprint:
name: ZHA – THIRDREALITY Gen2 Calibration (Strict per-device isolation)
description: >
Firmware-level soil moisture and temperature calibration for
THIRDREALITY Smart Soil Moisture Sensor Gen2 (3RSM0347Z).
• Strict per-device isolation
• No global entities
• ZHA device selector
• Write → read → verify
• Retry-safe for sleepy battery devices
• Run manually (recommended) to avoid accidental repeated writes
domain: automation
input:
zigbee_device:
name: Gen2 Soil Moisture Sensor
description: Select the THIRDREALITY Gen2 sensor (ZHA)
selector:
device:
integration: zha
soil_offset:
name: Soil Moisture Calibration (%)
default: 0
selector:
number:
min: -30
max: 30
step: 1
unit_of_measurement: "%"
temperature_offset:
name: Temperature Calibration (centi-°C)
description: 100 = +1.00 °C
default: 0
selector:
number:
min: -500
max: 500
step: 10
unit_of_measurement: "c°C"
retry_minutes:
name: Retry interval (minutes)
default: 5
selector:
number:
min: 1
max: 30
step: 1
max_attempts:
name: Maximum retry attempts
default: 6
selector:
number:
min: 1
max: 30
step: 1
mode: restart
max_exceeded: silent
# Intentionally empty: this is a maintenance/provisioning workflow.
# You run it manually from the automation UI.
trigger: []
variables:
# Pull inputs into normal YAML variables first (NOT inside Jinja)
device_id: !input zigbee_device
soil_target: !input soil_offset
temp_target: !input temperature_offset
retry_delay: !input retry_minutes
retry_limit: !input max_attempts
# Now it's safe to use Jinja
ieee: "{{ device_attr(device_id, 'identifiers')[0][1] | lower }}"
action:
- repeat:
sequence:
# ---- WRITE soil moisture calibration ----
- service: zha.set_zigbee_cluster_attribute
data:
ieee: "{{ ieee }}"
cluster_id: 0x0408
attribute: 0xF001
value: "{{ soil_target | int }}"
# ---- WRITE temperature calibration ----
- service: zha.set_zigbee_cluster_attribute
data:
ieee: "{{ ieee }}"
cluster_id: 0x0402
attribute: 0xF001
value: "{{ temp_target | int }}"
# ---- READ soil moisture calibration ----
- service: zha.get_zigbee_cluster_attribute
data:
ieee: "{{ ieee }}"
cluster_id: 0x0408
attribute: 0xF001
# ---- READ temperature calibration ----
- service: zha.get_zigbee_cluster_attribute
data:
ieee: "{{ ieee }}"
cluster_id: 0x0402
attribute: 0xF001
# ---- WAIT for response from THIS device (strict isolation) ----
- wait_for_trigger:
- platform: event
event_type: zha_event
event_data:
command: read_attributes_response
timeout:
minutes: "{{ retry_delay | int }}"
continue_on_timeout: true
# ---- If we got a response, verify it is from our device and matches either value ----
- variables:
ok: >-
{{
wait.trigger is not none
and (
(wait.trigger.event.data.get('device_ieee') | default('') | lower) == ieee
or
(wait.trigger.event.data.get('ieee') | default('') | lower) == ieee
)
and (
(
wait.trigger.event.data.get('cluster_id') == 0x0408 and
wait.trigger.event.data.get('attribute_id') == 0xF001 and
(wait.trigger.event.data.get('value') | int) == (soil_target | int)
)
or
(
wait.trigger.event.data.get('cluster_id') == 0x0402 and
wait.trigger.event.data.get('attribute_id') == 0xF001 and
(wait.trigger.event.data.get('value') | int) == (temp_target | int)
)
)
}}
until:
- condition: or
conditions:
# success
- condition: template
value_template: "{{ ok }}"
# fail-safe
- condition: template
value_template: "{{ repeat.index >= (retry_limit | int) }}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment