pax_global_header 0000666 0000000 0000000 00000000064 14762105017 0014515 g ustar 00root root 0000000 0000000 52 comment=f3d6d8c5f553f1f1b5844baef713971666fece2a
govee-ble-0.43.1/ 0000775 0000000 0000000 00000000000 14762105017 0013447 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/.all-contributorsrc 0000664 0000000 0000000 00000000450 14762105017 0017277 0 ustar 00root root 0000000 0000000 {
"projectName": "govee-ble",
"projectOwner": "bluetooth-devices",
"repoType": "github",
"repoHost": "https://github.com",
"files": ["README.md"],
"imageSize": 80,
"commit": true,
"commitConvention": "angular",
"contributors": [],
"contributorsPerLine": 7,
"skipCi": true
}
govee-ble-0.43.1/.editorconfig 0000664 0000000 0000000 00000000444 14762105017 0016126 0 ustar 00root root 0000000 0000000 # http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = lf
[*.bat]
indent_style = tab
end_of_line = crlf
[LICENSE]
insert_final_newline = false
[Makefile]
indent_style = tab
govee-ble-0.43.1/.flake8 0000664 0000000 0000000 00000000056 14762105017 0014623 0 ustar 00root root 0000000 0000000 [flake8]
exclude = docs
max-line-length = 120
govee-ble-0.43.1/.github/ 0000775 0000000 0000000 00000000000 14762105017 0015007 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 14762105017 0017172 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/.github/ISSUE_TEMPLATE/1-bug_report.md 0000664 0000000 0000000 00000000422 14762105017 0022020 0 ustar 00root root 0000000 0000000 ---
name: Bug report
about: Create a report to help us improve
labels: bug
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
**Additional context**
Add any other context about the problem here.
govee-ble-0.43.1/.github/ISSUE_TEMPLATE/2-feature-request.md 0000664 0000000 0000000 00000000672 14762105017 0023001 0 ustar 00root root 0000000 0000000 ---
name: Feature request
about: Suggest an idea for this project
labels: enhancement
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Additional context**
Add any other context or screenshots about the feature request here.
govee-ble-0.43.1/.github/dependabot.yml 0000664 0000000 0000000 00000001344 14762105017 0017641 0 ustar 00root root 0000000 0000000 # To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
commit-message:
prefix: "chore(ci): "
groups:
github-actions:
patterns:
- "*"
- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
govee-ble-0.43.1/.github/labels.toml 0000664 0000000 0000000 00000003515 14762105017 0017152 0 ustar 00root root 0000000 0000000 [breaking]
color = "ffcc00"
name = "breaking"
description = "Breaking change."
[bug]
color = "d73a4a"
name = "bug"
description = "Something isn't working"
[dependencies]
color = "0366d6"
name = "dependencies"
description = "Pull requests that update a dependency file"
[github_actions]
color = "000000"
name = "github_actions"
description = "Update of github actions"
[documentation]
color = "1bc4a5"
name = "documentation"
description = "Improvements or additions to documentation"
[duplicate]
color = "cfd3d7"
name = "duplicate"
description = "This issue or pull request already exists"
[enhancement]
color = "a2eeef"
name = "enhancement"
description = "New feature or request"
["good first issue"]
color = "7057ff"
name = "good first issue"
description = "Good for newcomers"
["help wanted"]
color = "008672"
name = "help wanted"
description = "Extra attention is needed"
[invalid]
color = "e4e669"
name = "invalid"
description = "This doesn't seem right"
[nochangelog]
color = "555555"
name = "nochangelog"
description = "Exclude pull requests from changelog"
[question]
color = "d876e3"
name = "question"
description = "Further information is requested"
[removed]
color = "e99695"
name = "removed"
description = "Removed piece of functionalities."
[tests]
color = "bfd4f2"
name = "tests"
description = "CI, CD and testing related changes"
[wontfix]
color = "ffffff"
name = "wontfix"
description = "This will not be worked on"
[discussion]
color = "c2e0c6"
name = "discussion"
description = "Some discussion around the project"
[hacktoberfest]
color = "ffa663"
name = "hacktoberfest"
description = "Good issues for Hacktoberfest"
[answered]
color = "0ee2b6"
name = "answered"
description = "Automatically closes as answered after a delay"
[waiting]
color = "5f7972"
name = "waiting"
description = "Automatically closes if no answer after a delay"
govee-ble-0.43.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14762105017 0017044 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/.github/workflows/ci.yml 0000664 0000000 0000000 00000004726 14762105017 0020173 0 ustar 00root root 0000000 0000000 name: CI
on:
push:
branches:
- main
pull_request:
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.9"
- uses: pre-commit/action@v3.0.1
# Make sure commit messages follow the conventional commits convention:
# https://www.conventionalcommits.org
commitlint:
name: Lint Commit Messages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v6
test:
strategy:
fail-fast: false
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
os:
- ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- uses: snok/install-poetry@v1
- name: Install Dependencies
shell: bash
run: poetry install
- name: Test with Pytest
shell: bash
run: poetry run pytest --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
release:
runs-on: ubuntu-latest
environment: release
if: github.ref == 'refs/heads/main'
needs:
- test
- lint
- commitlint
permissions:
id-token: write
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# Run semantic release:
# - Update CHANGELOG.md
# - Update version in code
# - Create git tag
# - Create GitHub release
- name: Python Semantic Release
id: release
uses: python-semantic-release/python-semantic-release@v9.17.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
if: steps.release.outputs.released == 'true'
- name: Upload Github Release Assets
uses: python-semantic-release/publish-action@v9.17.0
if: steps.release.outputs.released == 'true'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ steps.release.outputs.tag }}
govee-ble-0.43.1/.github/workflows/hacktoberfest.yml 0000664 0000000 0000000 00000000534 14762105017 0022415 0 ustar 00root root 0000000 0000000 name: Hacktoberfest
on:
schedule:
# Run every day in October
- cron: "0 0 * 10 *"
# Run on the 1st of November to revert
- cron: "0 13 1 11 *"
jobs:
hacktoberfest:
runs-on: ubuntu-latest
steps:
- uses: browniebroke/hacktoberfest-labeler-action@v2.3.0
with:
github_token: ${{ secrets.GH_PAT }}
govee-ble-0.43.1/.github/workflows/issue-manager.yml 0000664 0000000 0000000 00000001340 14762105017 0022325 0 ustar 00root root 0000000 0000000 name: Issue Manager
on:
schedule:
- cron: "0 0 * * *"
issue_comment:
types:
- created
issues:
types:
- labeled
pull_request_target:
types:
- labeled
workflow_dispatch:
jobs:
issue-manager:
runs-on: ubuntu-latest
steps:
- uses: tiangolo/issue-manager@0.5.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
config: >
{
"answered": {
"message": "Assuming the original issue was solved, it will be automatically closed now."
},
"waiting": {
"message": "Automatically closing. To re-open, please provide the additional information requested."
}
}
govee-ble-0.43.1/.github/workflows/labels.yml 0000664 0000000 0000000 00000000774 14762105017 0021041 0 ustar 00root root 0000000 0000000 name: Sync Github labels
on:
push:
branches:
- main
paths:
- ".github/**"
jobs:
labels:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Install labels
run: pip install labels
- name: Sync config with Github
run: labels -u ${{ github.repository_owner }} -t ${{ secrets.GITHUB_TOKEN }} sync -f .github/labels.toml
govee-ble-0.43.1/.gitignore 0000664 0000000 0000000 00000004066 14762105017 0015445 0 ustar 00root root 0000000 0000000 # Created by .ignore support plugin (hsz.mobi)
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
govee-ble-0.43.1/.gitpod.yml 0000664 0000000 0000000 00000000306 14762105017 0015535 0 ustar 00root root 0000000 0000000 tasks:
- command: |
pip install poetry
PIP_USER=false poetry install
- command: |
pip install pre-commit
pre-commit install
PIP_USER=false pre-commit install-hooks
govee-ble-0.43.1/.idea/ 0000775 0000000 0000000 00000000000 14762105017 0014427 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/.idea/govee-ble.iml 0000664 0000000 0000000 00000000515 14762105017 0017000 0 ustar 00root root 0000000 0000000
govee-ble-0.43.1/.idea/watcherTasks.xml 0000664 0000000 0000000 00000005253 14762105017 0017621 0 ustar 00root root 0000000 0000000
govee-ble-0.43.1/.idea/workspace.xml 0000664 0000000 0000000 00000002725 14762105017 0017155 0 ustar 00root root 0000000 0000000
govee-ble-0.43.1/.pre-commit-config.yaml 0000664 0000000 0000000 00000003141 14762105017 0017727 0 ustar 00root root 0000000 0000000 # See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
exclude: "CHANGELOG.md"
default_stages: [pre-commit]
ci:
autofix_commit_msg: "chore(pre-commit.ci): auto fixes"
autoupdate_commit_msg: "chore(pre-commit.ci): pre-commit autoupdate"
repos:
- repo: https://github.com/commitizen-tools/commitizen
rev: v4.2.1
hooks:
- id: commitizen
stages: [commit-msg]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: debug-statements
- id: check-builtin-literals
- id: check-case-conflict
- id: check-docstring-first
- id: check-json
- id: check-toml
- id: check-xml
- id: check-yaml
- id: detect-private-key
- id: end-of-file-fixer
- id: trailing-whitespace
- id: debug-statements
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v4.0.0-alpha.8
hooks:
- id: prettier
args: ["--tab-width", "2"]
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.1
hooks:
- id: pyupgrade
args: [--py310-plus]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.6
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
- id: codespell
- repo: https://github.com/PyCQA/flake8
rev: 7.1.2
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.15.0
hooks:
- id: mypy
additional_dependencies: []
govee-ble-0.43.1/.readthedocs.yml 0000664 0000000 0000000 00000001004 14762105017 0016530 0 ustar 00root root 0000000 0000000 # Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/source/conf.py
# Set the version of Python and other tools you might need
build:
os: ubuntu-20.04
tools:
python: "3.9"
# Optionally declare the Python requirements required to build your docs
python:
install:
- method: pip
path: .
extra_requirements:
- docs
govee-ble-0.43.1/CHANGELOG.md 0000664 0000000 0000000 00000101170 14762105017 0015260 0 ustar 00root root 0000000 0000000 # CHANGELOG
## v0.43.1 (2025-03-05)
### Bug Fixes
- Change minimum temp to -40 ([#145](https://github.com/Bluetooth-Devices/govee-ble/pull/145),
[`2f7360d`](https://github.com/Bluetooth-Devices/govee-ble/commit/2f7360de826527a2befb4a1942a9176776b6874c))
### Chores
- **ci**: Bump the github-actions group with 8 updates
([#139](https://github.com/Bluetooth-Devices/govee-ble/pull/139),
[`0bfccb1`](https://github.com/Bluetooth-Devices/govee-ble/commit/0bfccb1384eced110c498a3bcade7ea273ebd8d7))
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston
- **pre-commit.ci**: Pre-commit autoupdate
([#141](https://github.com/Bluetooth-Devices/govee-ble/pull/141),
[`0cf81b4`](https://github.com/Bluetooth-Devices/govee-ble/commit/0cf81b46d0dc4b3a384d4928627fada6bea81fe8))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#142](https://github.com/Bluetooth-Devices/govee-ble/pull/142),
[`48e5f0a`](https://github.com/Bluetooth-Devices/govee-ble/commit/48e5f0a0fcac604022bb2748b54b42941bf4cfdc))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
## v0.43.0 (2025-02-06)
### Chores
- Update dependabot.yml to include GHA
([#138](https://github.com/Bluetooth-Devices/govee-ble/pull/138),
[`e83b35d`](https://github.com/Bluetooth-Devices/govee-ble/commit/e83b35dc52dda4b38f0e53f3ef235b358ac47260))
### Features
- Add support for newer 5179 firmware
([#140](https://github.com/Bluetooth-Devices/govee-ble/pull/140),
[`3d0f853`](https://github.com/Bluetooth-Devices/govee-ble/commit/3d0f8535a0ca1b7cf3fa4ed0b7d12c58c776dffb))
## v0.42.1 (2025-02-04)
### Bug Fixes
- Update poetry to v2 + add license to metadata
([#137](https://github.com/Bluetooth-Devices/govee-ble/pull/137),
[`e61a9cb`](https://github.com/Bluetooth-Devices/govee-ble/commit/e61a9cb4903215bfce3dca7efec140b3a21d6d0b))
### Chores
- Add test data from ha issue 110528
([#128](https://github.com/Bluetooth-Devices/govee-ble/pull/128),
[`c5baa25`](https://github.com/Bluetooth-Devices/govee-ble/commit/c5baa253d04f7080de0546779a9abc915eecb8c8))
- Create dependabot.yml
([`3e55779`](https://github.com/Bluetooth-Devices/govee-ble/commit/3e55779b101a24d561544be654c79179a8d8a5ef))
- Update CI for Python 3.13 ([#124](https://github.com/Bluetooth-Devices/govee-ble/pull/124),
[`ddb0195`](https://github.com/Bluetooth-Devices/govee-ble/commit/ddb01959470f98c90c215998ff896e79c07199be))
- Update deps for Python 3.13 ([#125](https://github.com/Bluetooth-Devices/govee-ble/pull/125),
[`0b2ecbb`](https://github.com/Bluetooth-Devices/govee-ble/commit/0b2ecbbb36edc4aa54e4b9aeacb815450953400a))
- **deps**: Bump bluetooth-data-tools from 1.22.0 to 1.23.3
([#135](https://github.com/Bluetooth-Devices/govee-ble/pull/135),
[`fe74840`](https://github.com/Bluetooth-Devices/govee-ble/commit/fe74840c732046f143c825f04ffaa967c6f9af71))
- **deps**: Bump cryptography from 42.0.8 to 44.0.0
([#122](https://github.com/Bluetooth-Devices/govee-ble/pull/122),
[`9ec1fcf`](https://github.com/Bluetooth-Devices/govee-ble/commit/9ec1fcf5d992482cae297cf1f0671e51273c59f4))
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- **deps**: Bump jinja2 from 3.1.4 to 3.1.5
([#123](https://github.com/Bluetooth-Devices/govee-ble/pull/123),
[`9cd5c5c`](https://github.com/Bluetooth-Devices/govee-ble/commit/9cd5c5c6642e4c29f21743222f11f4fef3e5fd83))
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- **deps**: Bump myst-parser from 0.18.1 to 1.0.0
([#119](https://github.com/Bluetooth-Devices/govee-ble/pull/119),
[`9201df8`](https://github.com/Bluetooth-Devices/govee-ble/commit/9201df85046b4b4213ced94ffa5fd5f912efd8b8))
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- **deps**: Bump myst-parser from 1.0.0 to 3.0.1
([#131](https://github.com/Bluetooth-Devices/govee-ble/pull/131),
[`4e70715`](https://github.com/Bluetooth-Devices/govee-ble/commit/4e7071563aa1e9d2f0c18cc85449f80e3dc02bc2))
- **deps**: Bump sphinx from 5.3.0 to 6.2.1
([#126](https://github.com/Bluetooth-Devices/govee-ble/pull/126),
[`4d9a98b`](https://github.com/Bluetooth-Devices/govee-ble/commit/4d9a98b1633dd237f82e5b455098433ec5034845))
- **deps**: Bump sphinx from 6.2.1 to 7.4.7
([#134](https://github.com/Bluetooth-Devices/govee-ble/pull/134),
[`8b32dd7`](https://github.com/Bluetooth-Devices/govee-ble/commit/8b32dd7d69031ffc356f86dbc502a274920ffbf4))
- **deps**: Bump sphinx-rtd-theme from 1.3.0 to 2.0.0
([#120](https://github.com/Bluetooth-Devices/govee-ble/pull/120),
[`ba94d1e`](https://github.com/Bluetooth-Devices/govee-ble/commit/ba94d1eafe9a7cd4eed4440cb9afd39f7996d108))
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- **deps**: Bump sphinx-rtd-theme from 2.0.0 to 3.0.2
([#132](https://github.com/Bluetooth-Devices/govee-ble/pull/132),
[`2288823`](https://github.com/Bluetooth-Devices/govee-ble/commit/22888233d51b777a65195642907de30709dc942f))
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 2.0.0 to 3.0.2. -
[Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) -
[Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/2.0.0...3.0.2)
--- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- **deps-dev**: Bump pytest from 7.4.4 to 8.3.4
([#118](https://github.com/Bluetooth-Devices/govee-ble/pull/118),
[`e94e1fc`](https://github.com/Bluetooth-Devices/govee-ble/commit/e94e1fc854c5b22c0fe9d2ea85aa5c5afb72933d))
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- **deps-dev**: Bump pytest-cov from 3.0.0 to 6.0.0
([#121](https://github.com/Bluetooth-Devices/govee-ble/pull/121),
[`ecbeb28`](https://github.com/Bluetooth-Devices/govee-ble/commit/ecbeb28e3f31f0395cdf24b9c6d908a269663817))
- **pre-commit.ci**: Pre-commit autoupdate
([#127](https://github.com/Bluetooth-Devices/govee-ble/pull/127),
[`90f701c`](https://github.com/Bluetooth-Devices/govee-ble/commit/90f701c6fdeb523a144f174fff8bd5361d1f9adf))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#133](https://github.com/Bluetooth-Devices/govee-ble/pull/133),
[`882ad48`](https://github.com/Bluetooth-Devices/govee-ble/commit/882ad48343050d113bfc8f8d02009bdeaf57337a))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#136](https://github.com/Bluetooth-Devices/govee-ble/pull/136),
[`8b0568f`](https://github.com/Bluetooth-Devices/govee-ble/commit/8b0568fe21e115e8a001771767c6a1f81b89252d))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
### Refactoring
- Reduce duplicate code ([#129](https://github.com/Bluetooth-Devices/govee-ble/pull/129),
[`f265edd`](https://github.com/Bluetooth-Devices/govee-ble/commit/f265edd415371063720e1d027f912b9d16e6fd24))
- Reduce duplicate code ([#130](https://github.com/Bluetooth-Devices/govee-ble/pull/130),
[`e359472`](https://github.com/Bluetooth-Devices/govee-ble/commit/e35947253a35f51603fafbad1f155ab75b936d34))
## v0.42.0 (2025-01-16)
### Features
- Add support for gvh5130 button ([#117](https://github.com/Bluetooth-Devices/govee-ble/pull/117),
[`0d499db`](https://github.com/Bluetooth-Devices/govee-ble/commit/0d499db328c19b2403c5d0089224a3fc46300e56))
## v0.41.0 (2025-01-16)
### Chores
- **pre-commit.ci**: Pre-commit autoupdate
([#103](https://github.com/Bluetooth-Devices/govee-ble/pull/103),
[`c4f1937`](https://github.com/Bluetooth-Devices/govee-ble/commit/c4f19377053fd1213a0e0eaaa675f3850d9faf7b))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#104](https://github.com/Bluetooth-Devices/govee-ble/pull/104),
[`a3e80b5`](https://github.com/Bluetooth-Devices/govee-ble/commit/a3e80b57dc896a7251c64d7e164ce90207fc3951))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#105](https://github.com/Bluetooth-Devices/govee-ble/pull/105),
[`b31d39e`](https://github.com/Bluetooth-Devices/govee-ble/commit/b31d39ece0bb991b1ef92e8fb46ed32ea22e2202))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#106](https://github.com/Bluetooth-Devices/govee-ble/pull/106),
[`be92194`](https://github.com/Bluetooth-Devices/govee-ble/commit/be921949f7162c6ed77421d690ec709f2c511024))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#107](https://github.com/Bluetooth-Devices/govee-ble/pull/107),
[`2b0cb41`](https://github.com/Bluetooth-Devices/govee-ble/commit/2b0cb4162f4419045bfbec9b95f30a8cc4ce70c2))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#108](https://github.com/Bluetooth-Devices/govee-ble/pull/108),
[`1d7da8c`](https://github.com/Bluetooth-Devices/govee-ble/commit/1d7da8c1fc19ad0dd2ed151492a2027780823b6f))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#109](https://github.com/Bluetooth-Devices/govee-ble/pull/109),
[`7c0ccda`](https://github.com/Bluetooth-Devices/govee-ble/commit/7c0ccda3c9c8d661cc3c6cb3b7fca56b3c5fcc99))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#110](https://github.com/Bluetooth-Devices/govee-ble/pull/110),
[`41d2374`](https://github.com/Bluetooth-Devices/govee-ble/commit/41d2374dd29d93dbf3a30ea0158503cf95cc34c2))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#112](https://github.com/Bluetooth-Devices/govee-ble/pull/112),
[`5c0f0c1`](https://github.com/Bluetooth-Devices/govee-ble/commit/5c0f0c1ea3cb49a689a0e9c9c9288d815b0d6a3f))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#113](https://github.com/Bluetooth-Devices/govee-ble/pull/113),
[`4b7d53d`](https://github.com/Bluetooth-Devices/govee-ble/commit/4b7d53dfc674495bbf4126faa3d1f704c69b040f))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#114](https://github.com/Bluetooth-Devices/govee-ble/pull/114),
[`281c20b`](https://github.com/Bluetooth-Devices/govee-ble/commit/281c20b5fc56018aec1d30353794edf1553447d8))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- **pre-commit.ci**: Pre-commit autoupdate
([#115](https://github.com/Bluetooth-Devices/govee-ble/pull/115),
[`1d2dcaf`](https://github.com/Bluetooth-Devices/govee-ble/commit/1d2dcaf28ed11faa6455aded30b5eaae43e5b0ea))
### Features
- Add support for H5130 Pressure sensor
([#116](https://github.com/Bluetooth-Devices/govee-ble/pull/116),
[`5336114`](https://github.com/Bluetooth-Devices/govee-ble/commit/5336114250175ea92217e73d3b5c674e76ffbb2b))
## v0.40.0 (2024-07-24)
### Features
- Add support for h5127 ([#101](https://github.com/Bluetooth-Devices/govee-ble/pull/101),
[`5e84208`](https://github.com/Bluetooth-Devices/govee-ble/commit/5e8420811b07540999bdb8580f13653f2e413a21))
## v0.39.1 (2024-07-24)
### Bug Fixes
- Vibration sensor is on only and should have been an event
([#100](https://github.com/Bluetooth-Devices/govee-ble/pull/100),
[`142e7c5`](https://github.com/Bluetooth-Devices/govee-ble/commit/142e7c50bb6db8cdf3f9818c85645280b0bb25fc))
## v0.39.0 (2024-07-24)
### Chores
- **pre-commit.ci**: Pre-commit autoupdate
([#98](https://github.com/Bluetooth-Devices/govee-ble/pull/98),
[`69daf5f`](https://github.com/Bluetooth-Devices/govee-ble/commit/69daf5f24e6f30469eb020f43866f49394a2ba50))
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
### Features
- Add support for h5124 vibration sensors
([#99](https://github.com/Bluetooth-Devices/govee-ble/pull/99),
[`d88ffd6`](https://github.com/Bluetooth-Devices/govee-ble/commit/d88ffd62e0089b87831ed10b00782a642eca253e))
## v0.38.0 (2024-07-17)
### Features
- Add support for binary sensors ([#97](https://github.com/Bluetooth-Devices/govee-ble/pull/97),
[`ab22cdb`](https://github.com/Bluetooth-Devices/govee-ble/commit/ab22cdbc291ee95ad107003dad1d7ec001e1f63b))
## v0.37.0 (2024-07-16)
### Features
- Add support for sleepy devices ([#96](https://github.com/Bluetooth-Devices/govee-ble/pull/96),
[`bbe36fa`](https://github.com/Bluetooth-Devices/govee-ble/commit/bbe36fa862f022c5f0f47f42cbfddb3fe92f19a3))
## v0.36.1 (2024-07-16)
### Bug Fixes
- Handle model not yet set ([#95](https://github.com/Bluetooth-Devices/govee-ble/pull/95),
[`2083a01`](https://github.com/Bluetooth-Devices/govee-ble/commit/2083a01ecb102e1c9dd2292b898c22da8695b1d3))
## v0.36.0 (2024-07-16)
### Features
- Expose ModelInfo ([#94](https://github.com/Bluetooth-Devices/govee-ble/pull/94),
[`9111e16`](https://github.com/Bluetooth-Devices/govee-ble/commit/9111e16a6385258dd11b9756c2ed4d2cbdd7c50a))
## v0.35.1 (2024-07-16)
### Bug Fixes
- Handle remote discovered first ([#93](https://github.com/Bluetooth-Devices/govee-ble/pull/93),
[`ae375f6`](https://github.com/Bluetooth-Devices/govee-ble/commit/ae375f627d66fa505727f6da9388fd94b138b2be))
## v0.35.0 (2024-07-16)
### Features
- Refactor to support get_model_info for offline devices
([#92](https://github.com/Bluetooth-Devices/govee-ble/pull/92),
[`a12d139`](https://github.com/Bluetooth-Devices/govee-ble/commit/a12d139cd29b73bd17225958f13b534425f4f7e1))
## v0.34.0 (2024-07-16)
### Features
- Add sensor type and button count ([#91](https://github.com/Bluetooth-Devices/govee-ble/pull/91),
[`747dcb0`](https://github.com/Bluetooth-Devices/govee-ble/commit/747dcb091c2ff2234d2d3eccc39f551a09d5a878))
## v0.33.1 (2024-07-16)
### Bug Fixes
- Remove unused device id code ([#90](https://github.com/Bluetooth-Devices/govee-ble/pull/90),
[`a071f2e`](https://github.com/Bluetooth-Devices/govee-ble/commit/a071f2ecfd7b14d504cfdaee46e289e530383008))
## v0.33.0 (2024-07-16)
### Features
- Add passive support for GV5121/GV5122/GV5123/GV5125/GV5126
([#89](https://github.com/Bluetooth-Devices/govee-ble/pull/89),
[`83ac0d5`](https://github.com/Bluetooth-Devices/govee-ble/commit/83ac0d5950d420e35113c38a58553b413b27c1f8))
## v0.32.0 (2024-07-15)
### Chores
- **pre-commit.ci**: Pre-commit autoupdate
([#87](https://github.com/Bluetooth-Devices/govee-ble/pull/87),
[`d6e3cc4`](https://github.com/Bluetooth-Devices/govee-ble/commit/d6e3cc448e41d031544dbca0ba91f18fc6e76b6c))
* chore(pre-commit.ci): pre-commit autoupdate
updates: - [github.com/commitizen-tools/commitizen: v2.28.0 →
v3.27.0](https://github.com/commitizen-tools/commitizen/compare/v2.28.0...v3.27.0) -
[github.com/pre-commit/pre-commit-hooks: v4.3.0 →
v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.6.0) -
[github.com/pre-commit/mirrors-prettier: v2.7.1 →
v4.0.0-alpha.8](https://github.com/pre-commit/mirrors-prettier/compare/v2.7.1...v4.0.0-alpha.8) -
[github.com/asottile/pyupgrade: v2.37.1 →
v3.16.0](https://github.com/asottile/pyupgrade/compare/v2.37.1...v3.16.0) -
[github.com/PyCQA/isort: 5.12.0 → 5.13.2](https://github.com/PyCQA/isort/compare/5.12.0...5.13.2)
- [github.com/psf/black: 22.6.0 → 24.4.2](https://github.com/psf/black/compare/22.6.0...24.4.2) -
[github.com/codespell-project/codespell: v2.1.0 →
v2.3.0](https://github.com/codespell-project/codespell/compare/v2.1.0...v2.3.0) -
[github.com/PyCQA/flake8: 4.0.1 → 7.1.0](https://github.com/PyCQA/flake8/compare/4.0.1...7.1.0) -
[github.com/pre-commit/mirrors-mypy: v0.931 →
v1.10.1](https://github.com/pre-commit/mirrors-mypy/compare/v0.931...v1.10.1) -
[github.com/PyCQA/bandit: 1.7.4 → 1.7.9](https://github.com/PyCQA/bandit/compare/1.7.4...1.7.9)
* chore(pre-commit.ci): auto fixes
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
### Features
- Add support for GV5121/GV5122/GV5123/GV5125/GV5126
([#88](https://github.com/Bluetooth-Devices/govee-ble/pull/88),
[`e71ca98`](https://github.com/Bluetooth-Devices/govee-ble/commit/e71ca9897fc2de04adeb3c70a5777e52a3588c04))
## v0.31.3 (2024-06-24)
### Bug Fixes
- Fix license classifier ([#86](https://github.com/Bluetooth-Devices/govee-ble/pull/86),
[`88408cf`](https://github.com/Bluetooth-Devices/govee-ble/commit/88408cfe3c6d075718e0fdddbf7fed38c27e59f1))
## v0.31.2 (2024-04-25)
### Bug Fixes
- Ryse smart shades where being detected as an h5106
([#85](https://github.com/Bluetooth-Devices/govee-ble/pull/85),
[`509977f`](https://github.com/Bluetooth-Devices/govee-ble/commit/509977f0c1e309b496ebbae2f2f930b38548f2b0))
### Testing
- Add more 5105 tests ([#84](https://github.com/Bluetooth-Devices/govee-ble/pull/84),
[`94bfe57`](https://github.com/Bluetooth-Devices/govee-ble/commit/94bfe57af1d134805aede008459b7dfeb78e0597))
## v0.31.1 (2024-04-25)
### Bug Fixes
- Show h5075 as h5075 instead of h5075/h5072
([#83](https://github.com/Bluetooth-Devices/govee-ble/pull/83),
[`8fc22f7`](https://github.com/Bluetooth-Devices/govee-ble/commit/8fc22f7e4183341e02c38667ab830c9edeb27cd3))
## v0.31.0 (2024-01-31)
### Features
- Add support for H5108 with external probe
([#82](https://github.com/Bluetooth-Devices/govee-ble/pull/82),
[`46bccd8`](https://github.com/Bluetooth-Devices/govee-ble/commit/46bccd8a487dc736f4e75b6b584d8610e008c306))
## v0.30.0 (2024-01-31)
### Features
- Add support for h5100 ([#81](https://github.com/Bluetooth-Devices/govee-ble/pull/81),
[`00d9581`](https://github.com/Bluetooth-Devices/govee-ble/commit/00d9581bfb766f9ab95d3034afc45e4f9dcaf58f))
## v0.29.0 (2024-01-31)
### Features
- Add support for h5105 ([#80](https://github.com/Bluetooth-Devices/govee-ble/pull/80),
[`d1ab246`](https://github.com/Bluetooth-Devices/govee-ble/commit/d1ab246b766df4775ae1c3534b52b66f8f88e39f))
## v0.28.0 (2024-01-31)
### Features
- Add support for h5103 ([#79](https://github.com/Bluetooth-Devices/govee-ble/pull/79),
[`0c698bb`](https://github.com/Bluetooth-Devices/govee-ble/commit/0c698bbfd3d30233c60fdec0722d41f86904c120))
## v0.27.3 (2024-01-12)
### Bug Fixes
- Ensure H5106 is not detected as a H5101
([#77](https://github.com/Bluetooth-Devices/govee-ble/pull/77),
[`0f847ea`](https://github.com/Bluetooth-Devices/govee-ble/commit/0f847ea83473d5c385664e62ebd4771aa4a8ba82))
## v0.27.2 (2024-01-11)
### Bug Fixes
- Ensure H5106 has a name in passive mode
([#76](https://github.com/Bluetooth-Devices/govee-ble/pull/76),
[`491977e`](https://github.com/Bluetooth-Devices/govee-ble/commit/491977e12363f25fd543e4663e419c9e0c891bcb))
## v0.27.1 (2024-01-11)
### Bug Fixes
- Update sensor state data to fix pm25 in library
([#75](https://github.com/Bluetooth-Devices/govee-ble/pull/75),
[`425d322`](https://github.com/Bluetooth-Devices/govee-ble/commit/425d32230af45990bb5383ee64c8d03a815d64d6))
## v0.27.0 (2024-01-11)
### Features
- Add support for H5106 ([#74](https://github.com/Bluetooth-Devices/govee-ble/pull/74),
[`1466f9d`](https://github.com/Bluetooth-Devices/govee-ble/commit/1466f9d680d6bca900677eda9fcef2c02150c374))
## v0.26.0 (2024-01-10)
### Features
- Add support for 5104 and 5174 ([#73](https://github.com/Bluetooth-Devices/govee-ble/pull/73),
[`ce7e266`](https://github.com/Bluetooth-Devices/govee-ble/commit/ce7e266e27afddc46e607ce8cd08f2a941749f69))
## v0.25.0 (2024-01-10)
### Features
- Add support for H5108 ([#72](https://github.com/Bluetooth-Devices/govee-ble/pull/72),
[`0f52384`](https://github.com/Bluetooth-Devices/govee-ble/commit/0f5238472177402361f3d1a39861c2a9db29307d))
## v0.24.0 (2023-08-11)
### Chores
- Update python-semantic-release ([#67](https://github.com/Bluetooth-Devices/govee-ble/pull/67),
[`082e358`](https://github.com/Bluetooth-Devices/govee-ble/commit/082e35861194395b9539726e466cc7abee529ba1))
### Features
- Add support for govee h5055 ([#66](https://github.com/Bluetooth-Devices/govee-ble/pull/66),
[`badd966`](https://github.com/Bluetooth-Devices/govee-ble/commit/badd966b529225f7ce55e97362e0b3c15be5191a))
## v0.23.0 (2023-02-10)
### Bug Fixes
- Update isort to fix ci ([#62](https://github.com/Bluetooth-Devices/govee-ble/pull/62),
[`9147504`](https://github.com/Bluetooth-Devices/govee-ble/commit/914750424c33fcaa1268d7d36dac1cccd7441ae6))
### Features
- Add low temperature alarm to h5198 ([#61](https://github.com/Bluetooth-Devices/govee-ble/pull/61),
[`d2b8e0f`](https://github.com/Bluetooth-Devices/govee-ble/commit/d2b8e0f5ddc0faa1bd2699439605601c0ca58f08))
## v0.22.0 (2023-01-27)
### Features
- Add govee h5198 ([#60](https://github.com/Bluetooth-Devices/govee-ble/pull/60),
[`821a55d`](https://github.com/Bluetooth-Devices/govee-ble/commit/821a55d1162b9d87e2a7745e9e015b925f7bf816))
## v0.21.1 (2023-01-12)
### Bug Fixes
- Decrease minimum temperature to -30C
([#57](https://github.com/Bluetooth-Devices/govee-ble/pull/57),
[`c41c9b5`](https://github.com/Bluetooth-Devices/govee-ble/commit/c41c9b5858a469e07cbb6b6666f2bdd4f5eee2c8))
Fixes https://github.com/home-assistant/core/issues/85580
## v0.21.0 (2022-12-27)
### Features
- Implement error bit ([#55](https://github.com/Bluetooth-Devices/govee-ble/pull/55),
[`b4b2f82`](https://github.com/Bluetooth-Devices/govee-ble/commit/b4b2f821e8d1dc6e1517ca76d29d124add369eb7))
Fixes https://github.com/Bluetooth-Devices/govee-ble/issues/51
## v0.20.0 (2022-12-19)
### Features
- Log data as hex ([#53](https://github.com/Bluetooth-Devices/govee-ble/pull/53),
[`d014bfc`](https://github.com/Bluetooth-Devices/govee-ble/commit/d014bfc9e1ed278c8fe2f25b469941748bac19cb))
## v0.19.4 (2022-12-18)
### Bug Fixes
- Round temp values ([#52](https://github.com/Bluetooth-Devices/govee-ble/pull/52),
[`e7ec133`](https://github.com/Bluetooth-Devices/govee-ble/commit/e7ec133fa7a884f67b841a5f1f42c7d98946657e))
## v0.19.3 (2022-12-15)
### Bug Fixes
- Reject impossible temp values take 2
([#50](https://github.com/Bluetooth-Devices/govee-ble/pull/50),
[`c0a54eb`](https://github.com/Bluetooth-Devices/govee-ble/commit/c0a54eb3e00afe20bacbb930ea8ce251d760d8bc))
## v0.19.2 (2022-12-15)
### Bug Fixes
- Reject impossible temp values ([#47](https://github.com/Bluetooth-Devices/govee-ble/pull/47),
[`bb8b6e0`](https://github.com/Bluetooth-Devices/govee-ble/commit/bb8b6e00b8c0a2a8779806e6b25330ef50cb41f8))
## v0.19.1 (2022-09-30)
### Bug Fixes
- Handle another H5181 ([#45](https://github.com/Bluetooth-Devices/govee-ble/pull/45),
[`af2da30`](https://github.com/Bluetooth-Devices/govee-ble/commit/af2da30574db19674ec5e76bfaa5c84adcbbe9f0))
## v0.19.0 (2022-09-24)
### Features
- Add support for yet another H5183 variant
([#44](https://github.com/Bluetooth-Devices/govee-ble/pull/44),
[`d699552`](https://github.com/Bluetooth-Devices/govee-ble/commit/d699552bef2c3be13b34899f34e355a54914ffdb))
## v0.18.0 (2022-09-24)
### Features
- Add support for another H5181 variant
([#43](https://github.com/Bluetooth-Devices/govee-ble/pull/43),
[`7738d25`](https://github.com/Bluetooth-Devices/govee-ble/commit/7738d25fe6737a2c41d4d1f7af6e3fa41861ba0e))
## v0.17.3 (2022-09-13)
### Bug Fixes
- Publish ([#41](https://github.com/Bluetooth-Devices/govee-ble/pull/41),
[`40ce706`](https://github.com/Bluetooth-Devices/govee-ble/commit/40ce70653f9cd52eb584253f6893d0f20677d2c7))
## v0.17.2 (2022-09-05)
### Bug Fixes
- Names are now human readable ([#39](https://github.com/Bluetooth-Devices/govee-ble/pull/39),
[`fefc6b4`](https://github.com/Bluetooth-Devices/govee-ble/commit/fefc6b405e62a063234d12c8d812f9581b24369c))
## v0.17.1 (2022-08-31)
### Bug Fixes
- Model H5181 var fixes ([#38](https://github.com/Bluetooth-Devices/govee-ble/pull/38),
[`42012bc`](https://github.com/Bluetooth-Devices/govee-ble/commit/42012bc8be9028c62054a7b143ea990ffeb67deb))
## v0.17.0 (2022-08-30)
### Features
- Add support for additional H5185 firmware
([#37](https://github.com/Bluetooth-Devices/govee-ble/pull/37),
[`0a5dfa5`](https://github.com/Bluetooth-Devices/govee-ble/commit/0a5dfa5e4e95d79f3f9a5e076355963ba75d34be))
## v0.16.1 (2022-08-25)
### Bug Fixes
- Use bluetooth-data-tools short_address
([#36](https://github.com/Bluetooth-Devices/govee-ble/pull/36),
[`e137d93`](https://github.com/Bluetooth-Devices/govee-ble/commit/e137d930d7605a41f7112fd342cfc4bd269dc7da))
## v0.16.0 (2022-08-16)
### Features
- Add support for H5071 ([#34](https://github.com/Bluetooth-Devices/govee-ble/pull/34),
[`cf7e809`](https://github.com/Bluetooth-Devices/govee-ble/commit/cf7e8095c3f15a5d2ccde2cd14cf294edb4ba379))
## v0.15.0 (2022-08-16)
### Features
- Implement rounding ([#33](https://github.com/Bluetooth-Devices/govee-ble/pull/33),
[`eeed1aa`](https://github.com/Bluetooth-Devices/govee-ble/commit/eeed1aa231be0df9f3193511124ca2dfeeeaee51))
## v0.14.1 (2022-08-11)
### Bug Fixes
- Older 5181 firmwares ([#31](https://github.com/Bluetooth-Devices/govee-ble/pull/31),
[`61eac60`](https://github.com/Bluetooth-Devices/govee-ble/commit/61eac6038177b58c07a80882d3cebe9debc25430))
## v0.14.0 (2022-08-08)
### Features
- Add support for the h5052 ([#30](https://github.com/Bluetooth-Devices/govee-ble/pull/30),
[`625594c`](https://github.com/Bluetooth-Devices/govee-ble/commit/625594c16ad67801cf2a57fa2534900e6ef28310))
## v0.13.0 (2022-08-08)
### Features
- Add support for the 5184 devices ([#29](https://github.com/Bluetooth-Devices/govee-ble/pull/29),
[`d9d6d6a`](https://github.com/Bluetooth-Devices/govee-ble/commit/d9d6d6a84e7b7647c829be8471915e15fa61ca0d))
## v0.12.7 (2022-08-07)
### Bug Fixes
- Add 818 to the manufacturer_ids for the gvh5185
([#28](https://github.com/Bluetooth-Devices/govee-ble/pull/28),
[`f3cfb61`](https://github.com/Bluetooth-Devices/govee-ble/commit/f3cfb61c2d562b801570956901f669c27b0d77fb))
## v0.12.6 (2022-08-02)
### Bug Fixes
- The GVH5074 is little endian ([#27](https://github.com/Bluetooth-Devices/govee-ble/pull/27),
[`28e626c`](https://github.com/Bluetooth-Devices/govee-ble/commit/28e626c2527c395c507fbe00e7f18a184a3484f0))
## v0.12.5 (2022-07-30)
### Bug Fixes
- H5179 is little endian and not big endian like the rest
([#26](https://github.com/Bluetooth-Devices/govee-ble/pull/26),
[`24a0e92`](https://github.com/Bluetooth-Devices/govee-ble/commit/24a0e922f32ef476d51d0b13e90a737dfdc83676))
## v0.12.4 (2022-07-29)
### Bug Fixes
- Parser for h5182 had the wrong mfgr_id
([#25](https://github.com/Bluetooth-Devices/govee-ble/pull/25),
[`57abb96`](https://github.com/Bluetooth-Devices/govee-ble/commit/57abb962b32994fe4ec8cb938ad89947838b8294))
## v0.12.3 (2022-07-22)
### Bug Fixes
- Names for bbq devices ([#24](https://github.com/Bluetooth-Devices/govee-ble/pull/24),
[`4407ed4`](https://github.com/Bluetooth-Devices/govee-ble/commit/4407ed431f4280ca77b7a31cd4fa930f878aee77))
## v0.12.2 (2022-07-22)
### Bug Fixes
- Fixs for bbq sensors ([#23](https://github.com/Bluetooth-Devices/govee-ble/pull/23),
[`132d04d`](https://github.com/Bluetooth-Devices/govee-ble/commit/132d04d91fc9161ff1a67a34c9b00c46afb2f708))
## v0.12.1 (2022-07-21)
### Bug Fixes
- Bump sensor-state-data to fix typing
([#22](https://github.com/Bluetooth-Devices/govee-ble/pull/22),
[`d5cdfc5`](https://github.com/Bluetooth-Devices/govee-ble/commit/d5cdfc506abeb4c81bbb0c2d0c7515f7c81266c5))
## v0.12.0 (2022-07-21)
### Features
- Refactor for sensor-state-data 2 ([#21](https://github.com/Bluetooth-Devices/govee-ble/pull/21),
[`b7fb4dc`](https://github.com/Bluetooth-Devices/govee-ble/commit/b7fb4dcef279e1eeb4b53e47e8f684c3a785e3c2))
## v0.11.0 (2022-07-20)
### Features
- Export SensorDescription and SensorValue
([#20](https://github.com/Bluetooth-Devices/govee-ble/pull/20),
[`b61e938`](https://github.com/Bluetooth-Devices/govee-ble/commit/b61e938ce974bf892b2060bc95d6ee808191d1bf))
## v0.10.2 (2022-07-20)
### Bug Fixes
- Bump deps ([#19](https://github.com/Bluetooth-Devices/govee-ble/pull/19),
[`5fc9ece`](https://github.com/Bluetooth-Devices/govee-ble/commit/5fc9ece3d7502bfab84f9f287912f6375549cf49))
## v0.10.1 (2022-07-19)
### Bug Fixes
- Bump libs ([#18](https://github.com/Bluetooth-Devices/govee-ble/pull/18),
[`e818e7c`](https://github.com/Bluetooth-Devices/govee-ble/commit/e818e7c4dc797a571e1d78426f62b940ec60c585))
## v0.10.0 (2022-07-19)
### Features
- Export all needed objects ([#17](https://github.com/Bluetooth-Devices/govee-ble/pull/17),
[`3c5ca7b`](https://github.com/Bluetooth-Devices/govee-ble/commit/3c5ca7b42d20c36bcca650ba15b4b32280751a88))
## v0.9.1 (2022-07-19)
### Bug Fixes
- Add missing device classes to bbq probes
([#16](https://github.com/Bluetooth-Devices/govee-ble/pull/16),
[`f2cafd7`](https://github.com/Bluetooth-Devices/govee-ble/commit/f2cafd71dba9894cb7dc9ab6706bd23b77c61366))
## v0.9.0 (2022-07-19)
### Features
- Set manu for secondary sensor ([#15](https://github.com/Bluetooth-Devices/govee-ble/pull/15),
[`ec54d57`](https://github.com/Bluetooth-Devices/govee-ble/commit/ec54d57f25bdff968d9430421b64a751f1b2ce13))
## v0.8.0 (2022-07-19)
### Features
- Add set_device_manufacturer ([#14](https://github.com/Bluetooth-Devices/govee-ble/pull/14),
[`f0203b7`](https://github.com/Bluetooth-Devices/govee-ble/commit/f0203b7c50753127f298e7d7c6977580dccb8cd4))
## v0.7.0 (2022-07-19)
### Features
- Add support for B5178 local name variation
([#13](https://github.com/Bluetooth-Devices/govee-ble/pull/13),
[`324b3cd`](https://github.com/Bluetooth-Devices/govee-ble/commit/324b3cd99c833496af7427333e591f23d249ec70))
## v0.6.0 (2022-07-19)
### Features
- Do not drop mac from title ([#12](https://github.com/Bluetooth-Devices/govee-ble/pull/12),
[`cd187ed`](https://github.com/Bluetooth-Devices/govee-ble/commit/cd187ed19b0acf5b7b0c3a91dbc0e13fb321cce5))
## v0.5.0 (2022-07-19)
### Features
- Set title for outdoor sensors ([#11](https://github.com/Bluetooth-Devices/govee-ble/pull/11),
[`1031c78`](https://github.com/Bluetooth-Devices/govee-ble/commit/1031c782865e9b6ec74e38df5f3b4a5345d871ce))
## v0.4.1 (2022-07-19)
### Bug Fixes
- Fix device_id for remote sensors ([#10](https://github.com/Bluetooth-Devices/govee-ble/pull/10),
[`198caf2`](https://github.com/Bluetooth-Devices/govee-ble/commit/198caf26a535f070921ee3e24cc66070d64282d2))
## v0.4.0 (2022-07-19)
### Features
- Improve support for remote sensors ([#9](https://github.com/Bluetooth-Devices/govee-ble/pull/9),
[`bf6eca1`](https://github.com/Bluetooth-Devices/govee-ble/commit/bf6eca1d1f64770fd010475afaeeb642c5e175ff))
## v0.3.0 (2022-07-19)
### Features
- Change model ([#8](https://github.com/Bluetooth-Devices/govee-ble/pull/8),
[`9456bb3`](https://github.com/Bluetooth-Devices/govee-ble/commit/9456bb3ec459e9f2e7d7be4e1bfd670e5cb4fed6))
## v0.2.1 (2022-07-19)
### Bug Fixes
- Update sensor-state-data ([#7](https://github.com/Bluetooth-Devices/govee-ble/pull/7),
[`02b04a9`](https://github.com/Bluetooth-Devices/govee-ble/commit/02b04a91d47337dbdd925cc2c7e037500cd934f2))
## v0.2.0 (2022-07-19)
### Features
- Switch to using bluetooth-sensor-state-data
([#6](https://github.com/Bluetooth-Devices/govee-ble/pull/6),
[`8ad3ec5`](https://github.com/Bluetooth-Devices/govee-ble/commit/8ad3ec5f8e7117cf1847be79641b1f706eb9478f))
## v0.1.1 (2022-07-18)
### Bug Fixes
- Fix links ([#5](https://github.com/Bluetooth-Devices/govee-ble/pull/5),
[`455f2d2`](https://github.com/Bluetooth-Devices/govee-ble/commit/455f2d202e80c03bb0e15d1f0385316e3d9dfded))
## v0.1.0 (2022-07-18)
### Bug Fixes
- Fix publish process ([#4](https://github.com/Bluetooth-Devices/govee-ble/pull/4),
[`9c3f892`](https://github.com/Bluetooth-Devices/govee-ble/commit/9c3f89271d1226f05dbe6ec972096c2e822bd2bb))
### Features
- Init repo ([#2](https://github.com/Bluetooth-Devices/govee-ble/pull/2),
[`58fe30c`](https://github.com/Bluetooth-Devices/govee-ble/commit/58fe30ca51b74e3c822bb03e3876eced657915a8))
## v0.0.2 (2022-07-18)
### Bug Fixes
- Bump python min to 3.9
([`5913902`](https://github.com/Bluetooth-Devices/govee-ble/commit/5913902dd854a5e3fc86e290e76fcb8eef9d1804))
### Chores
- Initial commit
([`4b17198`](https://github.com/Bluetooth-Devices/govee-ble/commit/4b171988c2acc563cb05f48c98837be78a1dd656))
govee-ble-0.43.1/CONTRIBUTING.md 0000664 0000000 0000000 00000007422 14762105017 0015705 0 ustar 00root root 0000000 0000000 # Contributing
Contributions are welcome, and they are greatly appreciated! Every little helps, and credit will always be given.
You can contribute in many ways:
## Types of Contributions
### Report Bugs
Report bugs to [our issue page][gh-issues]. If you are reporting a bug, please include:
- Your operating system name and version.
- Any details about your local setup that might be helpful in troubleshooting.
- Detailed steps to reproduce the bug.
### Fix Bugs
Look through the GitHub issues for bugs. Anything tagged with "bug" and "help wanted" is open to whoever wants to implement it.
### Implement Features
Look through the GitHub issues for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it.
### Write Documentation
Govee BLE could always use more documentation, whether as part of the official Govee 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/govee-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/govee-ble/issues
govee-ble-0.43.1/LICENSE 0000664 0000000 0000000 00000026121 14762105017 0014456 0 ustar 00root root 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2022 J. Nick Koston
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
govee-ble-0.43.1/README.md 0000664 0000000 0000000 00000006637 14762105017 0014742 0 ustar 00root root 0000000 0000000 # Govee BLE
Manage Govee BLE devices
## Installation
Install this via pip (or your favourite package manager):
`pip install govee-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.
govee-ble-0.43.1/commitlint.config.mjs 0000664 0000000 0000000 00000000362 14762105017 0017606 0 ustar 00root root 0000000 0000000 export default {
extends: ["@commitlint/config-conventional"],
rules: {
"header-max-length": [0, "always", Infinity],
"body-max-line-length": [0, "always", Infinity],
"footer-max-line-length": [0, "always", Infinity],
},
};
govee-ble-0.43.1/docs/ 0000775 0000000 0000000 00000000000 14762105017 0014377 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/docs/Makefile 0000664 0000000 0000000 00000001175 14762105017 0016043 0 ustar 00root root 0000000 0000000 # Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
govee-ble-0.43.1/docs/make.bat 0000664 0000000 0000000 00000001374 14762105017 0016011 0 ustar 00root root 0000000 0000000 @ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd
govee-ble-0.43.1/docs/source/ 0000775 0000000 0000000 00000000000 14762105017 0015677 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/docs/source/_static/ 0000775 0000000 0000000 00000000000 14762105017 0017325 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/docs/source/_static/.gitkeep 0000664 0000000 0000000 00000000000 14762105017 0020744 0 ustar 00root root 0000000 0000000 govee-ble-0.43.1/docs/source/changelog.md 0000664 0000000 0000000 00000000045 14762105017 0020147 0 ustar 00root root 0000000 0000000 ```{include} ../../CHANGELOG.md
```
govee-ble-0.43.1/docs/source/conf.py 0000664 0000000 0000000 00000003643 14762105017 0017204 0 ustar 00root root 0000000 0000000 # Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
from typing import Any
# -- Project information -----------------------------------------------------
project = "Govee 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"]
govee-ble-0.43.1/docs/source/contributing.md 0000664 0000000 0000000 00000000050 14762105017 0020723 0 ustar 00root root 0000000 0000000 ```{include} ../../CONTRIBUTING.md
```
govee-ble-0.43.1/docs/source/index.md 0000664 0000000 0000000 00000000351 14762105017 0017327 0 ustar 00root root 0000000 0000000 # Welcome to Govee BLE documentation!
```{toctree}
:caption: Installation & Usage
:maxdepth: 2
installation
usage
```
```{toctree}
:caption: Project Info
:maxdepth: 2
changelog
contributing
```
```{include} ../../README.md
```
govee-ble-0.43.1/docs/source/installation.md 0000664 0000000 0000000 00000000264 14762105017 0020724 0 ustar 00root root 0000000 0000000 # Installation
The package is published on [PyPI](https://pypi.org/project/deezer-python/) and can be installed with `pip` (or any equivalent):
```bash
pip install govee-ble
```
govee-ble-0.43.1/docs/source/usage.md 0000664 0000000 0000000 00000000137 14762105017 0017326 0 ustar 00root root 0000000 0000000 # Usage
To use this package, import it:
```python
import govee_ble
```
TODO: Document usage
govee-ble-0.43.1/poetry.lock 0000664 0000000 0000000 00000271767 14762105017 0015667 0 ustar 00root root 0000000 0000000 # This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
[[package]]
name = "alabaster"
version = "0.7.16"
description = "A light, configurable Sphinx theme"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"},
{file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"},
]
[[package]]
name = "babel"
version = "2.16.0"
description = "Internationalization utilities"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
{file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
]
[package.extras]
dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
[[package]]
name = "bluetooth-data-tools"
version = "1.23.3"
description = "Tools for converting bluetooth data and packets"
optional = false
python-versions = "<4.0,>=3.10"
groups = ["main"]
files = [
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d0b26a38536134df408754d51d49a4b4881859a11637f3bec1b59158be5b71f3"},
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0e3df6794fa05ce6c665cee194def280aba0a44a0173af7f13f91916c7cec8"},
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01f4d42a219b224aff2b289bd28eb943100052d82b9fca8aeaeeec2c47f8770c"},
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a3ef21b471ac67d545c014bcf69cb0fbab54e5fd9d03fd800f6780d8a546199"},
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f668dfa76d140d093e0d0505472f0a259b738d8a61adf9d9efc97d3b94f57b04"},
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f17870153350d89091cb934edd60943c43c516bc30ba41b47feeb0ea901332c6"},
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34415696eafdb16e91d6e2bfef751614a7622e0a09c6d02d4999638bca4e994a"},
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-win32.whl", hash = "sha256:f1a74c26a66def85c086944177cccde9590dbb7cb22a0476006ea3876b5c21a7"},
{file = "bluetooth_data_tools-1.23.3-cp310-cp310-win_amd64.whl", hash = "sha256:74d2b252200c7ccce7d9c058ed8ff7f6ae8f908680f88838100d77a48dd2ada5"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3945be46adcb7bee19d80a2a2999d8c57140ff4b78bb04d06e3982b848e41702"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98792d10440fe7d0f6088dc45fe7a72f54a441133fee7f2c76d3e059fe8ed232"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20f8ad2a0d997052efdc3f9de35ad90d8a1b5d3bcad90b76b22ab19838dc102f"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d970a19b259cbdbd7d58da3984ee56b17b692f30fd971f23ff7466331b893033"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9fc427b10a40b775482e5b3a271c06eaa78a71823781b5452779628c4ebd707a"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fdb253aaf1e2d422a0998c0654ab5772b92074acddf8af7dcf26ab0422c44d0f"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cd869561d611a73d8b7a2df8e5089804c0f658c1f32c3203c2b02fa8bd0201aa"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-win32.whl", hash = "sha256:eb32feff75e272397266c2bb12b9b1f2de43acd7ed39a0ebbacf24bc5999ecd8"},
{file = "bluetooth_data_tools-1.23.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae7720975bfe1cdd810d14ba9262fdd3fbcd1ad367ad165cb254ea64f2aac38f"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:980b7710277612cbe78fbf707da007d4d0cbc128438e10dfc979a2bf66371e1b"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18a5327a387a2169ecf6fed5202ba0b2079305c8f298963891f406d99e588c30"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d589fa5b8e963ed9a060e354efbb1bc3190364829571a13920374b43ab96c29"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27c78a12363c6247a11eaee94520d8987058bdd2e818eb7ef9d8083d5f8895dd"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:001b267508156a66f10bd28fbffbf4a6db8e96d4cc31f98c8aec28ba8cda1af7"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:74114aaf9e4d5f807b9fe30fee9539ee507b5ea73750fe008fdd3dc8bad9ec5b"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:761920635d509a0d7298d86e0d0790ee5dc3dd50ad9d0d20e2546d72d61828c1"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-win32.whl", hash = "sha256:043f88dd7588ab480d85cfe00f2344103f15afd3b95b867aed1343d820068b5a"},
{file = "bluetooth_data_tools-1.23.3-cp312-cp312-win_amd64.whl", hash = "sha256:084122193b61b7e6686235b53acce67671b01329a283c35ee582fe0aaca35a53"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fbc72d0d66abd7670346088a7ad1a3dfda4a3aeb3b95b596e08d23bc2cc6c93a"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67c0e003a96a010af0f0ec2059bfbf446d5779b2c55f6bebec4f65aadecb545d"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a30b7f94112162485af21239adf1adf0fdf933ce6e4c5553c864da345fa28c8"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bb95934351c65044e79dbddc3d133302e597594993079458bb7eb8059d80e98"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-manylinux_2_36_x86_64.whl", hash = "sha256:e981cdd2e1f134882ed02291f9c2e9b7703da2196535eafee3896b69ac21525b"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d91ab051a7611e0f7059cac1d889380fc42b1410abfd1281a26105dd7b8c86bd"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:14346088783bce10d06fc110bad5cfc689911bd02c2fa4fc9adcc98b15b6d72c"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:92df35a5e44fb044734581de9ead4e0492470033d3c994c3ad010bfe77734aca"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-win32.whl", hash = "sha256:aa07ab4c83c9d924bd743be44ccaf39a20e9e9acdfa259a21030affb76584ae0"},
{file = "bluetooth_data_tools-1.23.3-cp313-cp313-win_amd64.whl", hash = "sha256:e85d1264a450d17a7cc0c9f296dee4ea11bda2c5be6127c89eda3bf8c12b4d8b"},
{file = "bluetooth_data_tools-1.23.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8adab9594c92f14b09e84cc9d288e2b94848b4e0b09079f5d8b0f3c4ca14f106"},
{file = "bluetooth_data_tools-1.23.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ef7f943c61dba7669b141031981c3bbc02e3b68f849acbf9e4b05741b26a0b1"},
{file = "bluetooth_data_tools-1.23.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23010e342c5615c0809efbfcb8c534baabe2878bf53395ffea7d1ac65fe7b055"},
{file = "bluetooth_data_tools-1.23.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d4505ec373b062c5210e98029baa744a57ad31dd8beac6eb6c7c68942abfb53"},
{file = "bluetooth_data_tools-1.23.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8f0536e2ef90ef530d42eb29b88743a962330322d7125aaad4eb21157917a112"},
{file = "bluetooth_data_tools-1.23.3.tar.gz", hash = "sha256:e953545d72e68ef80439a8c88ab7417bd28cfc2dacdcedda178ec78debb39eb6"},
]
[package.dependencies]
cryptography = ">=41.0.3"
[package.extras]
docs = ["Sphinx (>=5,<9)", "myst-parser (>=0.18,<4.1)", "sphinx-rtd-theme (>=1,<4)"]
[[package]]
name = "bluetooth-sensor-state-data"
version = "1.7.1"
description = "Models for storing and converting Bluetooth Sensor State Data"
optional = false
python-versions = "<4.0,>=3.9"
groups = ["main"]
files = [
{file = "bluetooth_sensor_state_data-1.7.1-py3-none-any.whl", hash = "sha256:65df4b1cd1777a5d2aed9e3e16cf00488f62838d745ae095ebc5ce7f7d7966cd"},
{file = "bluetooth_sensor_state_data-1.7.1.tar.gz", hash = "sha256:6e89909e72b596917b859673cf37eb37500e3cfdca94f08a121fca86bb2e79a4"},
]
[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 = "2024.12.14"
description = "Python package for providing Mozilla's CA Bundle."
optional = true
python-versions = ">=3.6"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"},
{file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"},
]
[[package]]
name = "cffi"
version = "1.17.1"
description = "Foreign Function Interface for Python calling C code."
optional = false
python-versions = ">=3.8"
groups = ["main"]
markers = "platform_python_implementation != \"PyPy\""
files = [
{file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"},
{file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"},
{file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"},
{file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"},
{file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"},
{file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"},
{file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"},
{file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"},
{file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"},
{file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"},
{file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"},
{file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"},
{file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"},
{file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"},
{file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"},
{file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"},
{file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"},
{file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"},
{file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"},
{file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"},
{file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"},
{file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"},
{file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"},
{file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"},
{file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"},
{file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"},
{file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"},
{file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"},
{file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"},
{file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"},
{file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"},
{file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"},
{file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"},
{file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"},
{file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"},
{file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"},
{file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"},
{file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"},
{file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"},
{file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"},
{file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"},
{file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"},
{file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"},
{file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"},
{file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"},
{file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"},
{file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"},
{file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"},
{file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"},
{file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"},
{file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"},
{file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"},
{file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"},
{file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"},
{file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"},
{file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"},
{file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"},
{file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"},
{file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"},
{file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"},
{file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"},
{file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"},
{file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"},
{file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"},
{file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"},
{file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"},
{file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"},
]
[package.dependencies]
pycparser = "*"
[[package]]
name = "charset-normalizer"
version = "3.4.1"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
optional = true
python-versions = ">=3.7"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"},
{file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"},
{file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"},
{file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"},
{file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"},
{file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"},
{file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"},
{file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"},
{file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"},
{file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"},
{file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"},
{file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"},
{file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"},
{file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"},
{file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"},
{file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"},
{file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"},
{file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"},
{file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"},
{file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"},
]
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
groups = ["main", "dev"]
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
markers = {main = "extra == \"docs\" and sys_platform == \"win32\"", dev = "sys_platform == \"win32\""}
[[package]]
name = "coverage"
version = "7.6.10"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
{file = "coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78"},
{file = "coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c"},
{file = "coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a"},
{file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165"},
{file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988"},
{file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5"},
{file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3"},
{file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5"},
{file = "coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244"},
{file = "coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e"},
{file = "coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3"},
{file = "coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43"},
{file = "coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132"},
{file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f"},
{file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994"},
{file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99"},
{file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd"},
{file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377"},
{file = "coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8"},
{file = "coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609"},
{file = "coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853"},
{file = "coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078"},
{file = "coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0"},
{file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50"},
{file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022"},
{file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b"},
{file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0"},
{file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852"},
{file = "coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359"},
{file = "coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247"},
{file = "coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9"},
{file = "coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b"},
{file = "coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690"},
{file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18"},
{file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c"},
{file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd"},
{file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e"},
{file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694"},
{file = "coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6"},
{file = "coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e"},
{file = "coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe"},
{file = "coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273"},
{file = "coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8"},
{file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098"},
{file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb"},
{file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0"},
{file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf"},
{file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2"},
{file = "coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312"},
{file = "coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d"},
{file = "coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a"},
{file = "coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27"},
{file = "coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4"},
{file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f"},
{file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25"},
{file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315"},
{file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90"},
{file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d"},
{file = "coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18"},
{file = "coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59"},
{file = "coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f"},
{file = "coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23"},
]
[package.dependencies]
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
[package.extras]
toml = ["tomli"]
[[package]]
name = "cryptography"
version = "44.0.0"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
python-versions = "!=3.9.0,!=3.9.1,>=3.7"
groups = ["main"]
files = [
{file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"},
{file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"},
{file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"},
{file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"},
{file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"},
{file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"},
{file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"},
{file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"},
{file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"},
{file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"},
{file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"},
{file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"},
{file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"},
{file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"},
{file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"},
{file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"},
{file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"},
{file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"},
{file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"},
{file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"},
{file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"},
{file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"},
{file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"},
{file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"},
{file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"},
{file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"},
{file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"},
]
[package.dependencies]
cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
[package.extras]
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"]
docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"]
nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"]
pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
sdist = ["build (>=1.0.0)"]
ssh = ["bcrypt (>=3.1.5)"]
test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
test-randomorder = ["pytest-randomly"]
[[package]]
name = "docutils"
version = "0.21.2"
description = "Docutils -- Python Documentation Utilities"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"},
{file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"},
]
[[package]]
name = "exceptiongroup"
version = "1.2.2"
description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
groups = ["dev"]
markers = "python_version < \"3.11\""
files = [
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
]
[package.extras]
test = ["pytest (>=6)"]
[[package]]
name = "home-assistant-bluetooth"
version = "1.10.4"
description = "Home Assistant Bluetooth Models and Helpers"
optional = false
python-versions = ">=3.9,<4.0"
groups = ["main"]
files = [
{file = "home_assistant_bluetooth-1.10.4-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:7c3434bdec5dcfe733d3e7c56d4a24418fcd03718dc2e7707c9133d1e48145a8"},
{file = "home_assistant_bluetooth-1.10.4.tar.gz", hash = "sha256:21216b6be9d028bc232b9188ac4dce773798c6b4e47482cc3524bfc5f82515e3"},
]
[[package]]
name = "idna"
version = "3.10"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = true
python-versions = ">=3.6"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
]
[package.extras]
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
[[package]]
name = "imagesize"
version = "1.4.1"
description = "Getting image size from png/jpeg/jpeg2000/gif file"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
{file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
]
[[package]]
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[package]]
name = "jinja2"
version = "3.1.5"
description = "A very fast and expressive template engine."
optional = true
python-versions = ">=3.7"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"},
{file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"},
]
[package.dependencies]
MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
[[package]]
name = "markdown-it-py"
version = "3.0.0"
description = "Python port of markdown-it. Markdown parsing, done right!"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
{file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
]
[package.dependencies]
mdurl = ">=0.1,<1.0"
[package.extras]
benchmarking = ["psutil", "pytest", "pytest-benchmark"]
code-style = ["pre-commit (>=3.0,<4.0)"]
compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
linkify = ["linkify-it-py (>=1,<3)"]
plugins = ["mdit-py-plugins"]
profiling = ["gprof2dot"]
rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
[[package]]
name = "markupsafe"
version = "3.0.2"
description = "Safely add untrusted strings to HTML/XML markup."
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
{file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
{file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
{file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
{file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
{file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
{file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
{file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
{file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
{file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
{file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
{file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
{file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
{file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
{file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
{file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
{file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
{file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
{file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
{file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
]
[[package]]
name = "mdit-py-plugins"
version = "0.4.2"
description = "Collection of plugins for markdown-it-py"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"},
{file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"},
]
[package.dependencies]
markdown-it-py = ">=1.0.0,<4.0.0"
[package.extras]
code-style = ["pre-commit"]
rtd = ["myst-parser", "sphinx-book-theme"]
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
[[package]]
name = "mdurl"
version = "0.1.2"
description = "Markdown URL utilities"
optional = true
python-versions = ">=3.7"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
]
[[package]]
name = "myst-parser"
version = "3.0.1"
description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser,"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1"},
{file = "myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87"},
]
[package.dependencies]
docutils = ">=0.18,<0.22"
jinja2 = "*"
markdown-it-py = ">=3.0,<4.0"
mdit-py-plugins = ">=0.4,<1.0"
pyyaml = "*"
sphinx = ">=6,<8"
[package.extras]
code-style = ["pre-commit (>=3.0,<4.0)"]
linkify = ["linkify-it-py (>=2.0,<3.0)"]
rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-book-theme (>=1.1,<2.0)", "sphinx-copybutton", "sphinx-design", "sphinx-pyscript", "sphinx-tippy (>=0.4.3)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.9.0,<0.10.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"]
testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"]
testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"]
[[package]]
name = "packaging"
version = "24.2"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.8"
groups = ["main", "dev"]
files = [
{file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
]
markers = {main = "extra == \"docs\""}
[[package]]
name = "pluggy"
version = "1.5.0"
description = "plugin and hook calling mechanisms for python"
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
]
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "pycparser"
version = "2.22"
description = "C parser in Python"
optional = false
python-versions = ">=3.8"
groups = ["main"]
markers = "platform_python_implementation != \"PyPy\""
files = [
{file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
]
[[package]]
name = "pygments"
version = "2.19.1"
description = "Pygments is a syntax highlighting package written in Python."
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"},
{file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"},
]
[package.extras]
windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pytest"
version = "8.3.4"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
{file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"},
{file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"},
]
[package.dependencies]
colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=1.5,<2"
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
[package.extras]
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
[[package]]
name = "pytest-cov"
version = "6.0.0"
description = "Pytest plugin for measuring coverage."
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
{file = "pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0"},
{file = "pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35"},
]
[package.dependencies]
coverage = {version = ">=7.5", extras = ["toml"]}
pytest = ">=4.6"
[package.extras]
testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"]
[[package]]
name = "pyyaml"
version = "6.0.2"
description = "YAML parser and emitter for Python"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
{file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"},
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"},
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"},
{file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"},
{file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"},
{file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"},
{file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"},
{file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"},
{file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"},
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"},
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"},
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"},
{file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"},
{file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"},
{file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"},
{file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"},
{file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
{file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
{file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
{file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
{file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
{file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
{file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
{file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
{file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
{file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
{file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
{file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
{file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"},
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"},
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"},
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"},
{file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"},
{file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"},
{file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"},
{file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"},
{file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"},
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"},
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"},
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"},
{file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"},
{file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"},
{file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"},
{file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"},
{file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
]
[[package]]
name = "requests"
version = "2.32.3"
description = "Python HTTP for Humans."
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<3"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "sensor-state-data"
version = "2.18.1"
description = "Models for storing and converting Sensor Data state"
optional = false
python-versions = "<4.0,>=3.9"
groups = ["main"]
files = [
{file = "sensor_state_data-2.18.1-py3-none-any.whl", hash = "sha256:45a223acf5d4aefde45c028fa810c7925db6448984097aa1b500fe4f206d113f"},
{file = "sensor_state_data-2.18.1.tar.gz", hash = "sha256:25f17ed98748ae006ddab82d5013cf30301daaf23526d1992f99c4dc0beb49c3"},
]
[package.extras]
docs = ["Sphinx (>=5.0,<6.0)", "myst-parser (>=0.18,<0.19)", "sphinx-rtd-theme (>=1.0,<2.0)"]
[[package]]
name = "snowballstemmer"
version = "2.2.0"
description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
optional = true
python-versions = "*"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
{file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
]
[[package]]
name = "sphinx"
version = "7.4.7"
description = "Python documentation generator"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"},
{file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"},
]
[package.dependencies]
alabaster = ">=0.7.14,<0.8.0"
babel = ">=2.13"
colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""}
docutils = ">=0.20,<0.22"
imagesize = ">=1.3"
Jinja2 = ">=3.1"
packaging = ">=23.0"
Pygments = ">=2.17"
requests = ">=2.30.0"
snowballstemmer = ">=2.2"
sphinxcontrib-applehelp = "*"
sphinxcontrib-devhelp = "*"
sphinxcontrib-htmlhelp = ">=2.0.0"
sphinxcontrib-jsmath = "*"
sphinxcontrib-qthelp = "*"
sphinxcontrib-serializinghtml = ">=1.1.9"
tomli = {version = ">=2", markers = "python_version < \"3.11\""}
[package.extras]
docs = ["sphinxcontrib-websupport"]
lint = ["flake8 (>=6.0)", "importlib-metadata (>=6.0)", "mypy (==1.10.1)", "pytest (>=6.0)", "ruff (==0.5.2)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-docutils (==0.21.0.20240711)", "types-requests (>=2.30.0)"]
test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"]
[[package]]
name = "sphinx-rtd-theme"
version = "3.0.2"
description = "Read the Docs theme for Sphinx"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13"},
{file = "sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85"},
]
[package.dependencies]
docutils = ">0.18,<0.22"
sphinx = ">=6,<9"
sphinxcontrib-jquery = ">=4,<5"
[package.extras]
dev = ["bump2version", "transifex-client", "twine", "wheel"]
[[package]]
name = "sphinxcontrib-applehelp"
version = "2.0.0"
description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"},
{file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"},
]
[package.extras]
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
standalone = ["Sphinx (>=5)"]
test = ["pytest"]
[[package]]
name = "sphinxcontrib-devhelp"
version = "2.0.0"
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"},
{file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"},
]
[package.extras]
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
standalone = ["Sphinx (>=5)"]
test = ["pytest"]
[[package]]
name = "sphinxcontrib-htmlhelp"
version = "2.1.0"
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"},
{file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"},
]
[package.extras]
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
standalone = ["Sphinx (>=5)"]
test = ["html5lib", "pytest"]
[[package]]
name = "sphinxcontrib-jquery"
version = "4.1"
description = "Extension to include jQuery on newer Sphinx releases"
optional = true
python-versions = ">=2.7"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"},
{file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"},
]
[package.dependencies]
Sphinx = ">=1.8"
[[package]]
name = "sphinxcontrib-jsmath"
version = "1.0.1"
description = "A sphinx extension which renders display math in HTML via JavaScript"
optional = true
python-versions = ">=3.5"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
{file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
]
[package.extras]
test = ["flake8", "mypy", "pytest"]
[[package]]
name = "sphinxcontrib-qthelp"
version = "2.0.0"
description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"},
{file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"},
]
[package.extras]
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
standalone = ["Sphinx (>=5)"]
test = ["defusedxml (>=0.7.1)", "pytest"]
[[package]]
name = "sphinxcontrib-serializinghtml"
version = "2.0.0"
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"},
{file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"},
]
[package.extras]
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
standalone = ["Sphinx (>=5)"]
test = ["pytest"]
[[package]]
name = "tomli"
version = "2.2.1"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.8"
groups = ["main", "dev"]
files = [
{file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
{file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
{file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
{file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
{file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
{file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
{file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
{file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
{file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
{file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
{file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
{file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
{file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
{file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
]
markers = {main = "extra == \"docs\" and python_version < \"3.11\"", dev = "python_full_version <= \"3.11.0a6\""}
[[package]]
name = "urllib3"
version = "2.3.0"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"docs\""
files = [
{file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"},
{file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
h2 = ["h2 (>=4,<5)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
[extras]
docs = ["Sphinx", "myst-parser", "sphinx-rtd-theme"]
[metadata]
lock-version = "2.1"
python-versions = "^3.10"
content-hash = "252231a48df1c5cfe5f18949bdeef4b526ca15da6d06c0f27555c9e5fa011e82"
govee-ble-0.43.1/pyproject.toml 0000664 0000000 0000000 00000004774 14762105017 0016377 0 ustar 00root root 0000000 0000000 [project]
name = "govee-ble"
version = "0.43.1"
license = "Apache-2.0"
description = "Manage Govee BLE devices"
authors = [{ name = "J. Nick Koston", email = "nick@koston.org" }]
readme = "README.md"
requires-python = ">=3.10"
dynamic = ["classifiers", "dependencies", "optional-dependencies"]
[project.urls]
"Repository" = "https://github.com/bluetooth-devices/govee-ble"
"Documentation" = "https://govee-ble.readthedocs.io"
"Bug Tracker" = "https://github.com/bluetooth-devices/govee-ble/issues"
"Changelog" = "https://github.com/bluetooth-devices/govee-ble/blob/main/CHANGELOG.md"
[tool.poetry]
classifiers = [
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Developers",
"Natural Language :: English",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries",
]
packages = [
{ include = "govee_ble", from = "src" },
]
[tool.poetry.dependencies]
python = "^3.10"
# Documentation Dependencies
Sphinx = {version = ">=5,<8", optional = true}
sphinx-rtd-theme = {version = ">=1,<4", optional = true}
myst-parser = {version = ">=0.18,<3.1", optional = true}
home-assistant-bluetooth = ">=1.3.0"
sensor-state-data = ">=2.18.0"
bluetooth-sensor-state-data = ">=1.5.0"
bluetooth-data-tools = ">=0.1.2"
cryptography = ">=42.0.0"
[tool.poetry.extras]
docs = [
"myst-parser",
"sphinx",
"sphinx-rtd-theme",
]
[tool.poetry.dev-dependencies]
pytest = "^8.3"
pytest-cov = "^6.0"
[tool.semantic_release]
branch = "main"
version_toml = ["pyproject.toml:project.version"]
version_variables = ["src/govee_ble/__init__.py:__version__"]
build_command = "pip install poetry && poetry build"
[tool.pytest.ini_options]
addopts = "-v -Wdefault --cov=govee_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 = ["govee_ble", "tests"]
[tool.mypy]
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_untyped_defs = true
mypy_path = "src/"
no_implicit_optional = true
show_error_codes = true
warn_unreachable = true
warn_unused_ignores = true
exclude = [
'docs/.*',
'setup.py',
]
[[tool.mypy.overrides]]
module = "tests.*"
allow_untyped_defs = true
[[tool.mypy.overrides]]
module = "docs.*"
ignore_errors = true
[build-system]
requires = ["poetry-core>=2.0.0"]
build-backend = "poetry.core.masonry.api"
govee-ble-0.43.1/renovate.json 0000664 0000000 0000000 00000000101 14762105017 0016155 0 ustar 00root root 0000000 0000000 {
"extends": ["github>browniebroke/renovate-configs:python"]
}
govee-ble-0.43.1/setup.py 0000664 0000000 0000000 00000000357 14762105017 0015166 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# This is a shim to allow GitHub to detect the package, build is done with poetry
# Taken from https://github.com/Textualize/rich
import setuptools
if __name__ == "__main__":
setuptools.setup(name="govee-ble")
govee-ble-0.43.1/src/ 0000775 0000000 0000000 00000000000 14762105017 0014236 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/src/govee_ble/ 0000775 0000000 0000000 00000000000 14762105017 0016165 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/src/govee_ble/__init__.py 0000664 0000000 0000000 00000001746 14762105017 0020306 0 ustar 00root root 0000000 0000000 """Parser for Govee BLE advertisements.
This file is shamelessly copied from the following repository:
https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/govee.py
MIT License applies.
"""
from __future__ import annotations
from sensor_state_data import (
BinarySensorDeviceClass,
BinarySensorValue,
DeviceKey,
SensorDescription,
SensorDeviceClass,
SensorDeviceInfo,
SensorUpdate,
SensorValue,
Units,
)
from sensor_state_data import (
DeviceClass,
)
from .parser import GoveeBluetoothDeviceData, SensorType, get_model_info, ModelInfo
__version__ = "0.43.1"
__all__ = [
"GoveeBluetoothDeviceData",
"BinarySensorDeviceClass",
"SensorDeviceClass",
"BinarySensorValue",
"SensorType",
"SensorDescription",
"SensorDeviceInfo",
"DeviceClass",
"DeviceKey",
"SensorUpdate",
"SensorDeviceInfo",
"SensorValue",
"Units",
"get_model_info",
"ModelInfo",
]
govee-ble-0.43.1/src/govee_ble/parser.py 0000664 0000000 0000000 00000071011 14762105017 0020033 0 ustar 00root root 0000000 0000000 """Parser for Govee BLE advertisements.
This file is shamelessly copied from the following repository:
https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/govee.py
MIT License applies.
"""
from __future__ import annotations
import logging
import struct
from dataclasses import dataclass
from enum import Enum
from bluetooth_data_tools import short_address
from bluetooth_sensor_state_data import BluetoothData
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from home_assistant_bluetooth import BluetoothServiceInfo
from sensor_state_data import BinarySensorDeviceClass, SensorLibrary
_LOGGER = logging.getLogger(__name__)
PACKED_hHB_LITTLE = struct.Struct("hHB")
PACKED_hh = struct.Struct(">hh")
PACKED_hhhchhh_LITTLE = struct.Struct("hhbhh")
PACKED_hhhhh = struct.Struct(">hhhhh")
PACKED_hhhhhh = struct.Struct(">hhhhhh")
ERROR = "error"
MIN_TEMP = -40
MAX_TEMP = 100
NOT_GOVEE_MANUFACTURER = {76}
PROBE_MAPPING_1_2 = [1, 2]
PROBE_MAPPING_3_4 = [3, 4]
FOUR_PROBES_MAPPING = {
sensor_id: PROBE_MAPPING_1_2 for sensor_id in (0x01, 0x41, 0x81, 0xC1)
} | {sensor_id: PROBE_MAPPING_3_4 for sensor_id in (0x02, 0x42, 0x82, 0xC2)}
SIX_PROBES_MAPPING = {
0: [[1, 0x01], [2, 0x02]],
64: [[3, 0x04], [4, 0x08]],
128: [[5, 0x10], [6, 0x20]],
}
def decode_temp_humid_battery_error(data: bytes) -> tuple[float, float, int, bool]:
temp, humi = decode_temp_humid(data[0:3])
batt = int(data[-1] & 0x7F)
err = bool(data[-1] & 0x80)
return temp, humi, batt, err
def decode_temp_humid(temp_humid_bytes: bytes) -> tuple[float, float]:
"""Decode potential negative temperatures."""
base_num = (
(temp_humid_bytes[0] << 16) + (temp_humid_bytes[1] << 8) + temp_humid_bytes[2]
)
is_negative = base_num & 0x800000
temp_as_int = base_num & 0x7FFFFF
temp_as_float = int(temp_as_int / 1000) / 10.0
if is_negative:
temp_as_float = -temp_as_float
humid = (temp_as_int % 1000) / 10.0
return temp_as_float, humid
def decode_temps_probes(packet_value: int) -> float:
"""Filter potential negative temperatures."""
if packet_value < 0:
return 0.0
return float(packet_value / 100)
def decode_temps_probes_none(packet_value: int) -> float | None:
"""Filter potential negative temperatures."""
if packet_value < 0:
return None
return float(packet_value)
def hex(data: bytes) -> str:
"""Return a string object containing two hexadecimal digits for each byte in the instance."""
return "b'{}'".format("".join(f"\\x{b:02x}" for b in data))
def decode_temps_from_4_bytes(packet_value: int) -> float:
"""Decode temperature values (to one decimal place)."""
if packet_value & 0x80000000:
# Handle freezing temperatures
packet_value &= 0x7FFFFFFF
return float(int(packet_value / -10000000) / -10)
return float(int(packet_value / 1000000) / 10)
def decode_humi_from_4_bytes(packet_value: int) -> float:
"""Decode humidity values (to one decimal place)"""
packet_value &= 0x7FFFFFFF
return float(int((packet_value % 1000000) / 1000) / 10)
def decode_pm25_from_4_bytes(packet_value: int) -> int:
"""Decode humidity values"""
packet_value &= 0x7FFFFFFF
return int(packet_value % 1000)
def calculate_crc(data: bytes) -> int:
crc = 0x1D0F
for b in data:
for s in range(7, -1, -1):
mask = 0
if (crc >> 15) ^ (b >> s) & 1:
mask = 0x1021
crc = ((crc << 1) ^ mask) & 0xFFFF
return crc
def decrypt_data(key: bytes, data: bytes) -> bytes:
cipher = Cipher(algorithms.AES(key[::-1]), modes.ECB())
decryptor = cipher.decryptor()
return (decryptor.update(data[::-1]) + decryptor.finalize())[::-1]
class SensorType(Enum):
THERMOMETER = "thermometer"
BUTTON = "button"
MOTION = "motion"
WINDOW = "window"
VIBRATION = "vibration"
PRESENCE = "presence"
PRESSURE = "pressure"
@dataclass
class ModelInfo:
"""Model information for Govee sensors."""
model_id: str
sensor_type: SensorType
button_count: int
sleepy: bool
_MODEL_DB = {
"H5121": ModelInfo("H5121", SensorType.MOTION, 0, True),
"H5122": ModelInfo("H5122", SensorType.BUTTON, 1, True),
"H5123": ModelInfo("H5123", SensorType.WINDOW, 0, True),
"H5124": ModelInfo("H5124", SensorType.VIBRATION, 0, True),
"H5125": ModelInfo("H5125", SensorType.BUTTON, 6, True),
"H5126": ModelInfo("H5126", SensorType.BUTTON, 2, True),
"H5127": ModelInfo("H5127", SensorType.PRESENCE, 0, True),
"H5130": ModelInfo("H5130", SensorType.PRESSURE, 1, True),
}
def get_model_info(model_id: str) -> ModelInfo:
"""Get model information for a Govee sensor."""
return _MODEL_DB.get(
model_id, ModelInfo(model_id, SensorType.THERMOMETER, 0, False)
)
class GoveeBluetoothDeviceData(BluetoothData):
"""Data for Govee BLE sensors."""
def _start_update(self, service_info: BluetoothServiceInfo) -> None:
"""Update from BLE advertisement data."""
_LOGGER.debug("Parsing Govee BLE advertisement data: %s", service_info)
manufacturer_data = service_info.manufacturer_data
service_uuids = service_info.service_uuids
local_name = service_info.name
address = service_info.address
self.set_device_manufacturer("Govee")
if local_name.startswith("Govee_"):
self.set_device_name(service_info.name[6:].replace("_", " "))
if local_name.startswith("GV"):
self.set_device_name(service_info.name[2:].replace("_", " "))
self.set_precision(2)
for mfr_id, mfr_data in manufacturer_data.items():
if mfr_id in NOT_GOVEE_MANUFACTURER:
continue
self._process_mfr_data(address, local_name, mfr_id, mfr_data, service_uuids)
@property
def device_type(self) -> str | None:
"""Return the device type."""
primary_device_id = self.primary_device_id
if device_type := self._device_id_to_type.get(primary_device_id):
return device_type.partition("-")[0]
return None
@property
def button_count(self) -> int:
"""Return the number of buttons on the device."""
device_type = self.device_type
assert device_type is not None
return get_model_info(device_type).button_count
@property
def sensor_type(self) -> SensorType:
"""Return the sensor type."""
device_type = self.device_type
assert device_type is not None
return get_model_info(device_type).sensor_type
@property
def sleepy(self) -> bool:
"""Return if the device is sleep."""
device_type = self.device_type
assert device_type is not None
return get_model_info(device_type).sleepy
def _process_mfr_data(
self,
address: str,
local_name: str,
mgr_id: int,
data: bytes,
service_uuids: list[str],
) -> None:
"""Parser for Govee sensors."""
if debug_logging := _LOGGER.isEnabledFor(logging.DEBUG):
_LOGGER.debug("Parsing Govee sensor: %s %s", mgr_id, hex(data))
msg_length = len(data)
if msg_length > 25 and b"INTELLI_ROCKS" in data:
# INTELLI_ROCKS sometimes ends up glued on to the end of the message
data = data[:-25]
msg_length = len(data)
if debug_logging:
_LOGGER.debug("Cleaned up packet: %s %s", mgr_id, data.hex())
if msg_length == 24:
time_ms = data[2:6]
enc_data = data[6:22]
enc_crc = data[22:24]
if not calculate_crc(enc_data) == int.from_bytes(enc_crc, "big"):
_LOGGER.debug("CRC check failed for H512/3x: %s", hex(data))
return
key = time_ms + bytes(12)
try:
decrypted = decrypt_data(key, enc_data)
except ValueError:
_LOGGER.warning("Failed to decrypt H512/3x: %s", hex(data))
return
_LOGGER.debug("Decrypted H512/3x: %s - %s", decrypted, decrypted.hex())
model_id = decrypted[2]
# GV5121
# 01040302640100000000000000000000
# GV5122
# 01050802640000000000000000000000
# 01050802640000000000000000000000
# GV5123
# 01050202640200000000000000000000
# GV5124
# 01030902640100000000000000000000
# GV5125
# 01010a02640000000000000000000000
# GV5126
# 01010b02640100000000000000000000
# GV5130
# 010e0d02640000000000000000000000
sensor_type = SensorType.BUTTON
if "GV5121" in local_name or model_id == 3:
self.set_device_type("H5121")
self.set_device_name(f"5121{short_address(address)}")
sensor_type = SensorType.MOTION
elif "GV5122" in local_name or model_id == 8:
self.set_device_type("H5122")
self.set_device_name(f"5122{short_address(address)}")
elif "GV5123" in local_name or model_id == 2:
self.set_device_type("H5123")
self.set_device_name(f"5123{short_address(address)}")
sensor_type = SensorType.WINDOW
elif "GV5124" in local_name or model_id == 9:
self.set_device_type("H5124")
self.set_device_name(f"5124{short_address(address)}")
sensor_type = SensorType.VIBRATION
elif "GV5125" in local_name or model_id == 10:
self.set_device_type("H5125")
self.set_device_name(f"5125{short_address(address)}")
elif "GV5126" in local_name or model_id == 11:
self.set_device_type("H5126")
self.set_device_name(f"5126{short_address(address)}")
elif "GV5130" in local_name or model_id == 13:
self.set_device_type("H5130")
self.set_device_name(f"5130{short_address(address)}")
sensor_type = SensorType.PRESSURE
else:
return
battery_percentage = decrypted[4]
button_number_pressed = decrypted[5]
self.update_predefined_sensor(
SensorLibrary.BATTERY__PERCENTAGE, battery_percentage
)
if sensor_type is SensorType.WINDOW:
# H5123 is a door/window sensor
self.update_predefined_binary_sensor(
BinarySensorDeviceClass.WINDOW, button_number_pressed == 2
)
elif sensor_type is SensorType.VIBRATION:
# H5124 is a vibration sensor
if button_number_pressed == 1:
self.fire_event("vibration", "vibration")
elif sensor_type is SensorType.MOTION:
if button_number_pressed == 1:
self.fire_event("motion", "motion")
elif sensor_type is SensorType.PRESSURE:
# H5130 is a pressure sensor
if button_number_pressed == 16:
self.fire_event("button_0", "press")
else:
self.update_predefined_binary_sensor(
BinarySensorDeviceClass.PRESENCE, button_number_pressed == 1
)
else:
self.fire_event(f"button_{button_number_pressed}", "press")
return
if msg_length == 6 and (
data.startswith(b"\xec\x00\x01\x01")
and "H5127" in local_name
or mgr_id == 0x8803
):
self.set_device_type("H5127")
self.set_device_name(f"H5127{short_address(address)}")
present = data[4] == 1
motion = data[5] == 17
self.update_predefined_binary_sensor(
BinarySensorDeviceClass.OCCUPANCY, present
)
self.update_predefined_binary_sensor(BinarySensorDeviceClass.MOTION, motion)
if msg_length == 6 and (
(is_5072 := "H5072" in local_name)
or (is_5075 := "H5075" in local_name)
or mgr_id == 0xEC88
):
if is_5072:
self.set_device_type("H5072")
elif is_5075:
self.set_device_type("H5075")
else:
self.set_device_type("H5072/H5075")
temp, humi, batt, err = decode_temp_humid_battery_error(data[1:5])
if temp >= MIN_TEMP and temp <= MAX_TEMP and not err:
self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp)
self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, humi)
else:
_LOGGER.debug(
"Ignoring invalid sensor values, temperature: %.1f, humidity: %.1f, error: %s",
temp,
humi,
err,
)
self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, ERROR)
self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, ERROR)
self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt)
return
if msg_length in (6, 8) and (
(is_5108 := "H5108" in local_name)
or (is_5100 := "H5100" in local_name)
or (is_5101 := "H5101" in local_name)
or (is_5102 := "H5102" in local_name)
or (is_5103 := "H5103" in local_name)
or (is_5104 := "H5104" in local_name)
or (is_5105 := "H5105" in local_name)
or (is_5174 := "H5174" in local_name)
or (is_5177 := "H5177" in local_name)
or (is_5179 := "GV5179" in local_name)
or (mgr_id == 0x0001 and msg_length == 8)
):
if is_5108 or msg_length == 8:
self.set_device_type("H5108")
elif is_5100:
self.set_device_type("H5100")
elif is_5101:
self.set_device_type("H5101")
elif is_5102:
self.set_device_type("H5102")
elif is_5103:
self.set_device_type("H5103")
elif is_5104:
self.set_device_type("H5104")
elif is_5105:
self.set_device_type("H5105")
elif is_5174:
self.set_device_type("H5174")
elif is_5177:
self.set_device_type("H5177")
elif is_5179:
self.set_device_type("GV5179")
else:
self.set_device_type("H5101/H5102/H5104/H5108/H5174/H5177/GV5179")
temp, humi, batt, err = decode_temp_humid_battery_error(data[2:6])
if temp >= MIN_TEMP and temp <= MAX_TEMP and not err:
self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp)
self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, humi)
else:
_LOGGER.debug(
"Ignoring invalid sensor values, temperature: %.1f, humidity: %.1f, error: %s",
temp,
humi,
err,
)
self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, ERROR)
self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, ERROR)
self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt)
return
if msg_length == 7 and ("H5074" in local_name or mgr_id == 0xEC88):
self.set_device_type("H5074")
(temp, humi, batt) = PACKED_hHB_LITTLE.unpack(data[1:6])
self.update_predefined_sensor(
SensorLibrary.TEMPERATURE__CELSIUS, temp / 100
)
self.update_predefined_sensor(
SensorLibrary.HUMIDITY__PERCENTAGE, humi / 100
)
self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt)
return
if msg_length == 9 and (
mgr_id == 0xEC88
or "H5051" in local_name
or "H5052" in local_name
or "H5071" in local_name
):
if "H5071" in local_name:
self.set_device_type("H5071")
elif "H5052" in local_name:
self.set_device_type("H5052")
else:
self.set_device_type("H5051")
self.set_device_name(f"H5051 {short_address(address)}")
(temp, humi, batt) = PACKED_hHB_LITTLE.unpack(data[1:6])
self.update_predefined_sensor(
SensorLibrary.TEMPERATURE__CELSIUS, temp / 100
)
self.update_predefined_sensor(
SensorLibrary.HUMIDITY__PERCENTAGE, humi / 100
)
self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt)
return
if msg_length == 9 and (
"H5178" in local_name or "B5178" in local_name or mgr_id == 0x0001
):
temp, humi, batt, err = decode_temp_humid_battery_error(data[3:7])
sensor_id = data[2]
device_id = "primary"
if local_name.startswith("H5178") or local_name.startswith("B5178"):
self.set_title(local_name)
else:
self.set_title("H5178")
if sensor_id == 0:
self.set_device_name(
f"{local_name} Primary".replace("_", " "), device_id
)
self.set_device_type("H5178", device_id)
self.set_device_manufacturer("Govee", device_id)
elif sensor_id == 1:
device_id = "remote"
self.set_device_name(
f"{local_name} Remote".replace("_", " "), device_id
)
self.set_device_type("H5178-REMOTE", device_id)
self.set_device_manufacturer("Govee", device_id)
elif debug_logging:
_LOGGER.debug(
"Unknown sensor id for Govee H5178,"
" please report to the developers, data: %s",
hex(data),
)
if temp >= MIN_TEMP and temp <= MAX_TEMP and not err:
self.update_predefined_sensor(
SensorLibrary.TEMPERATURE__CELSIUS, temp, device_id=device_id
)
self.update_predefined_sensor(
SensorLibrary.HUMIDITY__PERCENTAGE, humi, device_id=device_id
)
else:
_LOGGER.debug(
"Ignoring invalid sensor values, temperature: %.1f, humidity: %.1f, error: %s",
temp,
humi,
err,
)
self.update_predefined_sensor(
SensorLibrary.TEMPERATURE__CELSIUS, ERROR, device_id=device_id
)
self.update_predefined_sensor(
SensorLibrary.HUMIDITY__PERCENTAGE, ERROR, device_id=device_id
)
self.update_predefined_sensor(
SensorLibrary.BATTERY__PERCENTAGE, batt, device_id=device_id
)
return
if msg_length == 9 and ("H5179" in local_name or mgr_id == 0x8801):
self.set_device_type("H5179")
temp, humi, batt = PACKED_hHB_LITTLE.unpack(data[4:9])
self.update_predefined_sensor(
SensorLibrary.TEMPERATURE__CELSIUS, temp / 100
)
self.update_predefined_sensor(
SensorLibrary.HUMIDITY__PERCENTAGE, humi / 100
)
self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt)
return
if msg_length == 14 and (
"H5181" in local_name
or mgr_id in {0xF861, 0x388A, 0xEA42, 0xAAA2, 0xD14B}
or "00008151-0000-1000-8000-00805f9b34fb" in service_uuids
):
self.set_device_type("H5181")
self.set_device_name(f"H5181 {short_address(address)}")
(temp_probe_1, temp_alarm_1) = PACKED_hh.unpack(data[8:12])
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1
)
return
if msg_length == 17 and (
"H5182" in local_name
or mgr_id == 0x2730
or "00008251-0000-1000-8000-00805f9b34fb" in service_uuids
):
self.set_device_type("H5182")
self.set_device_name(f"H5182 {short_address(address)}")
(
temp_probe_1,
temp_alarm_1,
_,
temp_probe_2,
temp_alarm_2,
) = PACKED_hhbhh.unpack(data[8:17])
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1
)
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_2), decode_temps_probes(temp_alarm_2), 2
)
return
if msg_length == 14 and (
"H5183" in local_name
or mgr_id in {0x67DD, 0xE02F, 0xF79F}
or "00008351-0000-1000-8000-00805f9b34fb" in service_uuids
):
self.set_device_type("H5183")
self.set_device_name(f"H5183 {short_address(address)}")
(temp_probe_1, temp_alarm_1) = PACKED_hh.unpack(data[8:12])
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1
)
return
if msg_length == 17 and (
"H5184" in local_name
or mgr_id == 0x1B36
or "00008451-0000-1000-8000-00805f9b34fb" in service_uuids
):
sensor_id = data[6]
self.set_device_type("H5184")
self.set_device_name(f"H5184 {short_address(address)}")
(
temp_probe_first,
temp_alarm_first,
_,
temp_probe_second,
temp_alarm_second,
) = PACKED_hhbhh.unpack(data[8:17])
if not (ids := FOUR_PROBES_MAPPING.get(sensor_id)):
if debug_logging:
_LOGGER.debug(
"Unknown sensor id: %s for a H5184, data: %s",
sensor_id,
hex(data),
)
return
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_first),
decode_temps_probes(temp_alarm_first),
ids[0],
)
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_second),
decode_temps_probes(temp_alarm_second),
ids[1],
)
return
if msg_length == 20 and (
"H5185" in local_name
or mgr_id in (0x4A32, 0x332, 0x4C32)
or "00008551-0000-1000-8000-00805f9b34fb" in service_uuids
):
self.set_device_type("H5185")
self.set_device_name(f"H5185 {short_address(address)}")
(
temp_probe_1,
temp_alarm_1,
_,
temp_probe_2,
temp_alarm_2,
) = PACKED_hhhhh.unpack(data[8:18])
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1
)
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_2), decode_temps_probes(temp_alarm_2), 2
)
return
if msg_length == 20 and (
"H5198" in local_name
or mgr_id == 0x3022
or "00009851-0000-1000-8000-00805f9b34fb" in service_uuids
):
sensor_id = data[6]
self.set_device_type("H5198")
self.set_device_name(f"H5198 {short_address(address)}")
(
temp_probe_first,
temp_alarm_first,
low_temp_alarm_first,
temp_probe_second,
temp_alarm_second,
low_temp_alarm_second,
) = PACKED_hhhhhh.unpack(data[8:20])
if not (ids := FOUR_PROBES_MAPPING.get(sensor_id)):
if debug_logging:
_LOGGER.debug(
"Unknown sensor id: %s for a H5198, data: %s",
sensor_id,
hex(data),
)
return
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_first),
decode_temps_probes(temp_alarm_first),
ids[0],
decode_temps_probes(low_temp_alarm_first),
)
self.update_temp_probe_with_alarm(
decode_temps_probes(temp_probe_second),
decode_temps_probes(temp_alarm_second),
ids[1],
decode_temps_probes(low_temp_alarm_second),
)
return
if msg_length == 20 and "00005550-0000-1000-8000-00805f9b34fb" in service_uuids:
self.set_device_type("H5055")
self.set_device_name(f"H5055 {short_address(address)}")
(
temp_probe_first,
temp_min_first,
temp_max_first,
_,
temp_probe_second,
temp_min_second,
temp_max_second,
) = PACKED_hhhchhh_LITTLE.unpack(data[5:18])
sensor_ids = data[3]
if not (pids := SIX_PROBES_MAPPING.get(sensor_ids & 0xC0)):
if debug_logging:
_LOGGER.debug(
"Unknown sensor id: %s for a H5055, data: %s",
sensor_ids,
hex(data),
)
return
if sensor_ids & pids[0][1]:
self.update_temp_probe_with_alarm(
temp_probe_first,
decode_temps_probes_none(temp_max_first),
pids[0][0],
decode_temps_probes_none(temp_min_first),
)
if sensor_ids & pids[1][1]:
self.update_temp_probe_with_alarm(
temp_probe_second,
decode_temps_probes_none(temp_max_second),
pids[1][0],
decode_temps_probes_none(temp_min_second),
)
batt = int(data[2] & 0x7F)
self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt)
return
if msg_length == 6 and "H5106" in local_name:
self.set_device_type("H5106")
self.set_device_name(f"H5106 {short_address(address)}")
packet_5106 = data[2:6].hex()
four_bytes = int(packet_5106, 16)
temp = decode_temps_from_4_bytes(four_bytes)
humi = decode_humi_from_4_bytes(four_bytes)
pm25 = decode_pm25_from_4_bytes(four_bytes)
self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp)
self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, humi)
self.update_predefined_sensor(
SensorLibrary.PM25__CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, pm25
)
return
def update_temp_probe(self, temp: float, probe_id: int) -> None:
"""Update the temperature probe with the alarm temperature."""
self.update_predefined_sensor(
SensorLibrary.TEMPERATURE__CELSIUS,
temp,
key=f"temperature_probe_{probe_id}",
name=f"Temperature Probe {probe_id}",
)
def update_temp_probe_with_alarm(
self,
temp: float,
alarm_temp: float | None,
probe_id: int,
low_alarm_temp: float | None = None,
) -> None:
"""Update the temperature probe with the alarm temperature."""
self.update_temp_probe(temp, probe_id)
if alarm_temp is not None:
self.update_predefined_sensor(
SensorLibrary.TEMPERATURE__CELSIUS,
alarm_temp,
key=f"temperature_alarm_probe_{probe_id}",
name=f"Temperature Alarm Probe {probe_id}",
)
if low_alarm_temp is not None:
self.update_predefined_sensor(
SensorLibrary.TEMPERATURE__CELSIUS,
low_alarm_temp,
key=f"low_temperature_alarm_probe_{probe_id}",
name=f"Low Temperature Alarm Probe {probe_id}",
)
govee-ble-0.43.1/src/govee_ble/py.typed 0000664 0000000 0000000 00000000000 14762105017 0017652 0 ustar 00root root 0000000 0000000 govee-ble-0.43.1/tests/ 0000775 0000000 0000000 00000000000 14762105017 0014611 5 ustar 00root root 0000000 0000000 govee-ble-0.43.1/tests/__init__.py 0000664 0000000 0000000 00000000000 14762105017 0016710 0 ustar 00root root 0000000 0000000 govee-ble-0.43.1/tests/test_parser.py 0000664 0000000 0000000 00000564043 14762105017 0017532 0 ustar 00root root 0000000 0000000 import logging
from bluetooth_sensor_state_data import BluetoothServiceInfo, DeviceClass, SensorUpdate
from sensor_state_data import (
BinarySensorDescription,
BinarySensorDeviceClass,
BinarySensorValue,
DeviceKey,
Event,
SensorDescription,
SensorDeviceClass,
SensorDeviceInfo,
SensorValue,
Units,
)
from govee_ble.parser import GoveeBluetoothDeviceData, SensorType, get_model_info
GVH5051_SERVICE_INFO = BluetoothServiceInfo(
name="",
address="61DE521B-F0BF-9F44-64D4-75BBE1738105",
rssi=-63,
manufacturer_data={60552: b"\x00\xba\x0a\xf9\x0f\x63\x02\x01\x01"},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5075_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5075_2762",
address="61DE521B-F0BF-9F44-64D4-75BBE1738105",
rssi=-63,
manufacturer_data={
60552: b"\x00\x03A\xc2d\x00L\x00\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c"
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5075_SERVICE_INFO_2 = BluetoothServiceInfo(
name="GVH5075_DBF8",
address="A4:C1:38:DD:DB:F8",
rssi=-63,
manufacturer_data={60552: b"\x00\x03M\xb2d\x00"},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5075_SERVICE_INFO_NEGATIVE_VALUES = BluetoothServiceInfo(
name="GVH5075_2762",
address="61DE521B-F0BF-9F44-64D4-75BBE1738105",
rssi=-63,
manufacturer_data={60552: b"\x00\xbc\x00\x04>'"},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5075_SERVICE_INFO_OVERSIZED_VALUES = BluetoothServiceInfo(
name="GVH5075_2762",
address="61DE521B-F0BF-9F44-64D4-75BBE1738105",
rssi=-63,
manufacturer_data={
60552: b"\x00J\x00(;\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\xc2",
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5075_SERVICE_INFO_OTHER_VALUES = BluetoothServiceInfo(
name="GVH5075_2762",
address="61DE521B-F0BF-9F44-64D4-75BBE1738105",
rssi=-63,
manufacturer_data={60552: b"\x00\x03\x0f\xc95\x00"},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5071_SERVICE_INFO = BluetoothServiceInfo(
name="Govee_H5071_FD12",
address="61DE521B-F0BF-9F44-64D4-75BBE1738105",
rssi=-63,
manufacturer_data={60552: b"\x00!\n\xb6\x12\x18\xc8\x00\x01"},
service_uuids=[
"0000180a-0000-1000-8000-00805f9b34fb",
"0000fef5-0000-1000-8000-00805f9b34fb",
"0000ec88-0000-1000-8000-00805f9b34fb",
],
service_data={},
source="local",
)
GVH5052_SERVICE_INFO = BluetoothServiceInfo(
name="Govee_H5052_E81B",
address="61DE521B-F0BF-9F44-64D4-75BBE1738105",
rssi=-63,
manufacturer_data={60552: b"\x00\x1c\x01\xa7\x14;\x00\x00\x02"},
service_uuids=[
"0000180a-0000-1000-8000-00805f9b34fb",
"0000fef5-0000-1000-8000-00805f9b34fb",
"0000ec88-0000-1000-8000-00805f9b34fb",
],
service_data={},
source="local",
)
GVH5177_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5177_2EC8",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
1: b"\x01\x01\x036&dL\x00\x02\x15INTELLI_ROCKS_HWQw\xf2\xff\xc2"
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5184_SERVICE_INFO_1 = BluetoothServiceInfo(
name="GVH5184_XXXX",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
6966: b" \x01\x00\x01\x01\xe4\x01\x86\x0c\x1c\xff\xff\x86\n\xf0\xff\xff",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008451-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5184_SERVICE_INFO_2 = BluetoothServiceInfo(
name="GVH5184_XXXX",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
6966: b" \x01\x00\x01\x01\xe4\x02\x86\x0b\xb8\xff\xff\x86\x0bT\xff\xff",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008451-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5198_SERVICE_INFO = BluetoothServiceInfo(
name="",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
12322: b"\x6c\x01\x00\x01\x01\xa4\xc2\x0f\x0e\x10\xff\xff\xff\xff\x08\xfc\xff\xff\xff\xff"
},
service_uuids=["00009851-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5198_VARIANT_SERVICE_INFO = BluetoothServiceInfo(
name="",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
12322: b"\x6c\x01\x00\x01\x01\xa3\xc1\x0f\x0b\xb8\xff\xff\xff\xff\t`\xff\xff\xff\xff"
},
service_uuids=["00009851-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5198_INVALID_SERVICE_INFO = BluetoothServiceInfo(
name="",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
12322: b"\x6c\x01\x00\x01\x01\xa3\xd4\x0f\x0b\xb8\xff\xff\xff\xff\t`\xff\xff\xff\xff"
},
service_uuids=["00009851-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5185_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5185_2EC8",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
18994: b"\x87\x01\x00\x01\x01\xe4\xc1f\x084\xff\xff\xff\xff"
b"\x084\xff\xff\xff\xffL\x00\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c"
},
service_uuids=["00008551-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5185_VARIANT_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5185_VAR2",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
818: b"T\x01\x00\x01\x01\xe4\xc1f\t\xc4\xff\xff\xff\xff\t\xc4\xff\xff\xff\xff",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008551-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5185_VARIANT_2_SERVICE_INFO = BluetoothServiceInfo(
name="Govee_H5185_4C17",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
19506: b"\x17\x01\x00\x01\x01\xd7\x01f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=[
"00001800-0000-1000-8000-00805f9b34fb",
"00001801-0000-1000-8000-00805f9b34fb",
"02f00000-0000-0000-0000-00000000fe00",
"494e5445-4c4c-495f-524f-434b535f4857",
],
service_data={},
source="local",
)
GVH5183_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5183_2EC8",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
26589: b"\xef\x01\x00\x01\x01\xe4\x01\x80\x084\xff\xff\x00"
b"\x00L\x00\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c"
},
service_uuids=["00008351-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5183_NO_LOCAL_NAME_SERVICE_INFO = BluetoothServiceInfo(
name="",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
57391: b"\xcb\x01\x00\x01\x01\xe4\x00\x8f\x084\xff\xff\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008351-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5183_SERVICE_INFO_VARIANT = BluetoothServiceInfo(
name="",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
63391: b"s\x01\x00\x01\x01\xe4\x00\x80\n\xf0\xff\xff\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008351-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5181_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5181_2EC8",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
14474: b"\xd8\x01\x00\x01\x01\xe4\x01\x86\x08\x98\x1d"
b"\x10\x00\x00L\x00\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c"
},
service_uuids=["00008151-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5181_VARIANT_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5181_2EC8",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
59970: b"\xba\x01\x00\x01\x01d\x00\x06\xff\xff\x1c\xe8\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008151-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5181_VARIANT_SERVICE_INFO_2 = BluetoothServiceInfo(
name="GVH5181_2EC8",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
59970: b"\xba\x01\x00\x01\x01d\x00\x86\n(\x1c\xe8\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008151-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5181_VARIANT_SERVICE_INFO_3 = BluetoothServiceInfo(
name="GVPROBE",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
63585: b"&\x01\x00\x01\x01\xe4\x01\x06\xff\xff\x1c\xd4\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008151-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5181_VARIANT_SERVICE_INFO_4 = BluetoothServiceInfo(
name="",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",
rssi=-56,
manufacturer_data={
43682: b"\xc1\x01\x00\x01\x01\xe4\x01\x86\x08\x98\x1a\xae\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008151-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5181_VARIANT_SERVICE_INFO_5 = BluetoothServiceInfo(
name="",
address="AA:BB:CC:DD:EE:FF",
rssi=-56,
manufacturer_data={
53579: b"i\x01\x00\x01\x01\xe4\x01\x86\x07l \x1c\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["00008151-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5182_SERVICE_INFO = BluetoothServiceInfo(
name="F34DC3CB-9CCF-336F-3CB1-3C6F525509E6",
address="F34DC3CB-9CCF-336F-3CB1-3C6F525509E6",
rssi=-56,
manufacturer_data={
10032: b"c\x01\x00\x01\x01\xe4\x01\x01\xff\xff\x12\x03\x01"
b"\xff\xff\x00\x00L\x00\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c"
},
service_uuids=["00008251-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5179_SERVICE_INFO = BluetoothServiceInfo(
name="Govee_H5179_3CD5",
address="10F1A254-16A5-9F35-BE40-7034507A6967",
rssi=-50,
manufacturer_data={34817: b"\xec\x00\x01\x01\n\n\xa4\x06d"},
service_data={},
service_uuids=[
"0000180a-0000-1000-8000-00805f9b34fb",
"0000fef5-0000-1000-8000-00805f9b34fb",
"0000ec88-0000-1000-8000-00805f9b34fb",
],
source="local",
)
GVH5179_SERVICE_INFO_2 = BluetoothServiceInfo(
name="GV5179_6319",
address="D1:06:03:06:63:19",
rssi=-68,
manufacturer_data={
1: b"\x01\x01\x03\xb3\x14d",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_data={},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
source="B0:B2:1C:79:AB:80",
)
GVH5074_SERVICE_INFO = BluetoothServiceInfo(
name="Govee_H5074_5FF4",
address="99214D75-854A-E52B-704D-C5C9B7F5D59C",
rssi=-67,
manufacturer_data={
60552: b"\x00\xe6\t\xbc\x12d\x02",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\xc2",
},
service_data={},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
source="local",
)
GVH5178_SERVICE_INFO = BluetoothServiceInfo(
name="B51782BC8",
address="A4:C1:38:75:2B:C8",
rssi=-66,
manufacturer_data={
1: b"\x01\x01\x01\x00\x2a\xf7\x64\x00\x03",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\xc2",
},
service_data={},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
source="local",
)
GVH5178_SERVICE_INFO_ERROR = BluetoothServiceInfo(
name="B51782BC8",
address="A4:C1:38:75:2B:C8",
rssi=-66,
manufacturer_data={
1: b"\x01\x01\x01\x00\x03\xe7\xe4\x00\x01",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\xc2",
},
service_data={},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
source="local",
)
GVH5055_SERVICE_INFO_PROBE_12 = BluetoothServiceInfo(
name="",
address="A4:C1:38:2F:AF:55",
rssi=-63,
manufacturer_data={
44847: b"U\x00d\x01 \x1a\x00\xff\xff\xff\xff \x19\x00\xff\xff\xff\xff\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPr\xf2\xff\xc2",
},
service_uuids=["00005550-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5055_SERVICE_INFO_PROBE_34 = BluetoothServiceInfo(
name="",
address="A4:C1:38:2F:AF:55",
rssi=-63,
manufacturer_data={
44847: b"U\x00d\x4c \x1a\x00\xff\xff\xff\xff \x19\x00\x14\x00\xb1\x00\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPr\xf2\xff\xc2",
},
service_uuids=["00005550-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5055_SERVICE_INFO_PROBE_56 = BluetoothServiceInfo(
name="",
address="A4:C1:38:2F:AF:55",
rssi=-63,
manufacturer_data={
44847: b"U\x00d\xbf \x1a\x00\xff\xff\xb1\x00 \x19\x00\xff\xff\xff\xff\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPr\xf2\xff\xc2",
},
service_uuids=["00005550-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5055_SERVICE_INFO_ERROR = BluetoothServiceInfo(
name="",
address="A4:C1:38:2F:AF:55",
rssi=-63,
manufacturer_data={
44847: b"U\x00d\xfb \x1a\x00\xff\xff\xb1\x00 \x19\x00\xff\xff\xff\xff\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPr\xf2\xff\xc2",
},
service_uuids=["00005550-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5108_SERVICE_INFO = BluetoothServiceInfo(
name="GV51085242",
address="A4:C1:38:75:2B:C8",
rssi=-66,
manufacturer_data={
1: b"\x01\x01\x03\xc70d\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5108_SERVICE_INFO_NO_NAME = BluetoothServiceInfo(
name="G",
address="A4:C1:38:75:2B:C2",
rssi=-66,
manufacturer_data={
1: b"\x01\x01\x03\xc70d\x00\x00",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5106_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5106_4E05",
address="CC:32:37:35:4E:05",
rssi=-66,
manufacturer_data={1: b"\x01\x01\x0e\xd12\x98"},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
NOT_GVH5106_SERVICE_INFO = BluetoothServiceInfo(
name="RZSS",
address="C5:22:77:8E:E0:1A",
rssi=-66,
manufacturer_data={1033: b"\x8cd_d", 1: b"\x01\x01\x0b\x00Xd"},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
)
GVH5103_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5103_5A4E",
address="CB:37:34:36:5A:4E",
manufacturer_data={
1: b"\x01\x01\x03Q>dL\x00\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c"
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
rssi=-45,
)
GVH5105_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5105_7336",
address="D7:35:33:33:73:36",
manufacturer_data={
1: b"\x01\x01\x03:\xeddL\x00\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c"
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
rssi=-45,
)
GVH5105_SERVICE_INFO_2 = BluetoothServiceInfo(
name="GVH5105_7336",
address="D7:35:33:33:73:36",
manufacturer_data={1: b"\x01\x01\x032^d"},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
rssi=-73,
source="local",
)
GVH5100_SERVICE_INFO = BluetoothServiceInfo(
name="GVH5100_7738",
address="C4:35:33:33:77:38",
manufacturer_data={1: b"\x01\x01\x03FTd"},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
rssi=-45,
)
GVH5108_WITH_PROBE_SERVICE_INFO = BluetoothServiceInfo(
name="GV51080C25",
address="CC:38:30:34:0C:25",
manufacturer_data={
1: b"\x01\x01\x03FHd\x00\x00L\x00\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c"
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
service_data={},
source="local",
rssi=-45,
)
GV5126_BUTTON_SERVICE_INFO = BluetoothServiceInfo(
name="GV51260F45",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
61320: b"\x01\xc4\x00\x01k\x98\xd3]\xcb\xbc\x13\x16\xc4\xc9?+\xf9+\xec\x86Y\xce @"
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5126_BUTTON_0_SERVICE_INFO = BluetoothServiceInfo(
name="GV51260F45",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
61320: b"\x01\xc4\x00\x18\xd8\x96\xd1\xff\x10s\x1fL\x85]\xdfT\xf1\xe7\x7f\xe8\x8b\x0e\xc2?"
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5125_BUTTON_0_SERVICE_INFO = BluetoothServiceInfo(
name="GV51255367",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
60552: b"\x01\n.\xaf\xd9085Sg\x01\x01",
61320: b".\xaf\x00\x00b\\\xae\x92\x15\xb6\xa8\n\xd4\x81K\xcaK_s\xd9E40\x02",
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5125_BUTTON_1_SERVICE_INFO = BluetoothServiceInfo(
name="GV51255367",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
60552: b"\x01\n.\xaf\xd9085Sg\x01\x01",
61320: b".\xaf\x00\x00\xfb\x0e\xc9h\xd7\x05l\xaf*\xf3\x1b\xe8w\xf1\xe1\xe8\xe3\xa7\xf8\xc6",
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5122_BUTTON_0_SERVICE_INFO = BluetoothServiceInfo(
name="GV51225634",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
60552: b"\x01\x08\xf3\n\xd2297V4\x01\x05",
61320: b"\xf3\n\x00\x00d\x82H\xe8` b%\x88\xc0/\xd2X\xcb?\x1b\x85D\xd90",
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5123_OPEN_SERVICE_INFO = BluetoothServiceInfo(
name="GV51230B3D",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
61320: b"=\xec\x00\x00\xdeCw\xd5^U\xf9\x91In6\xbd\xc6\x7f\x8b,'\x06t\x97"
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5123_CLOSED_SERVICE_INFO = BluetoothServiceInfo(
name="GV51230B3D",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
61320: b"=\xec\x00\x01Y\xdbk\xd9\xbe\xd7\xaf\xf7*&\xaaK\xd7-\xfa\x94W>[\xe9"
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5121_MOTION_SERVICE_INFO = BluetoothServiceInfo(
name="GV5121195A",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
61320: b"Y\x94\x00\x00\xf0\xb9\x197\xaeP\xb67,\x86j\xc2\xf3\xd0a\xe7\x17\xc0,\xef"
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5121_MOTION_SERVICE_INFO_2 = BluetoothServiceInfo(
name="GV5121195A",
address="C1:37:37:32:0F:45",
rssi=-36,
manufacturer_data={
61320: b"Y\x94\x00\x06\xa3f6e\xc8\xe6\xfdv\x04\xaf\xe7k\xbf\xab\xeb\xbf\xb3\xa3\xd5\x19"
},
service_data={},
service_uuids=[],
source="24:4C:AB:03:E6:B8",
)
GV5122_PASSIVE_SERVICE_INFO = BluetoothServiceInfo(
name="D2:32:39:37:56:34",
address="D2:32:39:37:56:34",
rssi=-68,
manufacturer_data={
61320: b'\xf3\n\x00$\xaa\xea\xa5c\x1b\x81\x08\x99\xe1\xc4\xe1@\x98\x83\xfe"Y5\xc4d'
},
service_data={},
service_uuids=[],
source="08:3A:F2:7B:50:9C",
)
GV5122_PASSIVE_2_SERVICE_INFO = BluetoothServiceInfo(
name="D2:32:39:37:56:34",
address="D2:32:39:37:56:34",
rssi=-68,
manufacturer_data={
61320: b"\xfe~\x00\x00\tL\xa8j\x1a\xf0\xd2\xbcD&\x0b\xd5\xaf4L\x0b\xe5\xc7\xf1\n"
},
service_data={},
service_uuids=[],
source="08:3A:F2:7B:50:9C",
)
GVH5124_SERVICE_INFO = BluetoothServiceInfo(
name="GV51242F68",
address="D3:32:39:37:2F:68",
rssi=-67,
manufacturer_data={
61320: b"\x08\xa2\x00\x01%\xc2YW\xfdzu\x0e\xf24\xa2\x18\xbb\x15F|[s{\x04"
},
service_data={},
service_uuids=[],
source="local",
)
GVH5124_2_SERVICE_INFO = BluetoothServiceInfo(
name="GV51242F68",
address="D3:32:39:37:2F:68",
rssi=-67,
manufacturer_data={
61320: b"\x08\xa2\x00\x13^Sso\xaeC\x9aU\xcf\xd8\x02\x1b\xdf\xd5\xded;+\xd6\x13"
},
service_data={},
service_uuids=[],
source="local",
)
GVH5127_MOTION_SERVICE_INFO = BluetoothServiceInfo(
name="GVH51275E3F",
address="D0:C9:07:1B:5E:3F",
rssi=-61,
manufacturer_data={34819: b"\xec\x00\x01\x01\x01\x11"},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)
GVH5127_PRESENT_SERVICE_INFO = BluetoothServiceInfo(
name="GVH51275E3F",
address="D0:C9:07:1B:5E:3F",
rssi=-60,
manufacturer_data={34819: b"\xec\x00\x01\x01\x01\x01"},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)
GVH5127_ABSENT_SERVICE_INFO = BluetoothServiceInfo(
name="GVH51275E3F",
address="D0:C9:07:1B:5E:3F",
rssi=-53,
manufacturer_data={34819: b"\xec\x00\x01\x01\x00\x00"},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)
GVH5130_OFF_SERVICE_INFO = BluetoothServiceInfo(
name="GV51307479",
address="D3:21:C6:06:74:79",
rssi=-53,
manufacturer_data={
61320: b"Gu\x00\x9b$\xec\xdd\x98j\xa7\xbd\xdaW\xffE\x83\xcd=9s\xe8\x02\xe2N",
60552: b"\x01\rGu\xd3!\xc6\x06ty\x01\x0e",
},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)
GVH5130_ON_SERVICE_INFO = BluetoothServiceInfo(
name="GV51307479",
address="D3:21:C6:06:74:79",
rssi=-53,
manufacturer_data={
61320: b"Gu\x00\xaegP\xfa4GDQFI \x85\xc2v\x10\xea\x02\xb3\xa0\x06?"
},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)
GVH5130_BUTTON_SERVICE_INFO = BluetoothServiceInfo(
name="GV51307479",
address="D3:21:C6:06:74:79",
rssi=-53,
manufacturer_data={
61320: b"Gu\x00\xd6\xa6\xa5\x10\x19\xce\x84\x010\x04\xee\xd9\xb6\xb9\xeb\xe1V\xe8\xb4\xd0\xc1"
},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)
# https://github.com/home-assistant/core/issues/110528#issuecomment-2608907434
GVH5104_ISSUE_110528_SERVICE_INFO_1 = BluetoothServiceInfo(
# reported:
# HA reading:
# 26.1*C
# 15.8% humidity
#
# Govee app reading:
# 19.5 *C (18:50 recording, 18:49 was 19.4*C)
# 62.2% humidity (18:50 reading, 18:51 reading is 62.3%)
name="GVH5104_311C",
address="AA:BB:CC:DD:EE:FF",
service_data={},
source="",
manufacturer_data={
1: b"\x01\x01\x03\xfc&b",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
rssi=-59,
)
GVH5104_ISSUE_110528_SERVICE_INFO_3 = BluetoothServiceInfo(
# reported:
# HA reading: 13.2*C 5.7% humidity
# App reading: 19.6*C 59.4% humidity
name="GVH5104_311C",
address="AA:BB:CC:DD:EE:FF",
service_data={},
source="",
manufacturer_data={
1: b"\x01\x01\x02\x03\xd9^",
76: b"\x02\x15INTELLI_ROCKS_HWPu\xf2\xff\x0c",
},
service_uuids=["0000ec88-0000-1000-8000-00805f9b34fb"],
rssi=-59,
)
def test_can_create():
GoveeBluetoothDeviceData()
def test_gvh5054():
parser = GoveeBluetoothDeviceData()
result = parser.update(GVH5104_ISSUE_110528_SERVICE_INFO_1)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5104 311C",
model="H5104",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=26.1,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=98,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=15.8,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-59,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={},
)
result = parser.update(GVH5104_ISSUE_110528_SERVICE_INFO_3)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5104 311C",
model="H5104",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=13.2,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=94,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=5.7,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-59,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={},
)
def test_gvh5051():
parser = GoveeBluetoothDeviceData()
service_info = GVH5051_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5051 8105",
model="H5051",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=27.46,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=40.89,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=99,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5052():
parser = GoveeBluetoothDeviceData()
service_info = GVH5052_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5052 E81B",
model="H5052",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=2.84,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=52.87,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=59,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5071():
parser = GoveeBluetoothDeviceData()
service_info = GVH5071_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5071 FD12",
model="H5071",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=25.93,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=47.9,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=24,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5075():
parser = GoveeBluetoothDeviceData()
service_info = GVH5075_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5075 2762",
model="H5075",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=21.3,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=44.2,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5075_2():
parser = GoveeBluetoothDeviceData()
service_info = GVH5075_SERVICE_INFO_2
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5075 DBF8",
model="H5075",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=21.6,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=49.8,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5075_negative_values():
parser = GoveeBluetoothDeviceData()
service_info = GVH5075_SERVICE_INFO_NEGATIVE_VALUES
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5075 2762",
model="H5075",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value="error",
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value="error",
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=62,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5075_oversized_values():
parser = GoveeBluetoothDeviceData()
service_info = GVH5075_SERVICE_INFO_OVERSIZED_VALUES
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5075 2762",
model="H5075",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value="error",
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value="error",
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=59,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5075_other_values():
parser = GoveeBluetoothDeviceData()
service_info = GVH5075_SERVICE_INFO_OTHER_VALUES
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5075 2762",
model="H5075",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=20.0,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=64.9,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=53,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5177():
parser = GoveeBluetoothDeviceData()
service_info = GVH5177_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5177 2EC8",
model="H5177",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=21.0,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=47.0,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5103():
parser = GoveeBluetoothDeviceData()
service_info = GVH5103_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5103 5A4E",
model="H5103",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=21.7,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=40.6,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-45,
),
},
)
def test_gvh5105():
parser = GoveeBluetoothDeviceData()
service_info = GVH5105_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5105 7336",
model="H5105",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=21.1,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=69.3,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-45,
),
},
)
def test_gvh5105_2():
parser = GoveeBluetoothDeviceData()
service_info = GVH5105_SERVICE_INFO_2
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5105 7336",
model="H5105",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=20.9,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=50.2,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-73,
),
},
)
def test_gvh5100():
parser = GoveeBluetoothDeviceData()
service_info = GVH5100_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5100 7738",
model="H5100",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=21.4,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=61.2,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-45,
),
},
)
def test_gvh5108_with_external_probe():
parser = GoveeBluetoothDeviceData()
service_info = GVH5108_WITH_PROBE_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51080C25",
model="H5108",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=21.4,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=60.0,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-45,
),
},
)
def test_gvh5126_button_1():
parser = GoveeBluetoothDeviceData()
service_info = GV5126_BUTTON_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 2
assert parser.sleepy is True
assert parser.sensor_type is SensorType.BUTTON
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51260F45",
model="H5126",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="button_1", device_id=None): Event(
device_key=DeviceKey(key="button_1", device_id=None),
name="Button 1",
event_type="press",
event_properties=None,
)
},
)
def test_gvh5126_button_0():
parser = GoveeBluetoothDeviceData()
service_info = GV5126_BUTTON_0_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 2
assert parser.sensor_type is SensorType.BUTTON
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51260F45",
model="H5126",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="button_0", device_id=None): Event(
device_key=DeviceKey(key="button_0", device_id=None),
name="Button 0",
event_type="press",
event_properties=None,
)
},
)
def test_gvh5125_button_0():
parser = GoveeBluetoothDeviceData()
service_info = GV5125_BUTTON_0_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 6
assert parser.sensor_type is SensorType.BUTTON
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51250F45",
model="H5125",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="button_0", device_id=None): Event(
device_key=DeviceKey(key="button_0", device_id=None),
name="Button 0",
event_type="press",
event_properties=None,
)
},
)
def test_gvh5125_button_1():
parser = GoveeBluetoothDeviceData()
service_info = GV5125_BUTTON_1_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 6
assert parser.sensor_type is SensorType.BUTTON
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51250F45",
model="H5125",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="button_1", device_id=None): Event(
device_key=DeviceKey(key="button_1", device_id=None),
name="Button 1",
event_type="press",
event_properties=None,
)
},
)
def test_gvh5122_button_0():
parser = GoveeBluetoothDeviceData()
service_info = GV5122_BUTTON_0_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 1
assert parser.sensor_type is SensorType.BUTTON
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51220F45",
model="H5122",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="button_0", device_id=None): Event(
device_key=DeviceKey(key="button_0", device_id=None),
name="Button 0",
event_type="press",
event_properties=None,
)
},
)
def test_gvh5122_passive_button_0():
parser = GoveeBluetoothDeviceData()
service_info = GV5122_PASSIVE_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 1
assert parser.sensor_type is SensorType.BUTTON
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51225634",
model="H5122",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-68,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="button_0", device_id=None): Event(
device_key=DeviceKey(key="button_0", device_id=None),
name="Button 0",
event_type="press",
event_properties=None,
)
},
)
def test_gvh5122_passive_2_button_0():
parser = GoveeBluetoothDeviceData()
service_info = GV5122_PASSIVE_2_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 1
assert parser.sensor_type is SensorType.BUTTON
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51225634",
model="H5122",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-68,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="button_0", device_id=None): Event(
device_key=DeviceKey(key="button_0", device_id=None),
name="Button 0",
event_type="press",
event_properties=None,
)
},
)
def test_gvh5123_open():
parser = GoveeBluetoothDeviceData()
service_info = GV5123_OPEN_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51230F45",
model="H5123",
manufacturer="Govee",
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="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
},
binary_entity_descriptions={
DeviceKey(key="window", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="window", device_id=None),
device_class=BinarySensorDeviceClass.WINDOW,
)
},
binary_entity_values={
DeviceKey(key="window", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="window", device_id=None),
name="Window",
native_value=True,
)
},
events={},
)
def test_gvh5123_closed():
parser = GoveeBluetoothDeviceData()
service_info = GV5123_CLOSED_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.WINDOW
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51230F45",
model="H5123",
manufacturer="Govee",
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="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
},
binary_entity_descriptions={
DeviceKey(key="window", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="window", device_id=None),
device_class=BinarySensorDeviceClass.WINDOW,
)
},
binary_entity_values={
DeviceKey(key="window", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="window", device_id=None),
name="Window",
native_value=False,
)
},
events={},
)
def test_gvh5124_vibrating():
parser = GoveeBluetoothDeviceData()
service_info = GVH5124_SERVICE_INFO
result = parser.update(service_info)
assert parser.sensor_type is SensorType.VIBRATION
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51242F68",
model="H5124",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-67,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="vibration", device_id=None): Event(
device_key=DeviceKey(key="vibration", device_id=None),
name="Vibration",
event_type="vibration",
event_properties=None,
)
},
)
def test_gvh5124_vibrating_2():
parser = GoveeBluetoothDeviceData()
service_info = GVH5124_2_SERVICE_INFO
result = parser.update(service_info)
assert parser.sensor_type is SensorType.VIBRATION
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51242F68",
model="H5124",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-67,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="vibration", device_id=None): Event(
device_key=DeviceKey(key="vibration", device_id=None),
name="Vibration",
event_type="vibration",
event_properties=None,
)
},
)
def test_gvh5121_motion():
parser = GoveeBluetoothDeviceData()
service_info = GV5121_MOTION_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.MOTION
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51210F45",
model="H5121",
manufacturer="Govee",
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="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="motion", device_id=None): Event(
device_key=DeviceKey(key="motion", device_id=None),
name="Motion",
event_type="motion",
event_properties=None,
)
},
)
def test_gvh5121_motion_2():
parser = GoveeBluetoothDeviceData()
service_info = GV5121_MOTION_SERVICE_INFO_2
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.MOTION
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51210F45",
model="H5121",
manufacturer="Govee",
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="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-36,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="motion", device_id=None): Event(
device_key=DeviceKey(key="motion", device_id=None),
name="Motion",
event_type="motion",
event_properties=None,
)
},
)
def test_gvh5184_packet_type_1():
parser = GoveeBluetoothDeviceData()
result = parser.update(GVH5184_SERVICE_INFO_1)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5184 AC3D",
model="H5184",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_2", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=31.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=0.0,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
name="Temperature Probe 2",
native_value=28.0,
),
DeviceKey(key="temperature_alarm_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
name="Temperature Alarm Probe 2",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5184_packet_type_2():
parser = GoveeBluetoothDeviceData()
result = parser.update(GVH5184_SERVICE_INFO_2)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5184 AC3D",
model="H5184",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_3", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_3", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_3", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_3", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_4", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_4", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_4", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_4", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_3", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_3", device_id=None),
name="Temperature Probe 3",
native_value=30.0,
),
DeviceKey(key="temperature_alarm_probe_3", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_3", device_id=None),
name="Temperature Alarm Probe 3",
native_value=0.0,
),
DeviceKey(key="temperature_probe_4", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_4", device_id=None),
name="Temperature Probe 4",
native_value=29.0,
),
DeviceKey(key="temperature_alarm_probe_4", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_4", device_id=None),
name="Temperature Alarm Probe 4",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5185():
parser = GoveeBluetoothDeviceData()
service_info = GVH5185_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5185 AC3D",
model="H5185",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_2", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=21.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=0.0,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
name="Temperature Probe 2",
native_value=21.0,
),
DeviceKey(key="temperature_alarm_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
name="Temperature Alarm Probe 2",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5185_variant():
parser = GoveeBluetoothDeviceData()
service_info = GVH5185_VARIANT_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5185 AC3D",
model="H5185",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(
key="temperature_alarm_probe_2", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
},
entity_values={
DeviceKey(key="temperature_alarm_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
name="Temperature Alarm Probe 2",
native_value=0.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=0.0,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=25.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
name="Temperature Probe 2",
native_value=25.0,
),
},
)
def test_gvh5185_2_variant():
parser = GoveeBluetoothDeviceData()
service_info = GVH5185_VARIANT_2_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5185 AC3D",
model="H5185",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(
key="temperature_alarm_probe_2", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_alarm_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
name="Temperature Alarm Probe 2",
native_value=0.0,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=0.0,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
name="Temperature Probe 2",
native_value=0.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
binary_entity_descriptions={},
binary_entity_values={},
)
def test_gvh5183():
parser = GoveeBluetoothDeviceData()
service_info = GVH5183_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5183 AC3D",
model="H5183",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=21.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5183_no_local_name():
parser = GoveeBluetoothDeviceData()
service_info = GVH5183_NO_LOCAL_NAME_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5183 AC3D",
model="H5183",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=21.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5183_variant():
parser = GoveeBluetoothDeviceData()
service_info = GVH5183_SERVICE_INFO_VARIANT
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5183 AC3D",
model="H5183",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=28.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=0.0,
),
},
binary_entity_descriptions={},
binary_entity_values={},
)
def test_gvh5181():
parser = GoveeBluetoothDeviceData()
service_info = GVH5181_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5181 AC3D",
model="H5181",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=22.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=74.4,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5181_variant():
parser = GoveeBluetoothDeviceData()
service_info = GVH5181_VARIANT_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5181 AC3D",
model="H5181",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=0.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=74.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5181_variant_2():
parser = GoveeBluetoothDeviceData()
service_info = GVH5181_VARIANT_SERVICE_INFO_2
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5181 AC3D",
model="H5181",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=26.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=74.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5181_variant_3():
parser = GoveeBluetoothDeviceData()
service_info = GVH5181_VARIANT_SERVICE_INFO_3
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5181 AC3D",
model="H5181",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=73.8,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
binary_entity_descriptions={},
binary_entity_values={},
)
def test_gvh5181_variant_4():
parser = GoveeBluetoothDeviceData()
service_info = GVH5181_VARIANT_SERVICE_INFO_4
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5181 AC3D",
model="H5181",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=22.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=68.3,
),
},
binary_entity_descriptions={},
binary_entity_values={},
)
def test_gvh5181_variant_5():
parser = GoveeBluetoothDeviceData()
service_info = GVH5181_VARIANT_SERVICE_INFO_5
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5181 EEFF",
model="H5181",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
},
entity_values={
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=82.2,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=19.0,
),
},
binary_entity_descriptions={},
binary_entity_values={},
)
def test_gvh5182():
parser = GoveeBluetoothDeviceData()
service_info = GVH5182_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5182 09E6",
model="H5182",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_2", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=0.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=46.11,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
name="Temperature Probe 2",
native_value=0.0,
),
DeviceKey(key="temperature_alarm_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
name="Temperature Alarm Probe 2",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5179():
parser = GoveeBluetoothDeviceData()
service_info = GVH5179_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5179 3CD5",
model="H5179",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=25.7,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=17.0,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-50,
),
},
)
def test_gvh5179_2():
parser = GoveeBluetoothDeviceData()
service_info = GVH5179_SERVICE_INFO_2
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="5179 6319",
model="GV5179",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=24.2,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=45.2,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-68,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={},
)
def test_gvh5074():
parser = GoveeBluetoothDeviceData()
service_info = GVH5074_SERVICE_INFO
result = parser.update(service_info)
assert parser.sleepy is False
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5074 5FF4",
model="H5074",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=25.34,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=47.96,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-67,
),
},
)
def test_gvh5178():
parser = GoveeBluetoothDeviceData()
service_info = GVH5178_SERVICE_INFO
result = parser.update(service_info)
assert parser.device_type == "H5178"
assert result == SensorUpdate(
title="B51782BC8",
devices={
None: SensorDeviceInfo(
name=None,
model=None,
manufacturer="Govee",
sw_version=None,
hw_version=None,
),
"remote": SensorDeviceInfo(
name="B51782BC8 Remote",
model="H5178-REMOTE",
manufacturer="Govee",
sw_version=None,
hw_version=None,
),
},
entity_descriptions={
DeviceKey(key="temperature", device_id="remote"): SensorDescription(
device_key=DeviceKey(key="temperature", device_id="remote"),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id="remote"): SensorDescription(
device_key=DeviceKey(key="humidity", device_id="remote"),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id="remote"): SensorDescription(
device_key=DeviceKey(key="battery", device_id="remote"),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id="remote"): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id="remote"),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id="remote"): SensorValue(
device_key=DeviceKey(key="temperature", device_id="remote"),
name="Temperature",
native_value=1.0,
),
DeviceKey(key="humidity", device_id="remote"): SensorValue(
device_key=DeviceKey(key="humidity", device_id="remote"),
name="Humidity",
native_value=99.9,
),
DeviceKey(key="battery", device_id="remote"): SensorValue(
device_key=DeviceKey(key="battery", device_id="remote"),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id="remote"): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id="remote"),
name="Signal Strength",
native_value=-66,
),
},
)
def test_gvh5178_error():
parser = GoveeBluetoothDeviceData()
service_info = GVH5178_SERVICE_INFO_ERROR
result = parser.update(service_info)
assert result == SensorUpdate(
title="B51782BC8",
devices={
None: SensorDeviceInfo(
name=None,
model=None,
manufacturer="Govee",
sw_version=None,
hw_version=None,
),
"remote": SensorDeviceInfo(
name="B51782BC8 Remote",
model="H5178-REMOTE",
manufacturer="Govee",
sw_version=None,
hw_version=None,
),
},
entity_descriptions={
DeviceKey(key="temperature", device_id="remote"): SensorDescription(
device_key=DeviceKey(key="temperature", device_id="remote"),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id="remote"): SensorDescription(
device_key=DeviceKey(key="humidity", device_id="remote"),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id="remote"): SensorDescription(
device_key=DeviceKey(key="battery", device_id="remote"),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id="remote"): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id="remote"),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id="remote"): SensorValue(
device_key=DeviceKey(key="temperature", device_id="remote"),
name="Temperature",
native_value="error",
),
DeviceKey(key="humidity", device_id="remote"): SensorValue(
device_key=DeviceKey(key="humidity", device_id="remote"),
name="Humidity",
native_value="error",
),
DeviceKey(key="battery", device_id="remote"): SensorValue(
device_key=DeviceKey(key="battery", device_id="remote"),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id="remote"): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id="remote"),
name="Signal Strength",
native_value=-66,
),
},
)
def test_gvh5198_probe_1_2():
parser = GoveeBluetoothDeviceData()
service_info = GVH5198_VARIANT_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5198 AC3D",
model="H5198",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="low_temperature_alarm_probe_1", device_id=None
): SensorDescription(
device_key=DeviceKey(
key="low_temperature_alarm_probe_1", device_id=None
),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_2", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="low_temperature_alarm_probe_2", device_id=None
): SensorDescription(
device_key=DeviceKey(
key="low_temperature_alarm_probe_2", device_id=None
),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=30.0,
),
DeviceKey(key="temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_1", device_id=None),
name="Temperature Alarm Probe 1",
native_value=0.0,
),
DeviceKey(key="low_temperature_alarm_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(
key="low_temperature_alarm_probe_1", device_id=None
),
name="Low Temperature Alarm Probe 1",
native_value=0.0,
),
DeviceKey(key="temperature_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_2", device_id=None),
name="Temperature Probe 2",
native_value=24.0,
),
DeviceKey(key="temperature_alarm_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_2", device_id=None),
name="Temperature Alarm Probe 2",
native_value=0.0,
),
DeviceKey(key="low_temperature_alarm_probe_2", device_id=None): SensorValue(
device_key=DeviceKey(
key="low_temperature_alarm_probe_2", device_id=None
),
name="Low Temperature Alarm Probe 2",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5198_probe_3_4():
parser = GoveeBluetoothDeviceData()
service_info = GVH5198_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5198 AC3D",
model="H5198",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_3", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_3", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_3", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_3", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="low_temperature_alarm_probe_3", device_id=None
): SensorDescription(
device_key=DeviceKey(
key="low_temperature_alarm_probe_3", device_id=None
),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_4", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_4", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_4", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_4", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="low_temperature_alarm_probe_4", device_id=None
): SensorDescription(
device_key=DeviceKey(
key="low_temperature_alarm_probe_4", device_id=None
),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_3", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_3", device_id=None),
name="Temperature Probe 3",
native_value=36.0,
),
DeviceKey(key="temperature_alarm_probe_3", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_3", device_id=None),
name="Temperature Alarm Probe 3",
native_value=0.0,
),
DeviceKey(key="low_temperature_alarm_probe_3", device_id=None): SensorValue(
device_key=DeviceKey(
key="low_temperature_alarm_probe_3", device_id=None
),
name="Low Temperature Alarm Probe 3",
native_value=0.0,
),
DeviceKey(key="temperature_probe_4", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_4", device_id=None),
name="Temperature Probe 4",
native_value=23.0,
),
DeviceKey(key="temperature_alarm_probe_4", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_4", device_id=None),
name="Temperature Alarm Probe 4",
native_value=0.0,
),
DeviceKey(key="low_temperature_alarm_probe_4", device_id=None): SensorValue(
device_key=DeviceKey(
key="low_temperature_alarm_probe_4", device_id=None
),
name="Low Temperature Alarm Probe 4",
native_value=0.0,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5198_invalid():
parser = GoveeBluetoothDeviceData()
service_info = GVH5198_INVALID_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5198 AC3D",
model="H5198",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-56,
),
},
)
def test_gvh5075_debug_hex(caplog):
parser = GoveeBluetoothDeviceData()
service_info = GVH5075_SERVICE_INFO
with caplog.at_level(logging.DEBUG):
parser.update(service_info)
assert (
"Parsing Govee sensor: 60552 b'\\x00\\x03\\x41\\xc2\\x64\\x00\\x4c\\x00\\x02\\x15\\x49\\x4e\\x54"
"\\x45\\x4c\\x4c\\x49\\x5f\\x52\\x4f\\x43\\x4b\\x53\\x5f\\x48\\x57\\x50\\x75\\xf2\\xff\\x0c'"
in caplog.text
)
def test_gvh5055_probe_1_2():
parser = GoveeBluetoothDeviceData()
result = parser.update(GVH5055_SERVICE_INFO_PROBE_12)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5055 AF55",
model="H5055",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_1", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_1", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_1", device_id=None),
name="Temperature Probe 1",
native_value=26,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5055_probe_3_4():
parser = GoveeBluetoothDeviceData()
result = parser.update(GVH5055_SERVICE_INFO_PROBE_34)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5055 AF55",
model="H5055",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_3", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_3", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_4", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_4", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_4", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_4", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="low_temperature_alarm_probe_4", device_id=None
): SensorDescription(
device_key=DeviceKey(
key="low_temperature_alarm_probe_4", device_id=None
),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_3", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_3", device_id=None),
name="Temperature Probe 3",
native_value=26,
),
DeviceKey(key="temperature_probe_4", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_4", device_id=None),
name="Temperature Probe 4",
native_value=25,
),
DeviceKey(key="temperature_alarm_probe_4", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_4", device_id=None),
name="Temperature Alarm Probe 4",
native_value=177.0,
),
DeviceKey(key="low_temperature_alarm_probe_4", device_id=None): SensorValue(
device_key=DeviceKey(
key="low_temperature_alarm_probe_4", device_id=None
),
name="Low Temperature Alarm Probe 4",
native_value=20.0,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5055_probe_5_6():
parser = GoveeBluetoothDeviceData()
result = parser.update(GVH5055_SERVICE_INFO_PROBE_56)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5055 AF55",
model="H5055",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature_probe_5", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_5", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="temperature_probe_6", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature_probe_6", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(
key="temperature_alarm_probe_5", device_id=None
): SensorDescription(
device_key=DeviceKey(key="temperature_alarm_probe_5", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature_probe_5", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_5", device_id=None),
name="Temperature Probe 5",
native_value=26,
),
DeviceKey(key="temperature_probe_6", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_probe_6", device_id=None),
name="Temperature Probe 6",
native_value=25,
),
DeviceKey(key="temperature_alarm_probe_5", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature_alarm_probe_5", device_id=None),
name="Temperature Alarm Probe 5",
native_value=177.0,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-63,
),
},
)
def test_gvh5055_error(caplog):
parser = GoveeBluetoothDeviceData()
service_info = GVH5055_SERVICE_INFO_ERROR
with caplog.at_level(logging.DEBUG):
parser.update(service_info)
print(caplog.text)
assert (
"Parsing Govee sensor: 44847 b'\\x55\\x00\\x64\\xfb\\x20\\x1a\\x00\\xff\\xff\\xb1"
"\\x00\\x20\\x19\\x00\\xff\\xff\\xff\\xff\\x00\\x00'" in caplog.text
)
def test_gvh5108():
parser = GoveeBluetoothDeviceData()
service_info = GVH5108_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51085242",
model="H5108",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=24.7,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=60.00,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-66,
),
},
)
def test_gvh5108_no_name():
parser = GoveeBluetoothDeviceData()
service_info = GVH5108_SERVICE_INFO_NO_NAME
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name=None,
model="H5108",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=DeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=24.7,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=60.00,
),
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-66,
),
},
)
def test_gvh5106():
parser = GoveeBluetoothDeviceData()
service_info = GVH5106_SERVICE_INFO
result = parser.update(service_info)
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H5106 4E05",
model="H5106",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="temperature", device_id=None): SensorDescription(
device_key=DeviceKey(key="temperature", device_id=None),
device_class=DeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
DeviceKey(key="humidity", device_id=None): SensorDescription(
device_key=DeviceKey(key="humidity", device_id=None),
device_class=DeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="pm25", device_id=None): SensorDescription(
device_key=DeviceKey(key="pm25", device_id=None),
device_class=DeviceClass.PM25,
native_unit_of_measurement=Units.CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=DeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="temperature", device_id=None): SensorValue(
device_key=DeviceKey(key="temperature", device_id=None),
name="Temperature",
native_value=24.8,
),
DeviceKey(key="humidity", device_id=None): SensorValue(
device_key=DeviceKey(key="humidity", device_id=None),
name="Humidity",
native_value=59.1,
),
DeviceKey(key="pm25", device_id=None): SensorValue(
device_key=DeviceKey(key="pm25", device_id=None),
name="Pm25",
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=-66,
),
},
)
def test_not_gvh5106():
parser = GoveeBluetoothDeviceData()
service_info = NOT_GVH5106_SERVICE_INFO
assert not parser.supported(service_info)
def test_get_model_info():
assert get_model_info("H5074").sensor_type == SensorType.THERMOMETER
assert get_model_info("H5075").sensor_type == SensorType.THERMOMETER
assert get_model_info("H5072").sensor_type == SensorType.THERMOMETER
assert get_model_info("H5121").sensor_type == SensorType.MOTION
assert get_model_info("H5122").sensor_type == SensorType.BUTTON
assert get_model_info("H5122").button_count == 1
assert get_model_info("H5123").sensor_type == SensorType.WINDOW
assert get_model_info("H5125").sensor_type == SensorType.BUTTON
assert get_model_info("H5125").button_count == 6
assert get_model_info("H5126").sensor_type == SensorType.BUTTON
assert get_model_info("H5126").button_count == 2
assert get_model_info("H5124").sensor_type == SensorType.VIBRATION
assert get_model_info("H5127").sensor_type == SensorType.PRESENCE
def test_gvh5127_motion():
parser = GoveeBluetoothDeviceData()
service_info = GVH5127_MOTION_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.PRESENCE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H51275E3F",
model="H5127",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
)
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-61,
)
},
binary_entity_descriptions={
DeviceKey(key="occupancy", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="occupancy", device_id=None),
device_class=BinarySensorDeviceClass.OCCUPANCY,
),
DeviceKey(key="motion", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="motion", device_id=None),
device_class=BinarySensorDeviceClass.MOTION,
),
},
binary_entity_values={
DeviceKey(key="occupancy", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="occupancy", device_id=None),
name="Occupancy",
native_value=True,
),
DeviceKey(key="motion", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="motion", device_id=None),
name="Motion",
native_value=True,
),
},
events={},
)
def test_gvh5127_presence():
parser = GoveeBluetoothDeviceData()
service_info = GVH5127_PRESENT_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.PRESENCE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H51275E3F",
model="H5127",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
)
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-60,
)
},
binary_entity_descriptions={
DeviceKey(key="occupancy", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="occupancy", device_id=None),
device_class=BinarySensorDeviceClass.OCCUPANCY,
),
DeviceKey(key="motion", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="motion", device_id=None),
device_class=BinarySensorDeviceClass.MOTION,
),
},
binary_entity_values={
DeviceKey(key="occupancy", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="occupancy", device_id=None),
name="Occupancy",
native_value=True,
),
DeviceKey(key="motion", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="motion", device_id=None),
name="Motion",
native_value=False,
),
},
events={},
)
def test_gvh5127_absent():
parser = GoveeBluetoothDeviceData()
service_info = GVH5127_ABSENT_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.PRESENCE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H51275E3F",
model="H5127",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
)
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-53,
)
},
binary_entity_descriptions={
DeviceKey(key="occupancy", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="occupancy", device_id=None),
device_class=BinarySensorDeviceClass.OCCUPANCY,
),
DeviceKey(key="motion", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="motion", device_id=None),
device_class=BinarySensorDeviceClass.MOTION,
),
},
binary_entity_values={
DeviceKey(key="occupancy", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="occupancy", device_id=None),
name="Occupancy",
native_value=False,
),
DeviceKey(key="motion", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="motion", device_id=None),
name="Motion",
native_value=False,
),
},
events={},
)
def test_gvh5130_no_pressure_detected():
parser = GoveeBluetoothDeviceData()
service_info = GVH5130_OFF_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 1
assert parser.sensor_type is SensorType.PRESSURE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51307479",
model="H5130",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-53,
),
},
binary_entity_descriptions={
DeviceKey(key="presence", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="presence", device_id=None),
device_class=BinarySensorDeviceClass.PRESENCE,
)
},
binary_entity_values={
DeviceKey(key="presence", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="presence", device_id=None),
name="Presence",
native_value=False,
)
},
events={},
)
def test_gvh5130_pressure_detected():
parser = GoveeBluetoothDeviceData()
service_info = GVH5130_ON_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 1
assert parser.sensor_type is SensorType.PRESSURE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51307479",
model="H5130",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-53,
),
},
binary_entity_descriptions={
DeviceKey(key="presence", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="presence", device_id=None),
device_class=BinarySensorDeviceClass.PRESENCE,
)
},
binary_entity_values={
DeviceKey(key="presence", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="presence", device_id=None),
name="Presence",
native_value=True,
)
},
events={},
)
def test_gvh5130_button():
parser = GoveeBluetoothDeviceData()
service_info = GVH5130_BUTTON_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 1
assert parser.sensor_type is SensorType.PRESSURE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="51307479",
model="H5130",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="battery", device_id=None): SensorDescription(
device_key=DeviceKey(key="battery", device_id=None),
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=Units.PERCENTAGE,
),
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
DeviceKey(key="battery", device_id=None): SensorValue(
device_key=DeviceKey(key="battery", device_id=None),
name="Battery",
native_value=100,
),
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal Strength",
native_value=-53,
),
},
binary_entity_descriptions={},
binary_entity_values={},
events={
DeviceKey(key="button_0", device_id=None): Event(
device_key=DeviceKey(key="button_0", device_id=None),
name="Button 0",
event_type="press",
event_properties=None,
)
},
)