pax_global_header 0000666 0000000 0000000 00000000064 14565363351 0014525 g ustar 00root root 0000000 0000000 52 comment=bfe079ea2e0587506792f673f684172318e4d640
Bluetooth-Devices-oralb-ble-15e51c6/ 0000775 0000000 0000000 00000000000 14565363351 0017242 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/.all-contributorsrc 0000664 0000000 0000000 00000000460 14565363351 0023073 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
}
Bluetooth-Devices-oralb-ble-15e51c6/.editorconfig 0000664 0000000 0000000 00000000444 14565363351 0021721 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
Bluetooth-Devices-oralb-ble-15e51c6/.flake8 0000664 0000000 0000000 00000000057 14565363351 0020417 0 ustar 00root root 0000000 0000000 [flake8]
exclude = docs
max-line-length = 2188
Bluetooth-Devices-oralb-ble-15e51c6/.github/ 0000775 0000000 0000000 00000000000 14565363351 0020602 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/.github/FUNDING.yml 0000664 0000000 0000000 00000000036 14565363351 0022416 0 ustar 00root root 0000000 0000000 github: ["bluetooth-devices"]
Bluetooth-Devices-oralb-ble-15e51c6/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 14565363351 0022765 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/.github/ISSUE_TEMPLATE/1-bug_report.md 0000664 0000000 0000000 00000000422 14565363351 0025613 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.
Bluetooth-Devices-oralb-ble-15e51c6/.github/ISSUE_TEMPLATE/2-feature-request.md 0000664 0000000 0000000 00000000672 14565363351 0026574 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.
Bluetooth-Devices-oralb-ble-15e51c6/.github/labels.toml 0000664 0000000 0000000 00000003515 14565363351 0022745 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"
Bluetooth-Devices-oralb-ble-15e51c6/.github/workflows/ 0000775 0000000 0000000 00000000000 14565363351 0022637 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/.github/workflows/ci.yml 0000664 0000000 0000000 00000003746 14565363351 0023767 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@v3
- uses: actions/setup-python@v3
with:
python-version: "3.9"
- uses: pre-commit/action@v3.0.0
# 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@v3
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v5
test:
strategy:
fail-fast: false
matrix:
python-version:
- "3.9"
- "3.10"
- "3.11"
os:
- ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- uses: snok/install-poetry@v1
- name: Install Dependencies
run: poetry install
- name: Test with Pytest
run: poetry run pytest --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
release:
runs-on: ubuntu-latest
environment: release
if: github.ref == 'refs/heads/main'
needs:
- test
- lint
- commitlint
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
# Run semantic release:
# - Update CHANGELOG.md
# - Update version in code
# - Create git tag
# - Create GitHub release
# - Publish to PyPI
- name: Python Semantic Release
uses: relekang/python-semantic-release@v7.34.6
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
pypi_token: ${{ secrets.PYPI_TOKEN }}
Bluetooth-Devices-oralb-ble-15e51c6/.github/workflows/hacktoberfest.yml 0000664 0000000 0000000 00000000534 14565363351 0026210 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.2.0
with:
github_token: ${{ secrets.GH_PAT }}
Bluetooth-Devices-oralb-ble-15e51c6/.github/workflows/issue-manager.yml 0000664 0000000 0000000 00000001340 14565363351 0026120 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.4.0
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."
}
}
Bluetooth-Devices-oralb-ble-15e51c6/.github/workflows/labels.yml 0000664 0000000 0000000 00000000774 14565363351 0024634 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@v3
- name: Set up Python
uses: actions/setup-python@v3
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
Bluetooth-Devices-oralb-ble-15e51c6/.gitignore 0000664 0000000 0000000 00000004066 14565363351 0021240 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/
Bluetooth-Devices-oralb-ble-15e51c6/.gitpod.yml 0000664 0000000 0000000 00000000306 14565363351 0021330 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
Bluetooth-Devices-oralb-ble-15e51c6/.idea/ 0000775 0000000 0000000 00000000000 14565363351 0020222 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/.idea/oralb-ble.iml 0000664 0000000 0000000 00000000515 14565363351 0022565 0 ustar 00root root 0000000 0000000
Bluetooth-Devices-oralb-ble-15e51c6/.idea/watcherTasks.xml 0000664 0000000 0000000 00000005253 14565363351 0023414 0 ustar 00root root 0000000 0000000
Bluetooth-Devices-oralb-ble-15e51c6/.idea/workspace.xml 0000664 0000000 0000000 00000002725 14565363351 0022750 0 ustar 00root root 0000000 0000000
Bluetooth-Devices-oralb-ble-15e51c6/.pre-commit-config.yaml 0000664 0000000 0000000 00000003306 14565363351 0023525 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: [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: v2.35.0
hooks:
- id: commitizen
stages: [commit-msg]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.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: v2.7.1
hooks:
- id: prettier
args: ["--tab-width", "2"]
- repo: https://github.com/asottile/pyupgrade
rev: v3.1.0
hooks:
- id: pyupgrade
args: [--py37-plus]
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 22.10.0
hooks:
- id: black
- repo: https://github.com/codespell-project/codespell
rev: v2.2.2
hooks:
- id: codespell
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.931
hooks:
- id: mypy
additional_dependencies: []
- repo: https://github.com/PyCQA/bandit
rev: 1.7.4
hooks:
- id: bandit
args: [-x, tests]
Bluetooth-Devices-oralb-ble-15e51c6/.readthedocs.yml 0000664 0000000 0000000 00000001004 14565363351 0022323 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
Bluetooth-Devices-oralb-ble-15e51c6/CHANGELOG.md 0000664 0000000 0000000 00000020264 14565363351 0021057 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))
Bluetooth-Devices-oralb-ble-15e51c6/CONTRIBUTING.md 0000664 0000000 0000000 00000007422 14565363351 0021500 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
Bluetooth-Devices-oralb-ble-15e51c6/LICENSE 0000664 0000000 0000000 00000002060 14565363351 0020245 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.
Bluetooth-Devices-oralb-ble-15e51c6/README.md 0000664 0000000 0000000 00000006653 14565363351 0020533 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.
Bluetooth-Devices-oralb-ble-15e51c6/commitlint.config.js 0000664 0000000 0000000 00000000364 14565363351 0023226 0 ustar 00root root 0000000 0000000 module.exports = {
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],
},
};
Bluetooth-Devices-oralb-ble-15e51c6/docs/ 0000775 0000000 0000000 00000000000 14565363351 0020172 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/docs/Makefile 0000664 0000000 0000000 00000001175 14565363351 0021636 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)
Bluetooth-Devices-oralb-ble-15e51c6/docs/make.bat 0000664 0000000 0000000 00000001374 14565363351 0021604 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
Bluetooth-Devices-oralb-ble-15e51c6/docs/source/ 0000775 0000000 0000000 00000000000 14565363351 0021472 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/docs/source/_static/ 0000775 0000000 0000000 00000000000 14565363351 0023120 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/docs/source/_static/.gitkeep 0000664 0000000 0000000 00000000000 14565363351 0024537 0 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/docs/source/changelog.md 0000664 0000000 0000000 00000000045 14565363351 0023742 0 ustar 00root root 0000000 0000000 ```{include} ../../CHANGELOG.md
```
Bluetooth-Devices-oralb-ble-15e51c6/docs/source/conf.py 0000664 0000000 0000000 00000003651 14565363351 0022776 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, List
# -- 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"]
Bluetooth-Devices-oralb-ble-15e51c6/docs/source/contributing.md 0000664 0000000 0000000 00000000050 14565363351 0024516 0 ustar 00root root 0000000 0000000 ```{include} ../../CONTRIBUTING.md
```
Bluetooth-Devices-oralb-ble-15e51c6/docs/source/index.md 0000664 0000000 0000000 00000000351 14565363351 0023122 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
```
Bluetooth-Devices-oralb-ble-15e51c6/docs/source/installation.md 0000664 0000000 0000000 00000000264 14565363351 0024517 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
```
Bluetooth-Devices-oralb-ble-15e51c6/docs/source/usage.md 0000664 0000000 0000000 00000000137 14565363351 0023121 0 ustar 00root root 0000000 0000000 # Usage
To use this package, import it:
```python
import oralb_ble
```
TODO: Document usage
Bluetooth-Devices-oralb-ble-15e51c6/poetry.lock 0000664 0000000 0000000 00000341175 14565363351 0021451 0 ustar 00root root 0000000 0000000 [[package]]
name = "aiofiles"
version = "22.1.0"
description = "File support for asyncio."
category = "main"
optional = false
python-versions = ">=3.7,<4.0"
[[package]]
name = "aiohttp"
version = "3.8.3"
description = "Async http client/server framework (asyncio)"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
aiosignal = ">=1.1.2"
async-timeout = ">=4.0.0a3,<5.0"
attrs = ">=17.3.0"
charset-normalizer = ">=2.0,<3.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
yarl = ">=1.0,<2.0"
[package.extras]
speedups = ["Brotli", "aiodns", "cchardet"]
[[package]]
name = "aiosignal"
version = "1.3.1"
description = "aiosignal: a list of registered asynchronous callbacks"
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
frozenlist = ">=1.1.0"
[[package]]
name = "alabaster"
version = "0.7.12"
description = "A configurable sidebar-enabled Sphinx theme"
category = "main"
optional = true
python-versions = "*"
[[package]]
name = "async-timeout"
version = "4.0.2"
description = "Timeout context manager for asyncio programs"
category = "main"
optional = false
python-versions = ">=3.6"
[[package]]
name = "attrs"
version = "22.1.0"
description = "Classes Without Boilerplate"
category = "main"
optional = false
python-versions = ">=3.5"
[package.extras]
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
[[package]]
name = "Babel"
version = "2.10.3"
description = "Internationalization utilities"
category = "main"
optional = true
python-versions = ">=3.6"
[package.dependencies]
pytz = ">=2015.7"
[[package]]
name = "bleak"
version = "0.19.5"
description = "Bluetooth Low Energy platform Agnostic Klient"
category = "main"
optional = false
python-versions = ">=3.7,<4.0"
[package.dependencies]
async-timeout = ">=3.0.0,<5"
bleak-winrt = {version = ">=1.2.0,<2.0.0", markers = "platform_system == \"Windows\""}
dbus-fast = {version = ">=1.22.0,<2.0.0", markers = "platform_system == \"Linux\""}
pyobjc-core = {version = ">=8.5.1,<9.0.0", markers = "platform_system == \"Darwin\""}
pyobjc-framework-CoreBluetooth = {version = ">=8.5.1,<9.0.0", markers = "platform_system == \"Darwin\""}
pyobjc-framework-libdispatch = {version = ">=8.5.1,<9.0.0", markers = "platform_system == \"Darwin\""}
[[package]]
name = "bleak-retry-connector"
version = "2.13.0"
description = "A connector for Bleak Clients that handles transient connection failures"
category = "main"
optional = false
python-versions = ">=3.9,<4.0"
[package.dependencies]
async-timeout = ">=4.0.1"
bleak = ">=0.19.0"
bluetooth-adapters = ">=0.12.0"
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"
category = "main"
optional = false
python-versions = "*"
[[package]]
name = "bluetooth-adapters"
version = "0.15.2"
description = "Tools to enumerate and find Bluetooth Adapters"
category = "main"
optional = false
python-versions = ">=3.9,<4.0"
[package.dependencies]
aiohttp = ">=3.8.1"
async-timeout = ">=4.0.2"
bleak = ">=0.15.1"
dbus-fast = ">=1.21.0"
mac-vendor-lookup = ">=0.1.12"
usb-devices = ">=0.4.1"
[package.extras]
docs = ["Sphinx (>=5.0,<6.0)", "myst-parser (>=0.18,<0.19)", "sphinx-rtd-theme (>=1.0,<2.0)"]
[[package]]
name = "bluetooth-data-tools"
version = "0.1.2"
description = "Tools for converting bluetooth data and packets"
category = "main"
optional = false
python-versions = ">=3.9,<4.0"
[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.6.0"
description = "Models for storing and converting Bluetooth Sensor State Data"
category = "main"
optional = false
python-versions = ">=3.9,<4.0"
[package.dependencies]
home-assistant-bluetooth = ">=1.3.0"
sensor-state-data = ">=2.0"
[package.extras]
docs = ["Sphinx (>=5.0,<6.0)", "myst-parser (>=0.18,<0.19)", "sphinx-rtd-theme (>=1.0,<2.0)"]
[[package]]
name = "certifi"
version = "2022.9.24"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = true
python-versions = ">=3.6"
[[package]]
name = "charset-normalizer"
version = "2.1.1"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
python-versions = ">=3.6.0"
[package.extras]
unicode-backport = ["unicodedata2"]
[[package]]
name = "colorama"
version = "0.4.5"
description = "Cross-platform colored terminal text."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "coverage"
version = "6.5.0"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.dependencies]
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
[package.extras]
toml = ["tomli"]
[[package]]
name = "dbus-fast"
version = "1.48.0"
description = "A faster version of dbus-next"
category = "main"
optional = false
python-versions = ">=3.7,<4.0"
[package.dependencies]
async-timeout = ">=3.0.0"
[package.extras]
docs = ["Sphinx (>=5.1.1,<6.0.0)", "myst-parser (>=0.18.0,<0.19.0)", "sphinx-rtd-theme (>=1.0.0,<2.0.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinxcontrib-fulltoc (>=1.2.0,<2.0.0)"]
[[package]]
name = "docutils"
version = "0.17.1"
description = "Docutils -- Python Documentation Utilities"
category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "frozenlist"
version = "1.3.3"
description = "A list-like structure which implements collections.abc.MutableSequence"
category = "main"
optional = false
python-versions = ">=3.7"
[[package]]
name = "home-assistant-bluetooth"
version = "1.6.0"
description = "Home Assistant Bluetooth Models and Helpers"
category = "main"
optional = false
python-versions = ">=3.9,<4.0"
[package.dependencies]
bleak = ">=0.19.0"
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
python-versions = ">=3.5"
[[package]]
name = "imagesize"
version = "1.4.1"
description = "Getting image size from png/jpeg/jpeg2000/gif file"
category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "importlib-metadata"
version = "5.0.0"
description = "Read metadata from Python packages"
category = "main"
optional = true
python-versions = ">=3.7"
[package.dependencies]
zipp = ">=0.5"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
perf = ["ipython"]
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
[[package]]
name = "iniconfig"
version = "1.1.1"
description = "iniconfig: brain-dead simple config-ini parsing"
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "Jinja2"
version = "3.1.2"
description = "A very fast and expressive template engine."
category = "main"
optional = true
python-versions = ">=3.7"
[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"
category = "main"
optional = false
python-versions = "<4, >=3.5"
[package.dependencies]
aiofiles = "*"
aiohttp = "*"
[package.extras]
test = ["coverage", "pytest"]
[[package]]
name = "markdown-it-py"
version = "2.1.0"
description = "Python port of markdown-it. Markdown parsing, done right!"
category = "main"
optional = true
python-versions = ">=3.7"
[package.dependencies]
mdurl = ">=0.1,<1.0"
[package.extras]
benchmarking = ["psutil", "pytest", "pytest-benchmark (>=3.2,<4.0)"]
code-style = ["pre-commit (==2.6)"]
compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.3.6,<3.4.0)", "mistletoe (>=0.8.1,<0.9.0)", "mistune (>=2.0.2,<2.1.0)", "panflute (>=2.1.3,<2.2.0)"]
linkify = ["linkify-it-py (>=1.0,<2.0)"]
plugins = ["mdit-py-plugins"]
profiling = ["gprof2dot"]
rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
[[package]]
name = "MarkupSafe"
version = "2.1.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = true
python-versions = ">=3.7"
[[package]]
name = "mdit-py-plugins"
version = "0.3.1"
description = "Collection of plugins for markdown-it-py"
category = "main"
optional = true
python-versions = ">=3.7"
[package.dependencies]
markdown-it-py = ">=1.0.0,<3.0.0"
[package.extras]
code-style = ["pre-commit"]
rtd = ["attrs", "myst-parser (>=0.16.1,<0.17.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"]
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
[[package]]
name = "mdurl"
version = "0.1.2"
description = "Markdown URL utilities"
category = "main"
optional = true
python-versions = ">=3.7"
[[package]]
name = "mock"
version = "5.0.1"
description = "Rolling backport of unittest.mock for all Pythons"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.extras]
build = ["blurb", "twine", "wheel"]
docs = ["sphinx"]
test = ["pytest", "pytest-cov"]
[[package]]
name = "multidict"
version = "6.0.4"
description = "multidict implementation"
category = "main"
optional = false
python-versions = ">=3.7"
[[package]]
name = "myst-parser"
version = "0.18.1"
description = "An extended commonmark compliant parser, with bridges to docutils & sphinx."
category = "main"
optional = true
python-versions = ">=3.7"
[package.dependencies]
docutils = ">=0.15,<0.20"
jinja2 = "*"
markdown-it-py = ">=1.0.0,<3.0.0"
mdit-py-plugins = ">=0.3.1,<0.4.0"
pyyaml = "*"
sphinx = ">=4,<6"
typing-extensions = "*"
[package.extras]
code-style = ["pre-commit (>=2.12,<3.0)"]
linkify = ["linkify-it-py (>=1.0,<2.0)"]
rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"]
testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx (<5.2)", "sphinx-pytest"]
[[package]]
name = "packaging"
version = "21.3"
description = "Core utilities for Python packages"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]]
name = "pluggy"
version = "1.0.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "py"
version = "1.11.0"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "Pygments"
version = "2.13.0"
description = "Pygments is a syntax highlighting package written in Python."
category = "main"
optional = true
python-versions = ">=3.6"
[package.extras]
plugins = ["importlib-metadata"]
[[package]]
name = "pyobjc-core"
version = "8.5.1"
description = "Python<->ObjC Interoperability Module"
category = "main"
optional = false
python-versions = ">=3.6"
[[package]]
name = "pyobjc-framework-Cocoa"
version = "8.5.1"
description = "Wrappers for the Cocoa frameworks on macOS"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
pyobjc-core = ">=8.5.1"
[[package]]
name = "pyobjc-framework-CoreBluetooth"
version = "8.5.1"
description = "Wrappers for the framework CoreBluetooth on macOS"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
pyobjc-core = ">=8.5.1"
pyobjc-framework-Cocoa = ">=8.5.1"
[[package]]
name = "pyobjc-framework-libdispatch"
version = "8.5.1"
description = "Wrappers for libdispatch on macOS"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
pyobjc-core = ">=8.5.1"
[[package]]
name = "pyparsing"
version = "3.0.9"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
category = "main"
optional = false
python-versions = ">=3.6.8"
[package.extras]
diagrams = ["jinja2", "railroad-diagrams"]
[[package]]
name = "pytest"
version = "7.1.3"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.dependencies]
attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<2.0"
py = ">=1.8.2"
tomli = ">=1.0.0"
[package.extras]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
[[package]]
name = "pytest-asyncio"
version = "0.20.3"
description = "Pytest support for asyncio"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.dependencies]
pytest = ">=6.1.0"
[package.extras]
docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
[[package]]
name = "pytest-cov"
version = "3.0.0"
description = "Pytest plugin for measuring coverage."
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
coverage = {version = ">=5.2.1", extras = ["toml"]}
pytest = ">=4.6"
[package.extras]
testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
[[package]]
name = "pytz"
version = "2022.5"
description = "World timezone definitions, modern and historical"
category = "main"
optional = true
python-versions = "*"
[[package]]
name = "PyYAML"
version = "6.0"
description = "YAML parser and emitter for Python"
category = "main"
optional = true
python-versions = ">=3.6"
[[package]]
name = "requests"
version = "2.28.1"
description = "Python HTTP for Humans."
category = "main"
optional = true
python-versions = ">=3.7, <4"
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<3"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<1.27"
[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.9.1"
description = "Models for storing and converting Sensor Data state"
category = "main"
optional = false
python-versions = ">=3.9,<4.0"
[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."
category = "main"
optional = true
python-versions = "*"
[[package]]
name = "Sphinx"
version = "5.3.0"
description = "Python documentation generator"
category = "main"
optional = true
python-versions = ">=3.6"
[package.dependencies]
alabaster = ">=0.7,<0.8"
babel = ">=2.9"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
docutils = ">=0.14,<0.20"
imagesize = ">=1.3"
importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""}
Jinja2 = ">=3.0"
packaging = ">=21.0"
Pygments = ">=2.12"
requests = ">=2.5.0"
snowballstemmer = ">=2.0"
sphinxcontrib-applehelp = "*"
sphinxcontrib-devhelp = "*"
sphinxcontrib-htmlhelp = ">=2.0.0"
sphinxcontrib-jsmath = "*"
sphinxcontrib-qthelp = "*"
sphinxcontrib-serializinghtml = ">=1.1.5"
[package.extras]
docs = ["sphinxcontrib-websupport"]
lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"]
test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
[[package]]
name = "sphinx-rtd-theme"
version = "1.0.0"
description = "Read the Docs theme for Sphinx"
category = "main"
optional = true
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
[package.dependencies]
docutils = "<0.18"
sphinx = ">=1.6"
[package.extras]
dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client"]
[[package]]
name = "sphinxcontrib-applehelp"
version = "1.0.2"
description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books"
category = "main"
optional = true
python-versions = ">=3.5"
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
test = ["pytest"]
[[package]]
name = "sphinxcontrib-devhelp"
version = "1.0.2"
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
category = "main"
optional = true
python-versions = ">=3.5"
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
test = ["pytest"]
[[package]]
name = "sphinxcontrib-htmlhelp"
version = "2.0.0"
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
category = "main"
optional = true
python-versions = ">=3.6"
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
test = ["html5lib", "pytest"]
[[package]]
name = "sphinxcontrib-jsmath"
version = "1.0.1"
description = "A sphinx extension which renders display math in HTML via JavaScript"
category = "main"
optional = true
python-versions = ">=3.5"
[package.extras]
test = ["flake8", "mypy", "pytest"]
[[package]]
name = "sphinxcontrib-qthelp"
version = "1.0.3"
description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
category = "main"
optional = true
python-versions = ">=3.5"
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
test = ["pytest"]
[[package]]
name = "sphinxcontrib-serializinghtml"
version = "1.1.5"
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
category = "main"
optional = true
python-versions = ">=3.5"
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
test = ["pytest"]
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
category = "dev"
optional = false
python-versions = ">=3.7"
[[package]]
name = "typing-extensions"
version = "4.4.0"
description = "Backported and Experimental Type Hints for Python 3.7+"
category = "main"
optional = true
python-versions = ">=3.7"
[[package]]
name = "urllib3"
version = "1.26.12"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4"
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "usb-devices"
version = "0.4.1"
description = "Tools for mapping, describing, and resetting USB devices"
category = "main"
optional = false
python-versions = ">=3.9,<4.0"
[[package]]
name = "yarl"
version = "1.8.2"
description = "Yet another URL library"
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
idna = ">=2.0"
multidict = ">=4.0"
[[package]]
name = "zipp"
version = "3.10.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "main"
optional = true
python-versions = ">=3.7"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
[extras]
docs = ["myst-parser", "Sphinx", "sphinx-rtd-theme"]
[metadata]
lock-version = "1.1"
python-versions = "^3.9"
content-hash = "e31ea1212dbfe96ae75f5ceef1c6b02b27278fa79a92df75922cd38d92f820fe"
[metadata.files]
aiofiles = [
{file = "aiofiles-22.1.0-py3-none-any.whl", hash = "sha256:1142fa8e80dbae46bb6339573ad4c8c0841358f79c6eb50a493dceca14621bad"},
{file = "aiofiles-22.1.0.tar.gz", hash = "sha256:9107f1ca0b2a5553987a94a3c9959fe5b491fdf731389aa5b7b1bd0733e32de6"},
]
aiohttp = [
{file = "aiohttp-3.8.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ba71c9b4dcbb16212f334126cc3d8beb6af377f6703d9dc2d9fb3874fd667ee9"},
{file = "aiohttp-3.8.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d24b8bb40d5c61ef2d9b6a8f4528c2f17f1c5d2d31fed62ec860f6006142e83e"},
{file = "aiohttp-3.8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f88df3a83cf9df566f171adba39d5bd52814ac0b94778d2448652fc77f9eb491"},
{file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97decbb3372d4b69e4d4c8117f44632551c692bb1361b356a02b97b69e18a62"},
{file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:309aa21c1d54b8ef0723181d430347d7452daaff93e8e2363db8e75c72c2fb2d"},
{file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad5383a67514e8e76906a06741febd9126fc7c7ff0f599d6fcce3e82b80d026f"},
{file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20acae4f268317bb975671e375493dbdbc67cddb5f6c71eebdb85b34444ac46b"},
{file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05a3c31c6d7cd08c149e50dc7aa2568317f5844acd745621983380597f027a18"},
{file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d6f76310355e9fae637c3162936e9504b4767d5c52ca268331e2756e54fd4ca5"},
{file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:256deb4b29fe5e47893fa32e1de2d73c3afe7407738bd3c63829874661d4822d"},
{file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5c59fcd80b9049b49acd29bd3598cada4afc8d8d69bd4160cd613246912535d7"},
{file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:059a91e88f2c00fe40aed9031b3606c3f311414f86a90d696dd982e7aec48142"},
{file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2feebbb6074cdbd1ac276dbd737b40e890a1361b3cc30b74ac2f5e24aab41f7b"},
{file = "aiohttp-3.8.3-cp310-cp310-win32.whl", hash = "sha256:5bf651afd22d5f0c4be16cf39d0482ea494f5c88f03e75e5fef3a85177fecdeb"},
{file = "aiohttp-3.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:653acc3880459f82a65e27bd6526e47ddf19e643457d36a2250b85b41a564715"},
{file = "aiohttp-3.8.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:86fc24e58ecb32aee09f864cb11bb91bc4c1086615001647dbfc4dc8c32f4008"},
{file = "aiohttp-3.8.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75e14eac916f024305db517e00a9252714fce0abcb10ad327fb6dcdc0d060f1d"},
{file = "aiohttp-3.8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d1fde0f44029e02d02d3993ad55ce93ead9bb9b15c6b7ccd580f90bd7e3de476"},
{file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ab94426ddb1ecc6a0b601d832d5d9d421820989b8caa929114811369673235c"},
{file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89d2e02167fa95172c017732ed7725bc8523c598757f08d13c5acca308e1a061"},
{file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:02f9a2c72fc95d59b881cf38a4b2be9381b9527f9d328771e90f72ac76f31ad8"},
{file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c7149272fb5834fc186328e2c1fa01dda3e1fa940ce18fded6d412e8f2cf76d"},
{file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:512bd5ab136b8dc0ffe3fdf2dfb0c4b4f49c8577f6cae55dca862cd37a4564e2"},
{file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7018ecc5fe97027214556afbc7c502fbd718d0740e87eb1217b17efd05b3d276"},
{file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88c70ed9da9963d5496d38320160e8eb7e5f1886f9290475a881db12f351ab5d"},
{file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:da22885266bbfb3f78218dc40205fed2671909fbd0720aedba39b4515c038091"},
{file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:e65bc19919c910127c06759a63747ebe14f386cda573d95bcc62b427ca1afc73"},
{file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:08c78317e950e0762c2983f4dd58dc5e6c9ff75c8a0efeae299d363d439c8e34"},
{file = "aiohttp-3.8.3-cp311-cp311-win32.whl", hash = "sha256:45d88b016c849d74ebc6f2b6e8bc17cabf26e7e40c0661ddd8fae4c00f015697"},
{file = "aiohttp-3.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:96372fc29471646b9b106ee918c8eeb4cca423fcbf9a34daa1b93767a88a2290"},
{file = "aiohttp-3.8.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c971bf3786b5fad82ce5ad570dc6ee420f5b12527157929e830f51c55dc8af77"},
{file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff25f48fc8e623d95eca0670b8cc1469a83783c924a602e0fbd47363bb54aaca"},
{file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e381581b37db1db7597b62a2e6b8b57c3deec95d93b6d6407c5b61ddc98aca6d"},
{file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db19d60d846283ee275d0416e2a23493f4e6b6028825b51290ac05afc87a6f97"},
{file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25892c92bee6d9449ffac82c2fe257f3a6f297792cdb18ad784737d61e7a9a85"},
{file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:398701865e7a9565d49189f6c90868efaca21be65c725fc87fc305906be915da"},
{file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4a4fbc769ea9b6bd97f4ad0b430a6807f92f0e5eb020f1e42ece59f3ecfc4585"},
{file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:b29bfd650ed8e148f9c515474a6ef0ba1090b7a8faeee26b74a8ff3b33617502"},
{file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:1e56b9cafcd6531bab5d9b2e890bb4937f4165109fe98e2b98ef0dcfcb06ee9d"},
{file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ec40170327d4a404b0d91855d41bfe1fe4b699222b2b93e3d833a27330a87a6d"},
{file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2df5f139233060578d8c2c975128fb231a89ca0a462b35d4b5fcf7c501ebdbe1"},
{file = "aiohttp-3.8.3-cp36-cp36m-win32.whl", hash = "sha256:f973157ffeab5459eefe7b97a804987876dd0a55570b8fa56b4e1954bf11329b"},
{file = "aiohttp-3.8.3-cp36-cp36m-win_amd64.whl", hash = "sha256:437399385f2abcd634865705bdc180c8314124b98299d54fe1d4c8990f2f9494"},
{file = "aiohttp-3.8.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:09e28f572b21642128ef31f4e8372adb6888846f32fecb288c8b0457597ba61a"},
{file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f3553510abdbec67c043ca85727396ceed1272eef029b050677046d3387be8d"},
{file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e168a7560b7c61342ae0412997b069753f27ac4862ec7867eff74f0fe4ea2ad9"},
{file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db4c979b0b3e0fa7e9e69ecd11b2b3174c6963cebadeecfb7ad24532ffcdd11a"},
{file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e164e0a98e92d06da343d17d4e9c4da4654f4a4588a20d6c73548a29f176abe2"},
{file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8a78079d9a39ca9ca99a8b0ac2fdc0c4d25fc80c8a8a82e5c8211509c523363"},
{file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:21b30885a63c3f4ff5b77a5d6caf008b037cb521a5f33eab445dc566f6d092cc"},
{file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4b0f30372cef3fdc262f33d06e7b411cd59058ce9174ef159ad938c4a34a89da"},
{file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:8135fa153a20d82ffb64f70a1b5c2738684afa197839b34cc3e3c72fa88d302c"},
{file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ad61a9639792fd790523ba072c0555cd6be5a0baf03a49a5dd8cfcf20d56df48"},
{file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:978b046ca728073070e9abc074b6299ebf3501e8dee5e26efacb13cec2b2dea0"},
{file = "aiohttp-3.8.3-cp37-cp37m-win32.whl", hash = "sha256:0d2c6d8c6872df4a6ec37d2ede71eff62395b9e337b4e18efd2177de883a5033"},
{file = "aiohttp-3.8.3-cp37-cp37m-win_amd64.whl", hash = "sha256:21d69797eb951f155026651f7e9362877334508d39c2fc37bd04ff55b2007091"},
{file = "aiohttp-3.8.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ca9af5f8f5812d475c5259393f52d712f6d5f0d7fdad9acdb1107dd9e3cb7eb"},
{file = "aiohttp-3.8.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d90043c1882067f1bd26196d5d2db9aa6d268def3293ed5fb317e13c9413ea4"},
{file = "aiohttp-3.8.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d737fc67b9a970f3234754974531dc9afeea11c70791dcb7db53b0cf81b79784"},
{file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebf909ea0a3fc9596e40d55d8000702a85e27fd578ff41a5500f68f20fd32e6c"},
{file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5835f258ca9f7c455493a57ee707b76d2d9634d84d5d7f62e77be984ea80b849"},
{file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da37dcfbf4b7f45d80ee386a5f81122501ec75672f475da34784196690762f4b"},
{file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87f44875f2804bc0511a69ce44a9595d5944837a62caecc8490bbdb0e18b1342"},
{file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:527b3b87b24844ea7865284aabfab08eb0faf599b385b03c2aa91fc6edd6e4b6"},
{file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5ba88df9aa5e2f806650fcbeedbe4f6e8736e92fc0e73b0400538fd25a4dd96"},
{file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e7b8813be97cab8cb52b1375f41f8e6804f6507fe4660152e8ca5c48f0436017"},
{file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:2dea10edfa1a54098703cb7acaa665c07b4e7568472a47f4e64e6319d3821ccf"},
{file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:713d22cd9643ba9025d33c4af43943c7a1eb8547729228de18d3e02e278472b6"},
{file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2d252771fc85e0cf8da0b823157962d70639e63cb9b578b1dec9868dd1f4f937"},
{file = "aiohttp-3.8.3-cp38-cp38-win32.whl", hash = "sha256:66bd5f950344fb2b3dbdd421aaa4e84f4411a1a13fca3aeb2bcbe667f80c9f76"},
{file = "aiohttp-3.8.3-cp38-cp38-win_amd64.whl", hash = "sha256:84b14f36e85295fe69c6b9789b51a0903b774046d5f7df538176516c3e422446"},
{file = "aiohttp-3.8.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16c121ba0b1ec2b44b73e3a8a171c4f999b33929cd2397124a8c7fcfc8cd9e06"},
{file = "aiohttp-3.8.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8d6aaa4e7155afaf994d7924eb290abbe81a6905b303d8cb61310a2aba1c68ba"},
{file = "aiohttp-3.8.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43046a319664a04b146f81b40e1545d4c8ac7b7dd04c47e40bf09f65f2437346"},
{file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:599418aaaf88a6d02a8c515e656f6faf3d10618d3dd95866eb4436520096c84b"},
{file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92a2964319d359f494f16011e23434f6f8ef0434acd3cf154a6b7bec511e2fb7"},
{file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73a4131962e6d91109bca6536416aa067cf6c4efb871975df734f8d2fd821b37"},
{file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598adde339d2cf7d67beaccda3f2ce7c57b3b412702f29c946708f69cf8222aa"},
{file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75880ed07be39beff1881d81e4a907cafb802f306efd6d2d15f2b3c69935f6fb"},
{file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0239da9fbafd9ff82fd67c16704a7d1bccf0d107a300e790587ad05547681c8"},
{file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4e3a23ec214e95c9fe85a58470b660efe6534b83e6cbe38b3ed52b053d7cb6ad"},
{file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:47841407cc89a4b80b0c52276f3cc8138bbbfba4b179ee3acbd7d77ae33f7ac4"},
{file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:54d107c89a3ebcd13228278d68f1436d3f33f2dd2af5415e3feaeb1156e1a62c"},
{file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c37c5cce780349d4d51739ae682dec63573847a2a8dcb44381b174c3d9c8d403"},
{file = "aiohttp-3.8.3-cp39-cp39-win32.whl", hash = "sha256:f178d2aadf0166be4df834c4953da2d7eef24719e8aec9a65289483eeea9d618"},
{file = "aiohttp-3.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:88e5be56c231981428f4f506c68b6a46fa25c4123a2e86d156c58a8369d31ab7"},
{file = "aiohttp-3.8.3.tar.gz", hash = "sha256:3828fb41b7203176b82fe5d699e0d845435f2374750a44b480ea6b930f6be269"},
]
aiosignal = [
{file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
{file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
]
alabaster = [
{file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"},
{file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
]
async-timeout = [
{file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"},
{file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"},
]
attrs = [
{file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"},
{file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"},
]
Babel = [
{file = "Babel-2.10.3-py3-none-any.whl", hash = "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb"},
{file = "Babel-2.10.3.tar.gz", hash = "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51"},
]
bleak = [
{file = "bleak-0.19.5-py3-none-any.whl", hash = "sha256:31e92e6754379bb394b8544457c77ce09a8a7dbc5f9adf3119b34576c901ef1e"},
{file = "bleak-0.19.5.tar.gz", hash = "sha256:87845a96453c58c19031c735444a7b3156800534bcd3f23ba74e119e9ae3cd88"},
]
bleak-retry-connector = [
{file = "bleak_retry_connector-2.13.0-py3-none-any.whl", hash = "sha256:5c8f3fd560eaba1e10659d30a938a51ad94da8f2c9bcf3aeb9ecf9a2149fa8c3"},
{file = "bleak_retry_connector-2.13.0.tar.gz", hash = "sha256:980c373e24d51a8390a4e25afd4f124b9d0ba52cc72c6cc6297a8817dcbcfdf6"},
]
bleak-winrt = [
{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"},
]
bluetooth-adapters = [
{file = "bluetooth_adapters-0.15.2-py3-none-any.whl", hash = "sha256:6633ac7e654e48731b85daab24e304f5644e3410bfe3cbbab5bae45443fa93d1"},
{file = "bluetooth_adapters-0.15.2.tar.gz", hash = "sha256:472c3818fe1e3abd13080a1ee0ac8e92a9b8e5bd7bf4e4bb0204cdefe9cb7149"},
]
bluetooth-data-tools = [
{file = "bluetooth-data-tools-0.1.2.tar.gz", hash = "sha256:58eb956e05d3a92b805af6374d10bf32f0b606c24bf47bb34578edc92aa71aa1"},
{file = "bluetooth_data_tools-0.1.2-py3-none-any.whl", hash = "sha256:72cfd910d6231bb2c43c24e0013265a0fee63c99af9755fed8ed0d7f12d21f61"},
]
bluetooth-sensor-state-data = [
{file = "bluetooth-sensor-state-data-1.6.0.tar.gz", hash = "sha256:ebd973a0859fd4b3c2204cd9451bbcdc6b01cd792924e9759549476f03cd8762"},
{file = "bluetooth_sensor_state_data-1.6.0-py3-none-any.whl", hash = "sha256:c647f442891fdc02f57fc79d09ab8eb66f5ac7213012b5607755d40bcaec17a9"},
]
certifi = [
{file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"},
{file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"},
]
charset-normalizer = [
{file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"},
{file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"},
]
colorama = [
{file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
]
coverage = [
{file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"},
{file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"},
{file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"},
{file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"},
{file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"},
{file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"},
{file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"},
{file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"},
{file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"},
{file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"},
{file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"},
{file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"},
{file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"},
{file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"},
{file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"},
{file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"},
{file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"},
{file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"},
{file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"},
{file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"},
{file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"},
{file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"},
{file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"},
{file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"},
{file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"},
{file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"},
{file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"},
{file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"},
{file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"},
{file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"},
{file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"},
{file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"},
{file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"},
{file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"},
{file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"},
{file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"},
{file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"},
{file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"},
{file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"},
{file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"},
{file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"},
{file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"},
{file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"},
{file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"},
{file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"},
{file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"},
{file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"},
{file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"},
{file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"},
{file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"},
]
dbus-fast = [
{file = "dbus_fast-1.48.0-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:6c474d4f237d14e8f6de3a9c649ddbd2c79f08c112cf1195b86d53e34cad53fa"},
{file = "dbus_fast-1.48.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74569f7033ccfcd1b6353e2034c88e60d76a705cf263f6d5a5e2b0d5e4ec34f5"},
{file = "dbus_fast-1.48.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9b80514938fc1d029a1bade71d660ad315864d84cccd321279fb37fceb321f97"},
{file = "dbus_fast-1.48.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:989f8865ee357a0db0de0d90e9f0d0c8a81222abb9ce38170acaf1447812f1ba"},
{file = "dbus_fast-1.48.0-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:238f51cb7f82cf8962cfb915017fd15b7f1da09f01b44e98d073281accc62336"},
{file = "dbus_fast-1.48.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6caf05b1b4f2f02cc9be4eb52d984a215759bf9779633ba60d0892f8a1ab0625"},
{file = "dbus_fast-1.48.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e7eafaf562558525474bdf86baa50c606a3da8c5cc56ac0feb897052c58df58d"},
{file = "dbus_fast-1.48.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b5777ed00adc83102bd58d0a49cea8dd5d8dff6bc8fc5f5331439df0b0e93393"},
{file = "dbus_fast-1.48.0-cp37-cp37m-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:5c2d0d5137e1b142793b725db642bbdb69446b0a1dded4447bbd75f81fed1b66"},
{file = "dbus_fast-1.48.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c22ff2a876de16948e73a098e31804ae8b01c1efad3163a5a98dde1d122e81a5"},
{file = "dbus_fast-1.48.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3d72591678851e50a9cde2cce053a11ca40feb261d40b663374d2453902383eb"},
{file = "dbus_fast-1.48.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9a2ecc969b761945d6e475eebe48720e0b83f693d1bcf8d2f78e6962e3b58937"},
{file = "dbus_fast-1.48.0-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:f477d707ee5b92909736ea1fcd307c66aeb5e00367ec761fd0276fcdf9470374"},
{file = "dbus_fast-1.48.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a4037479f9212d27c8f2a4660251e29bec4e2e6e08e0c4bd942796aabd38149"},
{file = "dbus_fast-1.48.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c1039b7c9503c1aae395d55ea85790b38daf6b5c9ba19d5807745ace9ce360c6"},
{file = "dbus_fast-1.48.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:685d0a2eff6fe9324b1cad95e2ae1564e35127a22cec204cc200ca2f8c4f3ea8"},
{file = "dbus_fast-1.48.0-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:4bbc7947ddf9c391a6a0900d45394a0f4686c89e872bdeb8df2b9350c97bc64b"},
{file = "dbus_fast-1.48.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3281915b0e08abb05d13e64800805d96c0ef28f7b5b61c530b453936d562697"},
{file = "dbus_fast-1.48.0-cp39-cp39-manylinux_2_31_x86_64.whl", hash = "sha256:2b5a0412d868a29cf22a89ed435976f3544504139a5124bf97cffd0fba3bd740"},
{file = "dbus_fast-1.48.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b795387f1823f152431c8b647e4c0901797a7b13a82e7dfbf4549d3f1d127b2d"},
{file = "dbus_fast-1.48.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ba7a9df013ffe139d805ddd223e4dce047e4494ccdb6a003054c7e71526b8fa8"},
{file = "dbus_fast-1.48.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:947b5d2c9e8836e81aac4e775b595795b17f7264486ff43caf32a8b2f99fd470"},
{file = "dbus_fast-1.48.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:611efaaa1fa8d7f5cb1dfbbc7e728e8c4d97f1cc15c3165da895dcb79250efbd"},
{file = "dbus_fast-1.48.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:68ca4983a9963c11b16ae4d3817aa078b763eeaa5993f73f017c8d15fa7d0d2b"},
{file = "dbus_fast-1.48.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efacd6041091179e5cce62a21ac686836cdc491ca867e835aebba47f113a1b93"},
{file = "dbus_fast-1.48.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:ac5ae8a1c79e0f06926fd92656a2741de7e428e1f2ca173e0d0aae93597cf460"},
{file = "dbus_fast-1.48.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d7f85e8e6193dbfc4d0a8f26b89600f4ebb3b769590bc88730cfa8a5f346a69"},
{file = "dbus_fast-1.48.0.tar.gz", hash = "sha256:e6fa72ba18dff09f527c4563a16505832cae5d4ee5d3fcc602b1d602f819a4b4"},
]
docutils = [
{file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"},
{file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"},
]
frozenlist = [
{file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"},
{file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"},
{file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"},
{file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"},
{file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"},
{file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"},
{file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"},
{file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"},
{file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"},
{file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"},
{file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"},
{file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"},
{file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"},
{file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"},
{file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"},
{file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"},
{file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"},
{file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"},
{file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"},
{file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"},
{file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"},
{file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"},
{file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"},
{file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"},
{file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"},
{file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"},
{file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"},
{file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"},
{file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"},
{file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"},
{file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"},
{file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"},
{file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"},
{file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"},
{file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"},
{file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"},
{file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"},
{file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"},
{file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"},
{file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"},
{file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"},
{file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"},
{file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"},
{file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"},
{file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"},
{file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"},
{file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"},
{file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"},
{file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"},
{file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"},
{file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"},
{file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"},
{file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"},
{file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"},
{file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"},
{file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"},
{file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"},
{file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"},
{file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"},
{file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"},
{file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"},
{file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"},
{file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"},
{file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"},
{file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"},
{file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"},
{file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"},
{file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"},
{file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"},
{file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"},
{file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"},
{file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"},
{file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"},
{file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"},
]
home-assistant-bluetooth = [
{file = "home_assistant_bluetooth-1.6.0-py3-none-any.whl", hash = "sha256:a39e82f121d0178a7ccde4d09fba84875413ae27625795d1174634639d2a22df"},
{file = "home_assistant_bluetooth-1.6.0.tar.gz", hash = "sha256:82487a7e6bdcf59a703def06b1659c9d7ed1bd8d8742129f5bc198d00360c8c7"},
]
idna = [
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
imagesize = [
{file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
{file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
]
importlib-metadata = [
{file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"},
{file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"},
]
iniconfig = [
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
]
Jinja2 = [
{file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
{file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
]
mac-vendor-lookup = [
{file = "mac_vendor_lookup-0.1.12-py3-none-any.whl", hash = "sha256:aeec6eac01b07e6558d889b51f475a1e1e938e09cab409a069ab6a43b13cba58"},
]
markdown-it-py = [
{file = "markdown-it-py-2.1.0.tar.gz", hash = "sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da"},
{file = "markdown_it_py-2.1.0-py3-none-any.whl", hash = "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27"},
]
MarkupSafe = [
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
{file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
{file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
{file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
{file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
{file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
{file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
{file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
]
mdit-py-plugins = [
{file = "mdit-py-plugins-0.3.1.tar.gz", hash = "sha256:3fc13298497d6e04fe96efdd41281bfe7622152f9caa1815ea99b5c893de9441"},
{file = "mdit_py_plugins-0.3.1-py3-none-any.whl", hash = "sha256:606a7f29cf56dbdfaf914acb21709b8f8ee29d857e8f29dcc33d8cb84c57bfa1"},
]
mdurl = [
{file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
]
mock = [
{file = "mock-5.0.1-py3-none-any.whl", hash = "sha256:c41cfb1e99ba5d341fbcc5308836e7d7c9786d302f995b2c271ce2144dece9eb"},
{file = "mock-5.0.1.tar.gz", hash = "sha256:e3ea505c03babf7977fd21674a69ad328053d414f05e6433c30d8fa14a534a6b"},
]
multidict = [
{file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"},
{file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"},
{file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"},
{file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"},
{file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"},
{file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"},
{file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"},
{file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"},
{file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"},
{file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"},
{file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"},
{file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"},
{file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"},
{file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"},
{file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"},
{file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"},
{file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"},
{file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"},
{file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"},
{file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"},
{file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"},
{file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"},
{file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"},
{file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"},
{file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"},
{file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"},
{file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"},
{file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"},
{file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"},
{file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"},
{file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"},
{file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"},
{file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"},
{file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"},
{file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"},
{file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"},
{file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"},
{file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"},
{file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"},
{file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"},
{file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"},
{file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"},
{file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"},
{file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"},
{file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"},
{file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"},
{file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"},
{file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"},
{file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"},
{file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"},
{file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"},
{file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"},
{file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"},
{file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"},
{file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"},
{file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"},
{file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"},
{file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"},
{file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"},
{file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"},
{file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"},
{file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"},
{file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"},
{file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"},
]
myst-parser = [
{file = "myst-parser-0.18.1.tar.gz", hash = "sha256:79317f4bb2c13053dd6e64f9da1ba1da6cd9c40c8a430c447a7b146a594c246d"},
{file = "myst_parser-0.18.1-py3-none-any.whl", hash = "sha256:61b275b85d9f58aa327f370913ae1bec26ebad372cc99f3ab85c8ec3ee8d9fb8"},
]
packaging = [
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
pluggy = [
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
]
py = [
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
]
Pygments = [
{file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"},
{file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"},
]
pyobjc-core = [
{file = "pyobjc-core-8.5.1.tar.gz", hash = "sha256:f8592a12de076c27006700c4a46164478564fa33d7da41e7cbdd0a3bf9ddbccf"},
{file = "pyobjc_core-8.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b62dcf987cc511188fc2aa5b4d3b9fd895361ea4984380463497ce4b0752ddf4"},
{file = "pyobjc_core-8.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0accc653501a655f66c13f149a1d3d30e6cb65824edf852f7960a00c4f930d5b"},
{file = "pyobjc_core-8.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f82b32affc898e9e5af041c1cecde2c99f2ce160b87df77f678c99f1550a4655"},
{file = "pyobjc_core-8.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f7b2f6b6f3caeb882c658fe0c7098be2e8b79893d84daa8e636cb3e58a07df00"},
{file = "pyobjc_core-8.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:872c0202c911a5a2f1269261c168e36569f6ddac17e5d854ac19e581726570cc"},
{file = "pyobjc_core-8.5.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:21f92e231a4bae7f2d160d065f5afbf5e859a1e37f29d34ac12592205fc8c108"},
{file = "pyobjc_core-8.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:315334dd09781129af6a39641248891c4caa57043901750b0139c6614ce84ec0"},
]
pyobjc-framework-Cocoa = [
{file = "pyobjc-framework-Cocoa-8.5.1.tar.gz", hash = "sha256:9a3de5cdb4644e85daf53f2ed912ef6c16ea5804a9e65552eafe62c2e139eb8c"},
{file = "pyobjc_framework_Cocoa-8.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa572acc2628488a47be8d19f4701fc96fce7377cc4da18316e1e08c3918521a"},
{file = "pyobjc_framework_Cocoa-8.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cb3ae21c8d81b7f02a891088c623cef61bca89bd671eff58c632d2f926b649f3"},
{file = "pyobjc_framework_Cocoa-8.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:88f08f5bd94c66d373d8413c1d08218aff4cff0b586e0cc4249b2284023e7577"},
{file = "pyobjc_framework_Cocoa-8.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:063683b57e4bd88cb0f9631ae65d25ec4eecf427d2fe8d0c578f88da9c896f3f"},
{file = "pyobjc_framework_Cocoa-8.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f8806ddfac40620fb27f185d0f8937e69e330617319ecc2eccf6b9c8451bdd1"},
{file = "pyobjc_framework_Cocoa-8.5.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:7733a9a201df9e0cc2a0cf7bf54d76bd7981cba9b599353b243e3e0c9eefec10"},
{file = "pyobjc_framework_Cocoa-8.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f0ab227f99d3e25dd3db73f8cde0999914a5f0dd6a08600349d25f95eaa0da63"},
]
pyobjc-framework-CoreBluetooth = [
{file = "pyobjc-framework-CoreBluetooth-8.5.1.tar.gz", hash = "sha256:b4f621fc3b5bf289db58e64fd746773b18297f87a0ffc5502de74f69133301c1"},
{file = "pyobjc_framework_CoreBluetooth-8.5.1-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:bc720f2987a4d28dc73b13146e7c104d717100deb75c244da68f1d0849096661"},
{file = "pyobjc_framework_CoreBluetooth-8.5.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2167f22886beb5b3ae69e475e055403f28eab065c49a25e2b98b050b483be799"},
{file = "pyobjc_framework_CoreBluetooth-8.5.1-cp36-abi3-macosx_11_0_universal2.whl", hash = "sha256:aa9587a36eca143701731e8bb6c369148f8cc48c28168d41e7323828e5117f2d"},
]
pyobjc-framework-libdispatch = [
{file = "pyobjc-framework-libdispatch-8.5.1.tar.gz", hash = "sha256:066fb34fceb326307559104d45532ec2c7b55426f9910b70dbefd5d1b8fd530f"},
{file = "pyobjc_framework_libdispatch-8.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a316646ab30ba2a97bc828f8e27e7bb79efdf993d218a9c5118396b4f81dc762"},
{file = "pyobjc_framework_libdispatch-8.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7730a29e4d9c7d8c2e8d9ffb60af0ab6699b2186296d2bff0a2dd54527578bc3"},
{file = "pyobjc_framework_libdispatch-8.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:76208d9d2b0071df2950800495ac0300360bb5f25cbe9ab880b65cb809764979"},
{file = "pyobjc_framework_libdispatch-8.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1ad9aa4773ff1d89bf4385c081824c4f8708b50e3ac2fe0a9d590153242c0f67"},
{file = "pyobjc_framework_libdispatch-8.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:81e1833bd26f15930faba678f9efdffafc79ec04e2ea8b6d1b88cafc0883af97"},
{file = "pyobjc_framework_libdispatch-8.5.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:73226e224436eb6383e7a8a811c90ed597995adb155b4f46d727881a383ac550"},
{file = "pyobjc_framework_libdispatch-8.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d115355ce446fc073c75cedfd7ab0a13958adda8e3a3b1e421e1f1e5f65640da"},
]
pyparsing = [
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
]
pytest = [
{file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"},
{file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"},
]
pytest-asyncio = [
{file = "pytest-asyncio-0.20.3.tar.gz", hash = "sha256:83cbf01169ce3e8eb71c6c278ccb0574d1a7a3bb8eaaf5e50e0ad342afb33b36"},
{file = "pytest_asyncio-0.20.3-py3-none-any.whl", hash = "sha256:f129998b209d04fcc65c96fc85c11e5316738358909a8399e93be553d7656442"},
]
pytest-cov = [
{file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
{file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
]
pytz = [
{file = "pytz-2022.5-py2.py3-none-any.whl", hash = "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22"},
{file = "pytz-2022.5.tar.gz", hash = "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914"},
]
PyYAML = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
{file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
{file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
{file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
{file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
]
requests = [
{file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
{file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
]
sensor-state-data = [
{file = "sensor-state-data-2.9.1.tar.gz", hash = "sha256:510d598d52036cb11966d633cea3bd1d99c57b8dd6ff8bb05a9350e3101aa630"},
{file = "sensor_state_data-2.9.1-py3-none-any.whl", hash = "sha256:e383b6d61f399e460a8e0b03a232225b19841e8aeed0842861b9ae16b9e08383"},
]
snowballstemmer = [
{file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
{file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
]
Sphinx = [
{file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"},
{file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"},
]
sphinx-rtd-theme = [
{file = "sphinx_rtd_theme-1.0.0-py2.py3-none-any.whl", hash = "sha256:4d35a56f4508cfee4c4fb604373ede6feae2a306731d533f409ef5c3496fdbd8"},
{file = "sphinx_rtd_theme-1.0.0.tar.gz", hash = "sha256:eec6d497e4c2195fa0e8b2016b337532b8a699a68bcb22a512870e16925c6a5c"},
]
sphinxcontrib-applehelp = [
{file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"},
{file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"},
]
sphinxcontrib-devhelp = [
{file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
{file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
]
sphinxcontrib-htmlhelp = [
{file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"},
{file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"},
]
sphinxcontrib-jsmath = [
{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"},
]
sphinxcontrib-qthelp = [
{file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
{file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
]
sphinxcontrib-serializinghtml = [
{file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"},
{file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
]
tomli = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
typing-extensions = [
{file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
{file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
]
urllib3 = [
{file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"},
{file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},
]
usb-devices = [
{file = "usb_devices-0.4.1-py3-none-any.whl", hash = "sha256:7a4afd5b7cf2306c8afa52d43bdd8ae9667e32f09e57f12adf048bb490ff3512"},
{file = "usb_devices-0.4.1.tar.gz", hash = "sha256:2ad810ba1fd29817d014fe244179fbd06866b92a3285e2bb3a8442f99a8e47b6"},
]
yarl = [
{file = "yarl-1.8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5"},
{file = "yarl-1.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863"},
{file = "yarl-1.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80"},
{file = "yarl-1.8.2-cp310-cp310-win32.whl", hash = "sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42"},
{file = "yarl-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574"},
{file = "yarl-1.8.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634"},
{file = "yarl-1.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd"},
{file = "yarl-1.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2"},
{file = "yarl-1.8.2-cp311-cp311-win32.whl", hash = "sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b"},
{file = "yarl-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c"},
{file = "yarl-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37"},
{file = "yarl-1.8.2-cp37-cp37m-win32.whl", hash = "sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89"},
{file = "yarl-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5"},
{file = "yarl-1.8.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1"},
{file = "yarl-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918"},
{file = "yarl-1.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946"},
{file = "yarl-1.8.2-cp38-cp38-win32.whl", hash = "sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165"},
{file = "yarl-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f"},
{file = "yarl-1.8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8"},
{file = "yarl-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf"},
{file = "yarl-1.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588"},
{file = "yarl-1.8.2-cp39-cp39-win32.whl", hash = "sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83"},
{file = "yarl-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778"},
{file = "yarl-1.8.2.tar.gz", hash = "sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562"},
]
zipp = [
{file = "zipp-3.10.0-py3-none-any.whl", hash = "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1"},
{file = "zipp-3.10.0.tar.gz", hash = "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"},
]
Bluetooth-Devices-oralb-ble-15e51c6/pyproject.toml 0000664 0000000 0000000 00000004715 14565363351 0022165 0 ustar 00root root 0000000 0000000 [tool.poetry]
name = "oralb-ble"
version = "0.18.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.0", optional = true}
sphinx-rtd-theme = {version = "^1.0", optional = true}
myst-parser = {version = "^0.18", 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 = "^7.0"
pytest-cov = "^3.0"
[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_variable = "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"
Bluetooth-Devices-oralb-ble-15e51c6/renovate.json 0000664 0000000 0000000 00000000101 14565363351 0021750 0 ustar 00root root 0000000 0000000 {
"extends": ["github>browniebroke/renovate-configs:python"]
}
Bluetooth-Devices-oralb-ble-15e51c6/setup.py 0000664 0000000 0000000 00000000357 14565363351 0020761 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")
Bluetooth-Devices-oralb-ble-15e51c6/src/ 0000775 0000000 0000000 00000000000 14565363351 0020031 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/src/oralb_ble/ 0000775 0000000 0000000 00000000000 14565363351 0021752 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/src/oralb_ble/__init__.py 0000664 0000000 0000000 00000001614 14565363351 0024065 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__ = "0.18.0"
__all__ = [
"OralBSensor",
"OralBBinarySensor",
"OralBBluetoothDeviceData",
"BinarySensorDeviceClass",
"BinarySensorValue",
"SensorDescription",
"SensorDeviceInfo",
"DeviceKey",
"SensorUpdate",
"SensorDeviceClass",
"SensorDeviceInfo",
"SensorValue",
"Units",
]
Bluetooth-Devices-oralb-ble-15e51c6/src/oralb_ble/const.py 0000664 0000000 0000000 00000004344 14565363351 0023457 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"
Bluetooth-Devices-oralb-ble-15e51c6/src/oralb_ble/parser.py 0000664 0000000 0000000 00000025560 14565363351 0023630 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()
Bluetooth-Devices-oralb-ble-15e51c6/src/oralb_ble/py.typed 0000664 0000000 0000000 00000000000 14565363351 0023437 0 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/tests/ 0000775 0000000 0000000 00000000000 14565363351 0020404 5 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/tests/__init__.py 0000664 0000000 0000000 00000000000 14565363351 0022503 0 ustar 00root root 0000000 0000000 Bluetooth-Devices-oralb-ble-15e51c6/tests/test_parser.py 0000664 0000000 0000000 00000371731 14565363351 0023325 0 ustar 00root root 0000000 0000000 from unittest import mock
import pytest
from bleak import BLEDevice
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
# 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 = BLEDevice(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)