pax_global_header 0000666 0000000 0000000 00000000064 15040370547 0014517 g ustar 00root root 0000000 0000000 52 comment=27d35185345c92231fa5ac123f753084b9bae229
oralb-ble-1.0.0/ 0000775 0000000 0000000 00000000000 15040370547 0013354 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/.all-contributorsrc 0000664 0000000 0000000 00000000450 15040370547 0017204 0 ustar 00root root 0000000 0000000 {
"projectName": "oralb-ble",
"projectOwner": "Bluetooth-Devices",
"repoType": "github",
"repoHost": "https://github.com",
"files": ["README.md"],
"imageSize": 80,
"commit": true,
"commitConvention": "angular",
"contributors": [],
"contributorsPerLine": 7,
"skipCi": true
}
oralb-ble-1.0.0/.editorconfig 0000664 0000000 0000000 00000000444 15040370547 0016033 0 ustar 00root root 0000000 0000000 # 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
oralb-ble-1.0.0/.flake8 0000664 0000000 0000000 00000000057 15040370547 0014531 0 ustar 00root root 0000000 0000000 [flake8]
exclude = docs
max-line-length = 2188
oralb-ble-1.0.0/.github/ 0000775 0000000 0000000 00000000000 15040370547 0014714 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 15040370547 0017077 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/.github/ISSUE_TEMPLATE/1-bug_report.md 0000664 0000000 0000000 00000000422 15040370547 0021725 0 ustar 00root root 0000000 0000000 ---
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.
oralb-ble-1.0.0/.github/ISSUE_TEMPLATE/2-feature-request.md 0000664 0000000 0000000 00000000672 15040370547 0022706 0 ustar 00root root 0000000 0000000 ---
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.
oralb-ble-1.0.0/.github/dependabot.yml 0000664 0000000 0000000 00000001351 15040370547 0017544 0 ustar 00root root 0000000 0000000 # 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(deps-ci): "
groups:
github-actions:
patterns:
- "*"
- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
oralb-ble-1.0.0/.github/labels.toml 0000664 0000000 0000000 00000003515 15040370547 0017057 0 ustar 00root root 0000000 0000000 [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"
oralb-ble-1.0.0/.github/workflows/ 0000775 0000000 0000000 00000000000 15040370547 0016751 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/.github/workflows/ci.yml 0000664 0000000 0000000 00000004750 15040370547 0020075 0 ustar 00root root 0000000 0000000 name: 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.9"
- 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
test:
strategy:
fail-fast: false
matrix:
python-version:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
os:
- ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- uses: snok/install-poetry@v1
- name: Install Dependencies
shell: bash
run: poetry install
- name: Test with Pytest
shell: bash
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@v10.0.2
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@v10.0.2
if: steps.release.outputs.released == 'true'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ steps.release.outputs.tag }}
oralb-ble-1.0.0/.github/workflows/hacktoberfest.yml 0000664 0000000 0000000 00000000534 15040370547 0022322 0 ustar 00root root 0000000 0000000 name: 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 }}
oralb-ble-1.0.0/.github/workflows/issue-manager.yml 0000664 0000000 0000000 00000001340 15040370547 0022232 0 ustar 00root root 0000000 0000000 name: 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."
}
}
oralb-ble-1.0.0/.github/workflows/labels.yml 0000664 0000000 0000000 00000000774 15040370547 0020746 0 ustar 00root root 0000000 0000000 name: 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
oralb-ble-1.0.0/.gitignore 0000664 0000000 0000000 00000004066 15040370547 0015352 0 ustar 00root root 0000000 0000000 # 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/
oralb-ble-1.0.0/.gitpod.yml 0000664 0000000 0000000 00000000306 15040370547 0015442 0 ustar 00root root 0000000 0000000 tasks:
- command: |
pip install poetry
PIP_USER=false poetry install
- command: |
pip install pre-commit
pre-commit install
PIP_USER=false pre-commit install-hooks
oralb-ble-1.0.0/.idea/ 0000775 0000000 0000000 00000000000 15040370547 0014334 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/.idea/oralb-ble.iml 0000664 0000000 0000000 00000000515 15040370547 0016677 0 ustar 00root root 0000000 0000000
oralb-ble-1.0.0/.idea/watcherTasks.xml 0000664 0000000 0000000 00000005253 15040370547 0017526 0 ustar 00root root 0000000 0000000
oralb-ble-1.0.0/.idea/workspace.xml 0000664 0000000 0000000 00000002725 15040370547 0017062 0 ustar 00root root 0000000 0000000
oralb-ble-1.0.0/.pre-commit-config.yaml 0000664 0000000 0000000 00000003321 15040370547 0017634 0 ustar 00root root 0000000 0000000 # 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.8.3
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.20.0
hooks:
- id: pyupgrade
args: [--py39-plus]
- repo: https://github.com/PyCQA/isort
rev: 6.0.1
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
- id: black
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
- id: codespell
- repo: https://github.com/PyCQA/flake8
rev: 7.3.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.17.0
hooks:
- id: mypy
additional_dependencies: []
- repo: https://github.com/PyCQA/bandit
rev: 1.8.6
hooks:
- id: bandit
args: [-x, tests]
oralb-ble-1.0.0/.readthedocs.yml 0000664 0000000 0000000 00000001004 15040370547 0016435 0 ustar 00root root 0000000 0000000 # 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
oralb-ble-1.0.0/CHANGELOG.md 0000664 0000000 0000000 00000020264 15040370547 0015171 0 ustar 00root root 0000000 0000000 # Changelog
## v0.18.0 (2024-02-21)
### Feature
* Add brush modes to the parser ([#48](https://github.com/Bluetooth-Devices/oralb-ble/issues/48)) ([`2a55f37`](https://github.com/Bluetooth-Devices/oralb-ble/commit/2a55f375331d5e6b40050fa4230827486b4e2539))
## v0.17.6 (2023-03-21)
### Fix
* Add retries to polling functionality ([#43](https://github.com/Bluetooth-Devices/oralb-ble/issues/43)) ([`90ab0fa`](https://github.com/Bluetooth-Devices/oralb-ble/commit/90ab0fa99c072bc668897b094c8b6892ebcc2284))
## v0.17.5 (2023-02-07)
### Fix
* Change device bytes to len 2 ([#42](https://github.com/Bluetooth-Devices/oralb-ble/issues/42)) ([`006d94a`](https://github.com/Bluetooth-Devices/oralb-ble/commit/006d94a195e7f39b38185478377c7512e1dfa0a5))
## v0.17.4 (2023-02-06)
### Fix
* Bump commitlint-github-action ([#41](https://github.com/Bluetooth-Devices/oralb-ble/issues/41)) ([`9940fab`](https://github.com/Bluetooth-Devices/oralb-ble/commit/9940fab11d3dccbdd19ba93b53b0b9ffc71a89cf))
## v0.17.3 (2023-02-06)
### Fix
* Bump python-semantic-release ([#40](https://github.com/Bluetooth-Devices/oralb-ble/issues/40)) ([`0772a42`](https://github.com/Bluetooth-Devices/oralb-ble/commit/0772a4244788c5647645fe36a0a918d301da69cb))
* Identification of Genius X and 10000 ([#39](https://github.com/Bluetooth-Devices/oralb-ble/issues/39)) ([`93ea567`](https://github.com/Bluetooth-Devices/oralb-ble/commit/93ea567b150cf084e76504b9fdc741ad7a7db880))
## v0.17.2 (2023-02-03)
### Fix
* Io4 identification for some models ([#38](https://github.com/Bluetooth-Devices/oralb-ble/issues/38)) ([`2eaaf2b`](https://github.com/Bluetooth-Devices/oralb-ble/commit/2eaaf2be23d5c8b4d8a8af4ea93d90c5eefd1b63))
## v0.17.1 (2023-01-13)
### Fix
* Move mock and pytest-asyncio to dev deps ([#34](https://github.com/Bluetooth-Devices/oralb-ble/issues/34)) ([`acec5f6`](https://github.com/Bluetooth-Devices/oralb-ble/commit/acec5f64f1b978b57734884508da4bd909b548c0))
## v0.17.0 (2023-01-12)
### Feature
* Added init support for active connection to get battery ([#32](https://github.com/Bluetooth-Devices/oralb-ble/issues/32)) ([`efcf142`](https://github.com/Bluetooth-Devices/oralb-ble/commit/efcf1424b0e51e87844a539931d6cd26c4c6f32c))
## v0.16.1 (2023-01-08)
### Fix
* Added pressure and sector codes while connected to app ([#31](https://github.com/Bluetooth-Devices/oralb-ble/issues/31)) ([`9cff663`](https://github.com/Bluetooth-Devices/oralb-ble/commit/9cff663ee77b5b739b4f6eabc519aa21be7b92c6))
## v0.16.0 (2023-01-08)
### Feature
* Rework sectors, fix pressures, and fix misidentification of IO 9 as 8 ([#30](https://github.com/Bluetooth-Devices/oralb-ble/issues/30)) ([`7000169`](https://github.com/Bluetooth-Devices/oralb-ble/commit/70001694d8f8c2a99ca560566eff875c722dd0d3))
## v0.15.0 (2023-01-07)
### Feature
* Add support for IO Series 6 and Tongue Cleaning Mode ([#29](https://github.com/Bluetooth-Devices/oralb-ble/issues/29)) ([`a1426b5`](https://github.com/Bluetooth-Devices/oralb-ble/commit/a1426b5b9bdb456caa838bd971b6f73c9756ccfd))
## v0.14.3 (2022-12-01)
### Fix
* Ci ([#28](https://github.com/Bluetooth-Devices/oralb-ble/issues/28)) ([`9fd1c4e`](https://github.com/Bluetooth-Devices/oralb-ble/commit/9fd1c4ee7fc3afadb31f3beb5b1b94bb8bc9c624))
## v0.14.2 (2022-11-11)
### Fix
* Detction of Oral-B Genius 9000 black model ([#26](https://github.com/Bluetooth-Devices/oralb-ble/issues/26)) ([`6a114c5`](https://github.com/Bluetooth-Devices/oralb-ble/commit/6a114c55911b9ce332ad5e053e159e0f3b15e1f1))
## v0.14.1 (2022-11-09)
### Fix
* Add missing mapping for IO Series 8 ([#25](https://github.com/Bluetooth-Devices/oralb-ble/issues/25)) ([`20722d2`](https://github.com/Bluetooth-Devices/oralb-ble/commit/20722d22d8dc7ab1879e8ec8bbfa686047efeb80))
## v0.14.0 (2022-11-06)
### Feature
* Add support for Genius/Smart Series 8000 ([#21](https://github.com/Bluetooth-Devices/oralb-ble/issues/21)) ([`fe17ea4`](https://github.com/Bluetooth-Devices/oralb-ble/commit/fe17ea451a5e6ad10ea75a611495a4636fa1bfab))
## v0.13.0 (2022-11-05)
### Feature
* Add tests for smart series 6000 ([#19](https://github.com/Bluetooth-Devices/oralb-ble/issues/19)) ([`93ccc7c`](https://github.com/Bluetooth-Devices/oralb-ble/commit/93ccc7c569b00b6bb41468abe540dcda0f5e6e86))
## v0.12.0 (2022-11-05)
### Feature
* Add mapping for older 9 byte models ([#18](https://github.com/Bluetooth-Devices/oralb-ble/issues/18)) ([`95338aa`](https://github.com/Bluetooth-Devices/oralb-ble/commit/95338aa6d54e5668cb9f7605e44d662d3c05a212))
## v0.11.1 (2022-11-05)
### Fix
* Add pressure mappings for 32 ([#14](https://github.com/Bluetooth-Devices/oralb-ble/issues/14)) ([`b992a62`](https://github.com/Bluetooth-Devices/oralb-ble/commit/b992a625508b3f970cfe4ca855201431d005effe))
## v0.11.0 (2022-11-05)
### Feature
* Add more pressure mappings from a 6000 ([#17](https://github.com/Bluetooth-Devices/oralb-ble/issues/17)) ([`b1c5e31`](https://github.com/Bluetooth-Devices/oralb-ble/commit/b1c5e31bf045a0c23e0135055b5c3ed103e92d36))
## v0.10.2 (2022-11-04)
### Fix
* Add missing mapping for pressure 0 and 192 ([#15](https://github.com/Bluetooth-Devices/oralb-ble/issues/15)) ([`ef33150`](https://github.com/Bluetooth-Devices/oralb-ble/commit/ef331507284aa147b8365c21f7f0a99fc7f624b2))
## v0.10.1 (2022-11-03)
### Fix
* Pressure 48 not being mapped on 9000/4000 series ([#13](https://github.com/Bluetooth-Devices/oralb-ble/issues/13)) ([`71d95aa`](https://github.com/Bluetooth-Devices/oralb-ble/commit/71d95aa1ad1009f27afd02d5d1687a659f167197))
## v0.10.0 (2022-10-31)
### Feature
* Map IO Series 9 ([#12](https://github.com/Bluetooth-Devices/oralb-ble/issues/12)) ([`2b87fac`](https://github.com/Bluetooth-Devices/oralb-ble/commit/2b87facd73dbf8af5b244847c76a5f83e8a99144))
## v0.9.0 (2022-10-28)
### Feature
* Additional mappings for io series models ([#11](https://github.com/Bluetooth-Devices/oralb-ble/issues/11)) ([`32690dc`](https://github.com/Bluetooth-Devices/oralb-ble/commit/32690dc1c90e5344edd9e0f8c82828ebb787bc28))
## v0.8.0 (2022-10-27)
### Feature
* Refactor to improve code coverage ([#10](https://github.com/Bluetooth-Devices/oralb-ble/issues/10)) ([`5e8889e`](https://github.com/Bluetooth-Devices/oralb-ble/commit/5e8889ece3f45d1ade6bca6b76d66042e8b550ef))
## v0.7.0 (2022-10-27)
### Feature
* Add support for 9000 series ([#9](https://github.com/Bluetooth-Devices/oralb-ble/issues/9)) ([`1331e9d`](https://github.com/Bluetooth-Devices/oralb-ble/commit/1331e9dad8b290de93861d20a629e93925dcbca3))
## v0.6.0 (2022-10-27)
### Feature
* Add support for io series 4 ([#8](https://github.com/Bluetooth-Devices/oralb-ble/issues/8)) ([`f5ecd9d`](https://github.com/Bluetooth-Devices/oralb-ble/commit/f5ecd9d9619ca7c36c94cfec825d0e112f4bff72))
## v0.5.0 (2022-10-25)
### Feature
* Drop counter and replace with time ([#7](https://github.com/Bluetooth-Devices/oralb-ble/issues/7)) ([`b84045c`](https://github.com/Bluetooth-Devices/oralb-ble/commit/b84045c068435443770700387bf435c0d34f0f7a))
## v0.4.0 (2022-10-25)
### Feature
* Add support for IO Series 7 ([#6](https://github.com/Bluetooth-Devices/oralb-ble/issues/6)) ([`cc4d965`](https://github.com/Bluetooth-Devices/oralb-ble/commit/cc4d965ba5beff4d04ce3f9cdb0e32547c150160))
## v0.3.1 (2022-10-25)
### Fix
* Make strings ([#5](https://github.com/Bluetooth-Devices/oralb-ble/issues/5)) ([`c4dda18`](https://github.com/Bluetooth-Devices/oralb-ble/commit/c4dda1887a08b5a97aefa6ca1b21b14d5933725a))
## v0.3.0 (2022-10-24)
### Feature
* Add signal_strength sensor ([#4](https://github.com/Bluetooth-Devices/oralb-ble/issues/4)) ([`418a1a4`](https://github.com/Bluetooth-Devices/oralb-ble/commit/418a1a4f951e4f26bc8dce2c75a46366e158eb00))
## v0.2.0 (2022-10-24)
### Feature
* Add naming enum ([#3](https://github.com/Bluetooth-Devices/oralb-ble/issues/3)) ([`b8b7bf4`](https://github.com/Bluetooth-Devices/oralb-ble/commit/b8b7bf445d72128121cddf77fc8c4fad2f4bc918))
## v0.1.1 (2022-10-24)
### Fix
* Exports ([#2](https://github.com/Bluetooth-Devices/oralb-ble/issues/2)) ([`ea4faf0`](https://github.com/Bluetooth-Devices/oralb-ble/commit/ea4faf098171b8f1fa1f6c6ceaae25c1739785db))
## v0.1.0 (2022-10-24)
### Feature
* First publish ([#1](https://github.com/Bluetooth-Devices/oralb-ble/issues/1)) ([`5278ad6`](https://github.com/Bluetooth-Devices/oralb-ble/commit/5278ad6e412d0dff427dc18ce05010b31fc76ff7))
oralb-ble-1.0.0/CONTRIBUTING.md 0000664 0000000 0000000 00000007422 15040370547 0015612 0 ustar 00root root 0000000 0000000 # 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
OralB BLE could always use more documentation, whether as part of the official OralB 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/oralb-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/oralb-ble/issues
oralb-ble-1.0.0/LICENSE 0000664 0000000 0000000 00000002060 15040370547 0014357 0 ustar 00root root 0000000 0000000
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.
oralb-ble-1.0.0/README.md 0000664 0000000 0000000 00000006653 15040370547 0014645 0 ustar 00root root 0000000 0000000 # OralB BLE
Bluetooth library for Oral B devices
## Installation
Install this via pip (or your favourite package manager):
`pip install oralb-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.
oralb-ble-1.0.0/commitlint.config.mjs 0000664 0000000 0000000 00000000362 15040370547 0017513 0 ustar 00root root 0000000 0000000 export 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],
},
};
oralb-ble-1.0.0/docs/ 0000775 0000000 0000000 00000000000 15040370547 0014304 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/docs/Makefile 0000664 0000000 0000000 00000001175 15040370547 0015750 0 ustar 00root root 0000000 0000000 # 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)
oralb-ble-1.0.0/docs/make.bat 0000664 0000000 0000000 00000001374 15040370547 0015716 0 ustar 00root root 0000000 0000000 @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
oralb-ble-1.0.0/docs/source/ 0000775 0000000 0000000 00000000000 15040370547 0015604 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/docs/source/_static/ 0000775 0000000 0000000 00000000000 15040370547 0017232 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/docs/source/_static/.gitkeep 0000664 0000000 0000000 00000000000 15040370547 0020651 0 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/docs/source/changelog.md 0000664 0000000 0000000 00000000045 15040370547 0020054 0 ustar 00root root 0000000 0000000 ```{include} ../../CHANGELOG.md
```
oralb-ble-1.0.0/docs/source/conf.py 0000664 0000000 0000000 00000003643 15040370547 0017111 0 ustar 00root root 0000000 0000000 # 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 = "OralB 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"]
oralb-ble-1.0.0/docs/source/contributing.md 0000664 0000000 0000000 00000000050 15040370547 0020630 0 ustar 00root root 0000000 0000000 ```{include} ../../CONTRIBUTING.md
```
oralb-ble-1.0.0/docs/source/index.md 0000664 0000000 0000000 00000000351 15040370547 0017234 0 ustar 00root root 0000000 0000000 # Welcome to OralB BLE documentation!
```{toctree}
:caption: Installation & Usage
:maxdepth: 2
installation
usage
```
```{toctree}
:caption: Project Info
:maxdepth: 2
changelog
contributing
```
```{include} ../../README.md
```
oralb-ble-1.0.0/docs/source/installation.md 0000664 0000000 0000000 00000000264 15040370547 0020631 0 ustar 00root root 0000000 0000000 # 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 oralb-ble
```
oralb-ble-1.0.0/docs/source/usage.md 0000664 0000000 0000000 00000000137 15040370547 0017233 0 ustar 00root root 0000000 0000000 # Usage
To use this package, import it:
```python
import oralb_ble
```
TODO: Document usage
oralb-ble-1.0.0/poetry.lock 0000664 0000000 0000000 00000506204 15040370547 0015557 0 ustar 00root root 0000000 0000000 # This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand.
[[package]]
name = "aiofiles"
version = "24.1.0"
description = "File support for asyncio."
optional = false
python-versions = ">=3.8"
groups = ["main"]
markers = "platform_system == \"Linux\""
files = [
{file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"},
{file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"},
]
[[package]]
name = "aiohappyeyeballs"
version = "2.6.1"
description = "Happy Eyeballs for asyncio"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"},
{file = "aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558"},
]
[[package]]
name = "aiohttp"
version = "3.12.14"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "aiohttp-3.12.14-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:906d5075b5ba0dd1c66fcaaf60eb09926a9fef3ca92d912d2a0bbdbecf8b1248"},
{file = "aiohttp-3.12.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c875bf6fc2fd1a572aba0e02ef4e7a63694778c5646cdbda346ee24e630d30fb"},
{file = "aiohttp-3.12.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fbb284d15c6a45fab030740049d03c0ecd60edad9cd23b211d7e11d3be8d56fd"},
{file = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e360381e02e1a05d36b223ecab7bc4a6e7b5ab15760022dc92589ee1d4238c"},
{file = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:aaf90137b5e5d84a53632ad95ebee5c9e3e7468f0aab92ba3f608adcb914fa95"},
{file = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e532a25e4a0a2685fa295a31acf65e027fbe2bea7a4b02cdfbbba8a064577663"},
{file = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eab9762c4d1b08ae04a6c77474e6136da722e34fdc0e6d6eab5ee93ac29f35d1"},
{file = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abe53c3812b2899889a7fca763cdfaeee725f5be68ea89905e4275476ffd7e61"},
{file = "aiohttp-3.12.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5760909b7080aa2ec1d320baee90d03b21745573780a072b66ce633eb77a8656"},
{file = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:02fcd3f69051467bbaa7f84d7ec3267478c7df18d68b2e28279116e29d18d4f3"},
{file = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4dcd1172cd6794884c33e504d3da3c35648b8be9bfa946942d353b939d5f1288"},
{file = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:224d0da41355b942b43ad08101b1b41ce633a654128ee07e36d75133443adcda"},
{file = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e387668724f4d734e865c1776d841ed75b300ee61059aca0b05bce67061dcacc"},
{file = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:dec9cde5b5a24171e0b0a4ca064b1414950904053fb77c707efd876a2da525d8"},
{file = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bbad68a2af4877cc103cd94af9160e45676fc6f0c14abb88e6e092b945c2c8e3"},
{file = "aiohttp-3.12.14-cp310-cp310-win32.whl", hash = "sha256:ee580cb7c00bd857b3039ebca03c4448e84700dc1322f860cf7a500a6f62630c"},
{file = "aiohttp-3.12.14-cp310-cp310-win_amd64.whl", hash = "sha256:cf4f05b8cea571e2ccc3ca744e35ead24992d90a72ca2cf7ab7a2efbac6716db"},
{file = "aiohttp-3.12.14-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f4552ff7b18bcec18b60a90c6982049cdb9dac1dba48cf00b97934a06ce2e597"},
{file = "aiohttp-3.12.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8283f42181ff6ccbcf25acaae4e8ab2ff7e92b3ca4a4ced73b2c12d8cd971393"},
{file = "aiohttp-3.12.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:040afa180ea514495aaff7ad34ec3d27826eaa5d19812730fe9e529b04bb2179"},
{file = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b413c12f14c1149f0ffd890f4141a7471ba4b41234fe4fd4a0ff82b1dc299dbb"},
{file = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1d6f607ce2e1a93315414e3d448b831238f1874b9968e1195b06efaa5c87e245"},
{file = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:565e70d03e924333004ed101599902bba09ebb14843c8ea39d657f037115201b"},
{file = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4699979560728b168d5ab63c668a093c9570af2c7a78ea24ca5212c6cdc2b641"},
{file = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad5fdf6af93ec6c99bf800eba3af9a43d8bfd66dce920ac905c817ef4a712afe"},
{file = "aiohttp-3.12.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ac76627c0b7ee0e80e871bde0d376a057916cb008a8f3ffc889570a838f5cc7"},
{file = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:798204af1180885651b77bf03adc903743a86a39c7392c472891649610844635"},
{file = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4f1205f97de92c37dd71cf2d5bcfb65fdaed3c255d246172cce729a8d849b4da"},
{file = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:76ae6f1dd041f85065d9df77c6bc9c9703da9b5c018479d20262acc3df97d419"},
{file = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a194ace7bc43ce765338ca2dfb5661489317db216ea7ea700b0332878b392cab"},
{file = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:16260e8e03744a6fe3fcb05259eeab8e08342c4c33decf96a9dad9f1187275d0"},
{file = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c779e5ebbf0e2e15334ea404fcce54009dc069210164a244d2eac8352a44b28"},
{file = "aiohttp-3.12.14-cp311-cp311-win32.whl", hash = "sha256:a289f50bf1bd5be227376c067927f78079a7bdeccf8daa6a9e65c38bae14324b"},
{file = "aiohttp-3.12.14-cp311-cp311-win_amd64.whl", hash = "sha256:0b8a69acaf06b17e9c54151a6c956339cf46db4ff72b3ac28516d0f7068f4ced"},
{file = "aiohttp-3.12.14-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a0ecbb32fc3e69bc25efcda7d28d38e987d007096cbbeed04f14a6662d0eee22"},
{file = "aiohttp-3.12.14-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0400f0ca9bb3e0b02f6466421f253797f6384e9845820c8b05e976398ac1d81a"},
{file = "aiohttp-3.12.14-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a56809fed4c8a830b5cae18454b7464e1529dbf66f71c4772e3cfa9cbec0a1ff"},
{file = "aiohttp-3.12.14-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27f2e373276e4755691a963e5d11756d093e346119f0627c2d6518208483fb6d"},
{file = "aiohttp-3.12.14-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ca39e433630e9a16281125ef57ece6817afd1d54c9f1bf32e901f38f16035869"},
{file = "aiohttp-3.12.14-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c748b3f8b14c77720132b2510a7d9907a03c20ba80f469e58d5dfd90c079a1c"},
{file = "aiohttp-3.12.14-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0a568abe1b15ce69d4cc37e23020720423f0728e3cb1f9bcd3f53420ec3bfe7"},
{file = "aiohttp-3.12.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9888e60c2c54eaf56704b17feb558c7ed6b7439bca1e07d4818ab878f2083660"},
{file = "aiohttp-3.12.14-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3006a1dc579b9156de01e7916d38c63dc1ea0679b14627a37edf6151bc530088"},
{file = "aiohttp-3.12.14-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:aa8ec5c15ab80e5501a26719eb48a55f3c567da45c6ea5bb78c52c036b2655c7"},
{file = "aiohttp-3.12.14-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:39b94e50959aa07844c7fe2206b9f75d63cc3ad1c648aaa755aa257f6f2498a9"},
{file = "aiohttp-3.12.14-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:04c11907492f416dad9885d503fbfc5dcb6768d90cad8639a771922d584609d3"},
{file = "aiohttp-3.12.14-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:88167bd9ab69bb46cee91bd9761db6dfd45b6e76a0438c7e884c3f8160ff21eb"},
{file = "aiohttp-3.12.14-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:791504763f25e8f9f251e4688195e8b455f8820274320204f7eafc467e609425"},
{file = "aiohttp-3.12.14-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2785b112346e435dd3a1a67f67713a3fe692d288542f1347ad255683f066d8e0"},
{file = "aiohttp-3.12.14-cp312-cp312-win32.whl", hash = "sha256:15f5f4792c9c999a31d8decf444e79fcfd98497bf98e94284bf390a7bb8c1729"},
{file = "aiohttp-3.12.14-cp312-cp312-win_amd64.whl", hash = "sha256:3b66e1a182879f579b105a80d5c4bd448b91a57e8933564bf41665064796a338"},
{file = "aiohttp-3.12.14-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3143a7893d94dc82bc409f7308bc10d60285a3cd831a68faf1aa0836c5c3c767"},
{file = "aiohttp-3.12.14-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3d62ac3d506cef54b355bd34c2a7c230eb693880001dfcda0bf88b38f5d7af7e"},
{file = "aiohttp-3.12.14-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:48e43e075c6a438937c4de48ec30fa8ad8e6dfef122a038847456bfe7b947b63"},
{file = "aiohttp-3.12.14-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:077b4488411a9724cecc436cbc8c133e0d61e694995b8de51aaf351c7578949d"},
{file = "aiohttp-3.12.14-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d8c35632575653f297dcbc9546305b2c1133391089ab925a6a3706dfa775ccab"},
{file = "aiohttp-3.12.14-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b8ce87963f0035c6834b28f061df90cf525ff7c9b6283a8ac23acee6502afd4"},
{file = "aiohttp-3.12.14-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0a2cf66e32a2563bb0766eb24eae7e9a269ac0dc48db0aae90b575dc9583026"},
{file = "aiohttp-3.12.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdea089caf6d5cde975084a884c72d901e36ef9c2fd972c9f51efbbc64e96fbd"},
{file = "aiohttp-3.12.14-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a7865f27db67d49e81d463da64a59365ebd6b826e0e4847aa111056dcb9dc88"},
{file = "aiohttp-3.12.14-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0ab5b38a6a39781d77713ad930cb5e7feea6f253de656a5f9f281a8f5931b086"},
{file = "aiohttp-3.12.14-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9b3b15acee5c17e8848d90a4ebc27853f37077ba6aec4d8cb4dbbea56d156933"},
{file = "aiohttp-3.12.14-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e4c972b0bdaac167c1e53e16a16101b17c6d0ed7eac178e653a07b9f7fad7151"},
{file = "aiohttp-3.12.14-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7442488b0039257a3bdbc55f7209587911f143fca11df9869578db6c26feeeb8"},
{file = "aiohttp-3.12.14-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f68d3067eecb64c5e9bab4a26aa11bd676f4c70eea9ef6536b0a4e490639add3"},
{file = "aiohttp-3.12.14-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f88d3704c8b3d598a08ad17d06006cb1ca52a1182291f04979e305c8be6c9758"},
{file = "aiohttp-3.12.14-cp313-cp313-win32.whl", hash = "sha256:a3c99ab19c7bf375c4ae3debd91ca5d394b98b6089a03231d4c580ef3c2ae4c5"},
{file = "aiohttp-3.12.14-cp313-cp313-win_amd64.whl", hash = "sha256:3f8aad695e12edc9d571f878c62bedc91adf30c760c8632f09663e5f564f4baa"},
{file = "aiohttp-3.12.14-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b8cc6b05e94d837bcd71c6531e2344e1ff0fb87abe4ad78a9261d67ef5d83eae"},
{file = "aiohttp-3.12.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1dcb015ac6a3b8facd3677597edd5ff39d11d937456702f0bb2b762e390a21b"},
{file = "aiohttp-3.12.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3779ed96105cd70ee5e85ca4f457adbce3d9ff33ec3d0ebcdf6c5727f26b21b3"},
{file = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:717a0680729b4ebd7569c1dcd718c46b09b360745fd8eb12317abc74b14d14d0"},
{file = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b5dd3a2ef7c7e968dbbac8f5574ebeac4d2b813b247e8cec28174a2ba3627170"},
{file = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4710f77598c0092239bc12c1fcc278a444e16c7032d91babf5abbf7166463f7b"},
{file = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f3e9f75ae842a6c22a195d4a127263dbf87cbab729829e0bd7857fb1672400b2"},
{file = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f9c8d55d6802086edd188e3a7d85a77787e50d56ce3eb4757a3205fa4657922"},
{file = "aiohttp-3.12.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79b29053ff3ad307880d94562cca80693c62062a098a5776ea8ef5ef4b28d140"},
{file = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23e1332fff36bebd3183db0c7a547a1da9d3b4091509f6d818e098855f2f27d3"},
{file = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a564188ce831fd110ea76bcc97085dd6c625b427db3f1dbb14ca4baa1447dcbc"},
{file = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a7a1b4302f70bb3ec40ca86de82def532c97a80db49cac6a6700af0de41af5ee"},
{file = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:1b07ccef62950a2519f9bfc1e5b294de5dd84329f444ca0b329605ea787a3de5"},
{file = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:938bd3ca6259e7e48b38d84f753d548bd863e0c222ed6ee6ace3fd6752768a84"},
{file = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8bc784302b6b9f163b54c4e93d7a6f09563bd01ff2b841b29ed3ac126e5040bf"},
{file = "aiohttp-3.12.14-cp39-cp39-win32.whl", hash = "sha256:a3416f95961dd7d5393ecff99e3f41dc990fb72eda86c11f2a60308ac6dcd7a0"},
{file = "aiohttp-3.12.14-cp39-cp39-win_amd64.whl", hash = "sha256:196858b8820d7f60578f8b47e5669b3195c21d8ab261e39b1d705346458f445f"},
{file = "aiohttp-3.12.14.tar.gz", hash = "sha256:6e06e120e34d93100de448fd941522e11dafa78ef1a893c179901b7d66aa29f2"},
]
[package.dependencies]
aiohappyeyeballs = ">=2.5.0"
aiosignal = ">=1.4.0"
async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""}
attrs = ">=17.3.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
propcache = ">=0.2.0"
yarl = ">=1.17.0,<2.0"
[package.extras]
speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.3.0)", "brotlicffi ; platform_python_implementation != \"CPython\""]
[[package]]
name = "aiosignal"
version = "1.4.0"
description = "aiosignal: a list of registered asynchronous callbacks"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e"},
{file = "aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7"},
]
[package.dependencies]
frozenlist = ">=1.1.0"
typing-extensions = {version = ">=4.2", markers = "python_version < \"3.13\""}
[[package]]
name = "alabaster"
version = "0.7.16"
description = "A light, configurable Sphinx theme"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"},
{file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"},
]
[[package]]
name = "async-timeout"
version = "4.0.3"
description = "Timeout context manager for asyncio programs"
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
{file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"},
{file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
]
[[package]]
name = "attrs"
version = "24.3.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"},
{file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"},
]
[package.extras]
benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""]
[[package]]
name = "babel"
version = "2.16.0"
description = "Internationalization utilities"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
{file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
]
[package.extras]
dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
[[package]]
name = "bleak"
version = "0.20.2"
description = "Bluetooth Low Energy platform Agnostic Klient"
optional = false
python-versions = ">=3.7,<4.0"
groups = ["main"]
files = [
{file = "bleak-0.20.2-py3-none-any.whl", hash = "sha256:ce3106b7258212d92bb77be06f9301774f51f5bbc9f7cd50976ad794e9514dba"},
{file = "bleak-0.20.2.tar.gz", hash = "sha256:6c92a47abe34e6dea8ffc5cea9457cbff6e1be966854839dbc25cddb36b79ee4"},
]
[package.dependencies]
async-timeout = {version = ">=3.0.0,<5", markers = "python_version < \"3.11\""}
bleak-winrt = {version = ">=1.2.0,<2.0.0", markers = "platform_system == \"Windows\""}
dbus-fast = {version = ">=1.83.0,<2.0.0", markers = "platform_system == \"Linux\""}
pyobjc-core = {version = ">=9.0.1,<10.0.0", markers = "platform_system == \"Darwin\""}
pyobjc-framework-CoreBluetooth = {version = ">=9.0.1,<10.0.0", markers = "platform_system == \"Darwin\""}
pyobjc-framework-libdispatch = {version = ">=9.0.1,<10.0.0", markers = "platform_system == \"Darwin\""}
[[package]]
name = "bleak-retry-connector"
version = "2.13.1"
description = "A connector for Bleak Clients that handles transient connection failures"
optional = false
python-versions = ">=3.9,<4.0"
groups = ["main"]
files = [
{file = "bleak_retry_connector-2.13.1-py3-none-any.whl", hash = "sha256:9fdab97d7f1cc1b1948412af2cc6f7721e843fb9d2f9b02b7cc26eb52c7ee486"},
{file = "bleak_retry_connector-2.13.1.tar.gz", hash = "sha256:af344bd81d0f7d33a0994e30fe9e28dfdc3cb970095cc1ba547a3b6ae2ee4543"},
]
[package.dependencies]
async-timeout = ">=4.0.1"
bleak = ">=0.19.0"
bluetooth-adapters = {version = ">=0.15.2", markers = "platform_system == \"Linux\""}
dbus-fast = {version = ">=1.14.0", markers = "platform_system == \"Linux\""}
[package.extras]
docs = ["Sphinx (>=5.0,<6.0)", "myst-parser (>=0.18,<0.19)", "sphinx-rtd-theme (>=1.0,<2.0)"]
[[package]]
name = "bleak-winrt"
version = "1.2.0"
description = "Python WinRT bindings for Bleak"
optional = false
python-versions = "*"
groups = ["main"]
markers = "platform_system == \"Windows\""
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.16.2"
description = "Tools to enumerate and find Bluetooth Adapters"
optional = false
python-versions = ">=3.9,<4.0"
groups = ["main"]
markers = "platform_system == \"Linux\""
files = [
{file = "bluetooth_adapters-0.16.2-py3-none-any.whl", hash = "sha256:73ddb5537b2e854c3ffe6c2d07f255849d66d51a508e35b5e9a9d70c4f048a00"},
{file = "bluetooth_adapters-0.16.2.tar.gz", hash = "sha256:8919d88bdfad30b13fecf9bd67eb35eca2e096e142bbb6815888524580f33dd7"},
]
[package.dependencies]
aiohttp = ">=3.8.1"
async-timeout = {version = ">=3.0.0", markers = "python_version < \"3.11\""}
bleak = ">=0.15.1"
dbus-fast = ">=1.21.0"
mac-vendor-lookup = ">=0.1.12"
usb-devices = ">=0.4.5"
[package.extras]
docs = ["Sphinx (>=5,<8)", "myst-parser (>=0.18,<2.1)", "sphinx-rtd-theme (>=1,<3)"]
[[package]]
name = "bluetooth-data-tools"
version = "0.3.1"
description = "Tools for converting bluetooth data and packets"
optional = false
python-versions = ">=3.9,<4.0"
groups = ["main"]
files = [
{file = "bluetooth_data_tools-0.3.1-py3-none-any.whl", hash = "sha256:b7ebacecec2d30d69dd83077f7dce5da2eb713f040ddb7d5573a2c60078c313b"},
{file = "bluetooth_data_tools-0.3.1.tar.gz", hash = "sha256:247e896ec963bf2204c0e77bc5ec09dafaa4e065afffe38553b9d4d526b71617"},
]
[package.extras]
docs = ["Sphinx (>=5.0,<6.0)", "myst-parser (>=0.18,<0.19)", "sphinx-rtd-theme (>=1.0,<2.0)"]
[[package]]
name = "bluetooth-sensor-state-data"
version = "1.7.5"
description = "Models for storing and converting Bluetooth Sensor State Data"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "bluetooth_sensor_state_data-1.7.5-py3-none-any.whl", hash = "sha256:a4ce3cce9839422299209e5427a6ce24061ff844fbdb61af2a485e480b8d7e23"},
{file = "bluetooth_sensor_state_data-1.7.5.tar.gz", hash = "sha256:be9319a3d70745e11689e91c013bf71d0d5570d303a49d21668777ea7854227a"},
]
[package.dependencies]
home-assistant-bluetooth = ">=1.3.0"
sensor-state-data = ">=2.0"
[package.extras]
docs = ["Sphinx (>=5,<7)", "myst-parser (>=0.18,<3.1)", "sphinx-rtd-theme (>=1,<4)"]
[[package]]
name = "certifi"
version = "2024.12.14"
description = "Python package for providing Mozilla's CA Bundle."
optional = true
python-versions = ">=3.6"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"},
{file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"},
]
[[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.6.10"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
{file = "coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78"},
{file = "coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c"},
{file = "coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a"},
{file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165"},
{file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988"},
{file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5"},
{file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3"},
{file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5"},
{file = "coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244"},
{file = "coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e"},
{file = "coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3"},
{file = "coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43"},
{file = "coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132"},
{file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f"},
{file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994"},
{file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99"},
{file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd"},
{file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377"},
{file = "coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8"},
{file = "coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609"},
{file = "coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853"},
{file = "coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078"},
{file = "coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0"},
{file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50"},
{file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022"},
{file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b"},
{file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0"},
{file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852"},
{file = "coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359"},
{file = "coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247"},
{file = "coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9"},
{file = "coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b"},
{file = "coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690"},
{file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18"},
{file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c"},
{file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd"},
{file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e"},
{file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694"},
{file = "coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6"},
{file = "coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e"},
{file = "coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe"},
{file = "coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273"},
{file = "coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8"},
{file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098"},
{file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb"},
{file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0"},
{file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf"},
{file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2"},
{file = "coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312"},
{file = "coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d"},
{file = "coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a"},
{file = "coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27"},
{file = "coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4"},
{file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f"},
{file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25"},
{file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315"},
{file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90"},
{file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d"},
{file = "coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18"},
{file = "coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59"},
{file = "coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f"},
{file = "coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23"},
]
[package.dependencies]
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
[package.extras]
toml = ["tomli ; python_full_version <= \"3.11.0a6\""]
[[package]]
name = "dbus-fast"
version = "1.95.2"
description = "A faster version of dbus-next"
optional = false
python-versions = ">=3.7,<4.0"
groups = ["main"]
markers = "platform_system == \"Linux\""
files = [
{file = "dbus_fast-1.95.2-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:69f19fb94ac714b917c51fcc329b51695f085f779841edd6e429170f1f073f47"},
{file = "dbus_fast-1.95.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71e84a7ce3b050745dfb2bcd32ade891ecf6f4b06d3baa4dfe30ad09720a0be"},
{file = "dbus_fast-1.95.2-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:3ffcd1c999599da7806d7887d5ce1e9f0d814aa35af92daecab542c9b70794c1"},
{file = "dbus_fast-1.95.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:85739b90e6f983494c3c7187d4daaa50f4f4369aa1e87e876066de97ca1bcd58"},
{file = "dbus_fast-1.95.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e2c107caefa186919169e07a852edea3d931dfb6112584fa2c6e5653d91c0d2d"},
{file = "dbus_fast-1.95.2-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:99902ca6c10368492fdf5a28321d86c7e92e50fd742f0163599602c442232d29"},
{file = "dbus_fast-1.95.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3241252a744b0960e7eb9dcad2892af2bc695b4f47636bab2f17f6012d914ce"},
{file = "dbus_fast-1.95.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f52ef5edef41a0ed29645d7c6e1ee89b5e8f5e5c1ba9901699dcec9cfaf8d961"},
{file = "dbus_fast-1.95.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9706e10a6c24d4c03d28b1631e3882009964d5207a86cae2b42466635d7546be"},
{file = "dbus_fast-1.95.2-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:3277944b418063ad051e8e49144151962691188b972f1fbca7af39fdef4f8a47"},
{file = "dbus_fast-1.95.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cab158bcf86c4b2e03c2f3453738a61de83c82cbed11f23331ccc9a9aba6d5b1"},
{file = "dbus_fast-1.95.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:17d743d13dbde0691adb98f1a6c87f0cf5617a4c9169b4820972dc8869095c6b"},
{file = "dbus_fast-1.95.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aefa695088405d313c703790ac503ad0b2ac1e4807393f1f02e410b6984aedd0"},
{file = "dbus_fast-1.95.2-cp37-cp37m-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:ffd3665a6fbe318aadac998ae117b19214e0782397c86ab47792a120979783a6"},
{file = "dbus_fast-1.95.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43093d8e42342841c7ac69e236370c31949c35b659032888dae8b3af1fa35e9e"},
{file = "dbus_fast-1.95.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f4b26849254fafb11656fc8c10f8bce67deab683694e0fc7b56edd891d4e118"},
{file = "dbus_fast-1.95.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:331c4a26e010fd8ad3168b9680f39a7d0765507d3aadcbe5f250da0474877f14"},
{file = "dbus_fast-1.95.2-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:7aee30619c79334980a25a1e94299a751b3f276644ec0a69c76bfe57be184e7a"},
{file = "dbus_fast-1.95.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c5d344e3fe3c4b16593fad70448c66ca3130c8c692c74a921c15f18650581a7"},
{file = "dbus_fast-1.95.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9180d4d39d8688b9d8d43f427f0f2883354fa9df18a1f46d14f1762b82249d1f"},
{file = "dbus_fast-1.95.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e19173e65967581186666a47cd0af06111c7e957fb529198e532b35a47171460"},
{file = "dbus_fast-1.95.2-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:fae11a8ed320013decd2bf6a982f010fff011bf935c4f32141e804ba7963719b"},
{file = "dbus_fast-1.95.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f653085d9f96ed2e48434ba951cf4bf0229cc273a87b9799e7cf3a9a6612a56"},
{file = "dbus_fast-1.95.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05d53e0db08de6b3ba43eb110e01b9e6264e7143849ea9772af45b15575c21b2"},
{file = "dbus_fast-1.95.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4e73b7dcbac5f418bd4b334ad112e40e8b3bc05c53a3fc451926450ce3bb805e"},
{file = "dbus_fast-1.95.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:76fb9d11bd6ebe1f832350ec57ada352f096f24b5731e38bcbad86ab9b27190b"},
{file = "dbus_fast-1.95.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26045c50bbd8c1674814759332333799b073216b2b2cac9e1cfebf757c7f926d"},
{file = "dbus_fast-1.95.2-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:bd68b5e7d7c6cd10d804d072062100a4893ad0c19bdac03b53b1809c51a4e3c7"},
{file = "dbus_fast-1.95.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea2692efe0d6d6d58fb427cd0ed53ab44ced0c2ada642b0c15fd139c60a706d6"},
{file = "dbus_fast-1.95.2-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:33cee333a15241e516ee84aaabdd952dbb1a63f9e986028574451475e97a113f"},
{file = "dbus_fast-1.95.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dfd99cf624f769cf838e62d75ceb737b2866b1783a4f11a928cf38e4c906a5f"},
{file = "dbus_fast-1.95.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b842e94140e39a196d4d83e02eddcbc461b906871ba02f1c5374055f2d628c47"},
{file = "dbus_fast-1.95.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08ca9968dd46b854e5c7b00be32cb273edaf17ddc9647811ff63ae3b9dca822d"},
{file = "dbus_fast-1.95.2.tar.gz", hash = "sha256:3dd64c5cd362ceead6cc02603b6b4cbda58b2cbb6ec816a2f21b1901dfc3cb61"},
]
[[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 = "exceptiongroup"
version = "1.2.2"
description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
groups = ["dev"]
markers = "python_version < \"3.11\""
files = [
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
]
[package.extras]
test = ["pytest (>=6)"]
[[package]]
name = "frozenlist"
version = "1.5.0"
description = "A list-like structure which implements collections.abc.MutableSequence"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"},
{file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"},
{file = "frozenlist-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5"},
{file = "frozenlist-1.5.0-cp310-cp310-win32.whl", hash = "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb"},
{file = "frozenlist-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4"},
{file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30"},
{file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5"},
{file = "frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf"},
{file = "frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942"},
{file = "frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d"},
{file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21"},
{file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d"},
{file = "frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f"},
{file = "frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8"},
{file = "frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f"},
{file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953"},
{file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0"},
{file = "frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03"},
{file = "frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c"},
{file = "frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28"},
{file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca"},
{file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10"},
{file = "frozenlist-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e"},
{file = "frozenlist-1.5.0-cp38-cp38-win32.whl", hash = "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723"},
{file = "frozenlist-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923"},
{file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972"},
{file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336"},
{file = "frozenlist-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c"},
{file = "frozenlist-1.5.0-cp39-cp39-win32.whl", hash = "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3"},
{file = "frozenlist-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0"},
{file = "frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3"},
{file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"},
]
[[package]]
name = "home-assistant-bluetooth"
version = "1.10.4"
description = "Home Assistant Bluetooth Models and Helpers"
optional = false
python-versions = ">=3.9,<4.0"
groups = ["main"]
files = [
{file = "home_assistant_bluetooth-1.10.4-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:7c3434bdec5dcfe733d3e7c56d4a24418fcd03718dc2e7707c9133d1e48145a8"},
{file = "home_assistant_bluetooth-1.10.4.tar.gz", hash = "sha256:21216b6be9d028bc232b9188ac4dce773798c6b4e47482cc3524bfc5f82515e3"},
]
[[package]]
name = "idna"
version = "3.10"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.6"
groups = ["main"]
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 = "importlib-metadata"
version = "8.5.0"
description = "Read metadata from Python packages"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\" and python_version < \"3.10\""
files = [
{file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"},
{file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"},
]
[package.dependencies]
zipp = ">=3.20"
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""]
cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
enabler = ["pytest-enabler (>=2.2)"]
perf = ["ipython"]
test = ["flufl.flake8", "importlib-resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
type = ["pytest-mypy"]
[[package]]
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[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 = "mac-vendor-lookup"
version = "0.1.12"
description = "Find the vendor for a given MAC address"
optional = false
python-versions = "<4, >=3.5"
groups = ["main"]
markers = "platform_system == \"Linux\""
files = [
{file = "mac_vendor_lookup-0.1.12-py3-none-any.whl", hash = "sha256:aeec6eac01b07e6558d889b51f475a1e1e938e09cab409a069ab6a43b13cba58"},
{file = "mac_vendor_lookup-0.1.12.tar.gz", hash = "sha256:74e1723e177d4deb02977148d3fa04a7916f4bf93268e2afe3240529272bf80d"},
]
[package.dependencies]
aiofiles = "*"
aiohttp = "*"
[package.extras]
test = ["coverage", "pytest"]
[[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 = "mock"
version = "5.2.0"
description = "Rolling backport of unittest.mock for all Pythons"
optional = false
python-versions = ">=3.6"
groups = ["dev"]
files = [
{file = "mock-5.2.0-py3-none-any.whl", hash = "sha256:7ba87f72ca0e915175596069dbbcc7c75af7b5e9b9bc107ad6349ede0819982f"},
{file = "mock-5.2.0.tar.gz", hash = "sha256:4e460e818629b4b173f32d08bf30d3af8123afbb8e04bb5707a1fd4799e503f0"},
]
[package.extras]
build = ["blurb", "twine", "wheel"]
docs = ["sphinx"]
test = ["pytest", "pytest-cov"]
[[package]]
name = "multidict"
version = "6.1.0"
description = "multidict implementation"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"},
{file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"},
{file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"},
{file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"},
{file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"},
{file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"},
{file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"},
{file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"},
{file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"},
{file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"},
{file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"},
{file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"},
{file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"},
{file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"},
{file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"},
{file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"},
{file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"},
{file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"},
{file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"},
{file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"},
{file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"},
{file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"},
{file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"},
{file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"},
{file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"},
{file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"},
{file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"},
{file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"},
{file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"},
{file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"},
{file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"},
{file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"},
]
[package.dependencies]
typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""}
[[package]]
name = "myst-parser"
version = "3.0.1"
description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser,"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1"},
{file = "myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87"},
]
[package.dependencies]
docutils = ">=0.18,<0.22"
jinja2 = "*"
markdown-it-py = ">=3.0,<4.0"
mdit-py-plugins = ">=0.4,<1.0"
pyyaml = "*"
sphinx = ">=6,<8"
[package.extras]
code-style = ["pre-commit (>=3.0,<4.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", "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 = "propcache"
version = "0.2.1"
description = "Accelerated property cache"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"},
{file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"},
{file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"},
{file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"},
{file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"},
{file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"},
{file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"},
{file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"},
{file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"},
{file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"},
{file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"},
{file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"},
{file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"},
{file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"},
{file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"},
{file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"},
{file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"},
{file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"},
{file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"},
{file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"},
{file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"},
{file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"},
{file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"},
{file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"},
{file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"},
{file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"},
{file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"},
]
[[package]]
name = "pygments"
version = "2.19.1"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
python-versions = ">=3.8"
groups = ["main", "dev"]
files = [
{file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"},
{file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"},
]
markers = {main = "extra == \"docs\""}
[package.extras]
windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pyobjc-core"
version = "9.2"
description = "Python<->ObjC Interoperability Module"
optional = false
python-versions = ">=3.7"
groups = ["main"]
markers = "platform_system == \"Darwin\""
files = [
{file = "pyobjc-core-9.2.tar.gz", hash = "sha256:d734b9291fec91ff4e3ae38b9c6839debf02b79c07314476e87da8e90b2c68c3"},
{file = "pyobjc_core-9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fa674a39949f5cde8e5c7bbcd24496446bfc67592b028aedbec7f81dc5fc4daa"},
{file = "pyobjc_core-9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bbc8de304ee322a1ee530b4d2daca135a49b4a49aa3cedc6b2c26c43885f4842"},
{file = "pyobjc_core-9.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0fa950f092673883b8bd28bc18397415cabb457bf410920762109b411789ade9"},
{file = "pyobjc_core-9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:586e4cae966282eaa61b21cae66ccdcee9d69c036979def26eebdc08ddebe20f"},
{file = "pyobjc_core-9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41189c2c680931c0395a55691763c481fc681f454f21bb4f1644f98c24a45954"},
{file = "pyobjc_core-9.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:2d23ee539f2ba5e9f5653d75a13f575c7e36586fc0086792739e69e4c2617eda"},
{file = "pyobjc_core-9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b9809cf96678797acb72a758f34932fe8e2602d5ab7abec15c5ac68ddb481720"},
]
[[package]]
name = "pyobjc-framework-cocoa"
version = "9.2"
description = "Wrappers for the Cocoa frameworks on macOS"
optional = false
python-versions = ">=3.7"
groups = ["main"]
markers = "platform_system == \"Darwin\""
files = [
{file = "pyobjc-framework-Cocoa-9.2.tar.gz", hash = "sha256:efd78080872d8c8de6c2b97e0e4eac99d6203a5d1637aa135d071d464eb2db53"},
{file = "pyobjc_framework_Cocoa-9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9e02d8a7cc4eb7685377c50ba4f17345701acf4c05b1e7480d421bff9e2f62a4"},
{file = "pyobjc_framework_Cocoa-9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3b1e6287b3149e4c6679cdbccd8e9ef6557a4e492a892e80a77df143f40026d2"},
{file = "pyobjc_framework_Cocoa-9.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:312977ce2e3989073c6b324c69ba24283de206fe7acd6dbbbaf3e29238a22537"},
{file = "pyobjc_framework_Cocoa-9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aae7841cf40c26dd915f4dd828f91c6616e6b7998630b72e704750c09e00f334"},
{file = "pyobjc_framework_Cocoa-9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:739a421e14382a46cbeb9a883f192dceff368ad28ec34d895c48c0ad34cf2c1d"},
{file = "pyobjc_framework_Cocoa-9.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:32d9ac1033fac1b821ddee8c68f972a7074ad8c50bec0bea9a719034c1c2fb94"},
{file = "pyobjc_framework_Cocoa-9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b236bb965e41aeb2e215d4e98a5a230d4b63252c6d26e00924ea2e69540a59d6"},
]
[package.dependencies]
pyobjc-core = ">=9.2"
[[package]]
name = "pyobjc-framework-corebluetooth"
version = "9.2"
description = "Wrappers for the framework CoreBluetooth on macOS"
optional = false
python-versions = ">=3.7"
groups = ["main"]
markers = "platform_system == \"Darwin\""
files = [
{file = "pyobjc-framework-CoreBluetooth-9.2.tar.gz", hash = "sha256:cb2481b1dfe211ae9ce55f36537dc8155dbf0dc8ff26e0bc2e13f7afb0a291d1"},
{file = "pyobjc_framework_CoreBluetooth-9.2-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:53d888742119d0f0c725d0b0c2389f68e8f21f0cba6d6aec288c53260a0196b6"},
{file = "pyobjc_framework_CoreBluetooth-9.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:179532882126526e38fe716a50fb0ee8f440e0b838d290252c515e622b5d0e49"},
{file = "pyobjc_framework_CoreBluetooth-9.2-cp36-abi3-macosx_11_0_universal2.whl", hash = "sha256:256a5031ea9d8a7406541fa1b0dfac549b1de93deae8284605f9355b13fb58be"},
]
[package.dependencies]
pyobjc-core = ">=9.2"
pyobjc-framework-Cocoa = ">=9.2"
[[package]]
name = "pyobjc-framework-libdispatch"
version = "9.2"
description = "Wrappers for libdispatch on macOS"
optional = false
python-versions = ">=3.7"
groups = ["main"]
markers = "platform_system == \"Darwin\""
files = [
{file = "pyobjc-framework-libdispatch-9.2.tar.gz", hash = "sha256:542e7f7c2b041939db5ed6f3119c1d67d73ec14a996278b92485f8513039c168"},
{file = "pyobjc_framework_libdispatch-9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88d4091d4bcb5702783d6e86b4107db973425a17d1de491543f56bd348909b60"},
{file = "pyobjc_framework_libdispatch-9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1a67b007113328538b57893cc7829a722270764cdbeae6d5e1460a1d911314df"},
{file = "pyobjc_framework_libdispatch-9.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:6fccea1a57436cf1ac50d9ebc6e3e725bcf77f829ba6b118e62e6ed7866d359d"},
{file = "pyobjc_framework_libdispatch-9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6eba747b7ad91b0463265a7aee59235bb051fb97687f35ca2233690369b5e4e4"},
{file = "pyobjc_framework_libdispatch-9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2e835495860d04f63c2d2f73ae3dd79da4222864c107096dc0f99e8382700026"},
{file = "pyobjc_framework_libdispatch-9.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1b107e5c3580b09553030961ea6b17abad4a5132101eab1af3ad2cb36d0f08bb"},
{file = "pyobjc_framework_libdispatch-9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:83cdb672acf722717b5ecf004768f215f02ac02d7f7f2a9703da6e921ab02222"},
]
[package.dependencies]
pyobjc-core = ">=9.2"
[[package]]
name = "pytest"
version = "8.4.0"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
{file = "pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e"},
{file = "pytest-8.4.0.tar.gz", hash = "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6"},
]
[package.dependencies]
colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""}
iniconfig = ">=1"
packaging = ">=20"
pluggy = ">=1.5,<2"
pygments = ">=2.7.2"
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
[package.extras]
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "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"
typing-extensions = {version = ">=4.12", markers = "python_version < \"3.10\""}
[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 = "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 = "7.4.7"
description = "Python documentation generator"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"},
{file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"},
]
[package.dependencies]
alabaster = ">=0.7.14,<0.8.0"
babel = ">=2.13"
colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""}
docutils = ">=0.20,<0.22"
imagesize = ">=1.3"
importlib-metadata = {version = ">=6.0", markers = "python_version < \"3.10\""}
Jinja2 = ">=3.1"
packaging = ">=23.0"
Pygments = ">=2.17"
requests = ">=2.30.0"
snowballstemmer = ">=2.2"
sphinxcontrib-applehelp = "*"
sphinxcontrib-devhelp = "*"
sphinxcontrib-htmlhelp = ">=2.0.0"
sphinxcontrib-jsmath = "*"
sphinxcontrib-qthelp = "*"
sphinxcontrib-serializinghtml = ">=1.1.9"
tomli = {version = ">=2", markers = "python_version < \"3.11\""}
[package.extras]
docs = ["sphinxcontrib-websupport"]
lint = ["flake8 (>=6.0)", "importlib-metadata (>=6.0)", "mypy (==1.10.1)", "pytest (>=6.0)", "ruff (==0.5.2)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-docutils (==0.21.0.20240711)", "types-requests (>=2.30.0)"]
test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "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 = "tomli"
version = "2.2.1"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.8"
groups = ["main", "dev"]
files = [
{file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
{file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
{file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
{file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
{file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
{file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
{file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
{file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
{file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
{file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
{file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
{file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
{file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
{file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
]
markers = {main = "extra == \"docs\" and python_version < \"3.11\"", dev = "python_full_version <= \"3.11.0a6\""}
[[package]]
name = "typing-extensions"
version = "4.12.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
groups = ["main", "dev"]
files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
markers = {main = "python_version < \"3.13\"", dev = "python_version < \"3.10\""}
[[package]]
name = "urllib3"
version = "2.3.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.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"},
{file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"},
]
[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"]
markers = "platform_system == \"Linux\""
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 = "yarl"
version = "1.18.3"
description = "Yet another URL library"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"},
{file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"},
{file = "yarl-1.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690"},
{file = "yarl-1.18.3-cp310-cp310-win32.whl", hash = "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6"},
{file = "yarl-1.18.3-cp310-cp310-win_amd64.whl", hash = "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8"},
{file = "yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069"},
{file = "yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193"},
{file = "yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a"},
{file = "yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1"},
{file = "yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5"},
{file = "yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50"},
{file = "yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576"},
{file = "yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285"},
{file = "yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2"},
{file = "yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477"},
{file = "yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb"},
{file = "yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa"},
{file = "yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8"},
{file = "yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d"},
{file = "yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c"},
{file = "yarl-1.18.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04"},
{file = "yarl-1.18.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719"},
{file = "yarl-1.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1"},
{file = "yarl-1.18.3-cp39-cp39-win32.whl", hash = "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5"},
{file = "yarl-1.18.3-cp39-cp39-win_amd64.whl", hash = "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9"},
{file = "yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b"},
{file = "yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1"},
]
[package.dependencies]
idna = ">=2.0"
multidict = ">=4.0"
propcache = ">=0.2.0"
[[package]]
name = "zipp"
version = "3.21.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\" and python_version < \"3.10\""
files = [
{file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"},
{file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"},
]
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""]
cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
enabler = ["pytest-enabler (>=2.2)"]
test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"]
type = ["pytest-mypy"]
[extras]
docs = ["Sphinx", "myst-parser", "sphinx-rtd-theme"]
[metadata]
lock-version = "2.1"
python-versions = "^3.9"
content-hash = "ec1f9aaccf59893b9c565f2e4b6dbaa6aa993b07286721c1510c5d0c777d1fa9"
oralb-ble-1.0.0/pyproject.toml 0000664 0000000 0000000 00000004733 15040370547 0016277 0 ustar 00root root 0000000 0000000 [tool.poetry]
name = "oralb-ble"
version = "1.0.0"
description = "Bluetooth library for Oral B devices"
authors = ["J. Nick Koston "]
license = "MIT"
readme = "README.md"
repository = "https://github.com/Bluetooth-Devices/oralb-ble"
documentation = "https://oralb-ble.readthedocs.io"
classifiers = [
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Developers",
"Natural Language :: English",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries",
]
packages = [
{ include = "oralb_ble", from = "src" },
]
[tool.poetry.urls]
"Bug Tracker" = "https://github.com/Bluetooth-Devices/oralb-ble/issues"
"Changelog" = "https://github.com/Bluetooth-Devices/oralb-ble/blob/main/CHANGELOG.md"
[tool.poetry.dependencies]
python = "^3.9"
# Documentation Dependencies
Sphinx = {version = ">=5,<8", optional = true}
sphinx-rtd-theme = {version = ">=1,<4", optional = true}
myst-parser = {version = ">=0.18,<3.1", optional = true}
bluetooth-sensor-state-data = ">=1.6.0"
bluetooth-data-tools = ">=0.1.2"
bleak = ">=0.19.2"
home-assistant-bluetooth = ">=1.6.0"
bleak-retry-connector = ">=2.13.0"
[tool.poetry.extras]
docs = [
"myst-parser",
"sphinx",
"sphinx-rtd-theme",
]
[tool.poetry.dev-dependencies]
pytest = "^8.4"
pytest-cov = "^6.1"
[tool.poetry.group.dev.dependencies]
mock = ">=5.0.0"
pytest-asyncio = ">=0.20.0"
[tool.semantic_release]
branch = "main"
version_toml = ["pyproject.toml:tool.poetry.version"]
version_variables = ["src/oralb_ble/__init__.py:__version__"]
build_command = "pip install poetry && poetry build"
[tool.pytest.ini_options]
addopts = "-v -Wdefault --cov=oralb_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 = ["oralb_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>=1.0.0"]
build-backend = "poetry.core.masonry.api"
oralb-ble-1.0.0/renovate.json 0000664 0000000 0000000 00000000101 15040370547 0016062 0 ustar 00root root 0000000 0000000 {
"extends": ["github>browniebroke/renovate-configs:python"]
}
oralb-ble-1.0.0/setup.py 0000664 0000000 0000000 00000000357 15040370547 0015073 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# This is a shim to allow GitHub to detect the package, build is done with poetry
# Taken from https://github.com/Textualize/rich
import setuptools
if __name__ == "__main__":
setuptools.setup(name="oralb-ble")
oralb-ble-1.0.0/src/ 0000775 0000000 0000000 00000000000 15040370547 0014143 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/src/oralb_ble/ 0000775 0000000 0000000 00000000000 15040370547 0016064 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/src/oralb_ble/__init__.py 0000664 0000000 0000000 00000001614 15040370547 0020177 0 ustar 00root root 0000000 0000000 """Parser for OralB BLE advertisements.
This file is shamelessly copied from the following repository:
https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/oral_b.py
MIT License applies.
"""
from __future__ import annotations
from sensor_state_data import (
BinarySensorDeviceClass,
BinarySensorValue,
DeviceKey,
SensorDescription,
SensorDeviceClass,
SensorDeviceInfo,
SensorUpdate,
SensorValue,
Units,
)
from .parser import OralBBinarySensor, OralBBluetoothDeviceData, OralBSensor
__version__ = "1.0.0"
__all__ = [
"OralBSensor",
"OralBBinarySensor",
"OralBBluetoothDeviceData",
"BinarySensorDeviceClass",
"BinarySensorValue",
"SensorDescription",
"SensorDeviceInfo",
"DeviceKey",
"SensorUpdate",
"SensorDeviceClass",
"SensorDeviceInfo",
"SensorValue",
"Units",
]
oralb-ble-1.0.0/src/oralb_ble/const.py 0000664 0000000 0000000 00000004344 15040370547 0017571 0 ustar 00root root 0000000 0000000 TIMEOUT_RECENTLY_BRUSHING = 120
NOT_BRUSHING_UPDATE_INTERVAL_SECONDS = 86400
BRUSHING_UPDATE_INTERVAL_SECONDS = 60
# Pulled from here:
# https://github.com/wise86-android/OralBlue_python/blob/15e1a03bcb3350574d438e4593bcff59608a77a7/Protocol.md
# In Use
CHARACTERISTIC_BATTERY = "a0f0ff05-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_MODEL = "a0f0ff02-5047-4d53-8208-4f72616c2d42"
# Not from above link:
CHARACTERISTIC_PRESSURE = "a0f0ff0b-5047-4d53-8208-4f72616c2d42"
# Known but not in use
CHARACTERISTIC_SECTOR = "a0f0ff09-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_CONTROL = "a0f0ff21-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_SECTOR_TIMER = "a0f0ff26-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_SESSION_INFO = "a0f0ff29-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_TOOTHBRUSH_ID = "a0f0ff01-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_USER_ID = "a0f0ff03-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_STATUS = "a0f0ff04-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_BUTTON = "a0f0ff06-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_MODE = "a0f0ff07-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_BRUSHING_TIME = "a0f0ff08-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_CURRENT_TIME = "a0f0ff22-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_AVAILABLE_MODES = "a0f0ff25-5047-4d53-8208-4f72616c2d42"
# This seems to be giving positional data, but I have not quite nailed it down.
CHARACTERISTIC_POSITION = "a0f0ff0d-5047-4d53-8208-4f72616c2d42"
# Unknown
CHARACTERISTIC_UNKNOWN_1 = "a0f0ff84-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_2 = "a0f0ff85-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_3 = "a0f0ff83-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_4 = "a0f0ff81-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_5 = "a0f0ff82-5047-4d53-8208-4f72616c2d42"
# CHARACTERISTIC_UNKNOWN_6 = "a0f0ff0c-5047-4d53-8208-4f72616c2d42" # Failure when trying to grab
CHARACTERISTIC_UNKNOWN_7 = "a0f0ff0a-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_8 = "a0f0ff2c-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_9 = "a0f0ff2b-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_10 = "a0f0ff23-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_11 = "a0f0ff2d-5047-4d53-8208-4f72616c2d42"
CHARACTERISTIC_UNKNOWN_12 = "a0f0ff2a-5047-4d53-8208-4f72616c2d42"
oralb-ble-1.0.0/src/oralb_ble/parser.py 0000664 0000000 0000000 00000025561 15040370547 0017743 0 ustar 00root root 0000000 0000000 """Parser for OralB BLE advertisements.
This file is shamelessly copied from the following repository:
https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/oral_b.py
MIT License applies.
"""
from __future__ import annotations
import logging
import time
from dataclasses import dataclass
from enum import Enum, auto
from bleak import BleakError, BLEDevice
from bleak_retry_connector import (
BleakClientWithServiceCache,
establish_connection,
retry_bluetooth_connection_error,
)
from bluetooth_data_tools import short_address
from bluetooth_sensor_state_data import BluetoothData
from home_assistant_bluetooth import BluetoothServiceInfo
from sensor_state_data import SensorDeviceClass, SensorUpdate, Units
from sensor_state_data.enum import StrEnum
from .const import (
BRUSHING_UPDATE_INTERVAL_SECONDS,
CHARACTERISTIC_BATTERY,
CHARACTERISTIC_PRESSURE,
NOT_BRUSHING_UPDATE_INTERVAL_SECONDS,
TIMEOUT_RECENTLY_BRUSHING,
)
_LOGGER = logging.getLogger(__name__)
class OralBSensor(StrEnum):
TIME = "time"
SECTOR = "sector"
NUMBER_OF_SECTORS = "number_of_sectors"
SECTOR_TIMER = "sector_timer"
TOOTHBRUSH_STATE = "toothbrush_state"
PRESSURE = "pressure"
MODE = "mode"
SIGNAL_STRENGTH = "signal_strength"
BATTERY_PERCENT = "battery_percent"
class OralBBinarySensor(StrEnum):
BRUSHING = "brushing"
class Models(Enum):
Pro6000 = auto()
TriumphV2 = auto()
IOSeries4 = auto()
IOSeries67 = auto()
IOSeries8 = auto()
IOSeries9 = auto()
IOSeries89 = auto()
SmartSeries4000 = auto()
SmartSeries6000 = auto()
SmartSeries7000 = auto()
SmartSeries8000 = auto()
SmartSeries9000 = auto()
GeniusX = auto()
@dataclass
class ModelDescription:
device_type: str
modes: dict[int, str]
SMART_SERIES_MODES = {
0: "off",
1: "daily clean",
2: "sensitive",
3: "massage",
4: "whitening",
5: "deep clean",
6: "tongue cleaning",
7: "turbo",
255: "unknown",
}
SMART_SERIES_6000_MODES = SMART_SERIES_MODES | {2: "off"}
IO_SERIES_MODES = {
0: "daily clean",
1: "sensitive",
2: "gum care",
3: "whiten",
4: "intense",
5: "super sensitive",
6: "tongue cleaning",
8: "settings",
9: "off",
}
DEVICE_TYPES = {
Models.Pro6000: ModelDescription("Pro 6000", SMART_SERIES_MODES),
Models.TriumphV2: ModelDescription("Triumph V2", SMART_SERIES_MODES),
Models.IOSeries4: ModelDescription(
device_type="IO Series 4",
modes=IO_SERIES_MODES,
),
Models.IOSeries67: ModelDescription(
device_type="IO Series 6/7",
modes=IO_SERIES_MODES,
),
Models.IOSeries8: ModelDescription(
device_type="IO Series 8",
modes=IO_SERIES_MODES,
),
Models.IOSeries9: ModelDescription(
device_type="IO Series 9",
modes=IO_SERIES_MODES,
),
Models.IOSeries89: ModelDescription(
device_type="IO Series 8/9",
modes=IO_SERIES_MODES,
),
Models.SmartSeries4000: ModelDescription(
device_type="Smart Series 4000",
modes=SMART_SERIES_MODES,
),
Models.SmartSeries6000: ModelDescription(
device_type="Smart Series 6000",
modes=SMART_SERIES_6000_MODES,
),
Models.SmartSeries7000: ModelDescription(
device_type="Smart Series 7000",
modes=SMART_SERIES_MODES,
),
Models.SmartSeries8000: ModelDescription(
device_type="Smart Series 8000",
modes=SMART_SERIES_MODES,
),
Models.SmartSeries9000: ModelDescription(
device_type="Smart Series 9000/10000",
modes=SMART_SERIES_MODES,
),
Models.GeniusX: ModelDescription(device_type="Genius X", modes=SMART_SERIES_MODES),
}
STATES = {
0: "unknown",
1: "initializing",
2: "idle",
3: "running",
4: "charging",
5: "setup",
6: "flight menu",
8: "selection menu",
9: "off",
113: "final test",
114: "pcb test",
115: "sleeping",
116: "transport",
}
PRESSURE = {
0: "normal",
16: "normal",
32: "normal",
48: "normal",
50: "normal",
56: "power button pressed",
80: "normal",
82: "normal",
86: "button pressed",
90: "power button pressed",
114: "normal",
118: "button pressed",
122: "power button pressed",
144: "high",
146: "high",
150: "button pressed",
154: "power button pressed",
178: "high",
182: "button pressed",
186: "power button pressed",
192: "high",
240: "high",
242: "high",
}
ACTIVE_CONNECTION_PRESSURE = {0: "low", 1: "normal", 2: "high"}
ORALB_MANUFACTURER = 0x00DC
BYTES_TO_MODEL = {
b"\x062": Models.IOSeries67,
b"\x074": Models.IOSeries4,
b"\x03V": Models.SmartSeries4000,
b"\x04'": Models.SmartSeries6000,
b'\x03"': Models.SmartSeries8000,
b"\x03!": Models.SmartSeries9000,
b"\x061": Models.IOSeries89,
b"\x02\x02": Models.TriumphV2,
b"\x01\x02": Models.Pro6000,
b"\x04q": Models.GeniusX,
}
SECTOR_MAP = {
1: "sector 1",
9: "sector 1",
2: "sector 2",
10: "sector 2",
3: "sector 3",
11: "sector 3",
19: "sector 3",
27: "sector 3",
4: "sector 4",
7: "sector 4",
15: "sector 4",
31: "sector 4",
39: "sector 4",
41: "success",
42: "success",
43: "success",
47: "success",
55: "success",
}
class OralBBluetoothDeviceData(BluetoothData):
"""Data for OralB BLE sensors."""
def __init__(self) -> None:
super().__init__()
# If this is True, we are currently brushing or were brushing as of the last advertisement data
self._brushing = False
self._last_brush = 0.0
def _start_update(self, service_info: BluetoothServiceInfo) -> None:
"""Update from BLE advertisement data."""
_LOGGER.debug("Parsing OralB BLE advertisement data: %s", service_info)
manufacturer_data = service_info.manufacturer_data
address = service_info.address
if ORALB_MANUFACTURER not in manufacturer_data:
return None
data = manufacturer_data[ORALB_MANUFACTURER]
self.set_device_manufacturer("Oral-B")
_LOGGER.debug("Parsing Oral-B sensor: %s", data)
msg_length = len(data)
if msg_length not in (9, 11):
return
device_bytes = data[0:2]
state = data[3]
pressure = data[4]
brush_time = data[5] * 60 + data[6]
mode = data[7]
sector = data[8]
sector_timer = None
no_of_sectors = None
if msg_length >= 11:
sector_timer = data[9]
no_of_sectors = data[10]
model = BYTES_TO_MODEL.get(device_bytes, Models.SmartSeries7000)
model_info = DEVICE_TYPES[model]
self.brush_modes = model_info.modes
self.set_device_type(model_info.device_type)
name = f"{model_info.device_type} {short_address(address)}"
self.set_device_name(name)
self.set_title(name)
tb_state = STATES.get(state, f"unknown state {state}")
tb_mode = self.brush_modes.get(mode, f"unknown mode {mode}")
tb_pressure = PRESSURE.get(pressure, f"unknown pressure {pressure}")
tb_sector = SECTOR_MAP.get(sector, f"unknown sector code {sector}")
self.update_sensor(str(OralBSensor.TIME), None, brush_time, None, "Time")
if brush_time == 0 and tb_state != "running":
# When starting up, sector is not accurate.
self.update_sensor(
str(OralBSensor.SECTOR), None, "no sector", None, "Sector"
)
else:
self.update_sensor(str(OralBSensor.SECTOR), None, tb_sector, None, "Sector")
if no_of_sectors is not None:
self.update_sensor(
str(OralBSensor.NUMBER_OF_SECTORS),
None,
no_of_sectors,
None,
"Number of sectors",
)
if sector_timer is not None:
self.update_sensor(
str(OralBSensor.SECTOR_TIMER), None, sector_timer, None, "Sector Timer"
)
self.update_sensor(
str(OralBSensor.TOOTHBRUSH_STATE), None, tb_state, None, "Toothbrush State"
)
self.update_sensor(
str(OralBSensor.PRESSURE), None, tb_pressure, None, "Pressure"
)
self.update_sensor(str(OralBSensor.MODE), None, tb_mode, None, "Mode")
self.update_binary_sensor(
str(OralBBinarySensor.BRUSHING), bool(state == 3), None, "Brushing"
)
if state == 3:
self._brushing = True
self._last_brush = time.monotonic()
else:
self._brushing = False
def poll_needed(
self, service_info: BluetoothServiceInfo, last_poll: float | None
) -> bool:
"""
This is called every time we get a service_info for a device. It means the
device is working and online.
"""
if last_poll is None:
return True
update_interval = NOT_BRUSHING_UPDATE_INTERVAL_SECONDS
if (
self._brushing
or time.monotonic() - self._last_brush <= TIMEOUT_RECENTLY_BRUSHING
):
update_interval = BRUSHING_UPDATE_INTERVAL_SECONDS
return last_poll > update_interval
@retry_bluetooth_connection_error()
async def _get_payload(self, client: BleakClientWithServiceCache) -> None:
"""Get the payload from the brush using its gatt_characteristics."""
battery_char = client.services.get_characteristic(CHARACTERISTIC_BATTERY)
battery_payload = await client.read_gatt_char(battery_char)
pressure_char = client.services.get_characteristic(CHARACTERISTIC_PRESSURE)
pressure_payload = await client.read_gatt_char(pressure_char)
tb_pressure = ACTIVE_CONNECTION_PRESSURE.get(
pressure_payload[0], f"unknown pressure {pressure_payload[0]}"
)
self.update_sensor(
str(OralBSensor.PRESSURE), None, tb_pressure, None, "Pressure"
)
self.update_sensor(
str(OralBSensor.BATTERY_PERCENT),
Units.PERCENTAGE,
battery_payload[0],
SensorDeviceClass.BATTERY,
"Battery",
)
_LOGGER.debug("Successfully read active gatt characters")
async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate:
"""
Poll the device to retrieve any values we can't get from passive listening.
"""
_LOGGER.debug("Polling Oral-B device: %s", ble_device.address)
client = await establish_connection(
BleakClientWithServiceCache, ble_device, ble_device.address
)
try:
await self._get_payload(client)
except BleakError as err:
_LOGGER.warning(f"Reading gatt characters failed with err: {err}")
finally:
await client.disconnect()
_LOGGER.debug("Disconnected from active bluetooth client")
return self._finish_update()
oralb-ble-1.0.0/src/oralb_ble/py.typed 0000664 0000000 0000000 00000000000 15040370547 0017551 0 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/tests/ 0000775 0000000 0000000 00000000000 15040370547 0014516 5 ustar 00root root 0000000 0000000 oralb-ble-1.0.0/tests/__init__.py 0000664 0000000 0000000 00000002413 15040370547 0016627 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import Any
from bleak.backends.scanner import AdvertisementData, BLEDevice
ADVERTISEMENT_DATA_DEFAULTS = {
"local_name": "Unknown",
"manufacturer_data": {},
"service_data": {},
"service_uuids": [],
"rssi": -127,
"platform_data": ((),),
"tx_power": -127,
}
BLE_DEVICE_DEFAULTS = {
"name": None,
"rssi": -127,
"details": None,
}
def generate_advertisement_data(**kwargs: Any) -> AdvertisementData:
"""Generate advertisement data with defaults."""
new = kwargs.copy()
for key, value in ADVERTISEMENT_DATA_DEFAULTS.items():
new.setdefault(key, value)
return AdvertisementData(**new)
def generate_ble_device(
address: str | None = None,
name: str | None = None,
details: Any | None = None,
rssi: int | None = None,
**kwargs: Any,
) -> BLEDevice:
"""Generate a BLEDevice with defaults."""
new = kwargs.copy()
if address is not None:
new["address"] = address
if name is not None:
new["name"] = name
if details is not None:
new["details"] = details
if rssi is not None:
new["rssi"] = rssi
for key, value in BLE_DEVICE_DEFAULTS.items():
new.setdefault(key, value)
return BLEDevice(**new)
oralb-ble-1.0.0/tests/test_parser.py 0000664 0000000 0000000 00000372016 15040370547 0017434 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from unittest import mock
import pytest
from bluetooth_sensor_state_data import BluetoothServiceInfo, SensorUpdate
from sensor_state_data import (
BinarySensorDescription,
BinarySensorValue,
DeviceKey,
SensorDescription,
SensorDeviceClass,
SensorDeviceInfo,
SensorValue,
Units,
)
from oralb_ble.parser import SMART_SERIES_MODES, OralBBluetoothDeviceData
from . import generate_ble_device
# 2022-10-24 18:10:10.048 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] 00:E0:43:87:4B:03: 78:DB:2F:C2:48:BE AdvertisementData(manufacturer_data={220: b'\x02\x01\x08\x02 \x00\x00\x01\x01\x00\x04'}, rssi=-64) connectable: True match: set() rssi: -64
# 2022-10-24 18:10:12.604 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] 00:E0:43:87:4B:03: 78:DB:2F:C2:48:BE AdvertisementData(manufacturer_data={220: b'\x02\x01\x08\x03\x00\x00\x00\x01\x01\x00\x04'}, rssi=-56) connectable: True match: set() rssi: -56
# 2022-10-24 18:10:13.798 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] 00:E0:43:87:4B:03: 78:DB:2F:C2:48:BE AdvertisementData(manufacturer_data={220: b'\x02\x01\x08\x02\x00\x00\x01\x01\x01\x03\x04'}, rssi=-54) connectable: True match: set() rssi: -54
# 2022-10-24 18:10:14.930 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] 00:E0:43:87:4B:03: 78:DB:2F:C2:48:BE AdvertisementData(manufacturer_data={220: b'\x02\x01\x08\x02 \x00\x01\x01\x01\x03\x04'}, rssi=-64) connectable: True match: set() rssi: -64
ORALB_DATA_1 = BluetoothServiceInfo(
name="78:DB:2F:C2:48:BE",
address="78:DB:2F:C2:48:BE",
rssi=-63,
manufacturer_data={220: b"\x02\x01\x08\x02 \x00\x00\x01\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_DATA_2 = BluetoothServiceInfo(
name="78:DB:2F:C2:48:BE",
address="78:DB:2F:C2:48:BE",
rssi=-63,
manufacturer_data={220: b"\x02\x01\x08\x03\x00\x00\x00\x01\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_DATA_3 = BluetoothServiceInfo(
name="78:DB:2F:C2:48:BE",
address="78:DB:2F:C2:48:BE",
rssi=-63,
manufacturer_data={220: b"\x02\x01\x08\x02\x00\x00\x01\x01\x01\x03\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_DATA_4 = BluetoothServiceInfo(
name="78:DB:2F:C2:48:BE",
address="78:DB:2F:C2:48:BE",
rssi=-63,
manufacturer_data={220: b"\x02\x01\x08\x02 \x00\x01\x01\x01\x03\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_6 = BluetoothServiceInfo(
name="78:DB:2F:C2:48:BE",
address="78:DB:2F:C2:48:BE",
rssi=-63,
manufacturer_data={220: b"\x062k\x02r\x00\x00\x01\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_7 = BluetoothServiceInfo(
name="78:DB:2F:C2:48:BE",
address="78:DB:2F:C2:48:BE",
rssi=-63,
manufacturer_data={220: b"\x062k\x02 \x00\x01\x01\x01\x03\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_8 = BluetoothServiceInfo(
name="78:DB:2F:C2:48:BE",
address="78:DB:2F:C2:48:BE",
rssi=-63,
manufacturer_data={220: b"\x061\x19\x08r\x00\x00\x00\x07\x00\x00"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_4 = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="GXB772CD\x00\x00\x00\x00\x00\x00\x00\x00\x00",
manufacturer_data={220: b"\x074\x0c\x038\x00\x00\x02\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_9000_SERIES = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="9000",
manufacturer_data={220: b"\x03!\x0c\x020\x00\x06\x01\x01\x14\x04"},
service_uuids=[],
service_data={},
source="local",
)
# https://github.com/home-assistant/core/issues/81967
ORALB_9000_BLACK_SERIES = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="9000",
manufacturer_data={220: b"\x03!\x0b\x020\x00\x00\x01\x01\x80\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_9 = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="Oral-B Toothbrush",
manufacturer_data={220: b"\x061\x16\x08r\x00\x00\x03\x02\x00\x04"},
service_uuids=["0000fe0d-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
ORALB_4000_SERIES = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="4000",
manufacturer_data={220: b"\x03V\x04\x030\x00\x00\x01\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_6000_SERIES_DAILY_CLEAN_MODE = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="6000",
manufacturer_data={220: b"\x04'\r\x032\x00\x06\x01\x01\x14\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_6000_SERIES_DAILY_CLEAN_MODE_HIGH_PRESSURE = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="6000",
manufacturer_data={220: b"\x04'\r\x032\x00\x04\x01\x01\r\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_6000_SERIES_DAILY_CLEAN_MODE_NORMAL_PRESSURE = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="6000",
manufacturer_data={220: b"\x04'\r\x032\x00\x1b\x02\x01Z\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_TRIUMPH_V2 = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="T2",
manufacturer_data={220: b"\x02\x02\x06\x02 \x00\x00\x01\x0f\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_TRIUMPH_V2_DATA_2 = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="T2",
manufacturer_data={220: b"\x02\x02\x06\x03\x00\x00\x01\x01\x01\x03\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_PRO_SERIES_6000 = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="PRO6000",
manufacturer_data={220: b"\x01\x02\x05\x03\x00\x00\x08\x04\x01"},
service_uuids=[],
service_data={},
source="local",
)
GENIUS_8000 = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="GENIUS8000",
manufacturer_data={220: b'\x03"\x0c\x02 \x00\x00\x07\x0f\x00\x04'},
service_uuids=[],
service_data={},
source="local",
)
GENIUS_8000_HIGH_PRESSURE = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="GENIUS8000",
manufacturer_data={220: b'\x03"\x0c\x03\xc0\x010\x07\x04<\x04'},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_6_DAILY_CLEAN = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="Oral-B Toothbrush",
manufacturer_data={220: b"\x062k\x02r\x00\x00\x00\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_6_SENSITIVE = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="Oral-B Toothbrush",
manufacturer_data={220: b"\x062k\x02r\x00\x00\x01\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_6_GUM_CARE = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="Oral-B Toothbrush",
manufacturer_data={220: b"\x062k\x02r\x00\x00\x02\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
ORALB_IO_SERIES_6_WHITEN = BluetoothServiceInfo(
address="78:DB:2F:C2:48:BE",
rssi=-63,
name="Oral-B Toothbrush",
manufacturer_data={220: b"\x062k\x02r\x00\x00\x03\x01\x00\x04"},
service_uuids=[],
service_data={},
source="local",
)
def test_can_create():
OralBBluetoothDeviceData()
def test_dataset_1():
parser = OralBBluetoothDeviceData()
service_info = ORALB_DATA_1
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 7000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 7000 48BE",
model="Smart Series 7000",
manufacturer="Oral-B",
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="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_dataset_2():
parser = OralBBluetoothDeviceData()
service_info = ORALB_DATA_2
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 7000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 7000 48BE",
model="Smart Series 7000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_dataset_3():
parser = OralBBluetoothDeviceData()
service_info = ORALB_DATA_3
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 7000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 7000 48BE",
model="Smart Series 7000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=3,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=1,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_dataset_4():
parser = OralBBluetoothDeviceData()
service_info = ORALB_DATA_4
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 7000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 7000 48BE",
model="Smart Series 7000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=3,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=1,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_io_series_6():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_6
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 6/7 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 6/7 48BE",
model="IO Series 6/7",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="sensitive",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_io_series_6_daily_clean_mode():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_6_DAILY_CLEAN
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 6/7 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 6/7 48BE",
model="IO Series 6/7",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily clean",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_io_series_6_sensitive_mode():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_6_SENSITIVE
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 6/7 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 6/7 48BE",
model="IO Series 6/7",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="sensitive",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_io_series_6_gum_care_mode():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_6_GUM_CARE
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 6/7 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 6/7 48BE",
model="IO Series 6/7",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="gum care",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_io_series_6_whiten_mode():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_6_WHITEN
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 6/7 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 6/7 48BE",
model="IO Series 6/7",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="whiten",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_io_series_7():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_7
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 6/7 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 6/7 48BE",
model="IO Series 6/7",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=3,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="sensitive",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=1,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_io_series_4():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_4
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 4 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 4 48BE",
model="IO Series 4",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="gum " "care",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="power button pressed",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_9000_series():
parser = OralBBluetoothDeviceData()
service_info = ORALB_9000_SERIES
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 9000/10000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 9000/10000 48BE",
model="Smart Series 9000/10000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=20,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=6,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_9000_black_series():
parser = OralBBluetoothDeviceData()
service_info = ORALB_9000_BLACK_SERIES
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 9000/10000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 9000/10000 48BE",
model="Smart Series 9000/10000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=128,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_io_series_9():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_9
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 8/9 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 8/9 48BE",
model="IO Series 8/9",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="selection " "menu",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="whiten",
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_smart_series_4000():
parser = OralBBluetoothDeviceData()
service_info = ORALB_4000_SERIES
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 4000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 4000 48BE",
model="Smart Series 4000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_triumph_v2():
parser = OralBBluetoothDeviceData()
service_info = ORALB_TRIUMPH_V2
result = parser.update(service_info)
assert result == SensorUpdate(
title="Triumph V2 48BE",
devices={
None: SensorDeviceInfo(
name="Triumph V2 48BE",
model="Triumph V2",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_triumph_v2_data_2():
parser = OralBBluetoothDeviceData()
service_info = ORALB_TRIUMPH_V2_DATA_2
result = parser.update(service_info)
assert result == SensorUpdate(
title="Triumph V2 48BE",
devices={
None: SensorDeviceInfo(
name="Triumph V2 48BE",
model="Triumph V2",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=3,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=1,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_pro_series_6000():
parser = OralBBluetoothDeviceData()
service_info = ORALB_PRO_SERIES_6000
result = parser.update(service_info)
assert result == SensorUpdate(
title="Pro 6000 48BE",
devices={
None: SensorDeviceInfo(
name="Pro 6000 48BE",
model="Pro 6000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="whitening",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=8,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_smart_series_6000_daily_clean_mode():
parser = OralBBluetoothDeviceData()
service_info = ORALB_6000_SERIES_DAILY_CLEAN_MODE
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 6000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 6000 48BE",
model="Smart Series 6000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=6,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=20,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_smart_series_6000_daily_clean_mode_high_pressure():
parser = OralBBluetoothDeviceData()
service_info = ORALB_6000_SERIES_DAILY_CLEAN_MODE_HIGH_PRESSURE
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 6000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 6000 48BE",
model="Smart Series 6000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=13,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=4,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_smart_series_6000_daily_clean_mode_normal_pressure():
parser = OralBBluetoothDeviceData()
service_info = ORALB_6000_SERIES_DAILY_CLEAN_MODE_NORMAL_PRESSURE
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 6000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 6000 48BE",
model="Smart Series 6000",
manufacturer="Oral-B",
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="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="off",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=90,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=27,
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "1",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_genius_8000():
parser = OralBBluetoothDeviceData()
service_info = GENIUS_8000
result = parser.update(service_info)
assert result == SensorUpdate(
title="Smart Series 8000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 8000 48BE",
model="Smart Series 8000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="idle",
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="turbo",
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
def test_genius_8000_high_pressure():
parser = OralBBluetoothDeviceData()
service_info = GENIUS_8000_HIGH_PRESSURE
result = parser.update(service_info)
assert parser.brush_modes == SMART_SERIES_MODES
assert result == SensorUpdate(
title="Smart Series 8000 48BE",
devices={
None: SensorDeviceInfo(
name="Smart Series 8000 48BE",
model="Smart Series 8000",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="high",
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="running",
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=60,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="turbo",
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="sector " "4",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=108,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=4,
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=True,
)
},
events={},
)
def test_io_series_8():
parser = OralBBluetoothDeviceData()
service_info = ORALB_IO_SERIES_8
result = parser.update(service_info)
assert result == SensorUpdate(
title="IO Series 8/9 48BE",
devices={
None: SensorDeviceInfo(
name="IO Series 8/9 48BE",
model="IO Series 8/9",
manufacturer="Oral-B",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="sector_timer", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector_timer", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="mode", device_id=None): SensorDescription(
device_key=DeviceKey(key="mode", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
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="pressure", device_id=None): SensorDescription(
device_key=DeviceKey(key="pressure", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="sector", device_id=None): SensorDescription(
device_key=DeviceKey(key="sector", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="time", device_id=None): SensorDescription(
device_key=DeviceKey(key="time", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorDescription(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorDescription(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
device_class=None,
native_unit_of_measurement=None,
),
},
entity_values={
DeviceKey(key="sector_timer", device_id=None): SensorValue(
device_key=DeviceKey(key="sector_timer", device_id=None),
name="Sector " "Timer",
native_value=0,
),
DeviceKey(key="mode", device_id=None): SensorValue(
device_key=DeviceKey(key="mode", device_id=None),
name="Mode",
native_value="daily " "clean",
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-63,
),
DeviceKey(key="pressure", device_id=None): SensorValue(
device_key=DeviceKey(key="pressure", device_id=None),
name="Pressure",
native_value="normal",
),
DeviceKey(key="sector", device_id=None): SensorValue(
device_key=DeviceKey(key="sector", device_id=None),
name="Sector",
native_value="no " "sector",
),
DeviceKey(key="time", device_id=None): SensorValue(
device_key=DeviceKey(key="time", device_id=None),
name="Time",
native_value=0,
),
DeviceKey(key="number_of_sectors", device_id=None): SensorValue(
device_key=DeviceKey(key="number_of_sectors", device_id=None),
name="Number " "of " "sectors",
native_value=0,
),
DeviceKey(key="toothbrush_state", device_id=None): SensorValue(
device_key=DeviceKey(key="toothbrush_state", device_id=None),
name="Toothbrush " "State",
native_value="selection " "menu",
),
},
binary_entity_descriptions={
DeviceKey(key="brushing", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="brushing", device_id=None), device_class=None
)
},
binary_entity_values={
DeviceKey(key="brushing", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="brushing", device_id=None),
name="Brushing",
native_value=False,
)
},
events={},
)
@mock.patch("oralb_ble.parser.establish_connection")
@pytest.mark.asyncio
async def test_async_poll(mock_establish_connection):
parser = OralBBluetoothDeviceData()
device = generate_ble_device(address="abc", name="test_device")
mock_establish_connection.return_value.read_gatt_char.side_effect = [
bytearray(b";\x00\x00\x00"),
bytearray(b"\x01\x89\x7f\xbe\x04`\x7f\xbe\x047"),
]
res = await parser.async_poll(device)
assert (
res.entity_values.get(DeviceKey("battery_percent")).native_value == 59
and res.entity_values.get(DeviceKey("pressure")).native_value == "normal"
)
def test_poll_needed_no_time():
parser = OralBBluetoothDeviceData()
assert parser.poll_needed(None, None)
def test_poll_needed_brushing():
parser = OralBBluetoothDeviceData()
parser._brushing = True
assert parser.poll_needed(None, 61)
@mock.patch("oralb_ble.parser.time")
def test_poll_needed_brushing_recently(mocked_time):
parser = OralBBluetoothDeviceData()
mocked_time.monotonic.return_value = 5
parser._brushing = False
parser._last_brush = 0
assert parser.poll_needed(None, 61)