Skip to content

Change Third Reality soil moisture sensor device class 3RSM0147Z#3780

Merged
TheJulianJES merged 10 commits intozigpy:devfrom
iamjoshk:iamjoshk-3rsm0147z
Mar 24, 2026
Merged

Change Third Reality soil moisture sensor device class 3RSM0147Z#3780
TheJulianJES merged 10 commits intozigpy:devfrom
iamjoshk:iamjoshk-3rsm0147z

Conversation

@iamjoshk
Copy link
Copy Markdown
Contributor

@iamjoshk iamjoshk commented Jan 26, 2025

Proposed change

This quirk v2 changes the RelativeHumidity cluster for a SoilMoisture cluster to change the exposed entity from a humidity sensor to a soil moisture sensor, which is what this device is intended to measure.

Additional information

This Third Reality device measures temperature and soil moisture, but the soil moisture is exposed as Humidity in the default configuration.
I am currently using this quirk in my own ZHA integration.

Checklist

  • The changes are tested and work correctly
  • pre-commit checks pass / the code has been formatted using Black
  • Tests have been added to verify that the new code works

@codecov
Copy link
Copy Markdown

codecov bot commented Jan 26, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.95%. Comparing base (9d5c2ec) to head (76c6c50).
⚠️ Report is 1 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev    #3780   +/-   ##
=======================================
  Coverage   92.95%   92.95%           
=======================================
  Files         394      394           
  Lines       13173    13174    +1     
=======================================
+ Hits        12245    12246    +1     
  Misses        928      928           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@iamjoshk
Copy link
Copy Markdown
Contributor Author

Not sure why the proposed change and additional information sections didn't populate.

This is a quirk v2 for the 3RSM0147Z which replaces the humidity sensor for a soil moisture sensor, since the device is intended to be used to measure soil moisture and temperature.

I am currently using this in my ZHA implementation for two devices.

@TheJulianJES TheJulianJES added the needs reviewer answer An answer from a reviewer is needed (e.g. why a PR isn't acceptable in the current state). label Jan 26, 2025
@AlexGustafsson
Copy link
Copy Markdown

Thanks for sharing this. I've tried it and it works wonders.

As a temporary workaround for others using home assistant and waiting for this to make it upstream:

If you haven't already configured a directory for custom ZHA quirks, do so in your configuration.yaml:

zha:
  enable_quirks: true
  custom_quirks_path: /config/custom_zha_quirks

Next, add the 3RSM0147Z.py file from this PR to the directory and restart home assistant. You'll also have to remove and add any soil humidity devices you might already have added.

@AlexGustafsson
Copy link
Copy Markdown

@TheJulianJES any chance this can get a pair of eyes? As Josh wrote above, they're sold as "soil moisture sensors" but show up as humidity sensors. This change takes care of that.

@puddly
Copy link
Copy Markdown
Contributor

puddly commented Jun 19, 2025

I think renaming the cluster ID is a little too hacky, in my opinion. Untested, but you should be able to just directly create the exact entity you want:

from zigpy.quirks.v2 import QuirkBuilder, ReportingConfig
from zigpy.zcl.clusters.measurement import RelativeHumidity, SoilMoisture

from zhaquirks import CustomCluster

(
    QuirkBuilder("Third Reality, Inc", "3RSM0147Z")
    # Ignore the default relative humidity entity
    .prevent_default_entity_creation(cluster_id=RelativeHumidity, endpoint_id=1)
    # And instead create a new one
    .sensor(
        attribute_name=RelativeHumidity.AttributeDefs.measured_value.name,
        cluster_id=RelativeHumidity.cluster_id,
        state_class=SensorStateClass.MEASUREMENT,
        device_class=SensorDeviceClass.HUMIDITY,
        reporting_config=ReportingConfig(
            min_interval=30,
            max_interval=900,
            reportable_change=100,
        ),
        translation_key="soil_moisture",
        fallback_name="Soil moisture",
    )
    .add_to_registry()
)

@TheJulianJES
Copy link
Copy Markdown
Collaborator

Yeah, that. But do note that we'd still break every instance where the relative humidity sensor is currently used, so everyone would have to switch then.

@puddly
Copy link
Copy Markdown
Contributor

puddly commented Jun 19, 2025

True. This one works for me and registers the new entity with the old unique_id:

from zigpy.quirks.v2 import (
    QuirkBuilder,
    ReportingConfig,
    SensorStateClass,
    SensorDeviceClass,
)
from zigpy.quirks.v2.homeassistant import PERCENTAGE
from zigpy.zcl.clusters.measurement import RelativeHumidity, SoilMoisture

from zhaquirks import CustomCluster

(
    QuirkBuilder("Third Reality, Inc", "3RSM0147Z")
    # Ignore the default relative humidity entity
    .prevent_default_entity_creation(
        cluster_id=RelativeHumidity.cluster_id,
        endpoint_id=1,
        function=lambda entity: entity.translation_key is None,
    )
    # And instead create a new one
    .sensor(
        attribute_name=RelativeHumidity.AttributeDefs.measured_value.name,
        cluster_id=RelativeHumidity.cluster_id,
        state_class=SensorStateClass.MEASUREMENT,
        device_class=SensorDeviceClass.HUMIDITY,
        unit=PERCENTAGE,
        divisor=100,
        reporting_config=ReportingConfig(
            min_interval=30,
            max_interval=900,
            reportable_change=100,
        ),
        translation_key="soil_moisture",
        fallback_name="Soil moisture",
        primary=True,
        # To "migrate" existing entities, clone the unique ID suffix of the relative
        # humidity entity
        unique_id_suffix="1029",
    ).add_to_registry()
)
image

@TheJulianJES
Copy link
Copy Markdown
Collaborator

Nice! I think we might not even need reporting_config, since that's attribute based and should already be done in the RelativeHumidity handler.

@iamjoshk
Copy link
Copy Markdown
Contributor Author

iamjoshk commented Jul 3, 2025

My entire motivating factor for this quirk was to change the device class to moisture so it would be available as a soil moisture sensor when configuring a new entity for the Plant Monitor (HACS version).

So this
device_class=SensorDeviceClass.MOISTURE,

instead of
device_class=SensorDeviceClass.HUMIDITY,

will accomplish that.

(I don't think prevent_default_entity_creation was available when I originally submitted this PR in January? Not sure at this point.)

Copy link
Copy Markdown
Collaborator

@TheJulianJES TheJulianJES left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the long wait on this. I believe we can do this in a much better way now with change_entity_metadata. We should be able to remove both the custom sensor and prevent_default_entity_creation. Then, add something like this:

    .change_entity_metadata(
        endpoint_id=1,
        cluster_id=RelativeHumidity.cluster_id,
        new_device_class: SensorDeviceClass.MOISTURE,
    )

Please let me know if this works as well!

@iamjoshk
Copy link
Copy Markdown
Contributor Author

This worked:

(
    QuirkBuilder("Third Reality, Inc", "3RSM0147Z")
    .change_entity_metadata(
        endpoint_id=1,
        cluster_id=RelativeHumidity.cluster_id,
        new_device_class="moisture",
    )
    .add_to_registry()
)

Using new_device_class: SensorDeviceClass.MOISTURE, threw an error:

Error while adding entity from entity data: EntityData(entity=<zha.application.platforms.sensor.Humidity object at 0x7fa7ef599fd0>, device_proxy=<homeassistant.components.zha.helpers.ZHADeviceProxy object at 0x7fa7ef1fcad0>, group_proxy=None)
Error while adding entity from entity data: EntityData(entity=<zha.application.platforms.sensor.Humidity object at 0x7fa7ef58f610>, device_proxy=<homeassistant.components.zha.helpers.ZHADeviceProxy object at 0x7fa7ef1fca50>, group_proxy=None)
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/zha/helpers.py", line 1218, in async_add_entities
entities_to_add.append(entity_class(entity_data))
~~~~~~~~~~~~^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/zha/sensor.py", line 109, in init
self._attr_device_class = SensorDeviceClass(entity.device_class)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.13/enum.py", line 726, in call
return cls.new(cls, value)
~~~~~~~~~~~^^^^^^^^^^^^
File "/usr/local/lib/python3.13/enum.py", line 1203, in new
raise ve_exc
ValueError: <SensorDeviceClass.MOISTURE: 'moisture'> is not a valid SensorDeviceClass

When I got the error, the device loaded without the quirk and it still showed the entity as soil moisture instead of humidity. I won't have a chance for a few days to remove the device and re-pair it yet to see if the quirk is actually needed any longer. I am not sure if there was some other update to ZHA that may have supersedes this.

And TR appears to be working on something for it, too, so I don't want these to conflict.
#4380

@TheJulianJES
Copy link
Copy Markdown
Collaborator

TheJulianJES commented Mar 13, 2026

ValueError: <SensorDeviceClass.MOISTURE: 'moisture'> is not a valid SensorDeviceClass

Ah, this is a ZHA issue with how it processes change_entity_metadata. We'll take a look. Thanks for the logs.
(ZHA just uses a str otherwise, but change_entity_metadata just passes through the zigpy types as is.)

@TheJulianJES TheJulianJES added the priority: medium This should be addressed or looked at soon label Mar 20, 2026
Copilot AI review requested due to automatic review settings March 24, 2026 20:14
@TheJulianJES
Copy link
Copy Markdown
Collaborator

I believe change_entity_metadata should now work with device_classes from zigpy, since they were switched from an Enum to StrEnum, matching ZHA ones now. Related PRs:

I've pushed some changes to this PR that should work.

@TheJulianJES TheJulianJES changed the title Quirk v2 to expose soil moisture instead of humidity for 3RSM0147Z Change Third Reality soil moisture sensor device class 3RSM0147Z Mar 24, 2026
@TheJulianJES TheJulianJES removed the needs reviewer answer An answer from a reviewer is needed (e.g. why a PR isn't acceptable in the current state). label Mar 24, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the v2 quirk for Third Reality soil moisture sensors so the measurement currently exposed via the RelativeHumidity cluster is represented in Home Assistant as a moisture sensor (rather than a humidity sensor), aligning the entity with the device’s intended purpose.

Changes:

  • Import SensorDeviceClass and RelativeHumidity to support HA metadata updates.
  • Use QuirkBuilder.change_entity_metadata() to set the RelativeHumidity entity’s device_class to SensorDeviceClass.MOISTURE.

Comment on lines 40 to +48
(
QuirkBuilder("Third Reality, Inc", "3RSM0147Z")
.applies_to("Third Reality, Inc", "3RSM0347Z")
.replaces(ThirdRealitySoilMoistureCluster)
.change_entity_metadata(
endpoint_id=1,
cluster_id=RelativeHumidity.cluster_id,
new_device_class=SensorDeviceClass.MOISTURE,
)
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says the RelativeHumidity cluster is being changed to a SoilMoisture cluster and that tests were added, but the code change here only adjusts Home Assistant entity metadata (device class) for the existing RelativeHumidity entity and there are no corresponding test changes. Either update the PR description/checklist to match what’s implemented, or extend the change (and tests) to fully achieve the stated behavior.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the PR description should probably be updated slightly.

Copy link
Copy Markdown
Collaborator

@TheJulianJES TheJulianJES left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've regenerated ZHA diagnostics with this and the device class seems to have changed correctly. Thanks for the PR and helping getting this working!

@TheJulianJES TheJulianJES merged commit 2c80ae8 into zigpy:dev Mar 24, 2026
13 checks passed
@3reality-support
Copy link
Copy Markdown
Contributor

@iamjoshk What is the purpose of this modification, to change the humidity to soil moisture? Display 2 soil entities? I used the latest 2026.4.1 version, but it didn't have much effect. There is still humidity
6ea65bacd6d8d2dba349a15ead317f30

@3reality-support
Copy link
Copy Markdown
Contributor

In the future, we will remove excess humidity entities and only display temperature entities and soil moisture entities

@3reality-support
Copy link
Copy Markdown
Contributor

#4915

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: medium This should be addressed or looked at soon

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants