Skip to content

Fix sensor data retrieval for Broadlink A2 devices - #826

Open
kanshurichard wants to merge 2 commits into
mjg59:devfrom
kanshurichard:master
Open

Fix sensor data retrieval for Broadlink A2 devices#826
kanshurichard wants to merge 2 commits into
mjg59:devfrom
kanshurichard:master

Conversation

@kanshurichard

@kanshurichard kanshurichard commented Apr 3, 2025

Copy link
Copy Markdown

Hi there 👋

This PR fixes an issue that prevented Broadlink A2 air quality sensors from returning correct data. The problem was due to an incorrectly formatted packet being sent to the device when requesting sensor readings.

I’ve updated the request packet structure so that the device now responds with valid and complete data. This includes temperature, humidity, and PM10/2.5/1. The fix has been tested on a real A2 unit (4f60) and is working as expected.

Thanks for your time and effort maintaining this project! Please let me know if anything needs adjustment.

Best regards,
Kan

Context

The Broadlink A2 air quality sensor was previously unable to return valid data because the library sent incorrectly formatted request packets to the device. As a result, the response was shown as Error -5.

Proposed change

Corrected the format of the packet sent to A2 devices when requesting sensor data. With this fix, the device responds with valid data that can be parsed as expected (temperature, humidity, air quality, etc.).

Type of change

  • Bugfix (non-breaking change which fixes an issue)

Additional information

  • This PR fixes issue: N/A (no open issue was created)
  • This PR is related to:
  • Link to documentation pull request: N/A

Checklist

  • The code change is tested and works locally.
  • The code has been formatted using Black.
  • The code follows the Zen of Python.
  • I am creating the Pull Request against the correct branch.
  • Documentation added/updated.

@CloCkWeRX

Copy link
Copy Markdown

Can you point this at the dev branch please?

@kanshurichard
kanshurichard changed the base branch from master to dev March 13, 2026 03:21
@kanshurichard

Copy link
Copy Markdown
Author

Can you point this at the dev branch please?

done

DAB-LABS added a commit to DAB-LABS/python-broadlink that referenced this pull request Sep 6, 2026
A fourth review, of 1.0.3, drove the real socket path that the test suite
fakes and found two things the original library did that this one had
lost: a socket that goes bad is replaced, and a hostname that does not
resolve fails at once. This fixes both, carries one device fix from
upstream, and takes the small items along. Tested on 3.13 and 3.14, 269
tests under -X dev with ResourceWarning as an error, and live against an
RM4 Pro including a forced socket failure and a bad hostname.

Technical details:
- _Protocol.error_received and connection_lost put the error on the
  receive queue, so a waiting request fails at once with that OSError
  (send failures: no route, address gone) instead of waiting out the
  timeout. ICMP port unreachable is logged and treated as silence, which
  is what the original's unconnected socket saw, so the timeout decides
  as before.
- A request that fails for a network reason drops the endpoint; the next
  call opens a fresh socket, as the original did by opening one per call.
- scan(), ping() and send_setup_packet() resolve the destination once
  with loop.getaddrinfo and let socket.gaierror propagate; a send failure
  in ping() and setup() is raised. Nothing resolves on the loop any more.
- a2._send uses the SP4/LB1 frame layout (length 12, four-byte data
  length). The bytes match upstream mjg59#826, tested by its author on a real
  A2; the one oracle case re-recorded on purpose and noted in harness.py.
- xdiscover() closes the scan() generator it wraps; captured_at is
  excluded from CapturedSignal equality; async generator functions are
  annotated AsyncGenerator (mypy 40 to 37); TICK docstring matches the
  README.
- tests/test_loopback.py drives the real datagram endpoint, including 20
  concurrent requests and the ICMP path on loopback.
- README: errors discover()/hello() raise, the socket drop on failure,
  where CaptureInProgressError can come from.
- Version 1.0.4.

Co-authored-by: kanshurichard <29994770+kanshurichard@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants