pax_global_header00006660000000000000000000000064145653633510014525gustar00rootroot0000000000000052 comment=bfe079ea2e0587506792f673f684172318e4d640 Bluetooth-Devices-oralb-ble-15e51c6/000077500000000000000000000000001456536335100172425ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/.all-contributorsrc000066400000000000000000000004601456536335100230730ustar00rootroot00000000000000{ "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/.editorconfig000066400000000000000000000004441456536335100217210ustar00rootroot00000000000000# 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/.flake8000066400000000000000000000000571456536335100204170ustar00rootroot00000000000000[flake8] exclude = docs max-line-length = 2188 Bluetooth-Devices-oralb-ble-15e51c6/.github/000077500000000000000000000000001456536335100206025ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/.github/FUNDING.yml000066400000000000000000000000361456536335100224160ustar00rootroot00000000000000github: ["bluetooth-devices"] Bluetooth-Devices-oralb-ble-15e51c6/.github/ISSUE_TEMPLATE/000077500000000000000000000000001456536335100227655ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/.github/ISSUE_TEMPLATE/1-bug_report.md000066400000000000000000000004221456536335100256130ustar00rootroot00000000000000--- 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.md000066400000000000000000000006721456536335100265740ustar00rootroot00000000000000--- 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.toml000066400000000000000000000035151456536335100227450ustar00rootroot00000000000000[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/000077500000000000000000000000001456536335100226375ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/.github/workflows/ci.yml000066400000000000000000000037461456536335100237670ustar00rootroot00000000000000name: 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.yml000066400000000000000000000005341456536335100262100ustar00rootroot00000000000000name: 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.yml000066400000000000000000000013401456536335100261200ustar00rootroot00000000000000name: 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.yml000066400000000000000000000007741456536335100246340ustar00rootroot00000000000000name: 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/.gitignore000066400000000000000000000040661456536335100212400ustar00rootroot00000000000000# 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.yml000066400000000000000000000003061456536335100213300ustar00rootroot00000000000000tasks: - 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/000077500000000000000000000000001456536335100202225ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/.idea/oralb-ble.iml000066400000000000000000000005151456536335100225650ustar00rootroot00000000000000 Bluetooth-Devices-oralb-ble-15e51c6/.idea/watcherTasks.xml000066400000000000000000000052531456536335100234140ustar00rootroot00000000000000 Bluetooth-Devices-oralb-ble-15e51c6/.idea/workspace.xml000066400000000000000000000027251456536335100227500ustar00rootroot00000000000000 Bluetooth-Devices-oralb-ble-15e51c6/.pre-commit-config.yaml000066400000000000000000000033061456536335100235250ustar00rootroot00000000000000# 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.yml000066400000000000000000000010041456536335100223230ustar00rootroot00000000000000# 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.md000066400000000000000000000202641456536335100210570ustar00rootroot00000000000000# 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.md000066400000000000000000000074221456536335100215000ustar00rootroot00000000000000# 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/LICENSE000066400000000000000000000020601456536335100202450ustar00rootroot00000000000000 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.md000066400000000000000000000066531456536335100205330ustar00rootroot00000000000000# OralB BLE

CI Status Documentation Status Test coverage percentage

Poetry black pre-commit

PyPI Version Supported Python versions License

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.js000066400000000000000000000003641456536335100232260ustar00rootroot00000000000000module.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/000077500000000000000000000000001456536335100201725ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/docs/Makefile000066400000000000000000000011751456536335100216360ustar00rootroot00000000000000# 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.bat000066400000000000000000000013741456536335100216040ustar00rootroot00000000000000@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/000077500000000000000000000000001456536335100214725ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/docs/source/_static/000077500000000000000000000000001456536335100231205ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/docs/source/_static/.gitkeep000066400000000000000000000000001456536335100245370ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/docs/source/changelog.md000066400000000000000000000000451456536335100237420ustar00rootroot00000000000000```{include} ../../CHANGELOG.md ``` Bluetooth-Devices-oralb-ble-15e51c6/docs/source/conf.py000066400000000000000000000036511456536335100227760ustar00rootroot00000000000000# 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.md000066400000000000000000000000501456536335100245160ustar00rootroot00000000000000```{include} ../../CONTRIBUTING.md ``` Bluetooth-Devices-oralb-ble-15e51c6/docs/source/index.md000066400000000000000000000003511456536335100231220ustar00rootroot00000000000000# 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.md000066400000000000000000000002641456536335100245170ustar00rootroot00000000000000# 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.md000066400000000000000000000001371456536335100231210ustar00rootroot00000000000000# Usage To use this package, import it: ```python import oralb_ble ``` TODO: Document usage Bluetooth-Devices-oralb-ble-15e51c6/poetry.lock000066400000000000000000003411751456536335100214510ustar00rootroot00000000000000[[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.toml000066400000000000000000000047151456536335100221650ustar00rootroot00000000000000[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.json000066400000000000000000000001011456536335100217500ustar00rootroot00000000000000{ "extends": ["github>browniebroke/renovate-configs:python"] } Bluetooth-Devices-oralb-ble-15e51c6/setup.py000066400000000000000000000003571456536335100207610ustar00rootroot00000000000000#!/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/000077500000000000000000000000001456536335100200315ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/src/oralb_ble/000077500000000000000000000000001456536335100217525ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/src/oralb_ble/__init__.py000066400000000000000000000016141456536335100240650ustar00rootroot00000000000000"""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.py000066400000000000000000000043441456536335100234570ustar00rootroot00000000000000TIMEOUT_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.py000066400000000000000000000255601456536335100236300ustar00rootroot00000000000000"""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.typed000066400000000000000000000000001456536335100234370ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/tests/000077500000000000000000000000001456536335100204045ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/tests/__init__.py000066400000000000000000000000001456536335100225030ustar00rootroot00000000000000Bluetooth-Devices-oralb-ble-15e51c6/tests/test_parser.py000066400000000000000000003717311456536335100233250ustar00rootroot00000000000000from 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)