pax_global_header00006660000000000000000000000064150133554260014516gustar00rootroot0000000000000052 comment=962de613a2eeffa2f9b5e615f955e955d02d4d82 inkbird-ble-0.16.2/000077500000000000000000000000001501335542600137665ustar00rootroot00000000000000inkbird-ble-0.16.2/.all-contributorsrc000066400000000000000000000004521501335542600176200ustar00rootroot00000000000000{ "projectName": "inkbird-ble", "projectOwner": "bluetooth-devices", "repoType": "github", "repoHost": "https://github.com", "files": ["README.md"], "imageSize": 80, "commit": true, "commitConvention": "angular", "contributors": [], "contributorsPerLine": 7, "skipCi": true } inkbird-ble-0.16.2/.editorconfig000066400000000000000000000004441501335542600164450ustar00rootroot00000000000000# http://editorconfig.org root = true [*] indent_style = space indent_size = 4 trim_trailing_whitespace = true insert_final_newline = true charset = utf-8 end_of_line = lf [*.bat] indent_style = tab end_of_line = crlf [LICENSE] insert_final_newline = false [Makefile] indent_style = tab inkbird-ble-0.16.2/.flake8000066400000000000000000000000551501335542600151410ustar00rootroot00000000000000[flake8] exclude = docs max-line-length = 88 inkbird-ble-0.16.2/.github/000077500000000000000000000000001501335542600153265ustar00rootroot00000000000000inkbird-ble-0.16.2/.github/ISSUE_TEMPLATE/000077500000000000000000000000001501335542600175115ustar00rootroot00000000000000inkbird-ble-0.16.2/.github/ISSUE_TEMPLATE/1-bug_report.md000066400000000000000000000004221501335542600223370ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve labels: bug --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: **Additional context** Add any other context about the problem here. inkbird-ble-0.16.2/.github/ISSUE_TEMPLATE/2-feature-request.md000066400000000000000000000006721501335542600233200ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project labels: enhancement --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Additional context** Add any other context or screenshots about the feature request here. inkbird-ble-0.16.2/.github/dependabot.yml000066400000000000000000000013441501335542600201600ustar00rootroot00000000000000# To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" commit-message: prefix: "chore(ci): " groups: github-actions: patterns: - "*" - package-ecosystem: "pip" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "weekly" inkbird-ble-0.16.2/.github/labels.toml000066400000000000000000000035151501335542600174710ustar00rootroot00000000000000[breaking] color = "ffcc00" name = "breaking" description = "Breaking change." [bug] color = "d73a4a" name = "bug" description = "Something isn't working" [dependencies] color = "0366d6" name = "dependencies" description = "Pull requests that update a dependency file" [github_actions] color = "000000" name = "github_actions" description = "Update of github actions" [documentation] color = "1bc4a5" name = "documentation" description = "Improvements or additions to documentation" [duplicate] color = "cfd3d7" name = "duplicate" description = "This issue or pull request already exists" [enhancement] color = "a2eeef" name = "enhancement" description = "New feature or request" ["good first issue"] color = "7057ff" name = "good first issue" description = "Good for newcomers" ["help wanted"] color = "008672" name = "help wanted" description = "Extra attention is needed" [invalid] color = "e4e669" name = "invalid" description = "This doesn't seem right" [nochangelog] color = "555555" name = "nochangelog" description = "Exclude pull requests from changelog" [question] color = "d876e3" name = "question" description = "Further information is requested" [removed] color = "e99695" name = "removed" description = "Removed piece of functionalities." [tests] color = "bfd4f2" name = "tests" description = "CI, CD and testing related changes" [wontfix] color = "ffffff" name = "wontfix" description = "This will not be worked on" [discussion] color = "c2e0c6" name = "discussion" description = "Some discussion around the project" [hacktoberfest] color = "ffa663" name = "hacktoberfest" description = "Good issues for Hacktoberfest" [answered] color = "0ee2b6" name = "answered" description = "Automatically closes as answered after a delay" [waiting] color = "5f7972" name = "waiting" description = "Automatically closes if no answer after a delay" inkbird-ble-0.16.2/.github/workflows/000077500000000000000000000000001501335542600173635ustar00rootroot00000000000000inkbird-ble-0.16.2/.github/workflows/ci.yml000066400000000000000000000046721501335542600205120ustar00rootroot00000000000000name: CI on: push: branches: - main pull_request: concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" - uses: pre-commit/action@v3.0.1 # Make sure commit messages follow the conventional commits convention: # https://www.conventionalcommits.org commitlint: name: Lint Commit Messages runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: wagoid/commitlint-github-action@v6.2.1 test: strategy: fail-fast: false matrix: python-version: - "3.11" - "3.12" - "3.13" os: - ubuntu-latest runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: snok/install-poetry@v1 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: "poetry" - name: Install Dependencies run: poetry install - name: Test with Pytest run: poetry run pytest --cov-report=xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} release: runs-on: ubuntu-latest environment: release if: github.ref == 'refs/heads/main' needs: - test - lint - commitlint permissions: id-token: write contents: write steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # Run semantic release: # - Update CHANGELOG.md # - Update version in code # - Create git tag # - Create GitHub release - name: Python Semantic Release id: release uses: python-semantic-release/python-semantic-release@v9.21.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} - name: Upload package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 if: steps.release.outputs.released == 'true' - name: Upload Github Release Assets uses: python-semantic-release/publish-action@v9.21.0 if: steps.release.outputs.released == 'true' with: github_token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ steps.release.outputs.tag }} inkbird-ble-0.16.2/.github/workflows/hacktoberfest.yml000066400000000000000000000005341501335542600227340ustar00rootroot00000000000000name: Hacktoberfest on: schedule: # Run every day in October - cron: "0 0 * 10 *" # Run on the 1st of November to revert - cron: "0 13 1 11 *" jobs: hacktoberfest: runs-on: ubuntu-latest steps: - uses: browniebroke/hacktoberfest-labeler-action@v2.3.0 with: github_token: ${{ secrets.GH_PAT }} inkbird-ble-0.16.2/.github/workflows/issue-manager.yml000066400000000000000000000013401501335542600226440ustar00rootroot00000000000000name: Issue Manager on: schedule: - cron: "0 0 * * *" issue_comment: types: - created issues: types: - labeled pull_request_target: types: - labeled workflow_dispatch: jobs: issue-manager: runs-on: ubuntu-latest steps: - uses: tiangolo/issue-manager@0.5.1 with: token: ${{ secrets.GITHUB_TOKEN }} config: > { "answered": { "message": "Assuming the original issue was solved, it will be automatically closed now." }, "waiting": { "message": "Automatically closing. To re-open, please provide the additional information requested." } } inkbird-ble-0.16.2/.github/workflows/labels.yml000066400000000000000000000007741501335542600213600ustar00rootroot00000000000000name: Sync Github labels on: push: branches: - main paths: - ".github/**" jobs: labels: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: 3.8 - name: Install labels run: pip install labels - name: Sync config with Github run: labels -u ${{ github.repository_owner }} -t ${{ secrets.GITHUB_TOKEN }} sync -f .github/labels.toml inkbird-ble-0.16.2/.gitignore000066400000000000000000000040661501335542600157640ustar00rootroot00000000000000# Created by .ignore support plugin (hsz.mobi) ### Python template # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ inkbird-ble-0.16.2/.gitpod.yml000066400000000000000000000003061501335542600160540ustar00rootroot00000000000000tasks: - command: | pip install poetry PIP_USER=false poetry install - command: | pip install pre-commit pre-commit install PIP_USER=false pre-commit install-hooks inkbird-ble-0.16.2/.idea/000077500000000000000000000000001501335542600147465ustar00rootroot00000000000000inkbird-ble-0.16.2/.idea/inkbird-ble.iml000066400000000000000000000005151501335542600176340ustar00rootroot00000000000000 inkbird-ble-0.16.2/.idea/watcherTasks.xml000066400000000000000000000052531501335542600201400ustar00rootroot00000000000000 inkbird-ble-0.16.2/.idea/workspace.xml000066400000000000000000000027271501335542600174760ustar00rootroot00000000000000 inkbird-ble-0.16.2/.pre-commit-config.yaml000066400000000000000000000030131501335542600202440ustar00rootroot00000000000000# See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks exclude: "CHANGELOG.md" default_stages: [pre-commit] ci: autofix_commit_msg: "chore(pre-commit.ci): auto fixes" autoupdate_commit_msg: "chore(pre-commit.ci): pre-commit autoupdate" repos: - repo: https://github.com/commitizen-tools/commitizen rev: v4.6.1 hooks: - id: commitizen stages: [commit-msg] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: debug-statements - id: check-builtin-literals - id: check-case-conflict - id: check-docstring-first - id: check-json - id: check-toml - id: check-xml - id: check-yaml - id: detect-private-key - id: end-of-file-fixer - id: trailing-whitespace - id: debug-statements - repo: https://github.com/pre-commit/mirrors-prettier rev: v4.0.0-alpha.8 hooks: - id: prettier args: ["--tab-width", "2"] - repo: https://github.com/asottile/pyupgrade rev: v3.19.1 hooks: - id: pyupgrade args: [--py311-plus] - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.11.8 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] - id: ruff-format - repo: https://github.com/codespell-project/codespell rev: v2.4.1 hooks: - id: codespell - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.15.0 hooks: - id: mypy additional_dependencies: [] inkbird-ble-0.16.2/.readthedocs.yml000066400000000000000000000010041501335542600170470ustar00rootroot00000000000000# Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/source/conf.py # Set the version of Python and other tools you might need build: os: ubuntu-20.04 tools: python: "3.9" # Optionally declare the Python requirements required to build your docs python: install: - method: pip path: . extra_requirements: - docs inkbird-ble-0.16.2/CHANGELOG.md000066400000000000000000000750351501335542600156110ustar00rootroot00000000000000# CHANGELOG ## v0.16.2 (2025-05-21) ### Bug Fixes - Update poetry to v2 ([#112](https://github.com/Bluetooth-Devices/inkbird-ble/pull/112), [`aed3011`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/aed301162cbccc3af277b2487458134f24be13c4)) ### Chores - Add test for 12 updates in a row from an IBS-P02B ([#109](https://github.com/Bluetooth-Devices/inkbird-ble/pull/109), [`e3f9829`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e3f98298b781d58ad1782ca04daf002769d08481)) - Add tests for real world data from IBS-P02B ([#108](https://github.com/Bluetooth-Devices/inkbird-ble/pull/108), [`c529358`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/c529358b29f4dd98f93be0558af858dffa7fc15f)) - **pre-commit.ci**: Pre-commit autoupdate ([#106](https://github.com/Bluetooth-Devices/inkbird-ble/pull/106), [`61a4076`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/61a40763626e4ca058b7be792e86d8970b697ecd)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> ## v0.16.1 (2025-05-01) ### Bug Fixes - Detection of 18 byte models ([#105](https://github.com/Bluetooth-Devices/inkbird-ble/pull/105), [`2f8e6c5`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/2f8e6c5f9a280742c550bf0e2b91ea146aff4b04)) ## v0.16.0 (2025-05-01) ### Features - Add support for IBS-P02B ([#104](https://github.com/Bluetooth-Devices/inkbird-ble/pull/104), [`4b853ef`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/4b853efdfb68c6e4446987ce66da598bba7a47cb)) ## v0.15.0 (2025-04-30) ### Chores - **deps**: Bump bluetooth-data-tools from 1.28.0 to 1.28.1 ([#100](https://github.com/Bluetooth-Devices/inkbird-ble/pull/100), [`714849a`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/714849a7f4d4f35341f73fec29e69752fd94c5bf)) - **deps**: Bump habluetooth from 3.42.0 to 3.44.0 ([#101](https://github.com/Bluetooth-Devices/inkbird-ble/pull/101), [`f379f70`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/f379f70f7e4910c2ad2e4b29decde42a9e702c15)) - **pre-commit.ci**: Pre-commit autoupdate ([#99](https://github.com/Bluetooth-Devices/inkbird-ble/pull/99), [`f4830e8`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/f4830e80702c249b4215461b9f69a03e479e811f)) ### Features - Use changed_manufacturer_data from newer bluetooth-sensor-state-data ([#103](https://github.com/Bluetooth-Devices/inkbird-ble/pull/103), [`61d4414`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/61d4414c34535ebded6bf63c6499ffac33ac1265)) ## v0.14.1 (2025-04-28) ### Bug Fixes - Ensure habluetooth is installed with Python 3.13 ([#98](https://github.com/Bluetooth-Devices/inkbird-ble/pull/98), [`e104dc1`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e104dc162ee0f1885d5cace1ba6af1405fb35837)) ## v0.14.0 (2025-04-27) ### Chores - **deps**: Bump habluetooth from 3.38.0 to 3.38.1 ([#91](https://github.com/Bluetooth-Devices/inkbird-ble/pull/91), [`23949ee`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/23949ee90043929488f7f88fe2ca5e35bdf02be6)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **deps**: Bump habluetooth from 3.38.1 to 3.39.0 ([#94](https://github.com/Bluetooth-Devices/inkbird-ble/pull/94), [`a11c38a`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/a11c38a3f6d437e68761c253e171cc37de646e67)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#90](https://github.com/Bluetooth-Devices/inkbird-ble/pull/90), [`e9d8e02`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e9d8e0206284f0f7ec4b9e17746120d4fe21c8a7)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#93](https://github.com/Bluetooth-Devices/inkbird-ble/pull/93), [`2c9ff35`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/2c9ff35f1f70eaa36be10db447007dcffc3a5922)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> ### Features - Add support for raw data parsing ([#97](https://github.com/Bluetooth-Devices/inkbird-ble/pull/97), [`af80d38`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/af80d38203d94bbfa434bf6d9a3f98ef4e3c0146)) ## v0.13.0 (2025-04-14) ### Features - Avoid a time call on each parse since its already in the service info ([#89](https://github.com/Bluetooth-Devices/inkbird-ble/pull/89), [`844bcd6`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/844bcd691cc437e55dd545f5b286d85e35bd13f8)) ## v0.12.0 (2025-04-13) ### Features - Add passive detection for the IAM-T1 ([#88](https://github.com/Bluetooth-Devices/inkbird-ble/pull/88), [`7ff42be`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/7ff42be727f0617311046beaddd4670a983744b2)) ## v0.11.0 (2025-04-13) ### Chores - **deps-dev**: Bump pytest-cov from 6.1.0 to 6.1.1 ([#87](https://github.com/Bluetooth-Devices/inkbird-ble/pull/87), [`4362c7d`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/4362c7d04013932b50b99aceda70311bf707fb09)) - **pre-commit.ci**: Pre-commit autoupdate ([#86](https://github.com/Bluetooth-Devices/inkbird-ble/pull/86), [`9df0340`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/9df0340058cee1c47b08057fdd3d32b12fb128c3)) updates: - [github.com/commitizen-tools/commitizen: v4.4.1 → v4.5.0](https://github.com/commitizen-tools/commitizen/compare/v4.4.1...v4.5.0) - [github.com/astral-sh/ruff-pre-commit: v0.11.2 → v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.2...v0.11.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> ### Features - Add support for IAM-T1 ([#85](https://github.com/Bluetooth-Devices/inkbird-ble/pull/85), [`1ad0db0`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/1ad0db09c7546b50eb7614dd4cc7326b684a2b1c)) ## v0.10.1 (2025-04-05) ### Bug Fixes - Pytest-asyncio should have been a dev dep ([#84](https://github.com/Bluetooth-Devices/inkbird-ble/pull/84), [`d767490`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/d767490f5dfb00f25c9ec5967228374096704bb2)) ## v0.10.0 (2025-04-05) ### Chores - Update deps ([#83](https://github.com/Bluetooth-Devices/inkbird-ble/pull/83), [`265bfb2`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/265bfb2a7840451600a633749f19c2f85476778f)) - Updating coverage (7.7.1 -> 7.8.0) - Updating cryptography (44.0.1 -> 44.0.2) - Downgrading home-assistant-bluetooth (1.13.1 -> 1.10.4) - Updating pytest-cov (6.0.0 -> 6.1.0) - **deps**: Bump bluetooth-data-tools from 1.26.0 to 1.26.1 ([#78](https://github.com/Bluetooth-Devices/inkbird-ble/pull/78), [`c101274`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/c101274f83fae510b0b295b6256b5e5dff3c284a)) - **deps**: Bump bluetooth-data-tools from 1.26.1 to 1.27.0 ([#80](https://github.com/Bluetooth-Devices/inkbird-ble/pull/80), [`839c14b`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/839c14bed2e71d5a818caa0080b33cc541a82c22)) chore(deps): bump bluetooth-data-tools from 1.26.1 to 1.26.2 Bumps [bluetooth-data-tools](https://github.com/bdraco/bluetooth-data-tools) from 1.26.1 to 1.26.2. - [Release notes](https://github.com/bdraco/bluetooth-data-tools/releases) - [Changelog](https://github.com/Bluetooth-Devices/bluetooth-data-tools/blob/main/CHANGELOG.md) - [Commits](https://github.com/bdraco/bluetooth-data-tools/compare/v1.26.1...v1.26.2) --- updated-dependencies: - dependency-name: bluetooth-data-tools dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **deps**: Bump sphinx from 7.4.7 to 8.2.3 ([#79](https://github.com/Bluetooth-Devices/inkbird-ble/pull/79), [`bbd4903`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/bbd490301d7d16c35956f3979eda687486f03499)) - **pre-commit.ci**: Pre-commit autoupdate ([#77](https://github.com/Bluetooth-Devices/inkbird-ble/pull/77), [`1afa92e`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/1afa92eade4e13a6c5913a4e761b35b433400c06)) * chore(pre-commit.ci): pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.10 → v0.11.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.10...v0.11.2) * chore(pre-commit.ci): auto fixes * chore: fixes --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston - **pre-commit.ci**: Pre-commit autoupdate ([#81](https://github.com/Bluetooth-Devices/inkbird-ble/pull/81), [`c271c48`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/c271c480640b181225dcfb6491107424312b72e1)) updates: - [github.com/PyCQA/flake8: 7.1.2 → 7.2.0](https://github.com/PyCQA/flake8/compare/7.1.2...7.2.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> ### Features - Add polling support for sensors ([#82](https://github.com/Bluetooth-Devices/inkbird-ble/pull/82), [`0327676`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/032767655d4580c0f2775a19517776e6fba711fb)) ## v0.9.0 (2025-03-11) ### Chores - **deps**: Bump bluetooth-data-tools from 1.23.4 to 1.26.0 ([#71](https://github.com/Bluetooth-Devices/inkbird-ble/pull/71), [`1e6ba76`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/1e6ba7694661aaef29f0cdb729df380d166ef88b)) - **deps**: Bump myst-parser from 3.0.1 to 4.0.1 ([#72](https://github.com/Bluetooth-Devices/inkbird-ble/pull/72), [`2d4851e`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/2d4851e7b8d02a87633938958415358b24f5ff8f)) - **pre-commit.ci**: Pre-commit autoupdate ([#70](https://github.com/Bluetooth-Devices/inkbird-ble/pull/70), [`66dc43f`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/66dc43f865dbf08bd76d787f125e0dc62b33d19f)) ### Features - Add support for ITH-11-B ([#75](https://github.com/Bluetooth-Devices/inkbird-ble/pull/75), [`e6e48f3`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e6e48f36ea570a0ae717dd7297837c83b50b206f)) ## v0.8.0 (2025-03-10) ### Chores - **deps**: Bump sphinx from 6.2.1 to 7.4.7 ([#67](https://github.com/Bluetooth-Devices/inkbird-ble/pull/67), [`9ae0e2c`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/9ae0e2c101553da2da8161666a203b60594ec4b5)) Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.2.1 to 7.4.7. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/v7.4.7/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v6.2.1...v7.4.7) --- updated-dependencies: - dependency-name: sphinx dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **deps-dev**: Bump pytest from 8.3.4 to 8.3.5 ([#66](https://github.com/Bluetooth-Devices/inkbird-ble/pull/66), [`1938624`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/19386243bcad5a4b8a0b18e66206af160091f7ca)) Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.4 to 8.3.5. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.3.4...8.3.5) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#65](https://github.com/Bluetooth-Devices/inkbird-ble/pull/65), [`6dd8d09`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/6dd8d0901e182caa55473cbed41a03dc840fa8ab)) updates: - [github.com/commitizen-tools/commitizen: v4.2.2 → v4.4.1](https://github.com/commitizen-tools/commitizen/compare/v4.2.2...v4.4.1) - [github.com/astral-sh/ruff-pre-commit: v0.9.7 → v0.9.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.7...v0.9.9) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> ### Features - Add support for ITH-13-B and ITH-21-B ([#69](https://github.com/Bluetooth-Devices/inkbird-ble/pull/69), [`631a28b`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/631a28b8e92e8d0c334b96692a5f8c2001e68859)) ## v0.7.1 (2025-03-01) ### Bug Fixes - Add missing humid sensor on newer TH2 models that have it ([#64](https://github.com/Bluetooth-Devices/inkbird-ble/pull/64), [`e6283ad`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e6283ada62bfe3794c37889b1a82f5e72eef1d18)) ### Chores - **ci**: Bump the github-actions group with 2 updates ([#63](https://github.com/Bluetooth-Devices/inkbird-ble/pull/63), [`0929e03`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/0929e031bc3088570cc0698dd3e2a9ad492301a2)) Bumps the github-actions group with 2 updates: [python-semantic-release/python-semantic-release](https://github.com/python-semantic-release/python-semantic-release) and [python-semantic-release/publish-action](https://github.com/python-semantic-release/publish-action). Updates `python-semantic-release/python-semantic-release` from 9.20.0 to 9.21.0 - [Release notes](https://github.com/python-semantic-release/python-semantic-release/releases) - [Changelog](https://github.com/python-semantic-release/python-semantic-release/blob/master/CHANGELOG.rst) - [Commits](https://github.com/python-semantic-release/python-semantic-release/compare/v9.20.0...v9.21.0) Updates `python-semantic-release/publish-action` from 9.20.0 to 9.21.0 - [Release notes](https://github.com/python-semantic-release/publish-action/releases) - [Changelog](https://github.com/python-semantic-release/publish-action/blob/main/releaserc.toml) - [Commits](https://github.com/python-semantic-release/publish-action/compare/v9.20.0...v9.21.0) --- updated-dependencies: - dependency-name: python-semantic-release/python-semantic-release dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: python-semantic-release/publish-action dependency-type: direct:production dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **deps**: Bump myst-parser from 1.0.0 to 3.0.1 ([#61](https://github.com/Bluetooth-Devices/inkbird-ble/pull/61), [`7708961`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/77089618c5503e6041deca0e467506e5c100bd32)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **deps**: Bump sphinx-rtd-theme from 2.0.0 to 3.0.2 ([#62](https://github.com/Bluetooth-Devices/inkbird-ble/pull/62), [`564fb88`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/564fb882bdab262af23d2d1344d445caf2a007d8)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#60](https://github.com/Bluetooth-Devices/inkbird-ble/pull/60), [`65febcf`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/65febcfd2cd9835d339ec2526c44b5114bc7f80d)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> ## v0.7.0 (2025-02-20) ### Chores - Switch to ruff ([#58](https://github.com/Bluetooth-Devices/inkbird-ble/pull/58), [`d483e9d`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/d483e9d7a194129a84f6751fa456fbe31d858dee)) - Update dependabot.yml ([`63b15b6`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/63b15b6271e55cfa12f0709790fb18e2084f3b9f)) - **ci**: Bump the github-actions group with 6 updates ([#56](https://github.com/Bluetooth-Devices/inkbird-ble/pull/56), [`ffb5b0c`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/ffb5b0ce29f7035138aaca8779bf7e09cc6c01c5)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston - **deps**: Bump sphinx from 5.3.0 to 6.2.1 ([#57](https://github.com/Bluetooth-Devices/inkbird-ble/pull/57), [`897212c`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/897212c1f3484bf54eb8ab434e67cef8002fdd52)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ### Features - Switch to GH trusted publishing for PyPI ([#59](https://github.com/Bluetooth-Devices/inkbird-ble/pull/59), [`a017e3a`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/a017e3af6d31a16a9cccdde98e27855e9e219ca0)) ## v0.6.0 (2025-02-20) ### Chores - Add poetry cache to CI ([#54](https://github.com/Bluetooth-Devices/inkbird-ble/pull/54), [`47101db`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/47101db85fb7815072014f88abcfb9b85debffcd)) - Add some adv data from an ith-21-b ([#43](https://github.com/Bluetooth-Devices/inkbird-ble/pull/43), [`b86af8a`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/b86af8a813175d7437b788da0600f7bc822e1730)) - Create dependabot.yml ([`d719e63`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/d719e63d29e064b713adf55b3f87d4b8bda06a50)) - Fix codecov ([#55](https://github.com/Bluetooth-Devices/inkbird-ble/pull/55), [`6ef0734`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/6ef07340e93605d94d35310ff496b66007c59f84)) - Update Python versions ([#52](https://github.com/Bluetooth-Devices/inkbird-ble/pull/52), [`0eed983`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/0eed98378ac0bf5cf0068124d6e1bcbc5bc3f22b)) - **deps**: Bump myst-parser from 0.18.1 to 1.0.0 ([#49](https://github.com/Bluetooth-Devices/inkbird-ble/pull/49), [`613b2ce`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/613b2cedc8cbf3292a3575428320caefd61c75a0)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **deps**: Bump sphinx-rtd-theme from 1.3.0 to 2.0.0 ([#48](https://github.com/Bluetooth-Devices/inkbird-ble/pull/48), [`e1a94a1`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e1a94a1ad46750b69cf246dd160dae18dff4f2fd)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **deps-dev**: Bump pytest from 7.4.4 to 8.3.4 ([#53](https://github.com/Bluetooth-Devices/inkbird-ble/pull/53), [`263753d`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/263753d365a3e6262f259041771e71b0d2b86a27)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **deps-dev**: Bump pytest-cov from 3.0.0 to 6.0.0 ([#51](https://github.com/Bluetooth-Devices/inkbird-ble/pull/51), [`aed72d9`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/aed72d9bd8c31251984ab8420b7145743f0e8261)) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#28](https://github.com/Bluetooth-Devices/inkbird-ble/pull/28), [`9c565a4`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/9c565a4be62d6a54d79bc7af43a2e5f62ed96cdd)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#29](https://github.com/Bluetooth-Devices/inkbird-ble/pull/29), [`5a3360f`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/5a3360fbcb6c5f99968b8c3ba9fdd85c254c3b2c)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#30](https://github.com/Bluetooth-Devices/inkbird-ble/pull/30), [`e2996c0`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e2996c0abde2e3b3722da10882f69d065304cc65)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#31](https://github.com/Bluetooth-Devices/inkbird-ble/pull/31), [`a0907bc`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/a0907bceb8120c4a0293c3ffa6bff9939b4bbc86)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#32](https://github.com/Bluetooth-Devices/inkbird-ble/pull/32), [`e64a9e0`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e64a9e0dc08927d930f773e121b2d87ff1fcbead)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#33](https://github.com/Bluetooth-Devices/inkbird-ble/pull/33), [`f175c26`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/f175c26955f7d35e50a9b20603a92cfbc6f4c880)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#36](https://github.com/Bluetooth-Devices/inkbird-ble/pull/36), [`85f9934`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/85f9934619e9faea543b58031ca78b41e4306e98)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#38](https://github.com/Bluetooth-Devices/inkbird-ble/pull/38), [`7a413de`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/7a413de6f574f01f6904ea69e0e54da12a11f64c)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#39](https://github.com/Bluetooth-Devices/inkbird-ble/pull/39), [`cb5ceea`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/cb5ceeac9d7a2dd6d923c8ca5b7ddd220ef798a3)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#40](https://github.com/Bluetooth-Devices/inkbird-ble/pull/40), [`d6244d6`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/d6244d68172e607e2783db3b511211bc441d3ae1)) - **pre-commit.ci**: Pre-commit autoupdate ([#42](https://github.com/Bluetooth-Devices/inkbird-ble/pull/42), [`cf478cc`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/cf478ccd0a97362e5a74b4e16a24342c89a5951f)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#44](https://github.com/Bluetooth-Devices/inkbird-ble/pull/44), [`fbb7572`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/fbb7572828d6f6881fa8194d821b99a43ce412b7)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> - **pre-commit.ci**: Pre-commit autoupdate ([#46](https://github.com/Bluetooth-Devices/inkbird-ble/pull/46), [`7ac44d2`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/7ac44d239b2b912c2c93406b033af9a627f39c2c)) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> ### Features - Add support for passing in the model ([#47](https://github.com/Bluetooth-Devices/inkbird-ble/pull/47), [`886b180`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/886b1805eb38f4800785b31e3a55460d9bd7b045)) ## v0.5.8 (2024-07-03) ### Bug Fixes - Handle sps broadcasting N0BYD ([#27](https://github.com/Bluetooth-Devices/inkbird-ble/pull/27), [`4686f57`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/4686f57b1864fbe7163e3f82bb6f788a137baf6a)) ## v0.5.7 (2024-07-03) ### Bug Fixes - Switch data change detection algorithm to use newer method ([#25](https://github.com/Bluetooth-Devices/inkbird-ble/pull/25), [`b41b1d6`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/b41b1d64c34c9b46ea6085c1911d2b2fc9336768)) ### Chores - Fix ci ([#26](https://github.com/Bluetooth-Devices/inkbird-ble/pull/26), [`eadb3fd`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/eadb3fdb2be292c74fd2a82a9cf019414ff452a3)) - **pre-commit.ci**: Pre-commit autoupdate ([#24](https://github.com/Bluetooth-Devices/inkbird-ble/pull/24), [`0eddeb7`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/0eddeb7f3fb184a555b1d3f1a2f40d7f72731725)) * chore(pre-commit.ci): pre-commit autoupdate updates: - [github.com/commitizen-tools/commitizen: v2.28.0 → v3.27.0](https://github.com/commitizen-tools/commitizen/compare/v2.28.0...v3.27.0) - [github.com/pre-commit/pre-commit-hooks: v4.3.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.6.0) - [github.com/pre-commit/mirrors-prettier: v2.7.1 → v4.0.0-alpha.8](https://github.com/pre-commit/mirrors-prettier/compare/v2.7.1...v4.0.0-alpha.8) - [github.com/asottile/pyupgrade: v2.37.1 → v3.16.0](https://github.com/asottile/pyupgrade/compare/v2.37.1...v3.16.0) - [github.com/PyCQA/isort: 5.12.0 → 5.13.2](https://github.com/PyCQA/isort/compare/5.12.0...5.13.2) - [github.com/psf/black: 22.6.0 → 24.4.2](https://github.com/psf/black/compare/22.6.0...24.4.2) - [github.com/codespell-project/codespell: v2.1.0 → v2.3.0](https://github.com/codespell-project/codespell/compare/v2.1.0...v2.3.0) - [github.com/PyCQA/flake8: 4.0.1 → 7.1.0](https://github.com/PyCQA/flake8/compare/4.0.1...7.1.0) - [github.com/pre-commit/mirrors-mypy: v0.931 → v1.10.1](https://github.com/pre-commit/mirrors-mypy/compare/v0.931...v1.10.1) - [github.com/PyCQA/bandit: 1.7.4 → 1.7.9](https://github.com/PyCQA/bandit/compare/1.7.4...1.7.9) * chore(pre-commit.ci): auto fixes --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> ## v0.5.6 (2023-02-06) ### Bug Fixes - Account for switching adapter when finding changed_manufacturer_data ([#20](https://github.com/Bluetooth-Devices/inkbird-ble/pull/20), [`37400d0`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/37400d0a65fe3ff347ffb554fd0da4f8b78a187f)) - Bump python-semantic-release ([#21](https://github.com/Bluetooth-Devices/inkbird-ble/pull/21), [`64d17d7`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/64d17d7d90a49f882143cc3fb079cfa6ef488bcb)) - Update isort to fix CI ([#19](https://github.com/Bluetooth-Devices/inkbird-ble/pull/19), [`174b482`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/174b4825397add3b5f878d63e44aa108b3556b7e)) ## v0.5.5 (2022-08-14) ### Bug Fixes - Use new changed_manufacturer_data helper to remove bad data ([#18](https://github.com/Bluetooth-Devices/inkbird-ble/pull/18), [`cc4fcb2`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/cc4fcb2f14f3ba468bc634621883a2cb688f9feb)) ## v0.5.4 (2022-08-14) ### Bug Fixes - Parser when there are multiple manufacturer_data fields present ([#17](https://github.com/Bluetooth-Devices/inkbird-ble/pull/17), [`a4a9047`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/a4a9047816f22f2703b1109d62cf5c22e2ee09cb)) ## v0.5.3 (2022-08-14) ### Bug Fixes - Xbbq2 bad data ([#16](https://github.com/Bluetooth-Devices/inkbird-ble/pull/16), [`76b44d5`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/76b44d5bffd36750e8316a70dc27e4148c415687)) ## v0.5.2 (2022-08-08) ### Bug Fixes - Some IBBQ2 identify with xBBQ ([#15](https://github.com/Bluetooth-Devices/inkbird-ble/pull/15), [`0ebc14c`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/0ebc14c962ab95f6e76a69194f8bcd0d784345a0)) ### Chores - Add more tests ([#14](https://github.com/Bluetooth-Devices/inkbird-ble/pull/14), [`7e8369f`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/7e8369f728de6d745925913ce2348469605377a3)) ## v0.5.1 (2022-07-21) ### Bug Fixes - Bump sensor-state-data to fix typing ([#13](https://github.com/Bluetooth-Devices/inkbird-ble/pull/13), [`e7b1610`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/e7b161063899d34ae665e39ea425beb1db468f84)) ## v0.5.0 (2022-07-21) ### Features - Refactor for sensor-state-data 2 ([#12](https://github.com/Bluetooth-Devices/inkbird-ble/pull/12), [`02d7ca1`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/02d7ca1435e3aa98b7c46f7cf6bbbf9285330973)) ## v0.4.0 (2022-07-20) ### Features - Export SensorDescription and SensorValue ([#11](https://github.com/Bluetooth-Devices/inkbird-ble/pull/11), [`d362302`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/d362302b9f707abde4a4280422788010c01ff437)) ## v0.3.2 (2022-07-20) ### Bug Fixes - Bump deps ([#9](https://github.com/Bluetooth-Devices/inkbird-ble/pull/9), [`714cb68`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/714cb686f25ee4cd647ec1aafff774a8b47522f3)) - Test names ([#10](https://github.com/Bluetooth-Devices/inkbird-ble/pull/10), [`1379ea8`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/1379ea837ad5d80f885170d1545a64a057d2663c)) ## v0.3.1 (2022-07-20) ### Bug Fixes - Ibbq parser ([#8](https://github.com/Bluetooth-Devices/inkbird-ble/pull/8), [`1844d9f`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/1844d9fa659349685265e77ba079a87d68c4c6a0)) ## v0.3.0 (2022-07-19) ### Features - Set manufacturer ([#7](https://github.com/Bluetooth-Devices/inkbird-ble/pull/7), [`d0ba693`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/d0ba693652a083f208423aca6fd7a2e6742cff2a)) ## v0.2.4 (2022-07-19) ### Bug Fixes - Add guards to avoid matching unexpected devices ([#6](https://github.com/Bluetooth-Devices/inkbird-ble/pull/6), [`3a47dd7`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/3a47dd7ba3b9da547b5f7c1f32fcafae0bb9cee9)) ## v0.2.3 (2022-07-19) ### Bug Fixes - Parsing bbq data ([#5](https://github.com/Bluetooth-Devices/inkbird-ble/pull/5), [`7b2fe02`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/7b2fe02005021c2f5c15372f795c4777fbbb3d9c)) ## v0.2.2 (2022-07-19) ### Bug Fixes - Fix processing empty mfr data ([#4](https://github.com/Bluetooth-Devices/inkbird-ble/pull/4), [`1730e18`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/1730e18e75c7f345cce39db0f5234717602c2ae8)) ## v0.2.1 (2022-07-19) ### Bug Fixes - Bump libs ([#3](https://github.com/Bluetooth-Devices/inkbird-ble/pull/3), [`7d6d00b`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/7d6d00ba3b02404cf128df26b2093a1ff9a3f36b)) ## v0.2.0 (2022-07-19) ### Features - First publish ([#2](https://github.com/Bluetooth-Devices/inkbird-ble/pull/2), [`9b0b9ba`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/9b0b9ba5114c94a046a78a018f67423cc57df61a)) ## v0.1.0 (2022-07-19) ### Chores - Initial commit ([`176cb19`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/176cb19ab5431902e705feb48d31fa660019f027)) ### Features - Init repo ([#1](https://github.com/Bluetooth-Devices/inkbird-ble/pull/1), [`2920480`](https://github.com/Bluetooth-Devices/inkbird-ble/commit/29204806c2a5a9ab1b53ea268fbb4e7e5123b624)) inkbird-ble-0.16.2/CONTRIBUTING.md000066400000000000000000000074321501335542600162250ustar00rootroot00000000000000# Contributing Contributions are welcome, and they are greatly appreciated! Every little helps, and credit will always be given. You can contribute in many ways: ## Types of Contributions ### Report Bugs Report bugs to [our issue page][gh-issues]. If you are reporting a bug, please include: - Your operating system name and version. - Any details about your local setup that might be helpful in troubleshooting. - Detailed steps to reproduce the bug. ### Fix Bugs Look through the GitHub issues for bugs. Anything tagged with "bug" and "help wanted" is open to whoever wants to implement it. ### Implement Features Look through the GitHub issues for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it. ### Write Documentation INKBIRD BLE could always use more documentation, whether as part of the official INKBIRD BLE docs, in docstrings, or even on the web in blog posts, articles, and such. ### Submit Feedback The best way to send feedback [our issue page][gh-issues] on GitHub. If you are proposing a feature: - Explain in detail how it would work. - Keep the scope as narrow as possible, to make it easier to implement. - Remember that this is a volunteer-driven project, and that contributions are welcome 😊 ## Get Started! Ready to contribute? Here's how to set yourself up for local development. 1. Fork the repo on GitHub. 2. Clone your fork locally: ```shell $ git clone git@github.com:your_name_here/inkbird-ble.git ``` 3. Install the project dependencies with [Poetry](https://python-poetry.org): ```shell $ poetry install ``` 4. Create a branch for local development: ```shell $ git checkout -b name-of-your-bugfix-or-feature ``` Now you can make your changes locally. 5. When you're done making changes, check that your changes pass our tests: ```shell $ poetry run pytest ``` 6. Linting is done through [pre-commit](https://pre-commit.com). Provided you have the tool installed globally, you can run them all as one-off: ```shell $ pre-commit run -a ``` Or better, install the hooks once and have them run automatically each time you commit: ```shell $ pre-commit install ``` 7. Commit your changes and push your branch to GitHub: ```shell $ git add . $ git commit -m "feat(something): your detailed description of your changes" $ git push origin name-of-your-bugfix-or-feature ``` Note: the commit message should follow [the conventional commits](https://www.conventionalcommits.org). We run [`commitlint` on CI](https://github.com/marketplace/actions/commit-linter) to validate it, and if you've installed pre-commit hooks at the previous step, the message will be checked at commit time. 8. Submit a pull request through the GitHub website or using the GitHub CLI (if you have it installed): ```shell $ gh pr create --fill ``` ## Pull Request Guidelines We like to have the pull request open as soon as possible, that's a great place to discuss any piece of work, even unfinished. You can use draft pull request if it's still a work in progress. Here are a few guidelines to follow: 1. Include tests for feature or bug fixes. 2. Update the documentation for significant features. 3. Ensure tests are passing on CI. ## Tips To run a subset of tests: ```shell $ pytest tests ``` ## Making a new release The deployment should be automated and can be triggered from the Semantic Release workflow in GitHub. The next version will be based on [the commit logs](https://python-semantic-release.readthedocs.io/en/latest/commit-log-parsing.html#commit-log-parsing). This is done by [python-semantic-release](https://python-semantic-release.readthedocs.io/en/latest/index.html) via a GitHub action. [gh-issues]: https://github.com/bluetooth-devices/inkbird-ble/issues inkbird-ble-0.16.2/LICENSE000066400000000000000000000020601501335542600147710ustar00rootroot00000000000000 MIT License Copyright (c) 2022 J. Nick Koston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. inkbird-ble-0.16.2/README.md000066400000000000000000000066751501335542600152630ustar00rootroot00000000000000# INKBIRD BLE

CI Status Documentation Status Test coverage percentage

Poetry black pre-commit

PyPI Version Supported Python versions License

Parser for INKBIRD BLE devices ## Installation Install this via pip (or your favourite package manager): `pip install inkbird-ble` ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! ## Credits This package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter) and the [browniebroke/cookiecutter-pypackage](https://github.com/browniebroke/cookiecutter-pypackage) project template. inkbird-ble-0.16.2/commitlint.config.mjs000066400000000000000000000003621501335542600201250ustar00rootroot00000000000000export default { extends: ["@commitlint/config-conventional"], rules: { "header-max-length": [0, "always", Infinity], "body-max-line-length": [0, "always", Infinity], "footer-max-line-length": [0, "always", Infinity], }, }; inkbird-ble-0.16.2/docs/000077500000000000000000000000001501335542600147165ustar00rootroot00000000000000inkbird-ble-0.16.2/docs/Makefile000066400000000000000000000011751501335542600163620ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = source BUILDDIR = build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) inkbird-ble-0.16.2/docs/make.bat000066400000000000000000000013741501335542600163300ustar00rootroot00000000000000@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=source set BUILDDIR=build if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% :end popd inkbird-ble-0.16.2/docs/source/000077500000000000000000000000001501335542600162165ustar00rootroot00000000000000inkbird-ble-0.16.2/docs/source/_static/000077500000000000000000000000001501335542600176445ustar00rootroot00000000000000inkbird-ble-0.16.2/docs/source/_static/.gitkeep000066400000000000000000000000001501335542600212630ustar00rootroot00000000000000inkbird-ble-0.16.2/docs/source/changelog.md000066400000000000000000000000451501335542600204660ustar00rootroot00000000000000```{include} ../../CHANGELOG.md ``` inkbird-ble-0.16.2/docs/source/conf.py000066400000000000000000000036451501335542600175250ustar00rootroot00000000000000# Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) from typing import Any # -- Project information ----------------------------------------------------- project = "INKBIRD BLE" copyright = "2020, J. Nick Koston" author = "J. Nick Koston" # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "myst_parser", ] # The suffix of source filenames. source_suffix = [".rst", ".md"] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns: list[Any] = [] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = "sphinx_rtd_theme" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] inkbird-ble-0.16.2/docs/source/contributing.md000066400000000000000000000000501501335542600212420ustar00rootroot00000000000000```{include} ../../CONTRIBUTING.md ``` inkbird-ble-0.16.2/docs/source/index.md000066400000000000000000000003531501335542600176500ustar00rootroot00000000000000# Welcome to INKBIRD BLE documentation! ```{toctree} :caption: Installation & Usage :maxdepth: 2 installation usage ``` ```{toctree} :caption: Project Info :maxdepth: 2 changelog contributing ``` ```{include} ../../README.md ``` inkbird-ble-0.16.2/docs/source/installation.md000066400000000000000000000002661501335542600212450ustar00rootroot00000000000000# Installation The package is published on [PyPI](https://pypi.org/project/deezer-python/) and can be installed with `pip` (or any equivalent): ```bash pip install inkbird-ble ``` inkbird-ble-0.16.2/docs/source/usage.md000066400000000000000000000001411501335542600176400ustar00rootroot00000000000000# Usage To use this package, import it: ```python import inkbird_ble ``` TODO: Document usage inkbird-ble-0.16.2/poetry.lock000066400000000000000000004422761501335542600162010ustar00rootroot00000000000000# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. [[package]] name = "aiooui" version = "0.1.9" description = "Async OUI lookups" optional = false python-versions = "<4.0,>=3.9" groups = ["main"] files = [ {file = "aiooui-0.1.9-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:64d904b43f14dd1d8d9fcf1684d9e2f558bc5e0bd68dc10023c93355c9027907"}, {file = "aiooui-0.1.9-py3-none-any.whl", hash = "sha256:737a5e62d8726540218c2b70e5f966d9912121e4644f3d490daf8f3c18b182e5"}, {file = "aiooui-0.1.9.tar.gz", hash = "sha256:e8c8bc59ab352419e0747628b4cce7c4e04d492574c1971e223401126389c5d8"}, ] [[package]] name = "alabaster" version = "1.0.0" description = "A light, configurable Sphinx theme" optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"}, {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, ] [[package]] name = "async-interrupt" version = "1.2.2" description = "Context manager to raise an exception when a future is done" optional = false python-versions = ">=3.9" groups = ["main"] files = [ {file = "async_interrupt-1.2.2-py3-none-any.whl", hash = "sha256:0a8deb884acfb5fe55188a693ae8a4381bbbd2cb6e670dac83869489513eec2c"}, {file = "async_interrupt-1.2.2.tar.gz", hash = "sha256:be4331a029b8625777905376a6dc1370984c8c810f30b79703f3ee039d262bf7"}, ] [[package]] name = "babel" version = "2.17.0" description = "Internationalization utilities" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, ] [package.extras] dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] [[package]] name = "bleak" version = "0.22.3" description = "Bluetooth Low Energy platform Agnostic Klient" optional = false python-versions = "<3.14,>=3.8" groups = ["main"] files = [ {file = "bleak-0.22.3-py3-none-any.whl", hash = "sha256:1e62a9f5e0c184826e6c906e341d8aca53793e4596eeaf4e0b191e7aca5c461c"}, {file = "bleak-0.22.3.tar.gz", hash = "sha256:3149c3c19657e457727aa53d9d6aeb89658495822cd240afd8aeca4dd09c045c"}, ] [package.dependencies] bleak-winrt = {version = ">=1.2.0,<2.0.0", markers = "platform_system == \"Windows\" and python_version < \"3.12\""} dbus-fast = {version = ">=1.83.0,<3", markers = "platform_system == \"Linux\""} pyobjc-core = {version = ">=10.3,<11.0", markers = "platform_system == \"Darwin\""} pyobjc-framework-CoreBluetooth = {version = ">=10.3,<11.0", markers = "platform_system == \"Darwin\""} pyobjc-framework-libdispatch = {version = ">=10.3,<11.0", markers = "platform_system == \"Darwin\""} typing-extensions = {version = ">=4.7.0", markers = "python_version < \"3.12\""} winrt-runtime = {version = ">=2,<3", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""} "winrt-Windows.Devices.Bluetooth" = {version = ">=2,<3", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""} "winrt-Windows.Devices.Bluetooth.Advertisement" = {version = ">=2,<3", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""} "winrt-Windows.Devices.Bluetooth.GenericAttributeProfile" = {version = ">=2,<3", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""} "winrt-Windows.Devices.Enumeration" = {version = ">=2,<3", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""} "winrt-Windows.Foundation" = {version = ">=2,<3", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""} "winrt-Windows.Foundation.Collections" = {version = ">=2,<3", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""} "winrt-Windows.Storage.Streams" = {version = ">=2,<3", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""} [[package]] name = "bleak-retry-connector" version = "3.10.0" description = "A connector for Bleak Clients that handles transient connection failures" optional = false python-versions = ">=3.10" groups = ["main"] files = [ {file = "bleak_retry_connector-3.10.0-py3-none-any.whl", hash = "sha256:caaf976320ef280f1145b557bf3b13697f71ef2c1070e1dc643709eb2d29fb1f"}, {file = "bleak_retry_connector-3.10.0.tar.gz", hash = "sha256:a95172bd56d2af677fb9e250291cde8c70d8f72381d423f64e48c828dffbc93b"}, ] [package.dependencies] bleak = {version = ">=0.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.14\""} bluetooth-adapters = {version = ">=0.15.2", markers = "python_version >= \"3.10\" and python_version < \"3.14\" and platform_system == \"Linux\""} dbus-fast = {version = ">=1.14.0", markers = "platform_system == \"Linux\""} [[package]] name = "bleak-winrt" version = "1.2.0" description = "Python WinRT bindings for Bleak" optional = false python-versions = "*" groups = ["main"] markers = "platform_system == \"Windows\" and python_version == \"3.11\"" files = [ {file = "bleak-winrt-1.2.0.tar.gz", hash = "sha256:0577d070251b9354fc6c45ffac57e39341ebb08ead014b1bdbd43e211d2ce1d6"}, {file = "bleak_winrt-1.2.0-cp310-cp310-win32.whl", hash = "sha256:a2ae3054d6843ae0cfd3b94c83293a1dfd5804393977dd69bde91cb5099fc47c"}, {file = "bleak_winrt-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:677df51dc825c6657b3ae94f00bd09b8ab88422b40d6a7bdbf7972a63bc44e9a"}, {file = "bleak_winrt-1.2.0-cp311-cp311-win32.whl", hash = "sha256:9449cdb942f22c9892bc1ada99e2ccce9bea8a8af1493e81fefb6de2cb3a7b80"}, {file = "bleak_winrt-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:98c1b5a6a6c431ac7f76aa4285b752fe14a1c626bd8a1dfa56f66173ff120bee"}, {file = "bleak_winrt-1.2.0-cp37-cp37m-win32.whl", hash = "sha256:623ac511696e1f58d83cb9c431e32f613395f2199b3db7f125a3d872cab968a4"}, {file = "bleak_winrt-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:13ab06dec55469cf51a2c187be7b630a7a2922e1ea9ac1998135974a7239b1e3"}, {file = "bleak_winrt-1.2.0-cp38-cp38-win32.whl", hash = "sha256:5a36ff8cd53068c01a795a75d2c13054ddc5f99ce6de62c1a97cd343fc4d0727"}, {file = "bleak_winrt-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:810c00726653a962256b7acd8edf81ab9e4a3c66e936a342ce4aec7dbd3a7263"}, {file = "bleak_winrt-1.2.0-cp39-cp39-win32.whl", hash = "sha256:dd740047a08925bde54bec357391fcee595d7b8ca0c74c87170a5cbc3f97aa0a"}, {file = "bleak_winrt-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:63130c11acfe75c504a79c01f9919e87f009f5e742bfc7b7a5c2a9c72bf591a7"}, ] [[package]] name = "bluetooth-adapters" version = "0.21.4" description = "Tools to enumerate and find Bluetooth Adapters" optional = false python-versions = ">=3.9" groups = ["main"] files = [ {file = "bluetooth_adapters-0.21.4-py3-none-any.whl", hash = "sha256:ce2e8139cc9d7b103c21654c6309507979e469aae3efebcaeee9923080b0569b"}, {file = "bluetooth_adapters-0.21.4.tar.gz", hash = "sha256:a5a809ef7ba95ee673a78704f90ce34612deb3696269d1a6fd61f98642b99dd3"}, ] [package.dependencies] aiooui = ">=0.1.1" bleak = ">=0.21.1" dbus-fast = {version = ">=1.21.0", markers = "platform_system == \"Linux\""} uart-devices = ">=0.1.0" usb-devices = ">=0.4.5" [package.extras] docs = ["Sphinx (>=5,<8)", "myst-parser (>=0.18,<3.1)", "sphinx-rtd-theme (>=1,<4)"] [[package]] name = "bluetooth-auto-recovery" version = "1.4.5" description = "Recover bluetooth adapters that are in an stuck state" optional = false python-versions = "<4.0,>=3.9" groups = ["main"] files = [ {file = "bluetooth_auto_recovery-1.4.5-py3-none-any.whl", hash = "sha256:a55667366cbc29808877092ecd98e4ffc87957fb5012755904f766f2a42f52f0"}, {file = "bluetooth_auto_recovery-1.4.5.tar.gz", hash = "sha256:1c7c231bb53262bea8d15e72601ea0c839c3c6e5f840cd1c752e5c137b23aa17"}, ] [package.dependencies] bluetooth-adapters = ">=0.16.0" btsocket = ">=0.2.0" PyRIC = ">=0.1.6.3" usb-devices = ">=0.4.1" [package.extras] docs = ["Sphinx (>=5,<8)", "myst-parser (>=0.18,<3.1)", "sphinx-rtd-theme (>=1,<4)"] [[package]] name = "bluetooth-data-tools" version = "1.28.1" description = "Tools for converting bluetooth data and packets" optional = false python-versions = ">=3.10" groups = ["main"] files = [ {file = "bluetooth_data_tools-1.28.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3a1d77ec99e4a3d8d7fc64f7a0891440ecd8b88d2bbdfbf5367e1d9beddcff41"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:539b6578885b4fb71186035e0c49e616cdd5ef84afa2d6a3f5fab18e7b8ea52d"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3389f6f3d4e2dfc1708b179a113a60290c8a33710a7b02534978a6cef42f9cca"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a77c7ba723ae1b97e0d9b260d77bb0f578e7356a87a9f74b319e9277f7df602"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:965c1bf9c89e61a3055524c20c468c2953fb6a9ab5b40bb6369767855920fbbc"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-manylinux_2_31_armv7l.manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:961e145e71c3266705ade6da069ecc34896cb2759a1b5638db15cf18ec2ef0b4"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c5671ec965aff0b6e22de150b221413fb5d195429b73e623cd8935391652127f"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:8ff4cefe9734145e3ddd7f21709c82e7b569ec674f252c35ac4a45a947399f40"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3d204b2508214ea895daabd5b6428e71949eefe4cc30fbe1be0feda960767bb9"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ef02152ab79226bd7909a1a48d4c4c8797f9e83b56a6b233fc5c4f56e8670154"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-win32.whl", hash = "sha256:5fc8d37470c841999695f68932a3956aea90cfbac2781a6bce8d81c083f76802"}, {file = "bluetooth_data_tools-1.28.1-cp310-cp310-win_amd64.whl", hash = "sha256:4fa7db50ca5ad66d0578b6af4a9e82502c6f1248db8d856b18d5490a6b90bc99"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e711e28b1d7bf07dea4a47d9dfd46355b30fb903607f5075339d9b98a074dbe"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:590b65a2a3b72c31ab37c103bc1fb0727880672783c33c857e6e95dd9233fe8e"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:349fb3c30d1839c74485efa142be565103b9b821e1d3c35cdd4a1f268e4e3809"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:825568201917b102f0204b22351bc854c77f530b26269c291e5f2d868e88349d"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4225ff50c81f5b282e2967f7de6338a34e725f28a5769372e1dd4c1fbaa5f622"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-manylinux_2_31_armv7l.manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:88c72a520456004c415cc3b5802636c129c230c23a078a495531e1b3894fec06"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95735992c0df6f4259d76bea825f685484c4fa937184847377d1f2b69730b3a3"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e2d235d8b2c3ebf05df32df18db93e25dd8102d1c495a6010788bb7d15e60f16"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4218206a57db713d889f79aa6db11cd36df678532995ab4314a276142c9393af"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9061d8725a5681cf8ec8911282673f63a25dfb6c5d8134b84e916b0831e46f9c"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-win32.whl", hash = "sha256:4ca9c4ce92233ad2415fd33142914490c104abf2fbe2a220326f12810e5575a9"}, {file = "bluetooth_data_tools-1.28.1-cp311-cp311-win_amd64.whl", hash = "sha256:93f6466c2ad2945d6f2ccdad2a291efa46f5f0eab6c353830f5944d44b46c168"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae766a43303b897be1739d3c740d2bd59981c8f9c0681b316c3b9102787aa332"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13ebe3d99edf00ac0474f0252d364321be970f509c3c91d985459ba7de32b57b"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828c74ac6b41b2044eb26b282aacc2d04d8845409fe0c09b934cf5d436818516"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:593bf0e67575c6c3624df8761d15912429745704c901de27e643976a07e3d247"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:440cb050054c2cb33ccb2898873da9b35c529d77622c95dc381a64b540fd6997"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-manylinux_2_31_armv7l.manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91fdd90d4cc2c25b1cf9e5d420b63daa7c32b56337851d7a6d91738fbc0308e9"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c884e73f32ee68bafbb0e05339f850649daa745a22fba5818b7845c91c0e162"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a8bd5a430451977ca08f8dbd4ca7a1bb016ba70c1f4126831466999fd547be2f"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e9812fa5c50672898d4da1e901f736f6452437edc8788f674dc024595b0f4254"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:beaf78826e2b01aed00bdc66fc2d2a841899d57fbb7c1776cf1e7f4ee6ade9a0"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-win32.whl", hash = "sha256:e20634afd47cc80edcf5975892ea1d3a25f1d8f0fc9c45617c2e2f5db5e5ebe9"}, {file = "bluetooth_data_tools-1.28.1-cp312-cp312-win_amd64.whl", hash = "sha256:5b4e6329b26a3562e770bb1ce0f5b7a6e03d749f18d39ea8c3e7ff491d10f550"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c75802ff3576bd1f1e78934aed3f8bab3d3138d77b4ba47e024f4cb9c4e638f0"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e41d6643f2bfad77944515ad9a8d673539beca5bcccb3d9367255e452dd0c04e"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8249a8ffba384c2f3cfa464497d900b3040ca0fb94acaed7e7d43c963b8579"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1255c0c93846ab25ee9beab0670ca1a1aaee7912492cf74d2f77e54b61d81dda"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4598bf2d8eacca632c15b3c95e9a1bcc74bec392b823f1484df3e6f3df6d2024"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-manylinux_2_31_armv7l.manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b08d346fa13846312082e5a7ada84ef4d4f9f24ff710da1e328edc04faa1d9c8"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-manylinux_2_36_x86_64.whl", hash = "sha256:39f913ba76ce17a7664617941bab688597a7391c4065580de3fe354ddd71eb7b"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:493240081f1331e362c84b8a2c369e3f2c8cc35e3ffdf9eccd1366bed86565e6"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:76f72f64816352ecd3fd20c569e4ced1fd47fec5c2c5302b5560117d09085d14"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b28673e1b55664ed2bf475d9f985f3e860a03d697e59f43238b3457bef7776fb"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0d5b738088f0fc593e69817b3404dbf09b559842fab6027f7176eeca0438e831"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-win32.whl", hash = "sha256:1e96114fd3ad87d12631ba591c8b942ff27383ad4b310a2df230b2bbc2863532"}, {file = "bluetooth_data_tools-1.28.1-cp313-cp313-win_amd64.whl", hash = "sha256:0e3a7331fcd837025bb294af6790c7f61b56fd4aa0886434660dffab35ef422c"}, {file = "bluetooth_data_tools-1.28.1.tar.gz", hash = "sha256:47156468b220f4c7b3ed2e29b189fd782785b7a551ad5c61fecfe023dc4f6430"}, ] [package.dependencies] cryptography = ">=41.0.3" [package.extras] docs = ["Sphinx (>=5,<9)", "myst-parser (>=0.18,<4.1)", "sphinx-rtd-theme (>=1,<4)"] [[package]] name = "bluetooth-sensor-state-data" version = "1.8.0" description = "Models for storing and converting Bluetooth Sensor State Data" optional = false python-versions = ">=3.11" groups = ["main"] files = [ {file = "bluetooth_sensor_state_data-1.8.0-py3-none-any.whl", hash = "sha256:c001541d176da0071dd96b63e6327e7afa158c88726fd638b77042d8d823ca6c"}, {file = "bluetooth_sensor_state_data-1.8.0.tar.gz", hash = "sha256:b97a6c29da8b1c430e2524c1b1267e9981bee15d5cdf49f33c8b6e40ed69c9e8"}, ] [package.dependencies] bluetooth-data-tools = ">=1.28.0" habluetooth = ">=3.42.0" sensor-state-data = ">=2.0" [package.extras] docs = ["Sphinx (>=5,<8)", "myst-parser (>=0.18,<3.1)", "sphinx-rtd-theme (>=1,<4)"] [[package]] name = "btsocket" version = "0.3.0" description = "Python library for BlueZ Bluetooth Management API" optional = false python-versions = "*" groups = ["main"] files = [ {file = "btsocket-0.3.0-py2.py3-none-any.whl", hash = "sha256:949821c1b580a88e73804ad610f5173d6ae258e7b4e389da4f94d614344f1a9c"}, {file = "btsocket-0.3.0.tar.gz", hash = "sha256:7ea495de0ff883f0d9f8eea59c72ca7fed492994df668fe476b84d814a147a0d"}, ] [package.extras] dev = ["bumpversion", "coverage", "pycodestyle", "pygments", "sphinx", "sphinx-rtd-theme", "twine"] docs = ["pygments", "sphinx", "sphinx-rtd-theme"] rel = ["bumpversion", "twine"] test = ["coverage", "pycodestyle"] [[package]] name = "certifi" version = "2025.1.31" description = "Python package for providing Mozilla's CA Bundle." optional = true python-versions = ">=3.6" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, ] [[package]] name = "cffi" version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" groups = ["main"] markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] pycparser = "*" [[package]] name = "charset-normalizer" version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = true python-versions = ">=3.7" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, ] [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] markers = {main = "extra == \"docs\" and sys_platform == \"win32\"", dev = "sys_platform == \"win32\""} [[package]] name = "coverage" version = "7.8.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe"}, {file = "coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28"}, {file = "coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3"}, {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676"}, {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d"}, {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a"}, {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c"}, {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f"}, {file = "coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f"}, {file = "coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23"}, {file = "coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27"}, {file = "coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea"}, {file = "coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7"}, {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040"}, {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543"}, {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2"}, {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318"}, {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9"}, {file = "coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c"}, {file = "coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78"}, {file = "coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc"}, {file = "coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6"}, {file = "coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d"}, {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05"}, {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a"}, {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6"}, {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47"}, {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe"}, {file = "coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545"}, {file = "coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b"}, {file = "coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd"}, {file = "coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00"}, {file = "coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64"}, {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067"}, {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008"}, {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733"}, {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323"}, {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3"}, {file = "coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d"}, {file = "coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487"}, {file = "coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25"}, {file = "coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42"}, {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502"}, {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1"}, {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4"}, {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73"}, {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a"}, {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883"}, {file = "coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada"}, {file = "coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257"}, {file = "coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f"}, {file = "coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a"}, {file = "coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82"}, {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814"}, {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c"}, {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd"}, {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4"}, {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899"}, {file = "coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f"}, {file = "coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3"}, {file = "coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd"}, {file = "coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7"}, {file = "coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501"}, ] [package.extras] toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" version = "44.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" groups = ["main"] files = [ {file = "cryptography-44.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308"}, {file = "cryptography-44.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688"}, {file = "cryptography-44.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7"}, {file = "cryptography-44.0.2-cp37-abi3-win32.whl", hash = "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79"}, {file = "cryptography-44.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa"}, {file = "cryptography-44.0.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3"}, {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639"}, {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd"}, {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181"}, {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea"}, {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699"}, {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9"}, {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23"}, {file = "cryptography-44.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922"}, {file = "cryptography-44.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4"}, {file = "cryptography-44.0.2-cp39-abi3-win32.whl", hash = "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5"}, {file = "cryptography-44.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6"}, {file = "cryptography-44.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb"}, {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41"}, {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562"}, {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5"}, {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa"}, {file = "cryptography-44.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d"}, {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d"}, {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471"}, {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615"}, {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390"}, {file = "cryptography-44.0.2.tar.gz", hash = "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0"}, ] [package.dependencies] cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] test = ["certifi (>=2024)", "cryptography-vectors (==44.0.2)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] test-randomorder = ["pytest-randomly"] [[package]] name = "dbus-fast" version = "2.44.1" description = "A faster version of dbus-next" optional = false python-versions = ">=3.9" groups = ["main"] markers = "platform_system == \"Linux\"" files = [ {file = "dbus_fast-2.44.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c78a004ba43aeaf203a19169d2b4be238375905645999da30cb0da730df80cf2"}, {file = "dbus_fast-2.44.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65a634286651398f3f1326e8200fc54289d52c2c00249d29cacfc691660a5da1"}, {file = "dbus_fast-2.44.1-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:0c4a128f8b29941307fc5722f37a1bb87ddcf733188d917ab374d9da0c6e1ce7"}, {file = "dbus_fast-2.44.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adaf459fbce22a63d3578f3ec782c6978edf975eb06d71fb5b7a690496cf6bbe"}, {file = "dbus_fast-2.44.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:de871cf722c436bdcceb96b2a3af7084e1fa468f7916ae278ec8ec49a6fa7eef"}, {file = "dbus_fast-2.44.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b40863de172031bcc02f54c6f05cccb0b882dc2e1b09e11314a8ccf38c558760"}, {file = "dbus_fast-2.44.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8b7ae16555df6b56d3befcc51e036779ef47c0e954fdb9fb0821ac25212aefe9"}, {file = "dbus_fast-2.44.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a220a28e88062a2548f0c6da9eb15fb7e3af70eae56729fc3795ce3e3fba057d"}, {file = "dbus_fast-2.44.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ec5db912bd4cfeadf7134163d6dde684271cd44cf26e3b4720107f3de406623"}, {file = "dbus_fast-2.44.1-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:6ad99f626837753b39a39e09facd2091ee4851ee1eb6ebec5fa9a9a231734254"}, {file = "dbus_fast-2.44.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7aa157f689a114bfb5367c55884d35e25d57cf25202a6590ce05010f929e7df"}, {file = "dbus_fast-2.44.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f961d8bcad80359f24c0156b3094f58a87d583d56139ee50922fe5894b6797cf"}, {file = "dbus_fast-2.44.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1f38fb5c31846c3ada8fc2b693d8d19953d376a9ea21079e3686e93faa1f8a0f"}, {file = "dbus_fast-2.44.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:35e3cde53cc9180ce95c6c84a1e8d1ded429031e4a0a182606e8d22cf57d3294"}, {file = "dbus_fast-2.44.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f30fb09f1ea13658fb4316511e27d6b94f8363b16f2d093efe73e6e289b740"}, {file = "dbus_fast-2.44.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dd0f8d41f6ab9d4a782c116470bc319d690f9b50c97b6debc6d1fef08e4615a"}, {file = "dbus_fast-2.44.1-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:9d6e386658343db380b9e4e81b3bf4e3c17135dbb5889173b1f2582b675b9a8c"}, {file = "dbus_fast-2.44.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bd27563c11219b6fde7a5458141d860d8445c2defb036bab360d1f9bf1dfae0"}, {file = "dbus_fast-2.44.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0272784aceac821dd63c8187a8860179061a850269617ff5c5bd25ca37bf9307"}, {file = "dbus_fast-2.44.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:eed613a909a45f0e0a415c88b373024f007a9be56b1316812ed616d69a3b9161"}, {file = "dbus_fast-2.44.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0d4288f2cba4f8309dcfd9f4392e0f4f2b5be6c796dfdb0c5e03228b1ab649b1"}, {file = "dbus_fast-2.44.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50a9a4c6921f4b7446717fb4869750f54b561ce486b25b36550cb2a910c988d9"}, {file = "dbus_fast-2.44.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89dc5db158bf9838979f732acc39e0e1ecd7e3295a09fa8adb93b09c097615a4"}, {file = "dbus_fast-2.44.1-cp313-cp313-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:f11878c0c089d278861e48c02db8002496c2233b0f605b5630ef61f0b7fb0ea3"}, {file = "dbus_fast-2.44.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd81f483b3ffb71e88478cfabccc1fab8d7154fccb1c661bfafcff9b0cfd996"}, {file = "dbus_fast-2.44.1-cp313-cp313-manylinux_2_36_x86_64.whl", hash = "sha256:ad499de96a991287232749c98a59f2436ed260f6fd9ad4cb3b04a4b1bbbef148"}, {file = "dbus_fast-2.44.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36c44286b11e83977cd29f9551b66b446bb6890dff04585852d975aa3a038ca2"}, {file = "dbus_fast-2.44.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:89f2f6eccbb0e464b90e5a8741deb9d6a91873eeb41a8c7b963962b39eb1e0cd"}, {file = "dbus_fast-2.44.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb74a227b071e1a7c517bf3a3e4a5a0a2660620084162e74f15010075534c9d5"}, {file = "dbus_fast-2.44.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e3719399e687359b0ef66af1b720661dd4f12059db1c4f506e678569a2256b4"}, {file = "dbus_fast-2.44.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:806450623ef3f8df846524da7e448edc8174261a01cfd5dfda92e3df89c0de10"}, {file = "dbus_fast-2.44.1-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:55ad499b7ef08cb76fce9c9fdcdd6589d2ebfc7e53b3d261d8f40c6d97a8d901"}, {file = "dbus_fast-2.44.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55d717865219ec2ae9977b6d067c05261cdc3ef6205c687c8bb92b3437886e58"}, {file = "dbus_fast-2.44.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:39d4cc61e491e11912f76d70cc1c47387ab4f2e5b71f34bfa13eb11aa6026268"}, {file = "dbus_fast-2.44.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9b3b10151f1140f7b6dd47a89fc37edd05d6213be0a1748eadba82fc144c05c2"}, {file = "dbus_fast-2.44.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:33772c223f5cef1bacc298e83dc04b27b3a47065b245fde766fcc126e761dca7"}, {file = "dbus_fast-2.44.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:80e3f42f982af45bcfa0ff23e808f3aa54a45fe4bf43aadd3beb5ace816fba76"}, {file = "dbus_fast-2.44.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f29a81d86c9ce3020a5df8c1e5557edaa00e1e00c9804ec874d46c99d967a686"}, {file = "dbus_fast-2.44.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:5dec134715457601c0fa8df3040a56d319de1a152464ae4d4bfc53bbb5c02e04"}, {file = "dbus_fast-2.44.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:893509b516f2f24b4e3f09a6b1f3a30f856cf237cd773cdc505ea7ab4fa3c863"}, {file = "dbus_fast-2.44.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:db81275d708774f6a17c89f2e063398c0deb358c4d22b663a3dd99861f6683a4"}, {file = "dbus_fast-2.44.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:161a3e6fc8783c30c9feb072e09604d96ec0c465b06bd35b6acc1a0316bd2a27"}, {file = "dbus_fast-2.44.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:67febe6454e714d85a532bd84969001ed948bbaf1699a7e1e4c6abb5508c9522"}, {file = "dbus_fast-2.44.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:890f0fc046d5db66524ddedeca8c14b65739fbbf32d6488175c07428362bf250"}, {file = "dbus_fast-2.44.1.tar.gz", hash = "sha256:b027e96c39ed5622bb54d811dcdbbe9d9d6edec3454808a85a1ceb1867d9e25c"}, ] [[package]] name = "docutils" version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] [[package]] name = "habluetooth" version = "3.44.0" description = "High availability Bluetooth" optional = false python-versions = ">=3.11" groups = ["main"] files = [ {file = "habluetooth-3.44.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d40ee0ce2bd0123c7ae14a72071fa6927e125590e133c5e5a01ca90792291dd"}, {file = "habluetooth-3.44.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:721a9ad0eb06a5e64d57691f7010b27112cfc7ead9894675d8d494a21588b86f"}, {file = "habluetooth-3.44.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01acd300bf059fc017c5770dc616d54e4130244fe116e8b878c8dfcfaaab5a2a"}, {file = "habluetooth-3.44.0-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:055bb380c33725318490279d5dc3343093871e7f18a75655f57c69cbc82bdf37"}, {file = "habluetooth-3.44.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271479a8bfe16bab713b5fc0c5b31e4974d34625ce22030a18f83f7e1c500142"}, {file = "habluetooth-3.44.0-cp311-cp311-manylinux_2_31_armv7l.manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73ff0bea2860d65df967e6211ef1005f288e22358acde1e5c8aec1d021ffc8ba"}, {file = "habluetooth-3.44.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2359ee0cee3871dea3d9a0a82cf75d674b010d4b3de270b677c251780f8dca55"}, {file = "habluetooth-3.44.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:874b0ecf397b04ae687eca2ed51d63943a9dc695b1ef99249b5571eebc71cf3e"}, {file = "habluetooth-3.44.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b67e30b7cd6d067658a7eabab882f69b3b05d2947391c786451f43130cf88abc"}, {file = "habluetooth-3.44.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fefd78a7fa5e7dafb54df5e3cf8e953478c05d41a3c3367932a3ba8878c84e3"}, {file = "habluetooth-3.44.0-cp311-cp311-win32.whl", hash = "sha256:07481b9a93336b143805b30346e0b76015348d11ee208825d8604a4a8fbb7bdd"}, {file = "habluetooth-3.44.0-cp311-cp311-win_amd64.whl", hash = "sha256:3cc3423d81152489c8f5b312bc6249d1d112386c0392a3c8c5b7b820fbb402b1"}, {file = "habluetooth-3.44.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8efb7330214bad087a67bef795d4674a4afeaf074902db57de6eaafd28171e29"}, {file = "habluetooth-3.44.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:22344f1ea442c57aaa043dbd634bc4aad246e8d6f230bbdc1f78aeade6d84cba"}, {file = "habluetooth-3.44.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89585b7804bf055faa95fcd7161b1ca2b40c96c429db2932b409df1a5102958b"}, {file = "habluetooth-3.44.0-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:1bdfc1d227508aba4ea5580bd10b9595dd391afd3e76d4ea31ca4b06d3faf404"}, {file = "habluetooth-3.44.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cd14770ccf8cce76d338beb7614d87a7677392262f64ea034264e7bf90689b"}, {file = "habluetooth-3.44.0-cp312-cp312-manylinux_2_31_armv7l.manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:94be53edb6922f86aa3a520536c620e261549e56b1b73bf24293aada6739ff0a"}, {file = "habluetooth-3.44.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5c3b93bbc487dfb7f5e4b59f1304a4afdcefe71ae9acf2f0d106e573b297912c"}, {file = "habluetooth-3.44.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:051d86459d9a97d86f43876a03fdfffb171e7b89b20b0d606b67351117d38d6a"}, {file = "habluetooth-3.44.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3b9d2dc11a0932c1ee8e5663f0de59a33d516ef2ea1a64eb2b8667de07726570"}, {file = "habluetooth-3.44.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5c4d5e96dc9ed0d21046904e9bffd41d833b732ba62e349c0eb1917ab40b10e"}, {file = "habluetooth-3.44.0-cp312-cp312-win32.whl", hash = "sha256:774fc29fd89ba8e8056ba6b61d7984966e3a60d93cd80cd58f5cb80430b9562e"}, {file = "habluetooth-3.44.0-cp312-cp312-win_amd64.whl", hash = "sha256:a90578440052f6b09e2c791c8b1a14439cb6d935e1d1bdbfa96369bf4936c64f"}, {file = "habluetooth-3.44.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:765cef13658b10f754cd798e8eca85972c39639602aacf9a5f8666323c41b991"}, {file = "habluetooth-3.44.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e98eb44b5b6b0853128bd50861640771833464aa0fc28e1a5a7962fd6f495ade"}, {file = "habluetooth-3.44.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ba284442230f8e8f0b7da9e08180b57c603e159cb92c9e0a93db27e67a7f533"}, {file = "habluetooth-3.44.0-cp313-cp313-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:704bc7fbea21463b43f6252da687bb7cdd7cf354eeadf162121c3a488e360d7e"}, {file = "habluetooth-3.44.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe46fd82bd12e880c82cc0ccaff48e99e65e374421495dc13782582aaafc64d0"}, {file = "habluetooth-3.44.0-cp313-cp313-manylinux_2_31_armv7l.manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ddda83f21e055bea292ff70bac01e61a7c9bd3da1c85b61ad1821bc778749cc4"}, {file = "habluetooth-3.44.0-cp313-cp313-manylinux_2_36_x86_64.whl", hash = "sha256:5052488b18b352e287f569cf6d66268d486753a62bf93e02301b802e2923df21"}, {file = "habluetooth-3.44.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2b92c7bf02e3d527f0a2ce8366d1ac5dfa80073376d8a4cca26da2db6121f522"}, {file = "habluetooth-3.44.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:527c59c9a78f8c604a6f756a51887a780d4c4b0f4c364b05bca428047f659ad8"}, {file = "habluetooth-3.44.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:20f84969baad2faea0bc9ea1ef063cf31c8702c26e61fa7203512a8af1e5e6b1"}, {file = "habluetooth-3.44.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70eb748fdf96ed698ed5c4734b4f429b86e9baf1c10a862546217a00fdd1edfa"}, {file = "habluetooth-3.44.0-cp313-cp313-win32.whl", hash = "sha256:2866d5b39728807e82e2aebaf07e5fff5c12b0f0d63402443f4f3086966ff635"}, {file = "habluetooth-3.44.0-cp313-cp313-win_amd64.whl", hash = "sha256:63d5bccbbff4495816ef31684443a4c4277bda0f333e75d8ceb7161497f1bb07"}, {file = "habluetooth-3.44.0.tar.gz", hash = "sha256:f62fda33d25ae0d6860bec586e130925f4f5e2e8a05e27abec3d8e448c1c63fc"}, ] [package.dependencies] async-interrupt = ">=1.1.1" bleak = ">=0.21.1" bleak-retry-connector = ">=3.9.0" bluetooth-adapters = ">=0.16.1" bluetooth-auto-recovery = ">=1.2.3" bluetooth-data-tools = ">=1.28.0" dbus-fast = {version = ">=2.30.2", markers = "platform_system == \"Linux\""} [[package]] name = "idna" version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = true python-versions = ">=3.6" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, ] [[package]] name = "iniconfig" version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] [[package]] name = "jinja2" version = "3.1.6" description = "A very fast and expressive template engine." optional = true python-versions = ">=3.7" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, ] [package.dependencies] MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] [[package]] name = "markdown-it-py" version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, ] [package.dependencies] mdurl = ">=0.1,<1.0" [package.extras] benchmarking = ["psutil", "pytest", "pytest-benchmark"] code-style = ["pre-commit (>=3.0,<4.0)"] compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] linkify = ["linkify-it-py (>=1,<3)"] plugins = ["mdit-py-plugins"] profiling = ["gprof2dot"] rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, ] [[package]] name = "mdit-py-plugins" version = "0.4.2" description = "Collection of plugins for markdown-it-py" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, ] [package.dependencies] markdown-it-py = ">=1.0.0,<4.0.0" [package.extras] code-style = ["pre-commit"] rtd = ["myst-parser", "sphinx-book-theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" optional = true python-versions = ">=3.7" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] [[package]] name = "myst-parser" version = "4.0.1" description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d"}, {file = "myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4"}, ] [package.dependencies] docutils = ">=0.19,<0.22" jinja2 = "*" markdown-it-py = ">=3.0,<4.0" mdit-py-plugins = ">=0.4.1,<1.0" pyyaml = "*" sphinx = ">=7,<9" [package.extras] code-style = ["pre-commit (>=4.0,<5.0)"] linkify = ["linkify-it-py (>=2.0,<3.0)"] rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-book-theme (>=1.1,<2.0)", "sphinx-copybutton", "sphinx-design", "sphinx-pyscript", "sphinx-tippy (>=0.4.3)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.9.0,<0.10.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pygments (<2.19)", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"] testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"] [[package]] name = "packaging" version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" groups = ["main", "dev"] files = [ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] markers = {main = "extra == \"docs\""} [[package]] name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] [[package]] name = "pycparser" version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" groups = ["main"] markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] [[package]] name = "pygments" version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, ] [package.extras] windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyobjc-core" version = "10.3.2" description = "Python<->ObjC Interoperability Module" optional = false python-versions = ">=3.8" groups = ["main"] markers = "platform_system == \"Darwin\"" files = [ {file = "pyobjc_core-10.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:acb40672d682851a5c7fd84e5041c4d069b62076168d72591abb5fcc871bb039"}, {file = "pyobjc_core-10.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cea5e77659619ad93c782ca07644b6efe7d7ec6f59e46128843a0a87c1af511a"}, {file = "pyobjc_core-10.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:16644a92fb9661de841ba6115e5354db06a1d193a5e239046e840013c7b3874d"}, {file = "pyobjc_core-10.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:76b8b911d94501dac89821df349b1860bb770dce102a1a293f524b5b09dd9462"}, {file = "pyobjc_core-10.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:8c6288fdb210b64115760a4504efbc4daffdc390d309e9318eb0e3e3b78d2828"}, {file = "pyobjc_core-10.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:87901e9f7032f33eb4fa884e407bf2744d5a0791b379bfca783982a02be3f7fb"}, {file = "pyobjc_core-10.3.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:636971ab48a4198ca129e149fe58ccf85a7b4a9b93d27f5ae920d88eb2655431"}, {file = "pyobjc_core-10.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:48e9ac3af42b2340dae709a8b894f5ef7e5132d8546adcd1797cffcc449dabdc"}, {file = "pyobjc_core-10.3.2.tar.gz", hash = "sha256:dbf1475d864ce594288ce03e94e3a98dc7f0e4639971eb1e312bdf6661c21e0e"}, ] [[package]] name = "pyobjc-framework-cocoa" version = "10.3.2" description = "Wrappers for the Cocoa frameworks on macOS" optional = false python-versions = ">=3.8" groups = ["main"] markers = "platform_system == \"Darwin\"" files = [ {file = "pyobjc_framework_Cocoa-10.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:61f44c2adab28fdf3aa3d593c9497a2d9ceb9583ed9814adb48828c385d83ff4"}, {file = "pyobjc_framework_Cocoa-10.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7caaf8b260e81b27b7b787332846f644b9423bfc1536f6ec24edbde59ab77a87"}, {file = "pyobjc_framework_Cocoa-10.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c49e99fc4b9e613fb308651b99d52a8a9ae9916c8ef27aa2f5d585b6678a59bf"}, {file = "pyobjc_framework_Cocoa-10.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f1161b5713f9b9934c12649d73a6749617172e240f9431eff9e22175262fdfda"}, {file = "pyobjc_framework_Cocoa-10.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:08e48b9ee4eb393447b2b781d16663b954bd10a26927df74f92e924c05568d89"}, {file = "pyobjc_framework_Cocoa-10.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7faa448d2038ae0e0287a326d390002e744bb6470e45995e2dbd16c892e4495a"}, {file = "pyobjc_framework_Cocoa-10.3.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:fcd53fee2be9708576617994b107aedc2c40824b648cd51e780e8399c0a447b6"}, {file = "pyobjc_framework_Cocoa-10.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:838fcf0d10674bde9ff64a3f20c0e188f2dc5e804476d80509b81c4ac1dabc59"}, {file = "pyobjc_framework_cocoa-10.3.2.tar.gz", hash = "sha256:673968e5435845bef969bfe374f31a1a6dc660c98608d2b84d5cae6eafa5c39d"}, ] [package.dependencies] pyobjc-core = ">=10.3.2" [[package]] name = "pyobjc-framework-corebluetooth" version = "10.3.2" description = "Wrappers for the framework CoreBluetooth on macOS" optional = false python-versions = ">=3.8" groups = ["main"] markers = "platform_system == \"Darwin\"" files = [ {file = "pyobjc_framework_CoreBluetooth-10.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:af3e2f935a6a7e5b009b4cf63c64899592a7b46c3ddcbc8f2e28848842ef65f4"}, {file = "pyobjc_framework_CoreBluetooth-10.3.2-cp36-abi3-macosx_10_13_universal2.whl", hash = "sha256:973b78f47c7e2209a475e60bcc7d1b4a87be6645d39b4e8290ee82640e1cc364"}, {file = "pyobjc_framework_CoreBluetooth-10.3.2-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:4bafdf1be15eae48a4878dbbf1bf19877ce28cbbba5baa0267a9564719ee736e"}, {file = "pyobjc_framework_CoreBluetooth-10.3.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:4d7dc7494de66c850bda7b173579df7481dc97046fa229d480fe9bf90b2b9651"}, {file = "pyobjc_framework_CoreBluetooth-10.3.2-cp36-abi3-macosx_11_0_universal2.whl", hash = "sha256:62e09e730f4d98384f1b6d44718812195602b3c82d5c78e09f60e8a934e7b266"}, {file = "pyobjc_framework_corebluetooth-10.3.2.tar.gz", hash = "sha256:c0a077bc3a2466271efa382c1e024630bc43cc6f9ab8f3f97431ad08b1ad52bb"}, ] [package.dependencies] pyobjc-core = ">=10.3.2" pyobjc-framework-Cocoa = ">=10.3.2" [[package]] name = "pyobjc-framework-libdispatch" version = "10.3.2" description = "Wrappers for libdispatch on macOS" optional = false python-versions = ">=3.8" groups = ["main"] markers = "platform_system == \"Darwin\"" files = [ {file = "pyobjc_framework_libdispatch-10.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:35233a8b1135567c7696087f924e398799467c7f129200b559e8e4fa777af860"}, {file = "pyobjc_framework_libdispatch-10.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:061f6aa0f88d11d993e6546ec734303cb8979f40ae0f5cd23541236a6b426abd"}, {file = "pyobjc_framework_libdispatch-10.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:6bb528f34538f35e1b79d839dbfc398dd426990e190d9301fe2d811fddc3da62"}, {file = "pyobjc_framework_libdispatch-10.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1357729d5fded08fbf746834ebeef27bee07d6acb991f3b8366e8f4319d882c4"}, {file = "pyobjc_framework_libdispatch-10.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:210398f9e1815ceeff49b578bf51c2d6a4a30d4c33f573da322f3d7da1add121"}, {file = "pyobjc_framework_libdispatch-10.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e7ae5988ac0b369ad40ce5497af71864fac45c289fa52671009b427f03d6871f"}, {file = "pyobjc_framework_libdispatch-10.3.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:f9d51d52dff453a4b19c096171a6cd31dd5e665371c00c1d72d480e1c22cd3d4"}, {file = "pyobjc_framework_libdispatch-10.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ef755bcabff2ea8db45603a8294818e0eeae85bf0b7b9d59e42f5947a26e33b9"}, {file = "pyobjc_framework_libdispatch-10.3.2.tar.gz", hash = "sha256:e9f4311fbf8df602852557a98d2a64f37a9d363acf4d75634120251bbc7b7304"}, ] [package.dependencies] pyobjc-core = ">=10.3.2" pyobjc-framework-Cocoa = ">=10.3.2" [[package]] name = "pyric" version = "0.1.6.3" description = "Python Wireless Library" optional = false python-versions = "*" groups = ["main"] files = [ {file = "PyRIC-0.1.6.3.tar.gz", hash = "sha256:b539b01cafebd2406c00097f94525ea0f8ecd1dd92f7731f43eac0ef16c2ccc9"}, ] [[package]] name = "pytest" version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, ] [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} iniconfig = "*" packaging = "*" pluggy = ">=1.5,<2" [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" version = "0.26.0" description = "Pytest support for asyncio" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0"}, {file = "pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f"}, ] [package.dependencies] pytest = ">=8.2,<9" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"] testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] name = "pytest-cov" version = "6.1.1" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde"}, {file = "pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a"}, ] [package.dependencies] coverage = {version = ">=7.5", extras = ["toml"]} pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pyyaml" version = "6.0.2" description = "YAML parser and emitter for Python" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] name = "requests" version = "2.32.3" description = "Python HTTP for Humans." optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "roman-numerals-py" version = "3.1.0" description = "Manipulate well-formed Roman numerals" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c"}, {file = "roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d"}, ] [package.extras] lint = ["mypy (==1.15.0)", "pyright (==1.1.394)", "ruff (==0.9.7)"] test = ["pytest (>=8)"] [[package]] name = "sensor-state-data" version = "2.18.1" description = "Models for storing and converting Sensor Data state" optional = false python-versions = "<4.0,>=3.9" groups = ["main"] files = [ {file = "sensor_state_data-2.18.1-py3-none-any.whl", hash = "sha256:45a223acf5d4aefde45c028fa810c7925db6448984097aa1b500fe4f206d113f"}, {file = "sensor_state_data-2.18.1.tar.gz", hash = "sha256:25f17ed98748ae006ddab82d5013cf30301daaf23526d1992f99c4dc0beb49c3"}, ] [package.extras] docs = ["Sphinx (>=5.0,<6.0)", "myst-parser (>=0.18,<0.19)", "sphinx-rtd-theme (>=1.0,<2.0)"] [[package]] name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." optional = true python-versions = "*" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] [[package]] name = "sphinx" version = "8.2.3" description = "Python documentation generator" optional = true python-versions = ">=3.11" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3"}, {file = "sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348"}, ] [package.dependencies] alabaster = ">=0.7.14" babel = ">=2.13" colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} docutils = ">=0.20,<0.22" imagesize = ">=1.3" Jinja2 = ">=3.1" packaging = ">=23.0" Pygments = ">=2.17" requests = ">=2.30.0" roman-numerals-py = ">=1.0.0" snowballstemmer = ">=2.2" sphinxcontrib-applehelp = ">=1.0.7" sphinxcontrib-devhelp = ">=1.0.6" sphinxcontrib-htmlhelp = ">=2.0.6" sphinxcontrib-jsmath = ">=1.0.1" sphinxcontrib-qthelp = ">=1.0.6" sphinxcontrib-serializinghtml = ">=1.1.9" [package.extras] docs = ["sphinxcontrib-websupport"] lint = ["betterproto (==2.0.0b6)", "mypy (==1.15.0)", "pypi-attestations (==0.0.21)", "pyright (==1.1.395)", "pytest (>=8.0)", "ruff (==0.9.9)", "sphinx-lint (>=0.9)", "types-Pillow (==10.2.0.20240822)", "types-Pygments (==2.19.0.20250219)", "types-colorama (==0.4.15.20240311)", "types-defusedxml (==0.7.0.20240218)", "types-docutils (==0.21.0.20241128)", "types-requests (==2.32.0.20241016)", "types-urllib3 (==1.26.25.14)"] test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "pytest-xdist[psutil] (>=3.4)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] [[package]] name = "sphinx-rtd-theme" version = "3.0.2" description = "Read the Docs theme for Sphinx" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13"}, {file = "sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85"}, ] [package.dependencies] docutils = ">0.18,<0.22" sphinx = ">=6,<9" sphinxcontrib-jquery = ">=4,<5" [package.extras] dev = ["bump2version", "transifex-client", "twine", "wheel"] [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["html5lib", "pytest"] [[package]] name = "sphinxcontrib-jquery" version = "4.1" description = "Extension to include jQuery on newer Sphinx releases" optional = true python-versions = ">=2.7" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, ] [package.dependencies] Sphinx = ">=1.8" [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" optional = true python-versions = ">=3.5" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, ] [package.extras] test = ["flake8", "mypy", "pytest"] [[package]] name = "sphinxcontrib-qthelp" version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["defusedxml (>=0.7.1)", "pytest"] [[package]] name = "sphinxcontrib-serializinghtml" version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "typing-extensions" version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" groups = ["main"] markers = "python_version == \"3.11\"" files = [ {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] [[package]] name = "uart-devices" version = "0.1.1" description = "UART Devices for Linux" optional = false python-versions = "<4.0,>=3.9" groups = ["main"] files = [ {file = "uart_devices-0.1.1-py3-none-any.whl", hash = "sha256:55bc8cce66465e90b298f0910e5c496bc7be021341c5455954cf61c6253dc123"}, {file = "uart_devices-0.1.1.tar.gz", hash = "sha256:3a52c4ae0f5f7400ebe1ae5f6e2a2d40cc0b7f18a50e895236535c4e53c6ed34"}, ] [[package]] name = "urllib3" version = "2.4.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"docs\"" files = [ {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, ] [package.extras] brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "usb-devices" version = "0.4.5" description = "Tools for mapping, describing, and resetting USB devices" optional = false python-versions = ">=3.9,<4.0" groups = ["main"] files = [ {file = "usb_devices-0.4.5-py3-none-any.whl", hash = "sha256:8a415219ef1395e25aa0bddcad484c88edf9673acdeae8a07223ca7222a01dcf"}, {file = "usb_devices-0.4.5.tar.gz", hash = "sha256:9b5c7606df2bc791c6c45b7f76244a0cbed83cb6fa4c68791a143c03345e195d"}, ] [[package]] name = "winrt-runtime" version = "2.3.0" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] markers = "platform_system == \"Windows\" and python_version >= \"3.12\"" files = [ {file = "winrt_runtime-2.3.0-cp310-cp310-win32.whl", hash = "sha256:5c22ed339b420a6026134e28281b25078a9e6755eceb494dce5d42ee5814e3fd"}, {file = "winrt_runtime-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f3ef0d6b281a8d4155ea14a0f917faf82a004d4996d07beb2b3d2af191503fb1"}, {file = "winrt_runtime-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:93ce23df52396ed89dfe659ee0e1a968928e526b9c577942d4a54ad55b333644"}, {file = "winrt_runtime-2.3.0-cp311-cp311-win32.whl", hash = "sha256:352d70864846fd7ec89703845b82a35cef73f42d178a02a4635a38df5a61c0f8"}, {file = "winrt_runtime-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:286e6036af4903dd830398103c3edd110a46432347e8a52ba416d937c0e1f5f9"}, {file = "winrt_runtime-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:44d0f0f48f2f10c02b885989e8bbac41d7bf9c03550b20ddf562100356fca7a9"}, {file = "winrt_runtime-2.3.0-cp312-cp312-win32.whl", hash = "sha256:03d3e4aedc65832e57c0dbf210ec2a9d7fb2819c74d420ba889b323e9fa5cf28"}, {file = "winrt_runtime-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:0dc636aec2f4ee6c3849fa59dae10c128f4a908f0ce452e91af65d812ea66dcb"}, {file = "winrt_runtime-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:d9f140c71e4f3bf7bf7d6853b246eab2e1632c72f218ff163aa41a74b576736f"}, {file = "winrt_runtime-2.3.0-cp313-cp313-win32.whl", hash = "sha256:77f06df6b7a6cb536913ae455e30c1733d31d88dafe2c3cd8c3d0e2bcf7e2a20"}, {file = "winrt_runtime-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:7388774b74ea2f4510ab3a98c95af296665ebe69d9d7e2fd7ee2c3fc5856099e"}, {file = "winrt_runtime-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:0d3a4ac7661cad492d51653054e63328b940a6083c1ee1dd977f90069cb8afaa"}, {file = "winrt_runtime-2.3.0-cp39-cp39-win32.whl", hash = "sha256:cd7bce2c7703054e7f64d11be665e9728e15d9dae0d952a51228fe830e0c4b55"}, {file = "winrt_runtime-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:2da01af378ab9374a3a933da97543f471a676a3b844318316869bffeff811e8a"}, {file = "winrt_runtime-2.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:1c6bbfcc7cbe1c8159ed5d776b30b7f1cbc2c6990803292823b0788c22d75636"}, {file = "winrt_runtime-2.3.0.tar.gz", hash = "sha256:bb895a2b8c74b375781302215e2661914369c625aa1f8df84f8d37691b22db77"}, ] [[package]] name = "winrt-windows-devices-bluetooth" version = "2.3.0" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] markers = "platform_system == \"Windows\" and python_version >= \"3.12\"" files = [ {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp310-cp310-win32.whl", hash = "sha256:554aa6d0ca4bebc22a45f19fa60db1183a2b5643468f3c95cf0ebc33fbc1b0d0"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:cec2682e10431f027c1823647772671fb09bebc1e8a00021a3651120b846d36f"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:b4d42faef99845de2aded4c75c906f03cc3ba3df51fb4435e4cc88a19168cf99"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp311-cp311-win32.whl", hash = "sha256:64e0992175d4d5a1160179a8c586c2202a0edbd47a5b6da4efdbc8bb601f2f99"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:0830111c077508b599062fbe2d817203e4efa3605bd209cf4a3e03388ec39dda"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:3943d538cb7b6bde3fd8741591eb6e23487ee9ee6284f05428b205e7d10b6d92"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp312-cp312-win32.whl", hash = "sha256:544ed169039e6d5e250323cc18c87967cfeb4d3d09ce354fd7c5fd2283f3bb98"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:f7becf095bf9bc999629fcb6401a88b879c3531b3c55c820e63259c955ddc06c"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:a6a2980409c855b4e5dab0be9bde9f30236292ac1fc994df959fa5a518cd6690"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp313-cp313-win32.whl", hash = "sha256:82f443be43379d4762e72633047c82843c873b6f26428a18855ca7b53e1958d7"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:8b407da87ab52315c2d562a75d824dcafcae6e1628031cdb971072a47eb78ff0"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:e36d0b487bc5b64662b8470085edf8bfa5a220d7afc4f2e8d7faa3e3ac2bae80"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp39-cp39-win32.whl", hash = "sha256:6553023433edf5a75767e8962bf492d0623036975c7d8373d5bbccc633a77bbc"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:77bdeadb043190c40ebbad462cd06e38b6461bc976bc67daf587e9395c387aae"}, {file = "winrt_Windows.Devices.Bluetooth-2.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:c588ab79b534fedecce48f7082b419315e8d797d0120556166492e603e90d932"}, {file = "winrt_windows_devices_bluetooth-2.3.0.tar.gz", hash = "sha256:a1204b71c369a0399ec15d9a7b7c67990dd74504e486b839bf81825bd381a837"}, ] [package.dependencies] winrt-runtime = "2.3.0" [package.extras] all = ["winrt-Windows.Devices.Bluetooth.GenericAttributeProfile[all] (==2.3.0)", "winrt-Windows.Devices.Bluetooth.Rfcomm[all] (==2.3.0)", "winrt-Windows.Devices.Enumeration[all] (==2.3.0)", "winrt-Windows.Devices.Radios[all] (==2.3.0)", "winrt-Windows.Foundation.Collections[all] (==2.3.0)", "winrt-Windows.Foundation[all] (==2.3.0)", "winrt-Windows.Networking[all] (==2.3.0)", "winrt-Windows.Storage.Streams[all] (==2.3.0)"] [[package]] name = "winrt-windows-devices-bluetooth-advertisement" version = "2.3.0" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] markers = "platform_system == \"Windows\" and python_version >= \"3.12\"" files = [ {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp310-cp310-win32.whl", hash = "sha256:4386498e7794ed383542ea868f0aa2dd8fb5f09f12bdffde024d12bd9f5a3756"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6fa25b2541d2898ae17982e86e0977a639b04f75119612cb46e1719474513fd"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:b200ff5acd181353f61f5b6446176faf78a61867d8c1d21e77a15e239d2cdf6b"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp311-cp311-win32.whl", hash = "sha256:e56ad277813b48e35a3074f286c55a7a25884676e23ef9c3fc12349a42cb8fa4"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d6533fef6a5914dc8d519b83b1841becf6fd2f37163d6e07df318a6a6118f194"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:8f4369cb0108f8ee0cace559f9870b00a4dde3fc1abd52f84adba08bc733825c"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp312-cp312-win32.whl", hash = "sha256:d729d989acd7c1d703e2088299b6e219089a415db4a7b80cd52fdc507ec3ce95"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d3d258d4388a2b46f2e46f2fbdede1bf327eaa9c2dd4605f8a7fe454077c49e"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:d8c12457b00a79f8f1058d7a51bd8e7f177fb66e31389469e75b1104f6358921"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp313-cp313-win32.whl", hash = "sha256:ac1e55a350881f82cb51e162cb7a4b5d9359e9e5fbde922de802404a951d64ec"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0fc339340fb8be21c1c829816a49dc31b986c6d602d113d4a49ee8ffaf0e2396"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:da63d9c56edcb3b2d5135e65cc8c9c4658344dd480a8a2daf45beb2106f17874"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp39-cp39-win32.whl", hash = "sha256:e98c6ae4b0afd3e4f3ab4fa06e84d6017ff9242146a64e3bad73f7f34183a076"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdc485f4143fbbb3ae0c9c9ad03b1021a5cb233c6df65bf56ac14f8e22c918c3"}, {file = "winrt_Windows.Devices.Bluetooth.Advertisement-2.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:7af519cc895be84d6974e9f70d102545a5e8db05e065903b0fd84521218e60a9"}, {file = "winrt_windows_devices_bluetooth_advertisement-2.3.0.tar.gz", hash = "sha256:c8adbec690b765ca70337c35efec9910b0937a40a0a242184ea295367137f81c"}, ] [package.dependencies] winrt-runtime = "2.3.0" [package.extras] all = ["winrt-Windows.Devices.Bluetooth[all] (==2.3.0)", "winrt-Windows.Foundation.Collections[all] (==2.3.0)", "winrt-Windows.Foundation[all] (==2.3.0)", "winrt-Windows.Storage.Streams[all] (==2.3.0)"] [[package]] name = "winrt-windows-devices-bluetooth-genericattributeprofile" version = "2.3.0" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] markers = "platform_system == \"Windows\" and python_version >= \"3.12\"" files = [ {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp310-cp310-win32.whl", hash = "sha256:1ec75b107370827874d8435a47852d0459cb66d5694e02a833e0a75c4748e847"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:0a178aa936abbc56ae1cc54a222dee4a34ce6c09506a5b592d4f7d04dbe76b95"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:b7067b8578e19ad17b28694090d5b000fee57db5b219462155961b685d71fba5"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp311-cp311-win32.whl", hash = "sha256:e0aeba201e20b6c4bc18a4336b5b07d653d4ab4c9c17a301613db680a346cd5e"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:f87b3995de18b98075ec2b02afc7252873fa75e7c840eb770d7bfafb4fda5c12"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:7dccce04ec076666001efca8e2484d0ec444b2302ae150ef184aa253b8cfba09"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp312-cp312-win32.whl", hash = "sha256:1b97ef2ab9c9f5bae984989a47565d0d19c84969d74982a2664a4a3485cb8274"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:5fac2c7b301fa70e105785d7504176c76e4d824fc3823afed4d1ab6a7682272c"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:353fdccf2398b2a12e0835834cff8143a7efd9ba877fb5820fdcce531732b500"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp313-cp313-win32.whl", hash = "sha256:f414f793767ccc56d055b1c74830efb51fa4cbdc9163847b1a38b1ee35778f49"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ef35d9cda5bbdcc55aa7eaf143ab873227d6ee467aaf28edbd2428f229e7c94"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:6a9e7308ba264175c2a9ee31f6cf1d647cb35ee9a1da7350793d8fe033a6b9b8"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp39-cp39-win32.whl", hash = "sha256:aea58f7e484cf3480ab9472a3e99b61c157b8a47baae8694bc7400ea5335f5dc"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:992b792a9e7f5771ccdc18eec4e526a11f23b75d9be5de3ec552ff719333897a"}, {file = "winrt_Windows.Devices.Bluetooth.GenericAttributeProfile-2.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:66b030a9cc6099dafe4253239e8e625cc063bb9bb115bebed6260d92dd86f6b1"}, {file = "winrt_windows_devices_bluetooth_genericattributeprofile-2.3.0.tar.gz", hash = "sha256:f40f94bf2f7243848dc10e39cfde76c9044727a05e7e5dfb8cb7f062f3fd3dda"}, ] [package.dependencies] winrt-runtime = "2.3.0" [package.extras] all = ["winrt-Windows.Devices.Bluetooth[all] (==2.3.0)", "winrt-Windows.Devices.Enumeration[all] (==2.3.0)", "winrt-Windows.Foundation.Collections[all] (==2.3.0)", "winrt-Windows.Foundation[all] (==2.3.0)", "winrt-Windows.Storage.Streams[all] (==2.3.0)"] [[package]] name = "winrt-windows-devices-enumeration" version = "2.3.0" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] markers = "platform_system == \"Windows\" and python_version >= \"3.12\"" files = [ {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp310-cp310-win32.whl", hash = "sha256:461360ab47967f39721e71276fdcfe87ad2f71ba7b09d721f2f88bcdf16a6924"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a7d7b01d43d5dcc1f3846db12f4c552155efae75469f36052623faed7f0f74a8"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:6478fbe6f45172a9911c15b061ec9b0f30c9f4845ba3fd1e9e1bb78c1fb691c4"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp311-cp311-win32.whl", hash = "sha256:30be5cba8e9e81ea8dd514ba1300b5bb14ad7cc4e32efe908ddddd14c73e7f61"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86c2a1865e0a0146dd4f51f17e3d773d3e6732742f61838c05061f28738c6dbd"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:1b50d9304e49a9f04bc8139831b75be968ff19a1f50529d5eb0081dae2103d92"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp312-cp312-win32.whl", hash = "sha256:42ed0349f0290a1b0a101425a06196c5d5db1240db6f8bd7d2204f23c48d727b"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:83e385fbf85b9511699d33c659673611f42b98bd3a554a85b377a34cc3b68b2e"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:26f855caee61c12449c6b07e22ea1ad470f8daa24223d8581e1fe622c70b48a8"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp313-cp313-win32.whl", hash = "sha256:a5f2cff6ee584e5627a2246bdbcd1b3a3fd1e7ae0741f62c59f7d5a5650d5791"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:7516171521aa383ccdc8f422cc202979a2359d0d1256f22852bfb0b55d9154f0"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:80d01dfffe4b548439242f3f7a737189354768b203cca023dc29b267dfe5595a"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp39-cp39-win32.whl", hash = "sha256:990a375cd8edc2d30b939a49dcc1349ede3a4b8e4da78baf0de5e5711d3a4f00"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:2e7bedf0eac2066d7d37b1d34071b95bb57024e9e083867be1d24e916e012ac0"}, {file = "winrt_Windows.Devices.Enumeration-2.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:c53b673b80ba794f1c1320a5e0a14d795193c3f64b8132ebafba2f49c7301c2f"}, {file = "winrt_windows_devices_enumeration-2.3.0.tar.gz", hash = "sha256:a14078aac41432781acb0c950fcdcdeb096e2f80f7591a3d46435f30221fc3eb"}, ] [package.dependencies] winrt-runtime = "2.3.0" [package.extras] all = ["winrt-Windows.ApplicationModel.Background[all] (==2.3.0)", "winrt-Windows.Foundation.Collections[all] (==2.3.0)", "winrt-Windows.Foundation[all] (==2.3.0)", "winrt-Windows.Security.Credentials[all] (==2.3.0)", "winrt-Windows.Storage.Streams[all] (==2.3.0)", "winrt-Windows.UI.Popups[all] (==2.3.0)", "winrt-Windows.UI[all] (==2.3.0)"] [[package]] name = "winrt-windows-foundation" version = "2.3.0" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] markers = "platform_system == \"Windows\" and python_version >= \"3.12\"" files = [ {file = "winrt_Windows.Foundation-2.3.0-cp310-cp310-win32.whl", hash = "sha256:ea7b0e82be5c05690fedaf0dac5aa5e5fefd7ebf90b1497e5993197d305d916d"}, {file = "winrt_Windows.Foundation-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:6807dd40f8ecd6403679f6eae0db81674fdcf33768d08fdee66e0a17b7a02515"}, {file = "winrt_Windows.Foundation-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:0a861815e97ace82583210c03cf800507b0c3a97edd914bfffa5f88de1fbafcc"}, {file = "winrt_Windows.Foundation-2.3.0-cp311-cp311-win32.whl", hash = "sha256:c79b3d9384128b6b28c2483b4600f15c5d32c1f6646f9d77fdb3ee9bbaef6f81"}, {file = "winrt_Windows.Foundation-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:fdd9c4914070dc598f5961d9c7571dd7d745f5cc60347603bf39d6ee921bd85c"}, {file = "winrt_Windows.Foundation-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:62bbb0ffa273551d33fd533d6e09b6f9f633dc214225d483722af47d2525fb84"}, {file = "winrt_Windows.Foundation-2.3.0-cp312-cp312-win32.whl", hash = "sha256:d36f472ac258e79eee6061e1bb4ce50bfd200f9271392d23479c800ca6aee8d1"}, {file = "winrt_Windows.Foundation-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8de9b5e95a3fdabdb45b1952e05355dd5a678f80bf09a54d9f966dccc805b383"}, {file = "winrt_Windows.Foundation-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:37da09c08c9c772baedb1958e5ee116fe63809f33c6820c69750f340b3dda292"}, {file = "winrt_Windows.Foundation-2.3.0-cp313-cp313-win32.whl", hash = "sha256:2b00fad3f2a3859ccae41eee12ab44434813a371c2f3003b4f2419e5eecb4832"}, {file = "winrt_Windows.Foundation-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:686619932b2a2c689cbebc7f5196437a45fd2056656ef130bb10240bb111086a"}, {file = "winrt_Windows.Foundation-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b38dcb83fe82a7da9a57d7d5ad5deb09503b5be6d9357a9fd3016ca31673805d"}, {file = "winrt_Windows.Foundation-2.3.0-cp39-cp39-win32.whl", hash = "sha256:2d6922de4dc38061b86d314c7319d7c6bd78a52d64ee0c93eb81474bddb499bc"}, {file = "winrt_Windows.Foundation-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:1513e43adff3779d2f611d8bdf9350ac1a7c04389e9e6b1d777c5cd54f46e4fc"}, {file = "winrt_Windows.Foundation-2.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:c811e4a4f79b947fbbb50f74d34ef6840dd2dd26e0199bd61a4185e48c6a84a8"}, {file = "winrt_windows_foundation-2.3.0.tar.gz", hash = "sha256:c5766f011c8debbe89b460af4a97d026ca252144e62d7278c9c79c5581ea0c02"}, ] [package.dependencies] winrt-runtime = "2.3.0" [package.extras] all = ["winrt-Windows.Foundation.Collections[all] (==2.3.0)"] [[package]] name = "winrt-windows-foundation-collections" version = "2.3.0" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] markers = "platform_system == \"Windows\" and python_version >= \"3.12\"" files = [ {file = "winrt_Windows.Foundation.Collections-2.3.0-cp310-cp310-win32.whl", hash = "sha256:d2fca59eef9582a33c2797b1fda1d5757d66827cc34e6fc1d1c94a5875c4c043"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d14b47d9137aebad71aa4fde5892673f2fa326f5f4799378cb9f6158b07a9824"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:cca5398a4522dffd76decf64a28368cda67e81dc01cad35a9f39cc351af69bdd"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp311-cp311-win32.whl", hash = "sha256:3808af64c95a9b464e8e97f6bec57a8b22168185f1c893f30de69aaf48c85b17"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1e9a3842a39feb965545124abfe79ed726adc5a1fc6a192470a3c5d3ec3f7a74"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:751c2a68fef080dfe0af892ef4cebf317844e4baa786e979028757fe2740fba4"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp312-cp312-win32.whl", hash = "sha256:498c1fc403d3dc7a091aaac92af471615de4f9550d544347cb3b169c197183b5"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:4d1b1cacc159f38d8e6b662f6e7a5c41879a36aa7434c1580d7f948c9037419e"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:398d93b76a2cf70d5e75c1f802e1dd856501e63bc9a31f4510ac59f718951b9e"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp313-cp313-win32.whl", hash = "sha256:1e5f1637e0919c7bb5b11ba1eebbd43bc0ad9600cf887b59fcece0f8a6c0eac3"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:c809a70bc0f93d53c7289a0a86d8869740e09fff0c57318a14401f5c17e0b912"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:269942fe86af06293a2676c8b2dcd5cb1d8ddfe1b5244f11c16e48ae0a5d100f"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp39-cp39-win32.whl", hash = "sha256:936b1c5720b564ec699673198addee97f3bdb790622d24c8fd1b346a9767717c"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:905a6ac9cd6b51659a9bba08cf44cfc925f528ef34cdd9c3a6c2632e97804a96"}, {file = "winrt_Windows.Foundation.Collections-2.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:1d6eac85976bd831e1b8cc479d7f14afa51c27cec5a38e2540077d3400cbd3ef"}, {file = "winrt_windows_foundation_collections-2.3.0.tar.gz", hash = "sha256:15c997fd6b64ef0400a619319ea3c6851c9c24e31d51b6448ba9bac3616d25a0"}, ] [package.dependencies] winrt-runtime = "2.3.0" [package.extras] all = ["winrt-Windows.Foundation[all] (==2.3.0)"] [[package]] name = "winrt-windows-storage-streams" version = "2.3.0" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] markers = "platform_system == \"Windows\" and python_version >= \"3.12\"" files = [ {file = "winrt_Windows.Storage.Streams-2.3.0-cp310-cp310-win32.whl", hash = "sha256:2c0901aee1232e92ed9320644b853d7801a0bdb87790164d56e961cd39910f07"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:ba07dc25decffd29aa8603119629c167bd03fa274099e3bad331a4920c292b78"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:5b60b48460095c50a00a6f7f9b3b780f5bdcb1ec663fc09458201499f93e23ea"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp311-cp311-win32.whl", hash = "sha256:8388f37759df64ceef1423ae7dd9275c8a6eb3b8245d400173b4916adc94b5ad"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:e5783dbe3694cc3deda594256ebb1088655386959bb834a6bfb7cd763ee87631"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:0a487d19c73b82aafa3d5ef889bb35e6e8e2487ca4f16f5446f2445033d5219c"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp312-cp312-win32.whl", hash = "sha256:272e87e6c74cb2832261ab33db7966a99e7a2400240cc4f8bf526a80ca054c68"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:997bf1a2d52c5f104b172947e571f27d9916a4409b4da592ec3e7f907848dd1a"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:d56daa00205c24ede6669d41eb70d6017e0202371d99f8ee2b0b31350ab59bd5"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp313-cp313-win32.whl", hash = "sha256:7ac4e46fc5e21d8badc5d41779273c3f5e7196f1cf2df1959b6b70eca1d5d85f"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1460027c94c107fcee484997494f3a400f08ee40396f010facb0e72b3b74c457"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:e4553a70f5264a7733596802a2991e2414cdcd5e396b9d11ee87be9abae9329e"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp39-cp39-win32.whl", hash = "sha256:28e1117e23046e499831af16d11f5e61e6066ed6247ef58b93738702522c29b0"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:5511dc578f92eb303aee4d3345ee4ffc88aa414564e43e0e3d84ff29427068f0"}, {file = "winrt_Windows.Storage.Streams-2.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6f5b3f8af4df08f5bf9329373949236ffaef22d021070278795e56da5326a876"}, {file = "winrt_windows_storage_streams-2.3.0.tar.gz", hash = "sha256:d2c010beeb1dd7c135ed67ecfaea13440474a7c469e2e9aa2852db27d2063d44"}, ] [package.dependencies] winrt-runtime = "2.3.0" [package.extras] all = ["winrt-Windows.Foundation.Collections[all] (==2.3.0)", "winrt-Windows.Foundation[all] (==2.3.0)", "winrt-Windows.Storage[all] (==2.3.0)", "winrt-Windows.System[all] (==2.3.0)"] [extras] docs = ["Sphinx", "myst-parser", "sphinx-rtd-theme"] [metadata] lock-version = "2.1" python-versions = ">=3.11,<3.14" content-hash = "7426803dbc5e013aac02796b18495f27f0017813ee42ed5de808b61451cb588c" inkbird-ble-0.16.2/pyproject.toml000066400000000000000000000067751501335542600167210ustar00rootroot00000000000000[project] name = "inkbird-ble" version = "0.16.2" description = "Parser for INKBIRD BLE devices" authors = [{ name = "J. Nick Koston", email = "nick@koston.org" }] license = "MIT" readme = "README.md" requires-python = ">=3.11" dynamic = ["classifiers", "dependencies"] [project.urls] "Repository" = "https://github.com/bluetooth-devices/inkbird-ble" "Documentation" = "https://inkbird-ble.readthedocs.io" "Bug Tracker" = "https://github.com/bluetooth-devices/inkbird-ble/issues" "Changelog" = "https://github.com/bluetooth-devices/inkbird-ble/blob/main/CHANGELOG.md" [tool.poetry] classifiers = [ "Development Status :: 2 - Pre-Alpha", "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: OS Independent", "Topic :: Software Development :: Libraries", ] packages = [ { include = "inkbird_ble", from = "src" }, ] [tool.poetry.dependencies] python = ">=3.11,<3.14" # Documentation Dependencies Sphinx = {version = ">=5,<9", optional = true} sphinx-rtd-theme = {version = ">=1,<4", optional = true} myst-parser = {version = ">=0.18,<4.1", optional = true} bluetooth-sensor-state-data = ">=1.8.0" habluetooth = {version = ">=3.42.0", python = ">=3.11,<3.14"} sensor-state-data = ">=2.2.0" bluetooth-data-tools = ">=1.28.0" bleak-retry-connector = ">=1.20.0" [tool.poetry.extras] docs = [ "myst-parser", "sphinx", "sphinx-rtd-theme", ] [tool.poetry.group.dev.dependencies] pytest = "^8.3" pytest-asyncio = "^0.26.0" pytest-cov = "^6.1" [tool.semantic_release] branch = "main" version_toml = ["pyproject.toml:project.version"] version_variables = ["src/inkbird_ble/__init__.py:__version__"] build_command = "pip install poetry && poetry build" [tool.pytest.ini_options] addopts = "-v -Wdefault --cov=inkbird_ble --cov-report=term-missing:skip-covered" pythonpath = ["src"] [tool.coverage.run] branch = true [tool.coverage.report] exclude_lines = [ "pragma: no cover", "@overload", "if TYPE_CHECKING", "raise NotImplementedError", ] [tool.isort] profile = "black" known_first_party = ["inkbird_ble", "tests"] [tool.mypy] check_untyped_defs = true disallow_any_generics = true disallow_incomplete_defs = true disallow_untyped_defs = true mypy_path = "src/" no_implicit_optional = true show_error_codes = true warn_unreachable = true warn_unused_ignores = true exclude = [ 'docs/.*', 'setup.py', ] [[tool.mypy.overrides]] module = "tests.*" allow_untyped_defs = true [[tool.mypy.overrides]] module = "docs.*" ignore_errors = true [build-system] requires = ["poetry-core>=2.1.0"] build-backend = "poetry.core.masonry.api" [tool.ruff.lint] select = [ "ASYNC", # async rules "B", # flake8-bugbear "C4", # flake8-comprehensions "F", # pyflake "E", # pycodestyle "W", # pycodestyle "UP", # pyupgrade "I", # isort "RUF", # ruff specific "FLY", # flynt "FURB", # refurb "G", # flake8-logging-format , "PERF", # Perflint "PGH", # pygrep-hooks "PIE", # flake8-pie "PL", # pylint "PT", # flake8-pytest-style "PTH", # flake8-pathlib "PYI", # flake8-pyi "RET", # flake8-return "RSE", # flake8-raise , "SIM", # flake8-simplify "SLF", # flake8-self "SLOT", # flake8-slots "T100", # Trace found: {name} used "T20", # flake8-print "TC", # flake8-type-checking "TID", # Tidy imports "TRY", # tryceratops ] [tool.ruff.lint.per-file-ignores] "tests/**/*" = [ "D100", "D101", "D102", "D103", "D104", "S101", "PLR2004", "PLR0915", ] inkbird-ble-0.16.2/renovate.json000066400000000000000000000001011501335542600164740ustar00rootroot00000000000000{ "extends": ["github>browniebroke/renovate-configs:python"] } inkbird-ble-0.16.2/src/000077500000000000000000000000001501335542600145555ustar00rootroot00000000000000inkbird-ble-0.16.2/src/inkbird_ble/000077500000000000000000000000001501335542600170215ustar00rootroot00000000000000inkbird-ble-0.16.2/src/inkbird_ble/__init__.py000066400000000000000000000010111501335542600211230ustar00rootroot00000000000000"""Parser for Inkbird BLE advertisements.""" from __future__ import annotations from sensor_state_data import ( DeviceClass, DeviceKey, SensorDescription, SensorDeviceInfo, SensorUpdate, SensorValue, Units, ) from .parser import INKBIRDBluetoothDeviceData __version__ = "0.16.2" __all__ = [ "DeviceClass", "DeviceKey", "INKBIRDBluetoothDeviceData", "SensorDescription", "SensorDeviceInfo", "SensorDeviceInfo", "SensorUpdate", "SensorValue", "Units", ] inkbird-ble-0.16.2/src/inkbird_ble/parser.py000066400000000000000000000574121501335542600207000ustar00rootroot00000000000000""" Parser for Inkbird BLE advertisements. This file is shamelessly copied from the following repository: https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/inkbird.py MIT License applies. """ from __future__ import annotations import asyncio import contextlib import logging import struct from dataclasses import dataclass from enum import Enum, StrEnum, auto from functools import lru_cache from typing import TYPE_CHECKING, Any, ClassVar from uuid import UUID from bleak.exc import BleakCharacteristicNotFoundError, BleakError from bleak_retry_connector import BleakClientWithServiceCache, establish_connection from bluetooth_data_tools import ( monotonic_time_coarse, short_address, ) from bluetooth_sensor_state_data import BluetoothData, SensorUpdate from sensor_state_data import SensorLibrary, Units if TYPE_CHECKING: from collections.abc import Callable, Coroutine from bleak import BleakGATTCharacteristic, BLEDevice from habluetooth import BluetoothServiceInfoBleak _LOGGER = logging.getLogger(__name__) class Model(StrEnum): IBBQ_1 = "iBBQ-1" IBBQ_2 = "iBBQ-2" IBBQ_4 = "iBBQ-4" IBBQ_6 = "iBBQ-6" IBS_TH = "IBS-TH" IBS_TH2 = "IBS-TH2" IBS_P02B = "IBS-P02B" ITH_11_B = "ITH-11-B" ITH_13_B = "ITH-13-B" ITH_21_B = "ITH-21-B" GENERIC_18 = "Generic 18 byte model" IAM_T1 = "IAM-T1" class ModelType(Enum): BBQ = auto() SENSOR = auto() @dataclass(frozen=True) class ModelInfo: """Model information.""" name: str model_type: ModelType local_name: str | None message_length: int unpacker: Callable[[bytes], tuple[int, ...]] service_uuid: UUID | None characteristic_uuid: UUID | None notify_uuid: UUID | None use_local_name_for_device: bool parse_adv: bool INKBIRD_SERVICE_UUID = UUID("0000fff0-0000-1000-8000-00805f9b34fb") EIGHTEEN_BYTE_SENSOR_DATA_CHARACTERISTIC_UUID = UUID( "0000fff7-0000-1000-8000-00805f9b34fb" ) NINE_BYTE_SENSOR_DATA_CHARACTERISTIC_UUID = UUID("0000fff2-0000-1000-8000-00805f9b34fb") IAM_T1_CHARACTERISTIC_UUID = UUID("0000fff4-0000-1000-8000-00805f9b34fb") INKBIRD_UNPACK = struct.Struct(" bytes | None: """Connect to the device and read the data characteristic.""" for attempt in range(2): client = await establish_connection( BleakClientWithServiceCache, ble_device, ble_device.name or ble_device.address, ) try: return await action(client) except BleakCharacteristicNotFoundError: if attempt == 0: await client.clear_cache() continue raise except BleakError: if attempt == 0: continue raise finally: await client.disconnect() raise AssertionError("unreachable") # pragma: no cover @lru_cache def try_parse_model(value: str | Model | None) -> Model | None: """ Try to parse the value into a model. Return None if parsing fails. """ with contextlib.suppress(ValueError): return Model(value) # type: ignore[arg-type] return None def convert_temperature(temp: float) -> float: """Temperature converter.""" return temp / 10.0 if temp > 0 else 0 def is_bbq(lower_name: str) -> bool: """Check if the device is a BBQ sensor.""" return bool("xbbq" in lower_name or "ibbq" in lower_name) class INKBIRDBluetoothDeviceData(BluetoothData): """Date update for INKBIRD Bluetooth devices.""" def __init__( self, device_type: Model | str | None = None, device_data: dict[str, Any] | None = None, update_callback: Callable[[SensorUpdate], None] | None = None, device_data_changed_callback: Callable[[dict[str, Any]], None] | None = None, ) -> None: """Initialize the class.""" super().__init__() self._device_type = try_parse_model(device_type) # Last time we got a full update from ADV data self._last_full_update = 0.0 self._notify_task: asyncio.Task[None] | None = None self._running = True self._device_data = device_data.copy() if device_data else {} self._update_callback = update_callback self._device_data_changed_callback = device_data_changed_callback @property def uses_notify(self) -> bool: """Return True if the device uses notifications.""" return self._device_type in NOTIFY_MODELS async def async_start( self, service_info: BluetoothServiceInfoBleak, ble_device: BLEDevice ) -> None: """Start the device.""" self._set_name_and_manufacturer(service_info) assert self._device_type is not None self._running = True if self._device_type not in NOTIFY_MODELS: return self._notify_task = asyncio.create_task(self._async_start_notify(ble_device)) async def async_stop(self) -> None: """Stop the device.""" self._running = False if self._notify_task: self._notify_task.cancel() with contextlib.suppress(asyncio.CancelledError): await self._notify_task self._notify_task = None async def _async_start_notify(self, ble_device: BLEDevice) -> None: """Start the notification loop.""" while self._running: _LOGGER.debug("Starting notification for %s", self.name) try: await async_connect_action(ble_device, self._async_notify_action) except (BleakError, TimeoutError) as err: _LOGGER.debug("Error starting notification: %s", str(err) or type(err)) _LOGGER.debug("Notification loop for %s finished", self.name) # Wait for 5 seconds before trying again # This is needed to avoid a busy loop if the device is not # available await asyncio.sleep(5) async def _async_notify_action(self, client: BleakClientWithServiceCache) -> None: assert self._device_type is not None dev_info = MODEL_INFO[self._device_type] notify_uuid = dev_info.notify_uuid loop = asyncio.get_running_loop() disconnect_future = loop.create_future() def _resolve_disconnect_callback(_: BleakClientWithServiceCache) -> None: if not disconnect_future.done(): disconnect_future.set_result(None) client.set_disconnected_callback(_resolve_disconnect_callback) await client.start_notify(notify_uuid, self._notify_callback) await disconnect_future # wait for disconnect def _notify_callback( self, sender: BleakGATTCharacteristic, data: bytearray ) -> None: """Callback for notifications.""" _LOGGER.debug("Received notification from %s: %s", sender, data) if not self._running or self._device_type != Model.IAM_T1: return # IAM_T1 if len(data) == 12: # noqa: PLR2004 in_f = data[10] & 0xF unit = Units.TEMP_FAHRENHEIT if in_f else Units.TEMP_CELSIUS _LOGGER.debug("IAM-T1 unit: %s (%s)", unit, self._device_data) if unit != self._device_data.get("temp_unit"): self._device_data["temp_unit"] = unit assert self._device_data_changed_callback is not None _LOGGER.debug("IAM-T1 unit changed: %s (%s)", unit, self._device_data) self._device_data_changed_callback(self._device_data) elif len(data) == 16: # noqa: PLR2004 sign = data[4] & 0xF temp = data[5] << 8 | data[6] signed_temp = (temp if sign == 0 else -temp) / 10 _LOGGER.debug("IAM-T1 temperature: %s (%s)", signed_temp, self._device_data) if self._device_data.get("temp_unit") == Units.TEMP_FAHRENHEIT: # Convert to Celsius signed_temp = round((signed_temp - 32) * 5 / 9, 2) self.update_predefined_sensor( SensorLibrary.TEMPERATURE__CELSIUS, signed_temp ) self.update_predefined_sensor( SensorLibrary.HUMIDITY__PERCENTAGE, (data[7] << 8 | data[8]) / 10 ) self.update_predefined_sensor( SensorLibrary.CO2__CONCENTRATION_PARTS_PER_MILLION, data[9] << 8 | data[10], ) self.update_predefined_sensor( SensorLibrary.PRESSURE__HPA, data[11] << 8 | data[12] ) assert self._update_callback is not None self._update_callback(self._finish_update()) else: _LOGGER.debug( "Unexpected notification length %d from %s", len(data), sender ) @property def device_type(self) -> Model | None: """Return the device type.""" return self._device_type @property def name(self) -> str: """Return the device name.""" if (info := self._get_device_info(None)) and info.name: return info.name return self._device_type.name if self._device_type else "Unknown" def _set_name_and_manufacturer( self, service_info: BluetoothServiceInfoBleak ) -> None: if self._device_type is None: return self.set_device_manufacturer("INKBIRD") local_name = service_info.name address = service_info.address dev_info = MODEL_INFO[self._device_type] dev_type_name = dev_info.name if dev_info.use_local_name_for_device: self.set_device_name(f"{local_name} {short_address(address)}") self.set_device_type(f"{local_name[0]}{dev_type_name[1:]}") else: self.set_device_name(f"{dev_type_name} {short_address(address)}") self.set_device_type(dev_type_name) def _start_update(self, service_info: BluetoothServiceInfoBleak) -> None: """Update from BLE advertisement data.""" _LOGGER.debug("Parsing inkbird BLE advertisement data: %s", service_info) if not (manufacturer_data := service_info.manufacturer_data): self._set_name_and_manufacturer(service_info) return last_id = list(manufacturer_data)[-1] data = int(last_id).to_bytes(2, byteorder="little") + manufacturer_data[last_id] msg_length = len(data) if self._device_type in (None, Model.GENERIC_18): lower_name = service_info.name.lower() # If we do not know the device type yet, try to determine it # from the advertisement data. if (lower_name in INKBIRD_NAMES) and ( msg_length in SENSOR_MSG_LENGTHS or "0000fff0-0000-1000-8000-00805f9b34fb" in service_info.service_uuids ): self._device_type = INKBIRD_NAMES[lower_name] elif is_bbq(lower_name) and msg_length in BBQ_LENGTH_TO_TYPE: self._device_type = BBQ_LENGTH_TO_TYPE[msg_length] elif ( msg_length == 18 # noqa: PLR2004 and 9289 in manufacturer_data # noqa: PLR2004 and "0000fff0-0000-1000-8000-00805f9b34fb" in service_info.service_uuids and manufacturer_data[9289].endswith(b"\x00\x00\x00") ): self._device_type = Model.GENERIC_18 elif 12628 in manufacturer_data and manufacturer_data[12628].startswith( # noqa: PLR2004 b"AC-6200" ): # AC-6200 self._device_type = Model.IAM_T1 else: return self._set_name_and_manufacturer(service_info) assert self._device_type is not None if not MODEL_INFO[self._device_type].parse_adv: # Device does not support parsing advertisement data return excludes = MANUFACTURER_DATA_ID_EXCLUDES if len(manufacturer_data) > 1 else None changed_manufacturer_data = self.changed_manufacturer_data( service_info, excludes ) if not changed_manufacturer_data or len(changed_manufacturer_data) > 1: # If len(changed_manufacturer_data) > 1 it means we switched # ble adapters so we do not know which data is the latest # and we need to wait for the next update. return last_id = list(changed_manufacturer_data)[-1] data = ( int(last_id).to_bytes(2, byteorder="little") + changed_manufacturer_data[last_id] ) _LOGGER.debug("Parsing INKBIRD BLE advertisement data: %s", data) self._device_type_dispatch[self._device_type](self, data, msg_length) self._last_full_update = service_info.time def poll_needed( self, service_info: BluetoothServiceInfoBleak, last_poll: float | None ) -> bool: """ This is called every time we get a service_info for a device or if called manually. """ poll_needed = self._supports_polling and ( not self._last_full_update or (monotonic_time_coarse() - self._last_full_update) > MIN_POLL_INTERVAL ) _LOGGER.debug("Poll needed for INKBIRD device %s: %s", self.name, poll_needed) return poll_needed @property def _supports_polling(self) -> bool: """Return True if the device supports polling.""" return self._device_type is not None and self._device_type in SENSOR_MODELS async def _async_connect_and_read(self, ble_device: BLEDevice) -> bytes: """Connect to the device and read the data characteristic.""" _LOGGER.debug("Polling INKBIRD device %s", self.name) # Try to connect to the device and read the data characteristic # up to 2 times. # If the first attempt fails, clear the cache and try again. # This is needed because the cache may contain old data. # If the second attempt fails, raise an error. data = await async_connect_action(ble_device, self._async_poll_action) assert data is not None return data async def _async_poll_action( self, client: BleakClientWithServiceCache ) -> bytes | None: """Poll the device for updates.""" if TYPE_CHECKING: assert self._device_type is not None dev_info = MODEL_INFO[self._device_type] service = client.services.get_service(dev_info.service_uuid) char = service.get_characteristic(dev_info.characteristic_uuid) return await client.read_gatt_char(char) async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate: """Poll the device for updates.""" payload = await self._async_connect_and_read(ble_device) if self._device_type in EIGHTEEN_BYTE_SENSOR_MODELS: self._update_eighteen_byte_model_from_raw(payload[5:9], payload[9]) elif self._device_type in NINE_BYTE_SENSOR_MODELS: # Battery doesn't seem to be available for these models # but it is in the advertisement data self._update_nine_byte_model_from_raw(payload[0:4], None) return self._finish_update() def _update_bbq_model(self, data: bytes, msg_length: int) -> None: """Update a BBQ sensor model.""" # Some are iBBQ, some are xBBQ if TYPE_CHECKING: assert self._device_type is not None xvalue = data[10:] for idx, temp in enumerate(MODEL_INFO[self._device_type].unpacker(xvalue)): num = idx + 1 self.update_predefined_sensor( SensorLibrary.TEMPERATURE__CELSIUS, convert_temperature(temp), key=f"temperature_probe_{num}", name=f"Temperature Probe {num}", ) def _update_nine_byte_model(self, data: bytes, msg_length: int) -> None: """Update the sensor values for a 9 byte model.""" self._update_nine_byte_model_from_raw(data[0:4], data[7]) def _update_nine_byte_model_from_raw( self, temp_hum_bytes: bytes, bat: int | None ) -> None: if TYPE_CHECKING: assert self._device_type is not None temp, hum = MODEL_INFO[self._device_type].unpacker(temp_hum_bytes) self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp / 100) # Only some TH2 models have humidity if self._device_type == Model.IBS_TH or ( self._device_type == Model.IBS_TH2 and hum != 0 ): self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, hum / 100) if bat is not None: # Battery is only available in the advertisement data # for some models self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, bat) def _update_eighteen_byte_model(self, data: bytes, msg_length: int) -> None: """Update the sensor values for a 18 byte model.""" self._update_eighteen_byte_model_from_raw(data[6:10], data[10]) def _update_eighteen_byte_model_from_raw( self, temp_hum_bytes: bytes, bat: int ) -> None: """Update the sensor values for a 18 byte model.""" if TYPE_CHECKING: assert self._device_type is not None temp, hum = MODEL_INFO[self._device_type].unpacker(temp_hum_bytes) self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp / 10) self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, bat) if hum != 0: self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, hum / 10) _device_type_dispatch: ClassVar[ dict[Model, Callable[[INKBIRDBluetoothDeviceData, bytes, int], None]] ] INKBIRDBluetoothDeviceData._device_type_dispatch = { # noqa: SLF001 **dict.fromkeys( BBQ_MODELS, INKBIRDBluetoothDeviceData._update_bbq_model, # noqa: SLF001 ), **dict.fromkeys( NINE_BYTE_SENSOR_MODELS, INKBIRDBluetoothDeviceData._update_nine_byte_model, # noqa: SLF001 ), **dict.fromkeys( EIGHTEEN_BYTE_SENSOR_MODELS, INKBIRDBluetoothDeviceData._update_eighteen_byte_model, # noqa: SLF001 ), } inkbird-ble-0.16.2/src/inkbird_ble/py.typed000066400000000000000000000000001501335542600205060ustar00rootroot00000000000000inkbird-ble-0.16.2/tests/000077500000000000000000000000001501335542600151305ustar00rootroot00000000000000inkbird-ble-0.16.2/tests/__init__.py000066400000000000000000000014301501335542600172370ustar00rootroot00000000000000from __future__ import annotations import asyncio import time from typing import TYPE_CHECKING if TYPE_CHECKING: from datetime import datetime _MONOTONIC_RESOLUTION = 0.0001 def async_fire_time_changed(utc_datetime: datetime) -> None: timestamp = utc_datetime.timestamp() loop = asyncio.get_running_loop() for task in list(loop._scheduled): # type: ignore[attr-defined] # noqa: SLF001 if not isinstance(task, asyncio.TimerHandle): continue if task.cancelled(): continue mock_seconds_into_future = timestamp - time.time() future_seconds = task.when() - (loop.time() + _MONOTONIC_RESOLUTION) if mock_seconds_into_future >= future_seconds: task._run() # noqa: SLF001 task.cancel() inkbird-ble-0.16.2/tests/test_parser.py000066400000000000000000003102111501335542600200330ustar00rootroot00000000000000from __future__ import annotations import asyncio from datetime import datetime, timedelta from typing import TYPE_CHECKING, Any from unittest.mock import AsyncMock, MagicMock, patch import pytest from bleak.backends.device import BLEDevice from bleak.exc import BleakCharacteristicNotFoundError, BleakError from bluetooth_data_tools import monotonic_time_coarse from bluetooth_sensor_state_data import DeviceClass, SensorUpdate from habluetooth import BluetoothServiceInfoBleak from sensor_state_data import ( DeviceKey, SensorDescription, SensorDeviceClass, SensorDeviceInfo, SensorValue, Units, ) from inkbird_ble.parser import INKBIRDBluetoothDeviceData, Model from . import async_fire_time_changed if TYPE_CHECKING: from collections.abc import Callable from uuid import UUID def test_can_create(): parser = INKBIRDBluetoothDeviceData() assert parser.name == "Unknown" def make_bluetooth_service_info( # noqa: PLR0913 name: str, manufacturer_data: dict[int, bytes], service_uuids: list[str], address: str, rssi: int, service_data: dict[UUID, bytes], source: str, tx_power: int = 0, raw: bytes | None = None, ) -> BluetoothServiceInfoBleak: return BluetoothServiceInfoBleak( name=name, manufacturer_data=manufacturer_data, service_uuids=service_uuids, address=address, rssi=rssi, service_data=service_data, source=source, device=BLEDevice( name=name, address=address, details={}, rssi=rssi, ), time=monotonic_time_coarse(), advertisement=None, connectable=True, tx_power=tx_power, raw=raw, ) def test_unsupported(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="x", manufacturer_data={}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) assert parser.supported(service_info) is False assert parser.device_type is None def test_unsupported_with_manufacturer_data(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="x", manufacturer_data={2044: b"\xc7\x12\x00\xc8=V\x06"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) assert parser.supported(service_info) is False assert parser.device_type is None def test_raw_manufacturer_data(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="sps", manufacturer_data={1: b"\x00"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", raw=b"\x0a\xff\xfc\x07\xc7\x12\x00\xc8=V\x06", ) assert parser.supported(service_info) is True assert parser.device_type == Model.IBS_TH assert parser.update(service_info) == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH EEFF", model="IBS-TH", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), }, entity_values={ DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=20.44, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=48.07, ), DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=86, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_sps_with_invalid_model_passed(): parser = INKBIRDBluetoothDeviceData("invalid") service_info = make_bluetooth_service_info( name="sps", manufacturer_data={2044: b"\xc7\x12\x00\xc8=V\x06"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) parser.update(service_info) assert parser.device_type == Model.IBS_TH def test_sps(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="sps", manufacturer_data={2044: b"\xc7\x12\x00\xc8=V\x06"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_TH assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH EEFF", model="IBS-TH", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=DeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=DeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=DeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), native_value=86, name="Battery", ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=20.44, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), native_value=48.07, name="Humidity", ), }, ) def test_unknown_sps(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="sps", manufacturer_data={ 2063: b"\xc0\x12\x01p\x08d\x06", 2083: b"\x12\x01w\x08d\x06", }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:21:09:09:65:49", rssi=-54, service_data={}, source="local", ) assert parser.supported(service_info) is True assert parser.device_type == Model.IBS_TH def test_sps_variant(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="sps", manufacturer_data={ 2083: b"\x12\x01q\x08d\x06", }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:21:09:09:65:49", rssi=-96, service_data={}, source="local", ) assert parser.supported(service_info) is True assert parser.device_type == Model.IBS_TH def test_sps_variant2(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="sps", manufacturer_data={ 2363: b"\xd0\x13\x00\xce\x90d\x06", }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:22:03:25:01:46", rssi=-96, service_data={}, source="local", ) assert parser.supported(service_info) is True assert parser.device_type == Model.IBS_TH parser = INKBIRDBluetoothDeviceData() result = parser.update(service_info) assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH 0146", model="IBS-TH", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=100, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=50.72, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-96, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=23.63, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_sps_th2_dupe_updates(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="sps", manufacturer_data={2248: b"\x84\x14\x00\x88\x99d\x06"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_TH assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH EEFF", model="IBS-TH", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=DeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=DeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=DeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), native_value=100, name="Battery", ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=22.48, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), native_value=52.52, name="Humidity", ), }, ) def test_sps_th2(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="sps", manufacturer_data={2248: b"\x84\x14\x00\x88\x99d\x06"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_TH assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH EEFF", model="IBS-TH", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=DeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=DeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=DeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), native_value=100, name="Battery", ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=22.48, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), native_value=52.52, name="Humidity", ), }, ) def test_unknown_tps(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="tps", manufacturer_data={ 2120: b"\x00\x00\x00\xc6n\r\x06", }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:21:09:09:65:49", rssi=-54, service_data={}, source="local", ) assert parser.supported(service_info) is True parser = INKBIRDBluetoothDeviceData() result = parser.update(service_info) assert parser.device_type == Model.IBS_TH2 assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH2/P01B 6549", model="IBS-TH2/P01B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), }, entity_values={ DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=21.2, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-54, ), DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=13, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_ibbq_4(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="iBBQ", manufacturer_data={ 0: b"\x00\x000\xe2\x83}\xb5\x02\x04\x01\xfa\x00\x04\x01\xfa\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBBQ_4 assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="iBBQ EEFF", model="iBBQ-4", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=DeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_1", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_2", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="temperature_probe_3", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_3", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="temperature_probe_4", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_4", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature_probe_1", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_1", device_id=None), name="Temperature Probe 1", native_value=26.0, ), DeviceKey(key="temperature_probe_2", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_2", device_id=None), name="Temperature Probe 2", native_value=25.0, ), DeviceKey(key="temperature_probe_3", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_3", device_id=None), name="Temperature Probe 3", native_value=26.0, ), DeviceKey(key="temperature_probe_4", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_4", device_id=None), name="Temperature Probe 4", native_value=25.0, ), }, ) def test_ibt_2x(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="xBBQ", manufacturer_data={1: b"\x00\x00,\x11\x00\x00m\xd3\x14\x01\x11\x01"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBBQ_2 assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="xBBQ EEFF", model="xBBQ-2", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_1", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=DeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_2", device_id=None), device_class=DeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="temperature_probe_1", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_1", device_id=None), name="Temperature Probe 1", native_value=27.6, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature_probe_2", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_2", device_id=None), name="Temperature Probe 2", native_value=27.3, ), }, ) def test_xbbq_2a_adv1(): """Test xBBQ2 accepts 1 updates.""" parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="xBBQ", manufacturer_data={1: b"\x00\x00V\x11\x00\x00\x7fs\xf8\x00\xff\xff"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBBQ_2 assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="xBBQ EEFF", model="xBBQ-2", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_1", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_2", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="temperature_probe_1", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_1", device_id=None), name="Temperature Probe 1", native_value=24.8, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature_probe_2", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_2", device_id=None), name="Temperature Probe 2", native_value=6553.5, ), }, binary_entity_descriptions={}, binary_entity_values={}, ) def test_xbbq_2a_adv2(): """Test xBBQ2 ignores 2 updates.""" parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="xBBQ", manufacturer_data={2: b"\x00\x00V\x11\x00\x00\x7fs\x9a\x00\x13\x00"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) assert parser.supported(service_info) is True assert parser.device_type == Model.IBBQ_2 parser = INKBIRDBluetoothDeviceData() result = parser.update(service_info) assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="xBBQ EEFF", model="xBBQ-2", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_1", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_2", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), }, entity_values={ DeviceKey(key="temperature_probe_1", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_1", device_id=None), name="Temperature Probe 1", native_value=15.4, ), DeviceKey(key="temperature_probe_2", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_2", device_id=None), name="Temperature Probe 2", native_value=1.9, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_xbbq_multiple_mfr_data(): """Test xBBQ2 ignores 2 updates when there re multiple.""" parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="xBBQ", manufacturer_data={ 1: b"\x00\x00,\x11\x00\x00m\xd3\x11\x01\x12\x01", 2: b"\x00\x00,\x11\x00\x00m\xd3\xda\x03\xda\x03", }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBBQ_2 assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="xBBQ EEFF", model="xBBQ-2", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_2", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature_probe_1", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), }, entity_values={ DeviceKey(key="temperature_probe_2", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_2", device_id=None), name="Temperature Probe 2", native_value=27.4, ), DeviceKey(key="temperature_probe_1", device_id=None): SensorValue( device_key=DeviceKey(key="temperature_probe_1", device_id=None), name="Temperature Probe 1", native_value=27.3, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), }, binary_entity_descriptions={}, binary_entity_values={}, ) @pytest.mark.parametrize(("model"), [Model.IBS_TH, "IBS-TH"]) def test_corrupt_name(model: Model | str) -> None: """Test corrupt name.""" parser = INKBIRDBluetoothDeviceData(model) assert parser.device_type == Model.IBS_TH service_info = make_bluetooth_service_info( name="N0BYD", manufacturer_data={63915: b"\x1b\x1e\x00H\xe37\x08"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH EEFF", model="IBS-TH", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), }, entity_values={ DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=-16.21, ), DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=55, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=77.07, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_ith_21_b(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="ITH-21-B", manufacturer_data={ 9289: b"\x07\x11\x00\x98\xd8\x00\x13\x02d\x01\x90\x04\x00\x00\x00\x00", }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-34, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type is Model.ITH_21_B assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="ITH-21-B EEFF", model="ITH-21-B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=100, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=53.1, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-34, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=21.6, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_ith_31_b(): parser = INKBIRDBluetoothDeviceData() # 26.8C 53% b'\x12#\x05/\x0e\x01\x10\x02d\x00\x00\x00\x00\x00\x00\x00' # 24.0C 50% b'\x12#\x05/\xf0\x00\xf9\x01d\x00\x00\x04\x00\x00\x00\x00' service_info = make_bluetooth_service_info( name="ITH-13-B", manufacturer_data={ 9289: b"\x12#\x05/\x0e\x01\x10\x02d\x00\x00\x00\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-34, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type is Model.ITH_13_B assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="ITH-13-B EEFF", model="ITH-13-B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=100, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=52.8, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-34, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=27.0, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) service_info = make_bluetooth_service_info( name="ITH-13-B", manufacturer_data={ 9289: b"\x12#\x05/\xf0\x00\xf9\x01d\x00\x00\x04\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-34, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type is Model.ITH_13_B assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="ITH-13-B EEFF", model="ITH-13-B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=100, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=50.5, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-34, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=24.0, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_ith_11_b(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="ITH-11-B", manufacturer_data={ 9289: b"\x08\x12\x00^\x00\x00]\x03d\x00d\x08\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-34, service_data={}, source="local", ) result = parser.update(service_info) assert parser.name == "ITH-11-B EEFF" assert parser.poll_needed(service_info, None) is False assert parser.device_type is Model.ITH_11_B assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="ITH-11-B EEFF", model="ITH-11-B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=100, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=86.1, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-34, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=0.0, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) service_info = make_bluetooth_service_info( name="ITH-11-B", manufacturer_data={ 9289: b"\x08\x12\x00^\xfe\xffH\x03d\x00d\x08\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-34, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type is Model.ITH_11_B assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="ITH-11-B EEFF", model="ITH-11-B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=100, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=84.0, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-34, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=-0.2, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_passive_data_needs_polling() -> None: """Test passive data need polling.""" parser = INKBIRDBluetoothDeviceData(Model.IBS_TH) assert parser.device_type == Model.IBS_TH service_info = make_bluetooth_service_info( name="N0BYD", manufacturer_data={}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.poll_needed(service_info, None) is True assert parser.name == "IBS-TH EEFF" assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH EEFF", model="IBS-TH", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), }, entity_values={ DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) @pytest.mark.asyncio async def test_passive_polling_ibs_th() -> None: """Test polling with passing data.""" parser = INKBIRDBluetoothDeviceData(Model.IBS_TH) assert parser.device_type == Model.IBS_TH service_info = make_bluetooth_service_info( name="N0BYD", manufacturer_data={}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) parser.update(service_info) assert parser.poll_needed(service_info, None) is True read_gatt_char_mock = AsyncMock(return_value=b"\x09\x09\x00\x04\xe37\x08") disconnect_mock = AsyncMock() mock_client = MagicMock( read_gatt_char=read_gatt_char_mock, disconnect=disconnect_mock ) with patch("inkbird_ble.parser.establish_connection", return_value=mock_client): update = await parser.async_poll( BLEDevice( address="aa:bb:cc:dd:ee:ff", name="N0BYD", details={}, rssi=-60, ) ) assert update == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-TH EEFF", model="IBS-TH", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), }, entity_values={ DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=23.13, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=10.24, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) @pytest.mark.asyncio async def test_passive_polling_ith_11_b() -> None: """Test polling with passing data.""" parser = INKBIRDBluetoothDeviceData(Model.ITH_11_B) assert parser.device_type == Model.ITH_11_B service_info = make_bluetooth_service_info( name="N0BYD", manufacturer_data={}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) parser.update(service_info) assert parser.poll_needed(service_info, None) is True read_gatt_char_mock = AsyncMock(return_value=b"rtdth\xd8\x00\xef\x01a\x00\x90\x04") disconnect_mock = AsyncMock() mock_client = MagicMock( read_gatt_char=read_gatt_char_mock, disconnect=disconnect_mock ) with patch("inkbird_ble.parser.establish_connection", return_value=mock_client): update = await parser.async_poll( BLEDevice( address="aa:bb:cc:dd:ee:ff", name="N0BYD", details={}, rssi=-60, ) ) assert update == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="ITH-11-B EEFF", model="ITH-11-B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), }, entity_values={ DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=21.6, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=49.5, ), DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=97, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) @pytest.mark.asyncio async def test_passive_polling_fails_missing_char() -> None: """Test polling with passing data.""" parser = INKBIRDBluetoothDeviceData(Model.ITH_11_B) assert parser.device_type == Model.ITH_11_B service_info = make_bluetooth_service_info( name="N0BYD", manufacturer_data={}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) parser.update(service_info) assert parser.poll_needed(service_info, None) is True read_gatt_char_mock = AsyncMock(side_effect=BleakCharacteristicNotFoundError(1)) disconnect_mock = AsyncMock() clear_cache_mock = AsyncMock() mock_client = MagicMock( read_gatt_char=read_gatt_char_mock, disconnect=disconnect_mock, clear_cache=clear_cache_mock, ) with ( pytest.raises(BleakCharacteristicNotFoundError), patch("inkbird_ble.parser.establish_connection", return_value=mock_client), ): await parser.async_poll( BLEDevice( address="aa:bb:cc:dd:ee:ff", name="N0BYD", details={}, rssi=-60, ) ) clear_cache_mock.assert_awaited_once() @pytest.mark.asyncio async def test_passive_polling_fails_generic_bleak_error() -> None: """Test polling with passing data.""" parser = INKBIRDBluetoothDeviceData(Model.ITH_11_B) assert parser.device_type == Model.ITH_11_B service_info = make_bluetooth_service_info( name="N0BYD", manufacturer_data={}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) parser.update(service_info) assert parser.poll_needed(service_info, None) is True read_gatt_char_mock = AsyncMock(side_effect=BleakError) disconnect_mock = AsyncMock() clear_cache_mock = AsyncMock() mock_client = MagicMock( read_gatt_char=read_gatt_char_mock, disconnect=disconnect_mock, clear_cache=clear_cache_mock, ) with ( pytest.raises(BleakError), patch("inkbird_ble.parser.establish_connection", return_value=mock_client), ): await parser.async_poll( BLEDevice( address="aa:bb:cc:dd:ee:ff", name="N0BYD", details={}, rssi=-60, ) ) clear_cache_mock.assert_not_awaited() @pytest.mark.asyncio async def test_passive_detect_iam_t1() -> None: """Test polling with passing data.""" parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="", manufacturer_data={12628: bytes.fromhex("41432d363230306131336361650000")}, service_uuids=[], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) parser.update(service_info) assert parser.device_type == Model.IAM_T1 assert parser.poll_needed(service_info, None) is False assert parser.name == "IAM-T1 EEFF" assert parser.supported(service_info) is True @pytest.mark.asyncio async def test_notify_does_nothing_not_supported() -> None: """Test polling with passing data.""" parser = INKBIRDBluetoothDeviceData(Model.ITH_11_B) assert parser.device_type == Model.ITH_11_B assert parser.uses_notify is False await parser.async_start( make_bluetooth_service_info( name="N0BYD", manufacturer_data={}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ), BLEDevice( address="aa:bb:cc:dd:ee:ff", name="N0BYD", details={}, rssi=-60, ), ) await parser.async_stop() @pytest.mark.asyncio async def test_notify_callbacks_iam_t1_f() -> None: """Test notify with passing data in F.""" last_update: SensorUpdate | None = None def _update_callback(update: SensorUpdate) -> None: nonlocal last_update last_update = update def _data_callback(data: dict[str, Any]) -> None: """ Callback for data updates. """ parser = INKBIRDBluetoothDeviceData( Model.IAM_T1, {}, _update_callback, _data_callback ) assert parser.device_type == Model.IAM_T1 service_info = make_bluetooth_service_info( name="Ink@IAM-T1", manufacturer_data={12628: b"AC-6200a13cae\x00\x00"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="62:00:A1:3C:AE:7B", rssi=-44, service_data={}, source="local", ) parser.update(service_info) assert parser.supported(service_info) is True assert parser.poll_needed(service_info, None) is False assert parser.uses_notify disconnect_mock = AsyncMock() async def start_notify_mock( uuid: UUID, callback: Callable[[UUID, bytes], None] ) -> None: callback(uuid, b"U") callback(uuid, b"U\xaa\x05\x0c\x00\x00\x00\x00\x00\x00\x01\x11") callback(uuid, b"U\xaa\x01\x10\x10\x03\x0b\x01\xd6\x02\xe3\x03\xf1\x01\x00\xcf") mock_client = MagicMock(start_notify=start_notify_mock, disconnect=disconnect_mock) with patch("inkbird_ble.parser.establish_connection", return_value=mock_client): await parser.async_start( service_info, BLEDevice( address="62:00:A1:3C:AE:7B", name="Ink@IAM-T1", details={}, rssi=-60, ), ) await asyncio.sleep(0) await parser.async_stop() assert last_update == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IAM-T1 AE7B", model="IAM-T1", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="carbon_dioxide", device_id=None): SensorDescription( device_key=DeviceKey(key="carbon_dioxide", device_id=None), device_class=SensorDeviceClass.CO2, native_unit_of_measurement=Units.CONCENTRATION_PARTS_PER_MILLION, ), DeviceKey(key="pressure", device_id=None): SensorDescription( device_key=DeviceKey(key="pressure", device_id=None), device_class=SensorDeviceClass.PRESSURE, native_unit_of_measurement=Units.PRESSURE_HPA, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), }, entity_values={ DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=25.5, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=47.0, ), DeviceKey(key="carbon_dioxide", device_id=None): SensorValue( device_key=DeviceKey(key="carbon_dioxide", device_id=None), name="Carbon Dioxide", native_value=739, ), DeviceKey(key="pressure", device_id=None): SensorValue( device_key=DeviceKey(key="pressure", device_id=None), name="Pressure", native_value=1009, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-44, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) @pytest.mark.asyncio async def test_notify_iam_t1_c() -> None: """Test notify with passing data in C.""" last_update: SensorUpdate | None = None def _update_callback(update: SensorUpdate) -> None: nonlocal last_update last_update = update def _data_callback(data: dict[str, Any]) -> None: """ Callback for data updates. """ parser = INKBIRDBluetoothDeviceData( Model.IAM_T1, {}, _update_callback, _data_callback ) assert parser.device_type == Model.IAM_T1 service_info = make_bluetooth_service_info( name="Ink@IAM-T1", manufacturer_data={12628: b"AC-6200a13cae\x00\x00"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="62:00:A1:3C:AE:7B", rssi=-44, service_data={}, source="local", ) parser.update(service_info) assert parser.supported(service_info) is True assert parser.poll_needed(service_info, None) is False assert parser.uses_notify disconnect_mock = AsyncMock() async def start_notify_mock( uuid: UUID, callback: Callable[[UUID, bytes], None] ) -> None: callback(uuid, b"U\xaa\x05\x0c\x00\x00\x00\x00\x00\x00\x00\x10") callback(uuid, b"U\xaa\x01\x10\x00\x00\xfe\x01\xd6\x02\xd9\x03\xf1\x01\x00\xb5") mock_client = MagicMock(start_notify=start_notify_mock, disconnect=disconnect_mock) with patch("inkbird_ble.parser.establish_connection", return_value=mock_client): await parser.async_start( service_info, BLEDevice( address="62:00:A1:3C:AE:7B", name="Ink@IAM-T1", details={}, rssi=-60, ), ) await asyncio.sleep(0) await parser.async_stop() assert last_update == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IAM-T1 AE7B", model="IAM-T1", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="humidity", device_id=None): SensorDescription( device_key=DeviceKey(key="humidity", device_id=None), device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="carbon_dioxide", device_id=None): SensorDescription( device_key=DeviceKey(key="carbon_dioxide", device_id=None), device_class=SensorDeviceClass.CO2, native_unit_of_measurement=Units.CONCENTRATION_PARTS_PER_MILLION, ), DeviceKey(key="pressure", device_id=None): SensorDescription( device_key=DeviceKey(key="pressure", device_id=None), device_class=SensorDeviceClass.PRESSURE, native_unit_of_measurement=Units.PRESSURE_HPA, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), }, entity_values={ DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=25.4, ), DeviceKey(key="humidity", device_id=None): SensorValue( device_key=DeviceKey(key="humidity", device_id=None), name="Humidity", native_value=47.0, ), DeviceKey(key="carbon_dioxide", device_id=None): SensorValue( device_key=DeviceKey(key="carbon_dioxide", device_id=None), name="Carbon Dioxide", native_value=729, ), DeviceKey(key="pressure", device_id=None): SensorValue( device_key=DeviceKey(key="pressure", device_id=None), name="Pressure", native_value=1009, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-44, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) @pytest.mark.asyncio async def test_retry_iam_t1_f() -> None: """Test retry with notify with passing data in F.""" last_update: SensorUpdate | None = None data_callbacks: list[dict[str, Any]] = [] def _update_callback(update: SensorUpdate) -> None: nonlocal last_update last_update = update def _data_callback(data: dict[str, Any]) -> None: """ Callback for data updates. """ data_callbacks.append(data.copy()) parser = INKBIRDBluetoothDeviceData( Model.IAM_T1, {}, _update_callback, _data_callback ) assert parser.device_type == Model.IAM_T1 service_info = make_bluetooth_service_info( name="Ink@IAM-T1", manufacturer_data={12628: b"AC-6200a13cae\x00\x00"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="62:00:A1:3C:AE:7B", rssi=-44, service_data={}, source="local", ) parser.update(service_info) assert parser.supported(service_info) is True assert parser.poll_needed(service_info, None) is False assert parser.uses_notify disconnect_mock = AsyncMock() attempt = 0 async def start_notify_mock( uuid: UUID, callback: Callable[[UUID, bytes], None] ) -> None: nonlocal attempt attempt += 1 if attempt == 1: msg = "test error" raise BleakError(msg) callback(uuid, b"U") callback(uuid, b"U\xaa\x05\x0c\x00\x00\x00\x00\x00\x00\x00\x11") callback(uuid, b"U\xaa\x05\x0c\x00\x00\x00\x00\x00\x00\x01\x11") callback(uuid, b"U\xaa\x01\x10\x10\x03\x0b\x01\xd6\x02\xe3\x03\xf1\x01\x00\xcf") mock_client = MagicMock(start_notify=start_notify_mock, disconnect=disconnect_mock) with patch("inkbird_ble.parser.establish_connection", return_value=mock_client): await parser.async_start( service_info, BLEDevice( address="62:00:A1:3C:AE:7B", name="Ink@IAM-T1", details={}, rssi=-60, ), ) await asyncio.sleep(0) await parser.async_stop() assert last_update is not None assert data_callbacks == [ {"temp_unit": Units.TEMP_CELSIUS}, {"temp_unit": Units.TEMP_FAHRENHEIT}, ] @pytest.mark.asyncio async def test_reconnect_iam_t1_f() -> None: """Test reconnect with notify with passing data in F.""" last_update: SensorUpdate | None = None def _update_callback(update: SensorUpdate) -> None: nonlocal last_update last_update = update def _data_callback(data: dict[str, Any]) -> None: """ Callback for data updates. """ parser = INKBIRDBluetoothDeviceData( Model.IAM_T1, {}, _update_callback, _data_callback ) assert parser.device_type == Model.IAM_T1 service_info = make_bluetooth_service_info( name="Ink@IAM-T1", manufacturer_data={12628: b"AC-6200a13cae\x00\x00"}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="62:00:A1:3C:AE:7B", rssi=-44, service_data={}, source="local", ) parser.update(service_info) assert parser.supported(service_info) is True assert parser.poll_needed(service_info, None) is False assert parser.uses_notify disconnect_mock = AsyncMock() start_notify_calls = 0 async def start_notify_mock( uuid: UUID, callback: Callable[[UUID, bytes], None] ) -> None: nonlocal start_notify_calls start_notify_calls += 1 callback(uuid, b"U") callback(uuid, b"U\xaa\x05\x0c\x00\x00\x00\x00\x00\x00\x01\x11") callback(uuid, b"U\xaa\x01\x10\x10\x03\x0b\x01\xd6\x02\xe3\x03\xf1\x01\x00\xcf") set_disconnected_callback_mock = MagicMock() mock_client = MagicMock( start_notify=start_notify_mock, disconnect=disconnect_mock, set_disconnected_callback=set_disconnected_callback_mock, ) with patch("inkbird_ble.parser.establish_connection", return_value=mock_client): await parser.async_start( service_info, BLEDevice( address="62:00:A1:3C:AE:7B", name="Ink@IAM-T1", details={}, rssi=-60, ), ) await asyncio.sleep(0) assert set_disconnected_callback_mock.called set_disconnected_callback_mock.call_args[0][0](mock_client) await asyncio.sleep(0) assert start_notify_calls == 1 async_fire_time_changed(datetime.utcnow() + timedelta(seconds=5)) await asyncio.sleep(0) assert start_notify_calls == 2 await parser.async_stop() assert last_update is not None def test_IBS_P02B(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={9289: bytes.fromhex("11180065d00000005a00800000000000")}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-P02B EEFF", model="IBS-P02B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), }, entity_values={ DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=20.8, ), DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=90, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_IBS_P02B_real_data(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={9289: bytes.fromhex("111800656e0100005f00000100000000")}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="IBS-P02B 0065", model="IBS-P02B", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), }, entity_values={ DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=95, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=36.6, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_IBS_P02B_passive_detection(): parser = INKBIRDBluetoothDeviceData() service_info = make_bluetooth_service_info( name="", manufacturer_data={9289: bytes.fromhex("11180065d00000005a00800000000000")}, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="aa:bb:cc:dd:ee:ff", rssi=-60, service_data={}, source="local", ) result = parser.update(service_info) assert parser.device_type == Model.GENERIC_18 assert result == SensorUpdate( title=None, devices={ None: SensorDeviceInfo( name="Unknown 18-byte model EEFF", model="Unknown 18-byte model", manufacturer="INKBIRD", sw_version=None, hw_version=None, ) }, entity_descriptions={ DeviceKey(key="temperature", device_id=None): SensorDescription( device_key=DeviceKey(key="temperature", device_id=None), device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=Units.TEMP_CELSIUS, ), DeviceKey(key="battery", device_id=None): SensorDescription( device_key=DeviceKey(key="battery", device_id=None), device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=Units.PERCENTAGE, ), DeviceKey(key="signal_strength", device_id=None): SensorDescription( device_key=DeviceKey(key="signal_strength", device_id=None), device_class=SensorDeviceClass.SIGNAL_STRENGTH, native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT, ), }, entity_values={ DeviceKey(key="temperature", device_id=None): SensorValue( device_key=DeviceKey(key="temperature", device_id=None), name="Temperature", native_value=20.8, ), DeviceKey(key="battery", device_id=None): SensorValue( device_key=DeviceKey(key="battery", device_id=None), name="Battery", native_value=90, ), DeviceKey(key="signal_strength", device_id=None): SensorValue( device_key=DeviceKey(key="signal_strength", device_id=None), name="Signal Strength", native_value=-60, ), }, binary_entity_descriptions={}, binary_entity_values={}, events={}, ) def test_IBS_P02B_multiple_updates(): """Test multiple sequential updates from an IBS-P02B device with real-world data. This test uses real data captured from an IBS-P02B device to verify that the parser correctly handles multiple updates with varying signal strengths but consistent temperature readings. """ parser = INKBIRDBluetoothDeviceData() # 1st update - 2025-05-08 23:36:23.808 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-83, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -83 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 95 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 2nd update - 2025-05-08 23:36:44.518 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-77, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -77 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 96 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 3rd update - 2025-05-08 23:37:52.300 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-73, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -73 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 95 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 4th update - 2025-05-08 23:38:25.011 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-74, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -74 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 96 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 5th update - 2025-05-08 23:39:52.325 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-79, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -79 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 95 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 6th update - 2025-05-08 23:40:53.261 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-78, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -78 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 96 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 7th update - 2025-05-08 23:42:47.511 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-72, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -72 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 95 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 8th update - 2025-05-08 23:43:48.405 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-78, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -78 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 96 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 9th update - 2025-05-08 23:44:37.322 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-75, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -75 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 95 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 10th update - 2025-05-08 23:46:30.410 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-76, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -76 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 96 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 11th update - 2025-05-08 23:46:37.319 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-81, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00_\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -81 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 95 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # 12th update - 2025-05-08 23:47:57.110 service_info = make_bluetooth_service_info( name="IBS-P02B", manufacturer_data={ 9289: b"\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00" }, service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"], address="49:24:11:18:00:65", rssi=-78, service_data={}, source="B8:D6:1A:8B:C7:C6", raw=b"\x02\x01\x06\x03\x02\xf0\xff\t\tIBS-P02B\x13\xffI$\x11\x18\x00ev\x01\x00\x00`\x00\x00\x01\x00\x00\x00\x00", ) result = parser.update(service_info) assert parser.device_type == Model.IBS_P02B assert ( result.entity_values[ DeviceKey(key="signal_strength", device_id=None) ].native_value == -78 ) assert ( result.entity_values[DeviceKey(key="battery", device_id=None)].native_value == 96 ) assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 ) # Verify device information is consistent throughout all updates assert result.devices[None].name == "IBS-P02B 0065" assert result.devices[None].model == "IBS-P02B" assert result.devices[None].manufacturer == "INKBIRD" # Verify that temperature was consistent throughout all updates assert ( result.entity_values[DeviceKey(key="temperature", device_id=None)].native_value == 37.4 )