Skip to content

Conversation

@Antoninj
Copy link

Proposed change

Support for external temperature sensor.

Additional information

This is a copy of #2802 + the missing unit tests

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

@Antoninj Antoninj changed the title Aqara external temperature sensor Add support for Aqara external temperature sensor Mar 23, 2025
@codecov
Copy link

codecov bot commented Mar 23, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 91.33%. Comparing base (2fd3586) to head (c75465e).
Report is 49 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #3974      +/-   ##
==========================================
+ Coverage   91.04%   91.33%   +0.28%     
==========================================
  Files         331      339       +8     
  Lines       10698    11029     +331     
==========================================
+ Hits         9740    10073     +333     
+ Misses        958      956       -2     

☔ 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.

@TheJulianJES TheJulianJES added Xiaomi Request/PR regarding a Xiaomi or Aqara device needs review This PR should be reviewed soon, as it generally looks good. labels Mar 26, 2025
Copy link
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.

Thanks for adding the tests. I think this looks pretty good already.

Comment on lines +398 to +399
SENSOR_TEMP: ("sensor_temp", t.uint32_t, True),
SENSOR_ATTR: (SENSOR_ATTR_NAME, t.LVBytes, True),
Copy link
Collaborator

Choose a reason for hiding this comment

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

All these attributes should really be converted to the new zigpy AttributeDefs style. Search AttributeDefs in this repo or the zigpy repo for examples.
You don't have to do it in this PR, but it would be nice.

We can also access the name and id then: AqaraThermostatSpecificCluster.AttributeDefs.sensor_temp.name or .id.

Copy link
Author

Choose a reason for hiding this comment

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

I hear you but I honestly don't have much time to spend on this PR atm and multiple people have been emailing me to track progress on this change since it's a highly requested feature for the quirk.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is quite some time ago. I would like to help in this case.

I found that this PR is not up to date with the upstream.
In the upstream I see that the AttributeDefs are already defined.
So it is, I believe, straight forward to do this change.

Unfortunately, I don't know how I can collaborate on this PR.

@Antoninj - I believe you can do that quite easily by doing the following:

  1. Sync the fork (dev branch) with your the upstream (on GitHub you can do that easily)
  2. Pull the updated dev branch to your local machine (e.g. git checkout dev and then git pull)
  3. Now you can rebase the branch aqara_external_temperature_sensor onto dev branch (or merge dev branch into your branch)
  4. You will have merge conflicts, which are easily resolved:
  • The test file is new and is not affected
  • The file thermostat_agl001.py is already in the new style and you should keep the code of your branch, except the changes of the attributes. These are already in the new style and you need to add those two lines I believe:
        sensor_temp: Final = ZCLAttributeDef(
            id=SENSOR_TEMP, type=t.uint32_t, is_manufacturer_specific=True
        )
        sensor_attr: Final = ZCLAttributeDef(
            id=SENSOR_ATTR, type=t.LVBytes, is_manufacturer_specific=True
        )

The tests run fine when I tried it.

However, there is the comment of NJLangley, which needs to be addressed. I am trying to look into that. As I am still quite "new" I try to learn und understand what is meant by the comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

If you feel that you do not have time, I could replicate this PR and do the changes.
Let me know if that is ok for you.

Comment on lines 498 to 506
attrs1 = {}
attrs1[SENSOR_ATTR_NAME] = (
self.aqaraHeader(0x12, params1, 0x04) + params1
)
attrs[SENSOR_ATTR_NAME] = (
self.aqaraHeader(0x13, params2, 0x04) + params2
)

await super().write_attributes(attrs1, manufacturer)
Copy link
Collaborator

Choose a reason for hiding this comment

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

So these need to be written in separate calls?

Copy link
Author

Choose a reason for hiding this comment

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

I honestly have no idea, I bootstrapped this PR from existing work from someone else and mostly focused on addding unit tests tbh

Copy link

Choose a reason for hiding this comment

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

They need to be in separate calls otherwise its starts to misbehave

Copy link
Contributor

Choose a reason for hiding this comment

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

My guess is that two separate calls is necessary, otherwise it would not work correctly.
I conclude that there is nothing to do then.

@TheJulianJES TheJulianJES added waiting for changes Waiting for changes to the PR and removed needs review This PR should be reviewed soon, as it generally looks good. labels Apr 29, 2025
Antoninj added 2 commits June 29, 2025 17:13
…nsor

- Move SENSOR_ID constant outside write_attributes method for efficiency
- Use bytes(12) instead of long lists of zeros for cleaner code
- Improve attribute handling with find_attribute for better robustness
- Add proper type annotations for better code clarity
- Update README.md to reference requirements_test_all.txt
- Run ruff formatting
@Antoninj Antoninj requested a review from TheJulianJES June 29, 2025 15:34
@Antoninj
Copy link
Author

@TheJulianJES thanks for the detailed code review, I've addressed most of the remarks.

self._float_to_hex(round(float(value)))[2:]
)

params = SENSOR_ID

Choose a reason for hiding this comment

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

This seems to break the quirk for me. I can set the TRV into external sensor mode once and set the temp, but all subsequent calls fail and it seems that the max size of the constructed message is exceeded.

It's because the SENSOR_ID variable is not copied, so appending more bytes to the params variable is modifying SENSOR_ID, which means it's then bigger to start with the next time it's run. Changing the line to

params = bytearray(SENSOR_ID)

seems to fix it for me. Might want the tests to check the length of the message args for two subsequent calls to verify this?

Copy link
Contributor

Choose a reason for hiding this comment

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

I tried the suggestion you mentioned and wrote a test for this to avoid regression.

I hope to revceive an answer from @Antoninj in regard to collaborate on this PR or if I re-create the PR with the changes.

@NJLangley
Copy link

I was having some issues with this, as it worked for the first call to set the mode to external sensor and then set the temp, but for all subsequent calls until the ZHA integrations was reloaded then failed. Digging through the stack trace for the error suggests the message exceeded the size of the window used for Zigbee comms.

The original quirk from #2802 does work, and I've left a comment on the line that needs fixing. Looks like it's not copying the byte array before building the message from it, so it's them broken when it builds the next message

@Elyasin
Copy link
Contributor

Elyasin commented Nov 3, 2025

I created a new PR that continues Antonin's work with the review comments taken into account. I added two test cases and did little refactoring, which I believe helps read the code better.

#4463

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

Labels

waiting for changes Waiting for changes to the PR Xiaomi Request/PR regarding a Xiaomi or Aqara device

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants