├── tests └── __init__.py ├── src └── govee_ble │ ├── py.typed │ ├── __init__.py │ └── parser.py ├── docs ├── source │ ├── _static │ │ └── .gitkeep │ ├── changelog.md │ ├── contributing.md │ ├── usage.md │ ├── installation.md │ ├── index.md │ └── conf.py ├── Makefile └── make.bat ├── .flake8 ├── renovate.json ├── .gitpod.yml ├── setup.py ├── commitlint.config.mjs ├── .all-contributorsrc ├── .github ├── ISSUE_TEMPLATE │ ├── 1-bug_report.md │ └── 2-feature-request.md ├── workflows │ ├── hacktoberfest.yml │ ├── labels.yml │ ├── issue-manager.yml │ └── ci.yml ├── dependabot.yml └── labels.toml ├── .idea ├── govee-ble.iml ├── workspace.xml └── watcherTasks.xml ├── .editorconfig ├── .readthedocs.yml ├── .pre-commit-config.yaml ├── .gitignore ├── pyproject.toml ├── README.md ├── CONTRIBUTING.md ├── LICENSE └── CHANGELOG.md /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/govee_ble/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/source/_static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | exclude = docs 3 | max-line-length = 120 4 | -------------------------------------------------------------------------------- /docs/source/changelog.md: -------------------------------------------------------------------------------- 1 | ```{include} ../../CHANGELOG.md 2 | 3 | ``` 4 | -------------------------------------------------------------------------------- /docs/source/contributing.md: -------------------------------------------------------------------------------- 1 | ```{include} ../../CONTRIBUTING.md 2 | 3 | ``` 4 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["github>browniebroke/renovate-configs:python"] 3 | } 4 | -------------------------------------------------------------------------------- /docs/source/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | To use this package, import it: 4 | 5 | ```python 6 | import govee_ble 7 | ``` 8 | 9 | TODO: Document usage 10 | -------------------------------------------------------------------------------- /docs/source/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | The package is published on [PyPI](https://pypi.org/project/deezer-python/) and can be installed with `pip` (or any equivalent): 4 | 5 | ```bash 6 | pip install govee-ble 7 | ``` 8 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - command: | 3 | pip install poetry 4 | PIP_USER=false poetry install 5 | - command: | 6 | pip install pre-commit 7 | pre-commit install 8 | PIP_USER=false pre-commit install-hooks 9 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This is a shim to allow GitHub to detect the package, build is done with poetry 4 | # Taken from https://github.com/Textualize/rich 5 | 6 | import setuptools 7 | 8 | if __name__ == "__main__": 9 | setuptools.setup(name="govee-ble") 10 | -------------------------------------------------------------------------------- /commitlint.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | extends: ["@commitlint/config-conventional"], 3 | rules: { 4 | "header-max-length": [0, "always", Infinity], 5 | "body-max-line-length": [0, "always", Infinity], 6 | "footer-max-line-length": [0, "always", Infinity], 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /docs/source/index.md: -------------------------------------------------------------------------------- 1 | # Welcome to Govee BLE documentation! 2 | 3 | ```{toctree} 4 | :caption: Installation & Usage 5 | :maxdepth: 2 6 | 7 | installation 8 | usage 9 | ``` 10 | 11 | ```{toctree} 12 | :caption: Project Info 13 | :maxdepth: 2 14 | 15 | changelog 16 | contributing 17 | ``` 18 | 19 | ```{include} ../../README.md 20 | 21 | ``` 22 | -------------------------------------------------------------------------------- /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "govee-ble", 3 | "projectOwner": "bluetooth-devices", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": ["README.md"], 7 | "imageSize": 80, 8 | "commit": true, 9 | "commitConvention": "angular", 10 | "contributors": [], 11 | "contributorsPerLine": 7, 12 | "skipCi": true 13 | } 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | labels: bug 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 13 | **Additional context** 14 | Add any other context about the problem here. 15 | -------------------------------------------------------------------------------- /.idea/govee-ble.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 4 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | charset = utf-8 11 | end_of_line = lf 12 | 13 | [*.bat] 14 | indent_style = tab 15 | end_of_line = crlf 16 | 17 | [LICENSE] 18 | insert_final_newline = false 19 | 20 | [Makefile] 21 | indent_style = tab 22 | -------------------------------------------------------------------------------- /.github/workflows/hacktoberfest.yml: -------------------------------------------------------------------------------- 1 | name: Hacktoberfest 2 | 3 | on: 4 | schedule: 5 | # Run every day in October 6 | - cron: "0 0 * 10 *" 7 | # Run on the 1st of November to revert 8 | - cron: "0 13 1 11 *" 9 | 10 | jobs: 11 | hacktoberfest: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: browniebroke/hacktoberfest-labeler-action@v2.3.0 16 | with: 17 | github_token: ${{ secrets.GH_PAT }} 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | labels: enhancement 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Additional context** 14 | Add any other context or screenshots about the feature request here. 15 | -------------------------------------------------------------------------------- /.github/workflows/labels.yml: -------------------------------------------------------------------------------- 1 | name: Sync Github labels 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - ".github/**" 9 | 10 | jobs: 11 | labels: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v5 15 | - name: Set up Python 16 | uses: actions/setup-python@v6 17 | with: 18 | python-version: 3.8 19 | - name: Install labels 20 | run: pip install labels 21 | - name: Sync config with Github 22 | run: labels -u ${{ github.repository_owner }} -t ${{ secrets.GITHUB_TOKEN }} sync -f .github/labels.toml 23 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Build documentation in the docs/ directory with Sphinx 8 | sphinx: 9 | configuration: docs/source/conf.py 10 | 11 | # Set the version of Python and other tools you might need 12 | build: 13 | os: ubuntu-20.04 14 | tools: 15 | python: "3.9" 16 | 17 | # Optionally declare the Python requirements required to build your docs 18 | python: 19 | install: 20 | - method: pip 21 | path: . 22 | extra_requirements: 23 | - docs 24 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "monthly" 12 | commit-message: 13 | prefix: "chore(ci): " 14 | groups: 15 | github-actions: 16 | patterns: 17 | - "*" 18 | - package-ecosystem: "pip" # See documentation for possible values 19 | directory: "/" # Location of package manifests 20 | schedule: 21 | interval: "weekly" 22 | -------------------------------------------------------------------------------- /.github/workflows/issue-manager.yml: -------------------------------------------------------------------------------- 1 | name: Issue Manager 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | issue_comment: 7 | types: 8 | - created 9 | issues: 10 | types: 11 | - labeled 12 | pull_request_target: 13 | types: 14 | - labeled 15 | workflow_dispatch: 16 | 17 | jobs: 18 | issue-manager: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: tiangolo/issue-manager@0.5.1 22 | with: 23 | token: ${{ secrets.GITHUB_TOKEN }} 24 | config: > 25 | { 26 | "answered": { 27 | "message": "Assuming the original issue was solved, it will be automatically closed now." 28 | }, 29 | "waiting": { 30 | "message": "Automatically closing. To re-open, please provide the additional information requested." 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /src/govee_ble/__init__.py: -------------------------------------------------------------------------------- 1 | """Parser for Govee BLE advertisements. 2 | 3 | This file is shamelessly copied from the following repository: 4 | https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/govee.py 5 | 6 | MIT License applies. 7 | """ 8 | 9 | from __future__ import annotations 10 | 11 | from sensor_state_data import ( 12 | BinarySensorDeviceClass, 13 | BinarySensorValue, 14 | DeviceKey, 15 | SensorDescription, 16 | SensorDeviceClass, 17 | SensorDeviceInfo, 18 | SensorUpdate, 19 | SensorValue, 20 | Units, 21 | ) 22 | from sensor_state_data import ( 23 | DeviceClass, 24 | ) 25 | 26 | from .parser import GoveeBluetoothDeviceData, SensorType, get_model_info, ModelInfo 27 | 28 | __version__ = "1.0.0" 29 | 30 | __all__ = [ 31 | "GoveeBluetoothDeviceData", 32 | "BinarySensorDeviceClass", 33 | "SensorDeviceClass", 34 | "BinarySensorValue", 35 | "SensorType", 36 | "SensorDescription", 37 | "SensorDeviceInfo", 38 | "DeviceClass", 39 | "DeviceKey", 40 | "SensorUpdate", 41 | "SensorDeviceInfo", 42 | "SensorValue", 43 | "Units", 44 | "get_model_info", 45 | "ModelInfo", 46 | ] 47 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | exclude: "CHANGELOG.md" 4 | default_stages: [pre-commit] 5 | 6 | ci: 7 | autofix_commit_msg: "chore(pre-commit.ci): auto fixes" 8 | autoupdate_commit_msg: "chore(pre-commit.ci): pre-commit autoupdate" 9 | 10 | repos: 11 | - repo: https://github.com/commitizen-tools/commitizen 12 | rev: v4.9.1 13 | hooks: 14 | - id: commitizen 15 | stages: [commit-msg] 16 | - repo: https://github.com/pre-commit/pre-commit-hooks 17 | rev: v6.0.0 18 | hooks: 19 | - id: debug-statements 20 | - id: check-builtin-literals 21 | - id: check-case-conflict 22 | - id: check-docstring-first 23 | - id: check-json 24 | - id: check-toml 25 | - id: check-xml 26 | - id: check-yaml 27 | - id: detect-private-key 28 | - id: end-of-file-fixer 29 | - id: trailing-whitespace 30 | - id: debug-statements 31 | - repo: https://github.com/pre-commit/mirrors-prettier 32 | rev: v4.0.0-alpha.8 33 | hooks: 34 | - id: prettier 35 | args: ["--tab-width", "2"] 36 | - repo: https://github.com/asottile/pyupgrade 37 | rev: v3.20.0 38 | hooks: 39 | - id: pyupgrade 40 | args: [--py310-plus] 41 | - repo: https://github.com/astral-sh/ruff-pre-commit 42 | rev: v0.13.3 43 | hooks: 44 | - id: ruff 45 | args: [--fix, --exit-non-zero-on-fix] 46 | - id: ruff-format 47 | - repo: https://github.com/codespell-project/codespell 48 | rev: v2.4.1 49 | hooks: 50 | - id: codespell 51 | - repo: https://github.com/PyCQA/flake8 52 | rev: 7.3.0 53 | hooks: 54 | - id: flake8 55 | - repo: https://github.com/pre-commit/mirrors-mypy 56 | rev: v1.18.2 57 | hooks: 58 | - id: mypy 59 | additional_dependencies: [] 60 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | from typing import Any 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = "Govee BLE" 21 | copyright = "2020, J. Nick Koston" 22 | author = "J. Nick Koston" 23 | 24 | 25 | # -- General configuration --------------------------------------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be 28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 29 | # ones. 30 | extensions = [ 31 | "myst_parser", 32 | ] 33 | 34 | # The suffix of source filenames. 35 | source_suffix = [".rst", ".md"] 36 | 37 | # Add any paths that contain templates here, relative to this directory. 38 | templates_path = ["_templates"] 39 | 40 | # List of patterns, relative to source directory, that match files and 41 | # directories to ignore when looking for source files. 42 | # This pattern also affects html_static_path and html_extra_path. 43 | exclude_patterns: list[Any] = [] 44 | 45 | 46 | # -- Options for HTML output ------------------------------------------------- 47 | 48 | # The theme to use for HTML and HTML Help pages. See the documentation for 49 | # a list of builtin themes. 50 | # 51 | html_theme = "sphinx_rtd_theme" 52 | 53 | # Add any paths that contain custom static files (such as style sheets) here, 54 | # relative to this directory. They are copied after the builtin static files, 55 | # so a file named "default.css" will overwrite the builtin "default.css". 56 | html_static_path = ["_static"] 57 | -------------------------------------------------------------------------------- /.github/labels.toml: -------------------------------------------------------------------------------- 1 | [breaking] 2 | color = "ffcc00" 3 | name = "breaking" 4 | description = "Breaking change." 5 | 6 | [bug] 7 | color = "d73a4a" 8 | name = "bug" 9 | description = "Something isn't working" 10 | 11 | [dependencies] 12 | color = "0366d6" 13 | name = "dependencies" 14 | description = "Pull requests that update a dependency file" 15 | 16 | [github_actions] 17 | color = "000000" 18 | name = "github_actions" 19 | description = "Update of github actions" 20 | 21 | [documentation] 22 | color = "1bc4a5" 23 | name = "documentation" 24 | description = "Improvements or additions to documentation" 25 | 26 | [duplicate] 27 | color = "cfd3d7" 28 | name = "duplicate" 29 | description = "This issue or pull request already exists" 30 | 31 | [enhancement] 32 | color = "a2eeef" 33 | name = "enhancement" 34 | description = "New feature or request" 35 | 36 | ["good first issue"] 37 | color = "7057ff" 38 | name = "good first issue" 39 | description = "Good for newcomers" 40 | 41 | ["help wanted"] 42 | color = "008672" 43 | name = "help wanted" 44 | description = "Extra attention is needed" 45 | 46 | [invalid] 47 | color = "e4e669" 48 | name = "invalid" 49 | description = "This doesn't seem right" 50 | 51 | [nochangelog] 52 | color = "555555" 53 | name = "nochangelog" 54 | description = "Exclude pull requests from changelog" 55 | 56 | [question] 57 | color = "d876e3" 58 | name = "question" 59 | description = "Further information is requested" 60 | 61 | [removed] 62 | color = "e99695" 63 | name = "removed" 64 | description = "Removed piece of functionalities." 65 | 66 | [tests] 67 | color = "bfd4f2" 68 | name = "tests" 69 | description = "CI, CD and testing related changes" 70 | 71 | [wontfix] 72 | color = "ffffff" 73 | name = "wontfix" 74 | description = "This will not be worked on" 75 | 76 | [discussion] 77 | color = "c2e0c6" 78 | name = "discussion" 79 | description = "Some discussion around the project" 80 | 81 | [hacktoberfest] 82 | color = "ffa663" 83 | name = "hacktoberfest" 84 | description = "Good issues for Hacktoberfest" 85 | 86 | [answered] 87 | color = "0ee2b6" 88 | name = "answered" 89 | description = "Automatically closes as answered after a delay" 90 | 91 | [waiting] 92 | color = "5f7972" 93 | name = "waiting" 94 | description = "Automatically closes if no answer after a delay" 95 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | share/python-wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .nox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *.cover 51 | *.py,cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | cover/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | db.sqlite3-journal 65 | 66 | # Flask stuff: 67 | instance/ 68 | .webassets-cache 69 | 70 | # Scrapy stuff: 71 | .scrapy 72 | 73 | # Sphinx documentation 74 | docs/_build/ 75 | 76 | # PyBuilder 77 | .pybuilder/ 78 | target/ 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # IPython 84 | profile_default/ 85 | ipython_config.py 86 | 87 | # pyenv 88 | # For a library or package, you might want to ignore these files since the code is 89 | # intended to run in multiple environments; otherwise, check them in: 90 | # .python-version 91 | 92 | # pipenv 93 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 94 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 95 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 96 | # install all needed dependencies. 97 | #Pipfile.lock 98 | 99 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 100 | __pypackages__/ 101 | 102 | # Celery stuff 103 | celerybeat-schedule 104 | celerybeat.pid 105 | 106 | # SageMath parsed files 107 | *.sage.py 108 | 109 | # Environments 110 | .env 111 | .venv 112 | env/ 113 | venv/ 114 | ENV/ 115 | env.bak/ 116 | venv.bak/ 117 | 118 | # Spyder project settings 119 | .spyderproject 120 | .spyproject 121 | 122 | # Rope project settings 123 | .ropeproject 124 | 125 | # mkdocs documentation 126 | /site 127 | 128 | # mypy 129 | .mypy_cache/ 130 | .dmypy.json 131 | dmypy.json 132 | 133 | # Pyre type checker 134 | .pyre/ 135 | 136 | # pytype static type analyzer 137 | .pytype/ 138 | 139 | # Cython debug symbols 140 | cython_debug/ 141 | -------------------------------------------------------------------------------- /.idea/watcherTasks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 24 | 25 | 36 | 44 | 45 | 56 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | concurrency: 10 | group: ${{ github.head_ref || github.run_id }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v5 18 | - uses: actions/setup-python@v6 19 | with: 20 | python-version: "3.9" 21 | - uses: pre-commit/action@v3.0.1 22 | 23 | # Make sure commit messages follow the conventional commits convention: 24 | # https://www.conventionalcommits.org 25 | commitlint: 26 | name: Lint Commit Messages 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/checkout@v5 30 | with: 31 | fetch-depth: 0 32 | - uses: wagoid/commitlint-github-action@v6 33 | 34 | test: 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | python-version: 39 | - "3.10" 40 | - "3.11" 41 | - "3.12" 42 | - "3.13" 43 | os: 44 | - ubuntu-latest 45 | runs-on: ${{ matrix.os }} 46 | steps: 47 | - uses: actions/checkout@v5 48 | - name: Set up Python 49 | uses: actions/setup-python@v6 50 | with: 51 | python-version: ${{ matrix.python-version }} 52 | - uses: snok/install-poetry@v1 53 | - name: Install Dependencies 54 | shell: bash 55 | run: poetry install 56 | - name: Test with Pytest 57 | shell: bash 58 | run: poetry run pytest --cov-report=xml 59 | - name: Upload coverage to Codecov 60 | uses: codecov/codecov-action@v5 61 | with: 62 | token: ${{ secrets.CODECOV_TOKEN }} 63 | 64 | release: 65 | runs-on: ubuntu-latest 66 | environment: release 67 | if: github.ref == 'refs/heads/main' 68 | needs: 69 | - test 70 | - lint 71 | - commitlint 72 | permissions: 73 | id-token: write 74 | contents: write 75 | 76 | steps: 77 | - uses: actions/checkout@v5 78 | with: 79 | fetch-depth: 0 80 | 81 | # Run semantic release: 82 | # - Update CHANGELOG.md 83 | # - Update version in code 84 | # - Create git tag 85 | # - Create GitHub release 86 | - name: Python Semantic Release 87 | id: release 88 | uses: python-semantic-release/python-semantic-release@v10.4.1 89 | with: 90 | github_token: ${{ secrets.GITHUB_TOKEN }} 91 | - name: Upload package to PyPI 92 | uses: pypa/gh-action-pypi-publish@release/v1 93 | if: steps.release.outputs.released == 'true' 94 | - name: Upload Github Release Assets 95 | uses: python-semantic-release/publish-action@v10.4.1 96 | if: steps.release.outputs.released == 'true' 97 | with: 98 | github_token: ${{ secrets.GITHUB_TOKEN }} 99 | tag: ${{ steps.release.outputs.tag }} 100 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "govee-ble" 3 | version = "1.0.0" 4 | license = "Apache-2.0" 5 | description = "Manage Govee BLE devices" 6 | authors = [{ name = "J. Nick Koston", email = "nick@koston.org" }] 7 | readme = "README.md" 8 | requires-python = ">=3.10" 9 | dynamic = ["classifiers", "dependencies", "optional-dependencies"] 10 | 11 | [project.urls] 12 | "Repository" = "https://github.com/bluetooth-devices/govee-ble" 13 | "Documentation" = "https://govee-ble.readthedocs.io" 14 | "Bug Tracker" = "https://github.com/bluetooth-devices/govee-ble/issues" 15 | "Changelog" = "https://github.com/bluetooth-devices/govee-ble/blob/main/CHANGELOG.md" 16 | 17 | [tool.poetry] 18 | classifiers = [ 19 | "Development Status :: 2 - Pre-Alpha", 20 | "Intended Audience :: Developers", 21 | "Natural Language :: English", 22 | "Operating System :: OS Independent", 23 | "Topic :: Software Development :: Libraries", 24 | ] 25 | packages = [ 26 | { include = "govee_ble", from = "src" }, 27 | ] 28 | 29 | [tool.poetry.dependencies] 30 | python = "^3.10" 31 | 32 | # Documentation Dependencies 33 | Sphinx = {version = ">=5,<9", optional = true} 34 | sphinx-rtd-theme = {version = ">=1,<4", optional = true} 35 | myst-parser = {version = ">=0.18,<4.1", optional = true} 36 | home-assistant-bluetooth = ">=1.3.0" 37 | sensor-state-data = ">=2.18.0" 38 | bluetooth-sensor-state-data = ">=1.5.0" 39 | bluetooth-data-tools = ">=0.1.2" 40 | cryptography = ">=42.0.0" 41 | 42 | [tool.poetry.extras] 43 | docs = [ 44 | "myst-parser", 45 | "sphinx", 46 | "sphinx-rtd-theme", 47 | ] 48 | 49 | [tool.poetry.dev-dependencies] 50 | pytest = "^8.4" 51 | pytest-cov = "^7.0" 52 | 53 | [tool.semantic_release] 54 | branch = "main" 55 | version_toml = ["pyproject.toml:project.version"] 56 | version_variables = ["src/govee_ble/__init__.py:__version__"] 57 | build_command = "pip install poetry && poetry build" 58 | 59 | [tool.pytest.ini_options] 60 | addopts = "-v -Wdefault --cov=govee_ble --cov-report=term-missing:skip-covered" 61 | pythonpath = ["src"] 62 | 63 | [tool.coverage.run] 64 | branch = true 65 | 66 | [tool.coverage.report] 67 | exclude_lines = [ 68 | "pragma: no cover", 69 | "@overload", 70 | "if TYPE_CHECKING", 71 | "raise NotImplementedError", 72 | ] 73 | 74 | [tool.isort] 75 | profile = "black" 76 | known_first_party = ["govee_ble", "tests"] 77 | 78 | [tool.mypy] 79 | check_untyped_defs = true 80 | disallow_any_generics = true 81 | disallow_incomplete_defs = true 82 | disallow_untyped_defs = true 83 | mypy_path = "src/" 84 | no_implicit_optional = true 85 | show_error_codes = true 86 | warn_unreachable = true 87 | warn_unused_ignores = true 88 | exclude = [ 89 | 'docs/.*', 90 | 'setup.py', 91 | ] 92 | 93 | [[tool.mypy.overrides]] 94 | module = "tests.*" 95 | allow_untyped_defs = true 96 | 97 | [[tool.mypy.overrides]] 98 | module = "docs.*" 99 | ignore_errors = true 100 | 101 | [build-system] 102 | requires = ["poetry-core>=2.0.0"] 103 | build-backend = "poetry.core.masonry.api" 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Govee BLE 2 | 3 |

4 | 5 | CI Status 6 | 7 | 8 | Documentation Status 9 | 10 | 11 | Test coverage percentage 12 | 13 |

14 |

15 | 16 | Poetry 17 | 18 | 19 | black 20 | 21 | 22 | pre-commit 23 | 24 |

25 |

26 | 27 | PyPI Version 28 | 29 | Supported Python versions 30 | License 31 |

32 | 33 | Manage Govee BLE devices 34 | 35 | ## Installation 36 | 37 | Install this via pip (or your favourite package manager): 38 | 39 | `pip install govee-ble` 40 | 41 | ## Contributors ✨ 42 | 43 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 53 | 54 | ## Credits 55 | 56 | This package was created with 57 | [Cookiecutter](https://github.com/audreyr/cookiecutter) and the 58 | [browniebroke/cookiecutter-pypackage](https://github.com/browniebroke/cookiecutter-pypackage) 59 | project template. 60 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are welcome, and they are greatly appreciated! Every little helps, and credit will always be given. 4 | 5 | You can contribute in many ways: 6 | 7 | ## Types of Contributions 8 | 9 | ### Report Bugs 10 | 11 | Report bugs to [our issue page][gh-issues]. If you are reporting a bug, please include: 12 | 13 | - Your operating system name and version. 14 | - Any details about your local setup that might be helpful in troubleshooting. 15 | - Detailed steps to reproduce the bug. 16 | 17 | ### Fix Bugs 18 | 19 | Look through the GitHub issues for bugs. Anything tagged with "bug" and "help wanted" is open to whoever wants to implement it. 20 | 21 | ### Implement Features 22 | 23 | Look through the GitHub issues for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it. 24 | 25 | ### Write Documentation 26 | 27 | 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. 28 | 29 | ### Submit Feedback 30 | 31 | The best way to send feedback [our issue page][gh-issues] on GitHub. If you are proposing a feature: 32 | 33 | - Explain in detail how it would work. 34 | - Keep the scope as narrow as possible, to make it easier to implement. 35 | - Remember that this is a volunteer-driven project, and that contributions are welcome 😊 36 | 37 | ## Get Started! 38 | 39 | Ready to contribute? Here's how to set yourself up for local development. 40 | 41 | 1. Fork the repo on GitHub. 42 | 43 | 2. Clone your fork locally: 44 | 45 | ```shell 46 | $ git clone git@github.com:your_name_here/govee-ble.git 47 | ``` 48 | 49 | 3. Install the project dependencies with [Poetry](https://python-poetry.org): 50 | 51 | ```shell 52 | $ poetry install 53 | ``` 54 | 55 | 4. Create a branch for local development: 56 | 57 | ```shell 58 | $ git checkout -b name-of-your-bugfix-or-feature 59 | ``` 60 | 61 | Now you can make your changes locally. 62 | 63 | 5. When you're done making changes, check that your changes pass our tests: 64 | 65 | ```shell 66 | $ poetry run pytest 67 | ``` 68 | 69 | 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: 70 | 71 | ```shell 72 | $ pre-commit run -a 73 | ``` 74 | 75 | Or better, install the hooks once and have them run automatically each time you commit: 76 | 77 | ```shell 78 | $ pre-commit install 79 | ``` 80 | 81 | 7. Commit your changes and push your branch to GitHub: 82 | 83 | ```shell 84 | $ git add . 85 | $ git commit -m "feat(something): your detailed description of your changes" 86 | $ git push origin name-of-your-bugfix-or-feature 87 | ``` 88 | 89 | 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. 90 | 91 | 8. Submit a pull request through the GitHub website or using the GitHub CLI (if you have it installed): 92 | 93 | ```shell 94 | $ gh pr create --fill 95 | ``` 96 | 97 | ## Pull Request Guidelines 98 | 99 | 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: 100 | 101 | 1. Include tests for feature or bug fixes. 102 | 2. Update the documentation for significant features. 103 | 3. Ensure tests are passing on CI. 104 | 105 | ## Tips 106 | 107 | To run a subset of tests: 108 | 109 | ```shell 110 | $ pytest tests 111 | ``` 112 | 113 | ## Making a new release 114 | 115 | 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. 116 | 117 | [gh-issues]: https://github.com/bluetooth-devices/govee-ble/issues 118 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2022 J. Nick Koston 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /src/govee_ble/parser.py: -------------------------------------------------------------------------------- 1 | """ 2 | Parser for Govee BLE advertisements. 3 | 4 | This file is shamelessly copied from the following repository: 5 | https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/govee.py 6 | 7 | MIT License applies. 8 | """ 9 | 10 | from __future__ import annotations 11 | 12 | import logging 13 | import struct 14 | from dataclasses import dataclass 15 | from enum import Enum 16 | 17 | from bluetooth_data_tools import short_address 18 | from bluetooth_sensor_state_data import BluetoothData 19 | from home_assistant_bluetooth import BluetoothServiceInfo 20 | from sensor_state_data import BinarySensorDeviceClass, SensorLibrary 21 | 22 | from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes 23 | 24 | _LOGGER = logging.getLogger(__name__) 25 | 26 | 27 | PACKED_hHB_LITTLE = struct.Struct("hHB") 29 | PACKED_hh = struct.Struct(">hh") 30 | PACKED_hhhchhh_LITTLE = struct.Struct("hhhh") 33 | PACKED_hhbhh = struct.Struct(">hhbhh") 34 | PACKED_hhhhh = struct.Struct(">hhhhh") 35 | PACKED_hhhhhh = struct.Struct(">hhhhhh") 36 | 37 | 38 | ERROR = "error" 39 | 40 | MIN_TEMP = -40 41 | MAX_TEMP = 100 42 | 43 | NOT_GOVEE_MANUFACTURER = {76} 44 | 45 | PROBE_MAPPING_1_2 = [1, 2] 46 | PROBE_MAPPING_3_4 = [3, 4] 47 | 48 | FOUR_PROBES_MAPPING = dict.fromkeys( 49 | (1, 65, 129, 193), PROBE_MAPPING_1_2 50 | ) | dict.fromkeys((2, 66, 130, 194), PROBE_MAPPING_3_4) 51 | 52 | SIX_PROBES_MAPPING = { 53 | 0: [[1, 0x01], [2, 0x02]], 54 | 64: [[3, 0x04], [4, 0x08]], 55 | 128: [[5, 0x10], [6, 0x20]], 56 | } 57 | 58 | 59 | def decode_temp_humid_battery_error(data: bytes) -> tuple[float, float, int, bool]: 60 | temp, humi = decode_temp_humid(data[0:3]) 61 | batt = int(data[-1] & 0x7F) 62 | err = bool(data[-1] & 0x80) 63 | return temp, humi, batt, err 64 | 65 | 66 | def decode_temp_humid(temp_humid_bytes: bytes) -> tuple[float, float]: 67 | """Decode potential negative temperatures.""" 68 | base_num = ( 69 | (temp_humid_bytes[0] << 16) + (temp_humid_bytes[1] << 8) + temp_humid_bytes[2] 70 | ) 71 | is_negative = base_num & 0x800000 72 | temp_as_int = base_num & 0x7FFFFF 73 | temp_as_float = int(temp_as_int / 1000) / 10.0 74 | if is_negative: 75 | temp_as_float = -temp_as_float 76 | humid = (temp_as_int % 1000) / 10.0 77 | return temp_as_float, humid 78 | 79 | 80 | def decode_temps_probes(packet_value: int) -> float: 81 | """Filter potential negative temperatures.""" 82 | if packet_value < 0: 83 | return 0.0 84 | return float(packet_value / 100) 85 | 86 | 87 | def decode_temps_probes_none(packet_value: int) -> float | None: 88 | """Filter potential negative temperatures.""" 89 | if packet_value < 0: 90 | return None 91 | return float(packet_value) 92 | 93 | 94 | def hex(data: bytes) -> str: 95 | """Return a string object containing two hexadecimal digits for each byte in the instance.""" 96 | return "b'{}'".format("".join(f"\\x{b:02x}" for b in data)) 97 | 98 | 99 | def decode_temps_from_4_bytes(packet_value: int) -> float: 100 | """Decode temperature values (to one decimal place).""" 101 | if packet_value & 0x80000000: 102 | # Handle freezing temperatures 103 | packet_value &= 0x7FFFFFFF 104 | return float(int(packet_value / -10000000) / -10) 105 | return float(int(packet_value / 1000000) / 10) 106 | 107 | 108 | def decode_humi_from_4_bytes(packet_value: int) -> float: 109 | """Decode humidity values (to one decimal place)""" 110 | packet_value &= 0x7FFFFFFF 111 | return float(int((packet_value % 1000000) / 1000) / 10) 112 | 113 | 114 | def decode_pm25_from_4_bytes(packet_value: int) -> int: 115 | """Decode humidity values""" 116 | packet_value &= 0x7FFFFFFF 117 | return int(packet_value % 1000) 118 | 119 | 120 | def calculate_crc(data: bytes) -> int: 121 | crc = 0x1D0F 122 | for b in data: 123 | for s in range(7, -1, -1): 124 | mask = 0 125 | if (crc >> 15) ^ (b >> s) & 1: 126 | mask = 0x1021 127 | crc = ((crc << 1) ^ mask) & 0xFFFF 128 | return crc 129 | 130 | 131 | def decrypt_data(key: bytes, data: bytes) -> bytes: 132 | cipher = Cipher(algorithms.AES(key[::-1]), modes.ECB()) 133 | decryptor = cipher.decryptor() 134 | return (decryptor.update(data[::-1]) + decryptor.finalize())[::-1] 135 | 136 | 137 | class SensorType(Enum): 138 | THERMOMETER = "thermometer" 139 | BUTTON = "button" 140 | MOTION = "motion" 141 | WINDOW = "window" 142 | VIBRATION = "vibration" 143 | PRESENCE = "presence" 144 | PRESSURE = "pressure" 145 | 146 | 147 | @dataclass 148 | class ModelInfo: 149 | """Model information for Govee sensors.""" 150 | 151 | model_id: str 152 | sensor_type: SensorType 153 | button_count: int 154 | sleepy: bool 155 | 156 | 157 | _MODEL_DB = { 158 | "H5121": ModelInfo("H5121", SensorType.MOTION, 0, True), 159 | "H5122": ModelInfo("H5122", SensorType.BUTTON, 1, True), 160 | "H5123": ModelInfo("H5123", SensorType.WINDOW, 0, True), 161 | "H5124": ModelInfo("H5124", SensorType.VIBRATION, 0, True), 162 | "H5125": ModelInfo("H5125", SensorType.BUTTON, 6, True), 163 | "H5126": ModelInfo("H5126", SensorType.BUTTON, 2, True), 164 | "H5127": ModelInfo("H5127", SensorType.PRESENCE, 0, True), 165 | "H5130": ModelInfo("H5130", SensorType.PRESSURE, 1, True), 166 | } 167 | 168 | 169 | def get_model_info(model_id: str) -> ModelInfo: 170 | """Get model information for a Govee sensor.""" 171 | return _MODEL_DB.get( 172 | model_id, ModelInfo(model_id, SensorType.THERMOMETER, 0, False) 173 | ) 174 | 175 | 176 | class GoveeBluetoothDeviceData(BluetoothData): 177 | """Data for Govee BLE sensors.""" 178 | 179 | def _start_update(self, service_info: BluetoothServiceInfo) -> None: 180 | """Update from BLE advertisement data.""" 181 | _LOGGER.debug("Parsing Govee BLE advertisement data: %s", service_info) 182 | manufacturer_data = service_info.manufacturer_data 183 | service_uuids = service_info.service_uuids 184 | local_name = service_info.name 185 | address = service_info.address 186 | self.set_device_manufacturer("Govee") 187 | 188 | if local_name.startswith("Govee_"): 189 | self.set_device_name(service_info.name[6:].replace("_", " ")) 190 | 191 | if local_name.startswith("GV"): 192 | self.set_device_name(service_info.name[2:].replace("_", " ")) 193 | self.set_precision(2) 194 | 195 | for mfr_id, mfr_data in manufacturer_data.items(): 196 | if mfr_id in NOT_GOVEE_MANUFACTURER: 197 | continue 198 | self._process_mfr_data(address, local_name, mfr_id, mfr_data, service_uuids) 199 | 200 | @property 201 | def device_type(self) -> str | None: 202 | """Return the device type.""" 203 | primary_device_id = self.primary_device_id 204 | if device_type := self._device_id_to_type.get(primary_device_id): 205 | return device_type.partition("-")[0] 206 | return None 207 | 208 | @property 209 | def button_count(self) -> int: 210 | """Return the number of buttons on the device.""" 211 | device_type = self.device_type 212 | assert device_type is not None 213 | return get_model_info(device_type).button_count 214 | 215 | @property 216 | def sensor_type(self) -> SensorType: 217 | """Return the sensor type.""" 218 | device_type = self.device_type 219 | assert device_type is not None 220 | return get_model_info(device_type).sensor_type 221 | 222 | @property 223 | def sleepy(self) -> bool: 224 | """Return if the device is sleep.""" 225 | device_type = self.device_type 226 | assert device_type is not None 227 | return get_model_info(device_type).sleepy 228 | 229 | def _process_mfr_data( 230 | self, 231 | address: str, 232 | local_name: str, 233 | mgr_id: int, 234 | data: bytes, 235 | service_uuids: list[str], 236 | ) -> None: 237 | """Parser for Govee sensors.""" 238 | if debug_logging := _LOGGER.isEnabledFor(logging.DEBUG): 239 | _LOGGER.debug("Parsing Govee sensor: %s %s", mgr_id, hex(data)) 240 | msg_length = len(data) 241 | if msg_length > 25 and b"INTELLI_ROCKS" in data: 242 | # INTELLI_ROCKS sometimes ends up glued on to the end of the message 243 | data = data[:-25] 244 | msg_length = len(data) 245 | if debug_logging: 246 | _LOGGER.debug("Cleaned up packet: %s %s", mgr_id, data.hex()) 247 | 248 | if msg_length == 24: 249 | time_ms = data[2:6] 250 | enc_data = data[6:22] 251 | enc_crc = data[22:24] 252 | if not calculate_crc(enc_data) == int.from_bytes(enc_crc, "big"): 253 | _LOGGER.debug("CRC check failed for H512/3x: %s", hex(data)) 254 | return 255 | 256 | key = time_ms + bytes(12) 257 | try: 258 | decrypted = decrypt_data(key, enc_data) 259 | except ValueError: 260 | _LOGGER.warning("Failed to decrypt H512/3x: %s", hex(data)) 261 | return 262 | _LOGGER.debug("Decrypted H512/3x: %s - %s", decrypted, decrypted.hex()) 263 | model_id = decrypted[2] 264 | # GV5121 265 | # 01040302640100000000000000000000 266 | 267 | # GV5122 268 | # 01050802640000000000000000000000 269 | # 01050802640000000000000000000000 270 | 271 | # GV5123 272 | # 01050202640200000000000000000000 273 | 274 | # GV5124 275 | # 01030902640100000000000000000000 276 | 277 | # GV5125 278 | # 01010a02640000000000000000000000 279 | 280 | # GV5126 281 | # 01010b02640100000000000000000000 282 | 283 | # GV5130 284 | # 010e0d02640000000000000000000000 285 | sensor_type = SensorType.BUTTON 286 | if "GV5121" in local_name or model_id == 3: 287 | self.set_device_type("H5121") 288 | self.set_device_name(f"5121{short_address(address)}") 289 | sensor_type = SensorType.MOTION 290 | elif "GV5122" in local_name or model_id == 8: 291 | self.set_device_type("H5122") 292 | self.set_device_name(f"5122{short_address(address)}") 293 | elif "GV5123" in local_name or model_id == 2: 294 | self.set_device_type("H5123") 295 | self.set_device_name(f"5123{short_address(address)}") 296 | sensor_type = SensorType.WINDOW 297 | elif "GV5124" in local_name or model_id == 9: 298 | self.set_device_type("H5124") 299 | self.set_device_name(f"5124{short_address(address)}") 300 | sensor_type = SensorType.VIBRATION 301 | elif "GV5125" in local_name or model_id == 10: 302 | self.set_device_type("H5125") 303 | self.set_device_name(f"5125{short_address(address)}") 304 | elif "GV5126" in local_name or model_id == 11: 305 | self.set_device_type("H5126") 306 | self.set_device_name(f"5126{short_address(address)}") 307 | elif "GV5130" in local_name or model_id == 13: 308 | self.set_device_type("H5130") 309 | self.set_device_name(f"5130{short_address(address)}") 310 | sensor_type = SensorType.PRESSURE 311 | else: 312 | return 313 | 314 | battery_percentage = decrypted[4] 315 | button_number_pressed = decrypted[5] 316 | self.update_predefined_sensor( 317 | SensorLibrary.BATTERY__PERCENTAGE, battery_percentage 318 | ) 319 | if sensor_type is SensorType.WINDOW: 320 | # H5123 is a door/window sensor 321 | self.update_predefined_binary_sensor( 322 | BinarySensorDeviceClass.WINDOW, button_number_pressed == 2 323 | ) 324 | elif sensor_type is SensorType.VIBRATION: 325 | # H5124 is a vibration sensor 326 | if button_number_pressed == 1: 327 | self.fire_event("vibration", "vibration") 328 | elif sensor_type is SensorType.MOTION: 329 | if button_number_pressed == 1: 330 | self.fire_event("motion", "motion") 331 | elif sensor_type is SensorType.PRESSURE: 332 | # H5130 is a pressure sensor 333 | if button_number_pressed == 16: 334 | self.fire_event("button_0", "press") 335 | else: 336 | self.update_predefined_binary_sensor( 337 | BinarySensorDeviceClass.PRESENCE, button_number_pressed == 1 338 | ) 339 | else: 340 | self.fire_event(f"button_{button_number_pressed}", "press") 341 | return 342 | 343 | if msg_length == 6 and ( 344 | (data.startswith(b"\xec\x00\x01\x01") and "H5127" in local_name) 345 | or mgr_id == 0x8803 346 | ): 347 | self.set_device_type("H5127") 348 | self.set_device_name(f"H5127{short_address(address)}") 349 | present = data[4] == 1 350 | motion = data[5] == 17 351 | self.update_predefined_binary_sensor( 352 | BinarySensorDeviceClass.OCCUPANCY, present 353 | ) 354 | self.update_predefined_binary_sensor(BinarySensorDeviceClass.MOTION, motion) 355 | 356 | if msg_length == 6 and ( 357 | (is_5072 := "H5072" in local_name) 358 | or (is_5075 := "H5075" in local_name) 359 | or mgr_id == 0xEC88 360 | ): 361 | if is_5072: 362 | self.set_device_type("H5072") 363 | elif is_5075: 364 | self.set_device_type("H5075") 365 | else: 366 | self.set_device_type("H5072/H5075") 367 | temp, humi, batt, err = decode_temp_humid_battery_error(data[1:5]) 368 | if temp >= MIN_TEMP and temp <= MAX_TEMP and not err: 369 | self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp) 370 | self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, humi) 371 | else: 372 | _LOGGER.debug( 373 | "Ignoring invalid sensor values, temperature: %.1f, humidity: %.1f, error: %s", 374 | temp, 375 | humi, 376 | err, 377 | ) 378 | self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, ERROR) 379 | self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, ERROR) 380 | self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt) 381 | return 382 | 383 | if msg_length in (6, 8) and ( 384 | (is_5108 := "H5108" in local_name) 385 | or (is_5100 := "H5100" in local_name) 386 | or (is_5101 := "H5101" in local_name) 387 | or (is_5102 := "H5102" in local_name) 388 | or (is_5103 := "H5103" in local_name) 389 | or (is_5104 := "H5104" in local_name) 390 | or (is_5105 := "H5105" in local_name) 391 | or (is_5174 := "H5174" in local_name) 392 | or (is_5177 := "H5177" in local_name) 393 | or (is_5110 := "H5110" in local_name) 394 | or (is_5179 := "GV5179" in local_name) 395 | or (mgr_id == 0x0001 and msg_length == 8) 396 | ): 397 | if is_5108 or msg_length == 8: 398 | self.set_device_type("H5108") 399 | elif is_5100: 400 | self.set_device_type("H5100") 401 | elif is_5101: 402 | self.set_device_type("H5101") 403 | elif is_5102: 404 | self.set_device_type("H5102") 405 | elif is_5103: 406 | self.set_device_type("H5103") 407 | elif is_5104: 408 | self.set_device_type("H5104") 409 | elif is_5105: 410 | self.set_device_type("H5105") 411 | elif is_5174: 412 | self.set_device_type("H5174") 413 | elif is_5177: 414 | self.set_device_type("H5177") 415 | elif is_5110: 416 | self.set_device_type("H5110") 417 | elif is_5179: 418 | self.set_device_type("GV5179") 419 | else: 420 | self.set_device_type("H5101/H5102/H5104/H5108/H5174/H5177/GV5179") 421 | temp, humi, batt, err = decode_temp_humid_battery_error(data[2:6]) 422 | if temp >= MIN_TEMP and temp <= MAX_TEMP and not err: 423 | self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp) 424 | self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, humi) 425 | else: 426 | _LOGGER.debug( 427 | "Ignoring invalid sensor values, temperature: %.1f, humidity: %.1f, error: %s", 428 | temp, 429 | humi, 430 | err, 431 | ) 432 | self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, ERROR) 433 | self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, ERROR) 434 | self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt) 435 | return 436 | 437 | if msg_length == 7 and ("H5074" in local_name or mgr_id == 0xEC88): 438 | self.set_device_type("H5074") 439 | (temp, humi, batt) = PACKED_hHB_LITTLE.unpack(data[1:6]) 440 | self.update_predefined_sensor( 441 | SensorLibrary.TEMPERATURE__CELSIUS, temp / 100 442 | ) 443 | self.update_predefined_sensor( 444 | SensorLibrary.HUMIDITY__PERCENTAGE, humi / 100 445 | ) 446 | self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt) 447 | return 448 | 449 | if msg_length == 9 and ( 450 | mgr_id == 0xEC88 451 | or "H5051" in local_name 452 | or "H5052" in local_name 453 | or "H5071" in local_name 454 | ): 455 | if "H5071" in local_name: 456 | self.set_device_type("H5071") 457 | elif "H5052" in local_name: 458 | self.set_device_type("H5052") 459 | else: 460 | self.set_device_type("H5051") 461 | self.set_device_name(f"H5051 {short_address(address)}") 462 | (temp, humi, batt) = PACKED_hHB_LITTLE.unpack(data[1:6]) 463 | self.update_predefined_sensor( 464 | SensorLibrary.TEMPERATURE__CELSIUS, temp / 100 465 | ) 466 | self.update_predefined_sensor( 467 | SensorLibrary.HUMIDITY__PERCENTAGE, humi / 100 468 | ) 469 | self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt) 470 | return 471 | 472 | if msg_length == 9 and ( 473 | "H5178" in local_name or "B5178" in local_name or mgr_id == 0x0001 474 | ): 475 | temp, humi, batt, err = decode_temp_humid_battery_error(data[3:7]) 476 | sensor_id = data[2] 477 | device_id = "primary" 478 | if local_name.startswith("H5178") or local_name.startswith("B5178"): 479 | self.set_title(local_name) 480 | else: 481 | self.set_title("H5178") 482 | if sensor_id == 0: 483 | self.set_device_name( 484 | f"{local_name} Primary".replace("_", " "), device_id 485 | ) 486 | self.set_device_type("H5178", device_id) 487 | self.set_device_manufacturer("Govee", device_id) 488 | elif sensor_id == 1: 489 | device_id = "remote" 490 | self.set_device_name( 491 | f"{local_name} Remote".replace("_", " "), device_id 492 | ) 493 | self.set_device_type("H5178-REMOTE", device_id) 494 | self.set_device_manufacturer("Govee", device_id) 495 | elif debug_logging: 496 | _LOGGER.debug( 497 | "Unknown sensor id for Govee H5178," 498 | " please report to the developers, data: %s", 499 | hex(data), 500 | ) 501 | if temp >= MIN_TEMP and temp <= MAX_TEMP and not err: 502 | self.update_predefined_sensor( 503 | SensorLibrary.TEMPERATURE__CELSIUS, temp, device_id=device_id 504 | ) 505 | self.update_predefined_sensor( 506 | SensorLibrary.HUMIDITY__PERCENTAGE, humi, device_id=device_id 507 | ) 508 | else: 509 | _LOGGER.debug( 510 | "Ignoring invalid sensor values, temperature: %.1f, humidity: %.1f, error: %s", 511 | temp, 512 | humi, 513 | err, 514 | ) 515 | self.update_predefined_sensor( 516 | SensorLibrary.TEMPERATURE__CELSIUS, ERROR, device_id=device_id 517 | ) 518 | self.update_predefined_sensor( 519 | SensorLibrary.HUMIDITY__PERCENTAGE, ERROR, device_id=device_id 520 | ) 521 | self.update_predefined_sensor( 522 | SensorLibrary.BATTERY__PERCENTAGE, batt, device_id=device_id 523 | ) 524 | return 525 | 526 | if msg_length == 9 and ("H5179" in local_name or mgr_id == 0x8801): 527 | self.set_device_type("H5179") 528 | temp, humi, batt = PACKED_hHB_LITTLE.unpack(data[4:9]) 529 | self.update_predefined_sensor( 530 | SensorLibrary.TEMPERATURE__CELSIUS, temp / 100 531 | ) 532 | self.update_predefined_sensor( 533 | SensorLibrary.HUMIDITY__PERCENTAGE, humi / 100 534 | ) 535 | self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt) 536 | return 537 | 538 | if msg_length == 14 and ( 539 | "H5181" in local_name 540 | or mgr_id in {0xF861, 0x388A, 0xEA42, 0xAAA2, 0xD14B} 541 | or "00008151-0000-1000-8000-00805f9b34fb" in service_uuids 542 | ): 543 | self.set_device_type("H5181") 544 | self.set_device_name(f"H5181 {short_address(address)}") 545 | (temp_probe_1, temp_alarm_1) = PACKED_hh.unpack(data[8:12]) 546 | self.update_temp_probe_with_alarm( 547 | decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1 548 | ) 549 | return 550 | 551 | if msg_length == 17 and ( 552 | "H5182" in local_name 553 | or mgr_id == 0x2730 554 | or "00008251-0000-1000-8000-00805f9b34fb" in service_uuids 555 | ): 556 | self.set_device_type("H5182") 557 | self.set_device_name(f"H5182 {short_address(address)}") 558 | ( 559 | temp_probe_1, 560 | temp_alarm_1, 561 | _, 562 | temp_probe_2, 563 | temp_alarm_2, 564 | ) = PACKED_hhbhh.unpack(data[8:17]) 565 | self.update_temp_probe_with_alarm( 566 | decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1 567 | ) 568 | self.update_temp_probe_with_alarm( 569 | decode_temps_probes(temp_probe_2), decode_temps_probes(temp_alarm_2), 2 570 | ) 571 | return 572 | 573 | if msg_length == 14 and ( 574 | "H5183" in local_name 575 | or mgr_id in {0x67DD, 0xE02F, 0xF79F} 576 | or "00008351-0000-1000-8000-00805f9b34fb" in service_uuids 577 | ): 578 | self.set_device_type("H5183") 579 | self.set_device_name(f"H5183 {short_address(address)}") 580 | (temp_probe_1, temp_alarm_1) = PACKED_hh.unpack(data[8:12]) 581 | self.update_temp_probe_with_alarm( 582 | decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1 583 | ) 584 | return 585 | 586 | if msg_length == 17 and ( 587 | "H5184" in local_name 588 | or mgr_id == 0x1B36 589 | or "00008451-0000-1000-8000-00805f9b34fb" in service_uuids 590 | ): 591 | sensor_id = data[6] 592 | self.set_device_type("H5184") 593 | self.set_device_name(f"H5184 {short_address(address)}") 594 | ( 595 | temp_probe_first, 596 | temp_alarm_first, 597 | _, 598 | temp_probe_second, 599 | temp_alarm_second, 600 | ) = PACKED_hhbhh.unpack(data[8:17]) 601 | if not (ids := FOUR_PROBES_MAPPING.get(sensor_id)): 602 | if debug_logging: 603 | _LOGGER.debug( 604 | "Unknown sensor id: %s for a H5184, data: %s", 605 | sensor_id, 606 | hex(data), 607 | ) 608 | return 609 | self.update_temp_probe_with_alarm( 610 | decode_temps_probes(temp_probe_first), 611 | decode_temps_probes(temp_alarm_first), 612 | ids[0], 613 | ) 614 | self.update_temp_probe_with_alarm( 615 | decode_temps_probes(temp_probe_second), 616 | decode_temps_probes(temp_alarm_second), 617 | ids[1], 618 | ) 619 | return 620 | 621 | if msg_length == 20 and ( 622 | "H5185" in local_name 623 | or mgr_id in (0x4A32, 0x332, 0x4C32) 624 | or "00008551-0000-1000-8000-00805f9b34fb" in service_uuids 625 | ): 626 | self.set_device_type("H5185") 627 | self.set_device_name(f"H5185 {short_address(address)}") 628 | ( 629 | temp_probe_1, 630 | temp_alarm_1, 631 | _, 632 | temp_probe_2, 633 | temp_alarm_2, 634 | ) = PACKED_hhhhh.unpack(data[8:18]) 635 | self.update_temp_probe_with_alarm( 636 | decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1 637 | ) 638 | self.update_temp_probe_with_alarm( 639 | decode_temps_probes(temp_probe_2), decode_temps_probes(temp_alarm_2), 2 640 | ) 641 | return 642 | 643 | if msg_length == 20 and ( 644 | "H5191" in local_name 645 | or mgr_id == 0xAC63 646 | or "00009151-0000-1000-8000-00805f9b34fb" in service_uuids 647 | ): 648 | self.set_device_type("H5191") 649 | self.set_device_name(f"H5191 {short_address(address)}") 650 | ( 651 | temp_probe_1, 652 | temp_alarm_1, 653 | _, 654 | temp, 655 | ) = PACKED_hhhh.unpack(data[8:16]) 656 | self.update_temp_probe_with_alarm( 657 | decode_temps_probes(temp_probe_1), decode_temps_probes(temp_alarm_1), 1 658 | ) 659 | self.update_predefined_sensor( 660 | SensorLibrary.TEMPERATURE__CELSIUS, temp / 100 661 | ) 662 | return 663 | 664 | if msg_length == 20 and ( 665 | "H5198" in local_name 666 | or mgr_id == 0x3022 667 | or "00009851-0000-1000-8000-00805f9b34fb" in service_uuids 668 | ): 669 | sensor_id = data[6] 670 | self.set_device_type("H5198") 671 | self.set_device_name(f"H5198 {short_address(address)}") 672 | ( 673 | temp_probe_first, 674 | temp_alarm_first, 675 | low_temp_alarm_first, 676 | temp_probe_second, 677 | temp_alarm_second, 678 | low_temp_alarm_second, 679 | ) = PACKED_hhhhhh.unpack(data[8:20]) 680 | if not (ids := FOUR_PROBES_MAPPING.get(sensor_id)): 681 | if debug_logging: 682 | _LOGGER.debug( 683 | "Unknown sensor id: %s for a H5198, data: %s", 684 | sensor_id, 685 | hex(data), 686 | ) 687 | return 688 | self.update_temp_probe_with_alarm( 689 | decode_temps_probes(temp_probe_first), 690 | decode_temps_probes(temp_alarm_first), 691 | ids[0], 692 | decode_temps_probes(low_temp_alarm_first), 693 | ) 694 | self.update_temp_probe_with_alarm( 695 | decode_temps_probes(temp_probe_second), 696 | decode_temps_probes(temp_alarm_second), 697 | ids[1], 698 | decode_temps_probes(low_temp_alarm_second), 699 | ) 700 | return 701 | 702 | if msg_length == 20 and "00005550-0000-1000-8000-00805f9b34fb" in service_uuids: 703 | self.set_device_type("H5055") 704 | self.set_device_name(f"H5055 {short_address(address)}") 705 | ( 706 | temp_probe_first, 707 | temp_min_first, 708 | temp_max_first, 709 | _, 710 | temp_probe_second, 711 | temp_min_second, 712 | temp_max_second, 713 | ) = PACKED_hhhchhh_LITTLE.unpack(data[5:18]) 714 | sensor_ids = data[3] 715 | if not (pids := SIX_PROBES_MAPPING.get(sensor_ids & 0xC0)): 716 | if debug_logging: 717 | _LOGGER.debug( 718 | "Unknown sensor id: %s for a H5055, data: %s", 719 | sensor_ids, 720 | hex(data), 721 | ) 722 | return 723 | if sensor_ids & pids[0][1]: 724 | self.update_temp_probe_with_alarm( 725 | temp_probe_first, 726 | decode_temps_probes_none(temp_max_first), 727 | pids[0][0], 728 | decode_temps_probes_none(temp_min_first), 729 | ) 730 | if sensor_ids & pids[1][1]: 731 | self.update_temp_probe_with_alarm( 732 | temp_probe_second, 733 | decode_temps_probes_none(temp_max_second), 734 | pids[1][0], 735 | decode_temps_probes_none(temp_min_second), 736 | ) 737 | batt = int(data[2] & 0x7F) 738 | self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt) 739 | return 740 | 741 | if msg_length == 6 and "H5106" in local_name: 742 | self.set_device_type("H5106") 743 | self.set_device_name(f"H5106 {short_address(address)}") 744 | packet_5106 = data[2:6].hex() 745 | four_bytes = int(packet_5106, 16) 746 | temp = decode_temps_from_4_bytes(four_bytes) 747 | humi = decode_humi_from_4_bytes(four_bytes) 748 | pm25 = decode_pm25_from_4_bytes(four_bytes) 749 | self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp) 750 | self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, humi) 751 | self.update_predefined_sensor( 752 | SensorLibrary.PM25__CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, pm25 753 | ) 754 | return 755 | 756 | def update_temp_probe(self, temp: float, probe_id: int) -> None: 757 | """Update the temperature probe with the alarm temperature.""" 758 | self.update_predefined_sensor( 759 | SensorLibrary.TEMPERATURE__CELSIUS, 760 | temp, 761 | key=f"temperature_probe_{probe_id}", 762 | name=f"Temperature Probe {probe_id}", 763 | ) 764 | 765 | def update_temp_probe_with_alarm( 766 | self, 767 | temp: float, 768 | alarm_temp: float | None, 769 | probe_id: int, 770 | low_alarm_temp: float | None = None, 771 | ) -> None: 772 | """Update the temperature probe with the alarm temperature.""" 773 | self.update_temp_probe(temp, probe_id) 774 | if alarm_temp is not None: 775 | self.update_predefined_sensor( 776 | SensorLibrary.TEMPERATURE__CELSIUS, 777 | alarm_temp, 778 | key=f"temperature_alarm_probe_{probe_id}", 779 | name=f"Temperature Alarm Probe {probe_id}", 780 | ) 781 | if low_alarm_temp is not None: 782 | self.update_predefined_sensor( 783 | SensorLibrary.TEMPERATURE__CELSIUS, 784 | low_alarm_temp, 785 | key=f"low_temperature_alarm_probe_{probe_id}", 786 | name=f"Low Temperature Alarm Probe {probe_id}", 787 | ) 788 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | 4 | ## v0.45.0 (2025-08-14) 5 | 6 | ### Chores 7 | 8 | - Add more coverage for GVH5110 ([#170](https://github.com/Bluetooth-Devices/govee-ble/pull/170), 9 | [`44071f8`](https://github.com/Bluetooth-Devices/govee-ble/commit/44071f8b280319e0b69c3c51595c9d2ef8934a8c)) 10 | 11 | - **deps**: Bump bluetooth-data-tools from 1.23.3 to 1.28.1 12 | ([#162](https://github.com/Bluetooth-Devices/govee-ble/pull/162), 13 | [`0489c2a`](https://github.com/Bluetooth-Devices/govee-ble/commit/0489c2a1db9da807db735c221c97df651a871d6c)) 14 | 15 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 16 | 17 | - **deps**: Bump bluetooth-data-tools from 1.28.1 to 1.28.2 18 | ([#179](https://github.com/Bluetooth-Devices/govee-ble/pull/179), 19 | [`57e45a5`](https://github.com/Bluetooth-Devices/govee-ble/commit/57e45a5dde203a0285c32a5096eb2ed6c0c08944)) 20 | 21 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 22 | 23 | - **deps**: Bump bluetooth-sensor-state-data from 1.7.1 to 1.7.5 24 | ([#156](https://github.com/Bluetooth-Devices/govee-ble/pull/156), 25 | [`620b44f`](https://github.com/Bluetooth-Devices/govee-ble/commit/620b44fcf1ee8bfced833da0555a34e30b8c023f)) 26 | 27 | - **deps**: Bump cryptography from 44.0.0 to 44.0.1 28 | ([#155](https://github.com/Bluetooth-Devices/govee-ble/pull/155), 29 | [`18d0edf`](https://github.com/Bluetooth-Devices/govee-ble/commit/18d0edf47baa593765ec3fb59ec2d88737581be7)) 30 | 31 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 32 | 33 | - **deps**: Bump cryptography from 44.0.1 to 44.0.2 34 | ([#159](https://github.com/Bluetooth-Devices/govee-ble/pull/159), 35 | [`cc525de`](https://github.com/Bluetooth-Devices/govee-ble/commit/cc525decab60271826bcd36226b662f96d5bc032)) 36 | 37 | - **deps**: Bump cryptography from 44.0.2 to 44.0.3 38 | ([#164](https://github.com/Bluetooth-Devices/govee-ble/pull/164), 39 | [`4ed69e1`](https://github.com/Bluetooth-Devices/govee-ble/commit/4ed69e16c410832a45c28d52caefc2c2f4e655c2)) 40 | 41 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 42 | 43 | - **deps**: Bump cryptography from 44.0.3 to 45.0.2 44 | ([#167](https://github.com/Bluetooth-Devices/govee-ble/pull/167), 45 | [`a94ccce`](https://github.com/Bluetooth-Devices/govee-ble/commit/a94ccce1618eccd44334d3af499b262a5accdcee)) 46 | 47 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 48 | 49 | - **deps**: Bump cryptography from 45.0.2 to 45.0.3 50 | ([#168](https://github.com/Bluetooth-Devices/govee-ble/pull/168), 51 | [`ef97655`](https://github.com/Bluetooth-Devices/govee-ble/commit/ef9765529ec403f688cb40e3d797dec151d2ccf0)) 52 | 53 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 54 | 55 | - **deps**: Bump cryptography from 45.0.3 to 45.0.5 56 | ([#177](https://github.com/Bluetooth-Devices/govee-ble/pull/177), 57 | [`190e57c`](https://github.com/Bluetooth-Devices/govee-ble/commit/190e57cadb1beb4759c83ded460495e2bc9956c9)) 58 | 59 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 60 | 61 | - **deps**: Bump cryptography from 45.0.5 to 45.0.6 62 | ([#182](https://github.com/Bluetooth-Devices/govee-ble/pull/182), 63 | [`ddbce27`](https://github.com/Bluetooth-Devices/govee-ble/commit/ddbce27ee6d6d553a2747f63ae8064b048a57c2c)) 64 | 65 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 66 | 67 | - **deps**: Bump jinja2 from 3.1.5 to 3.1.6 68 | ([#154](https://github.com/Bluetooth-Devices/govee-ble/pull/154), 69 | [`a2fd9d1`](https://github.com/Bluetooth-Devices/govee-ble/commit/a2fd9d1afd2f4c3f1a5df7b35c2cf3e98c0e829d)) 70 | 71 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 72 | 73 | - **deps**: Bump myst-parser from 3.0.1 to 4.0.1 74 | ([#158](https://github.com/Bluetooth-Devices/govee-ble/pull/158), 75 | [`9324b62`](https://github.com/Bluetooth-Devices/govee-ble/commit/9324b6295d3bbe3ba7cdce102254e30a6f2b8108)) 76 | 77 | Bumps [myst-parser](https://github.com/executablebooks/MyST-Parser) from 3.0.1 to 4.0.1. - [Release 78 | notes](https://github.com/executablebooks/MyST-Parser/releases) - 79 | [Changelog](https://github.com/executablebooks/MyST-Parser/blob/master/CHANGELOG.md) - 80 | [Commits](https://github.com/executablebooks/MyST-Parser/compare/v3.0.1...v4.0.1) 81 | 82 | --- updated-dependencies: - dependency-name: myst-parser dependency-version: 4.0.1 83 | 84 | dependency-type: direct:production 85 | 86 | update-type: version-update:semver-major ... 87 | 88 | Signed-off-by: dependabot[bot] 89 | 90 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 91 | 92 | - **deps**: Bump requests from 2.32.3 to 2.32.4 93 | ([#172](https://github.com/Bluetooth-Devices/govee-ble/pull/172), 94 | [`1ef32dd`](https://github.com/Bluetooth-Devices/govee-ble/commit/1ef32dd4a9e617f04c277c734442e06e8727a369)) 95 | 96 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 97 | 98 | - **deps**: Bump sensor-state-data from 2.18.1 to 2.19.0 99 | ([#180](https://github.com/Bluetooth-Devices/govee-ble/pull/180), 100 | [`42e09f6`](https://github.com/Bluetooth-Devices/govee-ble/commit/42e09f6fe6d404557db59420a504d6b438f3d737)) 101 | 102 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 103 | 104 | - **deps**: Bump sphinx from 7.4.7 to 8.1.3 105 | ([#163](https://github.com/Bluetooth-Devices/govee-ble/pull/163), 106 | [`4c9d9c4`](https://github.com/Bluetooth-Devices/govee-ble/commit/4c9d9c48f80cc8cf71ceeb4ba8ee15ef55b90d31)) 107 | 108 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 109 | 110 | - **deps**: Bump urllib3 from 2.3.0 to 2.5.0 111 | ([#175](https://github.com/Bluetooth-Devices/govee-ble/pull/175), 112 | [`4053e68`](https://github.com/Bluetooth-Devices/govee-ble/commit/4053e6812a7e5759f70d4095f58a1f68935d16a4)) 113 | 114 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 115 | 116 | - **deps-dev**: Bump pytest from 8.3.4 to 8.3.5 117 | ([#157](https://github.com/Bluetooth-Devices/govee-ble/pull/157), 118 | [`ec2a87f`](https://github.com/Bluetooth-Devices/govee-ble/commit/ec2a87f8d071ce05db5f7b562309ee36aea54f06)) 119 | 120 | - **deps-dev**: Bump pytest from 8.3.5 to 8.4.1 121 | ([#176](https://github.com/Bluetooth-Devices/govee-ble/pull/176), 122 | [`24bc49d`](https://github.com/Bluetooth-Devices/govee-ble/commit/24bc49d5f4e18c2f52993b27209952296692dd5f)) 123 | 124 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 125 | 126 | - **deps-dev**: Bump pytest-cov from 6.0.0 to 6.1.1 127 | ([#160](https://github.com/Bluetooth-Devices/govee-ble/pull/160), 128 | [`3a38e71`](https://github.com/Bluetooth-Devices/govee-ble/commit/3a38e71ec342bf677abab7b546dc3ca2c00140ca)) 129 | 130 | - **deps-dev**: Bump pytest-cov from 6.1.1 to 6.2.1 131 | ([#173](https://github.com/Bluetooth-Devices/govee-ble/pull/173), 132 | [`8c993c1`](https://github.com/Bluetooth-Devices/govee-ble/commit/8c993c1df8307e874b3c53ee3a5c74fe98c97d24)) 133 | 134 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 135 | 136 | - **pre-commit.ci**: Pre-commit autoupdate 137 | ([#161](https://github.com/Bluetooth-Devices/govee-ble/pull/161), 138 | [`a0f7c41`](https://github.com/Bluetooth-Devices/govee-ble/commit/a0f7c4148449fb3815144dde71c73f7f4eb9a3c8)) 139 | 140 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 141 | 142 | - **pre-commit.ci**: Pre-commit autoupdate 143 | ([#165](https://github.com/Bluetooth-Devices/govee-ble/pull/165), 144 | [`0a19fdf`](https://github.com/Bluetooth-Devices/govee-ble/commit/0a19fdf8bd6414144ed1c1cad539a226a9a8a843)) 145 | 146 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 147 | 148 | - **pre-commit.ci**: Pre-commit autoupdate 149 | ([#166](https://github.com/Bluetooth-Devices/govee-ble/pull/166), 150 | [`3289ead`](https://github.com/Bluetooth-Devices/govee-ble/commit/3289ead82c96546fdab26e44349fed196360152c)) 151 | 152 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 153 | 154 | - **pre-commit.ci**: Pre-commit autoupdate 155 | ([#178](https://github.com/Bluetooth-Devices/govee-ble/pull/178), 156 | [`a6d4ede`](https://github.com/Bluetooth-Devices/govee-ble/commit/a6d4ede722ec1e82d7f8fa68a0e51d0cb3c5f4d9)) 157 | 158 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 159 | 160 | ### Features 161 | 162 | - Add support for H5191 ([#181](https://github.com/Bluetooth-Devices/govee-ble/pull/181), 163 | [`363f8e2`](https://github.com/Bluetooth-Devices/govee-ble/commit/363f8e286e208869bbcc41db7ff9ee5e99a87e65)) 164 | 165 | 166 | ## v0.44.0 (2025-04-28) 167 | 168 | ### Chores 169 | 170 | - **ci**: Bump the github-actions group with 2 updates 171 | ([#144](https://github.com/Bluetooth-Devices/govee-ble/pull/144), 172 | [`29cab59`](https://github.com/Bluetooth-Devices/govee-ble/commit/29cab597fb7ae1790e698afe9188ef729de08bdc)) 173 | 174 | Bumps the github-actions group with 2 updates: 175 | [python-semantic-release/python-semantic-release](https://github.com/python-semantic-release/python-semantic-release) 176 | and 177 | [python-semantic-release/publish-action](https://github.com/python-semantic-release/publish-action). 178 | 179 | Updates `python-semantic-release/python-semantic-release` from 9.17.0 to 9.21.0 - [Release 180 | notes](https://github.com/python-semantic-release/python-semantic-release/releases) - 181 | [Changelog](https://github.com/python-semantic-release/python-semantic-release/blob/master/CHANGELOG.rst) 182 | - 183 | [Commits](https://github.com/python-semantic-release/python-semantic-release/compare/v9.17.0...v9.21.0) 184 | 185 | Updates `python-semantic-release/publish-action` from 9.17.0 to 9.21.0 - [Release 186 | notes](https://github.com/python-semantic-release/publish-action/releases) - 187 | [Changelog](https://github.com/python-semantic-release/publish-action/blob/main/releaserc.toml) - 188 | [Commits](https://github.com/python-semantic-release/publish-action/compare/v9.17.0...v9.21.0) 189 | 190 | --- updated-dependencies: - dependency-name: python-semantic-release/python-semantic-release 191 | dependency-type: direct:production 192 | 193 | update-type: version-update:semver-minor 194 | 195 | dependency-group: github-actions 196 | 197 | - dependency-name: python-semantic-release/publish-action dependency-type: direct:production 198 | 199 | dependency-group: github-actions ... 200 | 201 | Signed-off-by: dependabot[bot] 202 | 203 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 204 | 205 | - **pre-commit.ci**: Pre-commit autoupdate 206 | ([#143](https://github.com/Bluetooth-Devices/govee-ble/pull/143), 207 | [`8758806`](https://github.com/Bluetooth-Devices/govee-ble/commit/87588061637edba85ef17ca90eb92df2544d0801)) 208 | 209 | - **pre-commit.ci**: Pre-commit autoupdate 210 | ([#146](https://github.com/Bluetooth-Devices/govee-ble/pull/146), 211 | [`f224903`](https://github.com/Bluetooth-Devices/govee-ble/commit/f224903ad94662ecd68229ec7001db26e4bf0188)) 212 | 213 | - **pre-commit.ci**: Pre-commit autoupdate 214 | ([#147](https://github.com/Bluetooth-Devices/govee-ble/pull/147), 215 | [`b434381`](https://github.com/Bluetooth-Devices/govee-ble/commit/b434381b21b477c40a7b0752fd0097b8f3f84490)) 216 | 217 | updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.0 → 218 | v0.11.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.0...v0.11.2) 219 | 220 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 221 | 222 | - **pre-commit.ci**: Pre-commit autoupdate 223 | ([#148](https://github.com/Bluetooth-Devices/govee-ble/pull/148), 224 | [`3d01fa8`](https://github.com/Bluetooth-Devices/govee-ble/commit/3d01fa8b868e508449131f80cb252323982aa367)) 225 | 226 | updates: - [github.com/PyCQA/flake8: 7.1.2 → 227 | 7.2.0](https://github.com/PyCQA/flake8/compare/7.1.2...7.2.0) 228 | 229 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 230 | 231 | - **pre-commit.ci**: Pre-commit autoupdate 232 | ([#149](https://github.com/Bluetooth-Devices/govee-ble/pull/149), 233 | [`bde11e7`](https://github.com/Bluetooth-Devices/govee-ble/commit/bde11e75948b23b802ee66b9fa1fc217d17208d8)) 234 | 235 | updates: - [github.com/commitizen-tools/commitizen: v4.4.1 → 236 | v4.5.0](https://github.com/commitizen-tools/commitizen/compare/v4.4.1...v4.5.0) - 237 | [github.com/astral-sh/ruff-pre-commit: v0.11.2 → 238 | v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.2...v0.11.4) 239 | 240 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 241 | 242 | - **pre-commit.ci**: Pre-commit autoupdate 243 | ([#150](https://github.com/Bluetooth-Devices/govee-ble/pull/150), 244 | [`d1fdcd3`](https://github.com/Bluetooth-Devices/govee-ble/commit/d1fdcd3e0b15645ee7228139e096b0767ba3c881)) 245 | 246 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 247 | 248 | - **pre-commit.ci**: Pre-commit autoupdate 249 | ([#152](https://github.com/Bluetooth-Devices/govee-ble/pull/152), 250 | [`e6ffe35`](https://github.com/Bluetooth-Devices/govee-ble/commit/e6ffe35bb907fe6654fddd67eab95df097ff1566)) 251 | 252 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 253 | 254 | ### Features 255 | 256 | - Add support for H5110 ([#153](https://github.com/Bluetooth-Devices/govee-ble/pull/153), 257 | [`9fd67ef`](https://github.com/Bluetooth-Devices/govee-ble/commit/9fd67ef312af0b602e7b94ef1594dc0fa772c9b8)) 258 | 259 | 260 | ## v0.43.1 (2025-03-05) 261 | 262 | ### Bug Fixes 263 | 264 | - Change minimum temp to -40 ([#145](https://github.com/Bluetooth-Devices/govee-ble/pull/145), 265 | [`2f7360d`](https://github.com/Bluetooth-Devices/govee-ble/commit/2f7360de826527a2befb4a1942a9176776b6874c)) 266 | 267 | ### Chores 268 | 269 | - **ci**: Bump the github-actions group with 8 updates 270 | ([#139](https://github.com/Bluetooth-Devices/govee-ble/pull/139), 271 | [`0bfccb1`](https://github.com/Bluetooth-Devices/govee-ble/commit/0bfccb1384eced110c498a3bcade7ea273ebd8d7)) 272 | 273 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 274 | 275 | Co-authored-by: J. Nick Koston 276 | 277 | - **pre-commit.ci**: Pre-commit autoupdate 278 | ([#141](https://github.com/Bluetooth-Devices/govee-ble/pull/141), 279 | [`0cf81b4`](https://github.com/Bluetooth-Devices/govee-ble/commit/0cf81b46d0dc4b3a384d4928627fada6bea81fe8)) 280 | 281 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 282 | 283 | - **pre-commit.ci**: Pre-commit autoupdate 284 | ([#142](https://github.com/Bluetooth-Devices/govee-ble/pull/142), 285 | [`48e5f0a`](https://github.com/Bluetooth-Devices/govee-ble/commit/48e5f0a0fcac604022bb2748b54b42941bf4cfdc)) 286 | 287 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 288 | 289 | 290 | ## v0.43.0 (2025-02-06) 291 | 292 | ### Chores 293 | 294 | - Update dependabot.yml to include GHA 295 | ([#138](https://github.com/Bluetooth-Devices/govee-ble/pull/138), 296 | [`e83b35d`](https://github.com/Bluetooth-Devices/govee-ble/commit/e83b35dc52dda4b38f0e53f3ef235b358ac47260)) 297 | 298 | ### Features 299 | 300 | - Add support for newer 5179 firmware 301 | ([#140](https://github.com/Bluetooth-Devices/govee-ble/pull/140), 302 | [`3d0f853`](https://github.com/Bluetooth-Devices/govee-ble/commit/3d0f8535a0ca1b7cf3fa4ed0b7d12c58c776dffb)) 303 | 304 | 305 | ## v0.42.1 (2025-02-04) 306 | 307 | ### Bug Fixes 308 | 309 | - Update poetry to v2 + add license to metadata 310 | ([#137](https://github.com/Bluetooth-Devices/govee-ble/pull/137), 311 | [`e61a9cb`](https://github.com/Bluetooth-Devices/govee-ble/commit/e61a9cb4903215bfce3dca7efec140b3a21d6d0b)) 312 | 313 | ### Chores 314 | 315 | - Add test data from ha issue 110528 316 | ([#128](https://github.com/Bluetooth-Devices/govee-ble/pull/128), 317 | [`c5baa25`](https://github.com/Bluetooth-Devices/govee-ble/commit/c5baa253d04f7080de0546779a9abc915eecb8c8)) 318 | 319 | - Create dependabot.yml 320 | ([`3e55779`](https://github.com/Bluetooth-Devices/govee-ble/commit/3e55779b101a24d561544be654c79179a8d8a5ef)) 321 | 322 | - Update CI for Python 3.13 ([#124](https://github.com/Bluetooth-Devices/govee-ble/pull/124), 323 | [`ddb0195`](https://github.com/Bluetooth-Devices/govee-ble/commit/ddb01959470f98c90c215998ff896e79c07199be)) 324 | 325 | - Update deps for Python 3.13 ([#125](https://github.com/Bluetooth-Devices/govee-ble/pull/125), 326 | [`0b2ecbb`](https://github.com/Bluetooth-Devices/govee-ble/commit/0b2ecbbb36edc4aa54e4b9aeacb815450953400a)) 327 | 328 | - **deps**: Bump bluetooth-data-tools from 1.22.0 to 1.23.3 329 | ([#135](https://github.com/Bluetooth-Devices/govee-ble/pull/135), 330 | [`fe74840`](https://github.com/Bluetooth-Devices/govee-ble/commit/fe74840c732046f143c825f04ffaa967c6f9af71)) 331 | 332 | - **deps**: Bump cryptography from 42.0.8 to 44.0.0 333 | ([#122](https://github.com/Bluetooth-Devices/govee-ble/pull/122), 334 | [`9ec1fcf`](https://github.com/Bluetooth-Devices/govee-ble/commit/9ec1fcf5d992482cae297cf1f0671e51273c59f4)) 335 | 336 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 337 | 338 | - **deps**: Bump jinja2 from 3.1.4 to 3.1.5 339 | ([#123](https://github.com/Bluetooth-Devices/govee-ble/pull/123), 340 | [`9cd5c5c`](https://github.com/Bluetooth-Devices/govee-ble/commit/9cd5c5c6642e4c29f21743222f11f4fef3e5fd83)) 341 | 342 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 343 | 344 | - **deps**: Bump myst-parser from 0.18.1 to 1.0.0 345 | ([#119](https://github.com/Bluetooth-Devices/govee-ble/pull/119), 346 | [`9201df8`](https://github.com/Bluetooth-Devices/govee-ble/commit/9201df85046b4b4213ced94ffa5fd5f912efd8b8)) 347 | 348 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 349 | 350 | - **deps**: Bump myst-parser from 1.0.0 to 3.0.1 351 | ([#131](https://github.com/Bluetooth-Devices/govee-ble/pull/131), 352 | [`4e70715`](https://github.com/Bluetooth-Devices/govee-ble/commit/4e7071563aa1e9d2f0c18cc85449f80e3dc02bc2)) 353 | 354 | - **deps**: Bump sphinx from 5.3.0 to 6.2.1 355 | ([#126](https://github.com/Bluetooth-Devices/govee-ble/pull/126), 356 | [`4d9a98b`](https://github.com/Bluetooth-Devices/govee-ble/commit/4d9a98b1633dd237f82e5b455098433ec5034845)) 357 | 358 | - **deps**: Bump sphinx from 6.2.1 to 7.4.7 359 | ([#134](https://github.com/Bluetooth-Devices/govee-ble/pull/134), 360 | [`8b32dd7`](https://github.com/Bluetooth-Devices/govee-ble/commit/8b32dd7d69031ffc356f86dbc502a274920ffbf4)) 361 | 362 | - **deps**: Bump sphinx-rtd-theme from 1.3.0 to 2.0.0 363 | ([#120](https://github.com/Bluetooth-Devices/govee-ble/pull/120), 364 | [`ba94d1e`](https://github.com/Bluetooth-Devices/govee-ble/commit/ba94d1eafe9a7cd4eed4440cb9afd39f7996d108)) 365 | 366 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 367 | 368 | - **deps**: Bump sphinx-rtd-theme from 2.0.0 to 3.0.2 369 | ([#132](https://github.com/Bluetooth-Devices/govee-ble/pull/132), 370 | [`2288823`](https://github.com/Bluetooth-Devices/govee-ble/commit/22888233d51b777a65195642907de30709dc942f)) 371 | 372 | Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 2.0.0 to 3.0.2. - 373 | [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - 374 | [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/2.0.0...3.0.2) 375 | 376 | --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production 377 | 378 | update-type: version-update:semver-major ... 379 | 380 | Signed-off-by: dependabot[bot] 381 | 382 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 383 | 384 | - **deps-dev**: Bump pytest from 7.4.4 to 8.3.4 385 | ([#118](https://github.com/Bluetooth-Devices/govee-ble/pull/118), 386 | [`e94e1fc`](https://github.com/Bluetooth-Devices/govee-ble/commit/e94e1fc854c5b22c0fe9d2ea85aa5c5afb72933d)) 387 | 388 | Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 389 | 390 | - **deps-dev**: Bump pytest-cov from 3.0.0 to 6.0.0 391 | ([#121](https://github.com/Bluetooth-Devices/govee-ble/pull/121), 392 | [`ecbeb28`](https://github.com/Bluetooth-Devices/govee-ble/commit/ecbeb28e3f31f0395cdf24b9c6d908a269663817)) 393 | 394 | - **pre-commit.ci**: Pre-commit autoupdate 395 | ([#127](https://github.com/Bluetooth-Devices/govee-ble/pull/127), 396 | [`90f701c`](https://github.com/Bluetooth-Devices/govee-ble/commit/90f701c6fdeb523a144f174fff8bd5361d1f9adf)) 397 | 398 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 399 | 400 | - **pre-commit.ci**: Pre-commit autoupdate 401 | ([#133](https://github.com/Bluetooth-Devices/govee-ble/pull/133), 402 | [`882ad48`](https://github.com/Bluetooth-Devices/govee-ble/commit/882ad48343050d113bfc8f8d02009bdeaf57337a)) 403 | 404 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 405 | 406 | - **pre-commit.ci**: Pre-commit autoupdate 407 | ([#136](https://github.com/Bluetooth-Devices/govee-ble/pull/136), 408 | [`8b0568f`](https://github.com/Bluetooth-Devices/govee-ble/commit/8b0568fe21e115e8a001771767c6a1f81b89252d)) 409 | 410 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 411 | 412 | ### Refactoring 413 | 414 | - Reduce duplicate code ([#129](https://github.com/Bluetooth-Devices/govee-ble/pull/129), 415 | [`f265edd`](https://github.com/Bluetooth-Devices/govee-ble/commit/f265edd415371063720e1d027f912b9d16e6fd24)) 416 | 417 | - Reduce duplicate code ([#130](https://github.com/Bluetooth-Devices/govee-ble/pull/130), 418 | [`e359472`](https://github.com/Bluetooth-Devices/govee-ble/commit/e35947253a35f51603fafbad1f155ab75b936d34)) 419 | 420 | 421 | ## v0.42.0 (2025-01-16) 422 | 423 | ### Features 424 | 425 | - Add support for gvh5130 button ([#117](https://github.com/Bluetooth-Devices/govee-ble/pull/117), 426 | [`0d499db`](https://github.com/Bluetooth-Devices/govee-ble/commit/0d499db328c19b2403c5d0089224a3fc46300e56)) 427 | 428 | 429 | ## v0.41.0 (2025-01-16) 430 | 431 | ### Chores 432 | 433 | - **pre-commit.ci**: Pre-commit autoupdate 434 | ([#103](https://github.com/Bluetooth-Devices/govee-ble/pull/103), 435 | [`c4f1937`](https://github.com/Bluetooth-Devices/govee-ble/commit/c4f19377053fd1213a0e0eaaa675f3850d9faf7b)) 436 | 437 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 438 | 439 | - **pre-commit.ci**: Pre-commit autoupdate 440 | ([#104](https://github.com/Bluetooth-Devices/govee-ble/pull/104), 441 | [`a3e80b5`](https://github.com/Bluetooth-Devices/govee-ble/commit/a3e80b57dc896a7251c64d7e164ce90207fc3951)) 442 | 443 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 444 | 445 | - **pre-commit.ci**: Pre-commit autoupdate 446 | ([#105](https://github.com/Bluetooth-Devices/govee-ble/pull/105), 447 | [`b31d39e`](https://github.com/Bluetooth-Devices/govee-ble/commit/b31d39ece0bb991b1ef92e8fb46ed32ea22e2202)) 448 | 449 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 450 | 451 | - **pre-commit.ci**: Pre-commit autoupdate 452 | ([#106](https://github.com/Bluetooth-Devices/govee-ble/pull/106), 453 | [`be92194`](https://github.com/Bluetooth-Devices/govee-ble/commit/be921949f7162c6ed77421d690ec709f2c511024)) 454 | 455 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 456 | 457 | - **pre-commit.ci**: Pre-commit autoupdate 458 | ([#107](https://github.com/Bluetooth-Devices/govee-ble/pull/107), 459 | [`2b0cb41`](https://github.com/Bluetooth-Devices/govee-ble/commit/2b0cb4162f4419045bfbec9b95f30a8cc4ce70c2)) 460 | 461 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 462 | 463 | - **pre-commit.ci**: Pre-commit autoupdate 464 | ([#108](https://github.com/Bluetooth-Devices/govee-ble/pull/108), 465 | [`1d7da8c`](https://github.com/Bluetooth-Devices/govee-ble/commit/1d7da8c1fc19ad0dd2ed151492a2027780823b6f)) 466 | 467 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 468 | 469 | - **pre-commit.ci**: Pre-commit autoupdate 470 | ([#109](https://github.com/Bluetooth-Devices/govee-ble/pull/109), 471 | [`7c0ccda`](https://github.com/Bluetooth-Devices/govee-ble/commit/7c0ccda3c9c8d661cc3c6cb3b7fca56b3c5fcc99)) 472 | 473 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 474 | 475 | - **pre-commit.ci**: Pre-commit autoupdate 476 | ([#110](https://github.com/Bluetooth-Devices/govee-ble/pull/110), 477 | [`41d2374`](https://github.com/Bluetooth-Devices/govee-ble/commit/41d2374dd29d93dbf3a30ea0158503cf95cc34c2)) 478 | 479 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 480 | 481 | - **pre-commit.ci**: Pre-commit autoupdate 482 | ([#112](https://github.com/Bluetooth-Devices/govee-ble/pull/112), 483 | [`5c0f0c1`](https://github.com/Bluetooth-Devices/govee-ble/commit/5c0f0c1ea3cb49a689a0e9c9c9288d815b0d6a3f)) 484 | 485 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 486 | 487 | - **pre-commit.ci**: Pre-commit autoupdate 488 | ([#113](https://github.com/Bluetooth-Devices/govee-ble/pull/113), 489 | [`4b7d53d`](https://github.com/Bluetooth-Devices/govee-ble/commit/4b7d53dfc674495bbf4126faa3d1f704c69b040f)) 490 | 491 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 492 | 493 | - **pre-commit.ci**: Pre-commit autoupdate 494 | ([#114](https://github.com/Bluetooth-Devices/govee-ble/pull/114), 495 | [`281c20b`](https://github.com/Bluetooth-Devices/govee-ble/commit/281c20b5fc56018aec1d30353794edf1553447d8)) 496 | 497 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 498 | 499 | - **pre-commit.ci**: Pre-commit autoupdate 500 | ([#115](https://github.com/Bluetooth-Devices/govee-ble/pull/115), 501 | [`1d2dcaf`](https://github.com/Bluetooth-Devices/govee-ble/commit/1d2dcaf28ed11faa6455aded30b5eaae43e5b0ea)) 502 | 503 | ### Features 504 | 505 | - Add support for H5130 Pressure sensor 506 | ([#116](https://github.com/Bluetooth-Devices/govee-ble/pull/116), 507 | [`5336114`](https://github.com/Bluetooth-Devices/govee-ble/commit/5336114250175ea92217e73d3b5c674e76ffbb2b)) 508 | 509 | 510 | ## v0.40.0 (2024-07-24) 511 | 512 | ### Features 513 | 514 | - Add support for h5127 ([#101](https://github.com/Bluetooth-Devices/govee-ble/pull/101), 515 | [`5e84208`](https://github.com/Bluetooth-Devices/govee-ble/commit/5e8420811b07540999bdb8580f13653f2e413a21)) 516 | 517 | 518 | ## v0.39.1 (2024-07-24) 519 | 520 | ### Bug Fixes 521 | 522 | - Vibration sensor is on only and should have been an event 523 | ([#100](https://github.com/Bluetooth-Devices/govee-ble/pull/100), 524 | [`142e7c5`](https://github.com/Bluetooth-Devices/govee-ble/commit/142e7c50bb6db8cdf3f9818c85645280b0bb25fc)) 525 | 526 | 527 | ## v0.39.0 (2024-07-24) 528 | 529 | ### Chores 530 | 531 | - **pre-commit.ci**: Pre-commit autoupdate 532 | ([#98](https://github.com/Bluetooth-Devices/govee-ble/pull/98), 533 | [`69daf5f`](https://github.com/Bluetooth-Devices/govee-ble/commit/69daf5f24e6f30469eb020f43866f49394a2ba50)) 534 | 535 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 536 | 537 | ### Features 538 | 539 | - Add support for h5124 vibration sensors 540 | ([#99](https://github.com/Bluetooth-Devices/govee-ble/pull/99), 541 | [`d88ffd6`](https://github.com/Bluetooth-Devices/govee-ble/commit/d88ffd62e0089b87831ed10b00782a642eca253e)) 542 | 543 | 544 | ## v0.38.0 (2024-07-17) 545 | 546 | ### Features 547 | 548 | - Add support for binary sensors ([#97](https://github.com/Bluetooth-Devices/govee-ble/pull/97), 549 | [`ab22cdb`](https://github.com/Bluetooth-Devices/govee-ble/commit/ab22cdbc291ee95ad107003dad1d7ec001e1f63b)) 550 | 551 | 552 | ## v0.37.0 (2024-07-16) 553 | 554 | ### Features 555 | 556 | - Add support for sleepy devices ([#96](https://github.com/Bluetooth-Devices/govee-ble/pull/96), 557 | [`bbe36fa`](https://github.com/Bluetooth-Devices/govee-ble/commit/bbe36fa862f022c5f0f47f42cbfddb3fe92f19a3)) 558 | 559 | 560 | ## v0.36.1 (2024-07-16) 561 | 562 | ### Bug Fixes 563 | 564 | - Handle model not yet set ([#95](https://github.com/Bluetooth-Devices/govee-ble/pull/95), 565 | [`2083a01`](https://github.com/Bluetooth-Devices/govee-ble/commit/2083a01ecb102e1c9dd2292b898c22da8695b1d3)) 566 | 567 | 568 | ## v0.36.0 (2024-07-16) 569 | 570 | ### Features 571 | 572 | - Expose ModelInfo ([#94](https://github.com/Bluetooth-Devices/govee-ble/pull/94), 573 | [`9111e16`](https://github.com/Bluetooth-Devices/govee-ble/commit/9111e16a6385258dd11b9756c2ed4d2cbdd7c50a)) 574 | 575 | 576 | ## v0.35.1 (2024-07-16) 577 | 578 | ### Bug Fixes 579 | 580 | - Handle remote discovered first ([#93](https://github.com/Bluetooth-Devices/govee-ble/pull/93), 581 | [`ae375f6`](https://github.com/Bluetooth-Devices/govee-ble/commit/ae375f627d66fa505727f6da9388fd94b138b2be)) 582 | 583 | 584 | ## v0.35.0 (2024-07-16) 585 | 586 | ### Features 587 | 588 | - Refactor to support get_model_info for offline devices 589 | ([#92](https://github.com/Bluetooth-Devices/govee-ble/pull/92), 590 | [`a12d139`](https://github.com/Bluetooth-Devices/govee-ble/commit/a12d139cd29b73bd17225958f13b534425f4f7e1)) 591 | 592 | 593 | ## v0.34.0 (2024-07-16) 594 | 595 | ### Features 596 | 597 | - Add sensor type and button count ([#91](https://github.com/Bluetooth-Devices/govee-ble/pull/91), 598 | [`747dcb0`](https://github.com/Bluetooth-Devices/govee-ble/commit/747dcb091c2ff2234d2d3eccc39f551a09d5a878)) 599 | 600 | 601 | ## v0.33.1 (2024-07-16) 602 | 603 | ### Bug Fixes 604 | 605 | - Remove unused device id code ([#90](https://github.com/Bluetooth-Devices/govee-ble/pull/90), 606 | [`a071f2e`](https://github.com/Bluetooth-Devices/govee-ble/commit/a071f2ecfd7b14d504cfdaee46e289e530383008)) 607 | 608 | 609 | ## v0.33.0 (2024-07-16) 610 | 611 | ### Features 612 | 613 | - Add passive support for GV5121/GV5122/GV5123/GV5125/GV5126 614 | ([#89](https://github.com/Bluetooth-Devices/govee-ble/pull/89), 615 | [`83ac0d5`](https://github.com/Bluetooth-Devices/govee-ble/commit/83ac0d5950d420e35113c38a58553b413b27c1f8)) 616 | 617 | 618 | ## v0.32.0 (2024-07-15) 619 | 620 | ### Chores 621 | 622 | - **pre-commit.ci**: Pre-commit autoupdate 623 | ([#87](https://github.com/Bluetooth-Devices/govee-ble/pull/87), 624 | [`d6e3cc4`](https://github.com/Bluetooth-Devices/govee-ble/commit/d6e3cc448e41d031544dbca0ba91f18fc6e76b6c)) 625 | 626 | * chore(pre-commit.ci): pre-commit autoupdate 627 | 628 | updates: - [github.com/commitizen-tools/commitizen: v2.28.0 → 629 | v3.27.0](https://github.com/commitizen-tools/commitizen/compare/v2.28.0...v3.27.0) - 630 | [github.com/pre-commit/pre-commit-hooks: v4.3.0 → 631 | v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.6.0) - 632 | [github.com/pre-commit/mirrors-prettier: v2.7.1 → 633 | v4.0.0-alpha.8](https://github.com/pre-commit/mirrors-prettier/compare/v2.7.1...v4.0.0-alpha.8) - 634 | [github.com/asottile/pyupgrade: v2.37.1 → 635 | v3.16.0](https://github.com/asottile/pyupgrade/compare/v2.37.1...v3.16.0) - 636 | [github.com/PyCQA/isort: 5.12.0 → 5.13.2](https://github.com/PyCQA/isort/compare/5.12.0...5.13.2) 637 | - [github.com/psf/black: 22.6.0 → 24.4.2](https://github.com/psf/black/compare/22.6.0...24.4.2) - 638 | [github.com/codespell-project/codespell: v2.1.0 → 639 | v2.3.0](https://github.com/codespell-project/codespell/compare/v2.1.0...v2.3.0) - 640 | [github.com/PyCQA/flake8: 4.0.1 → 7.1.0](https://github.com/PyCQA/flake8/compare/4.0.1...7.1.0) - 641 | [github.com/pre-commit/mirrors-mypy: v0.931 → 642 | v1.10.1](https://github.com/pre-commit/mirrors-mypy/compare/v0.931...v1.10.1) - 643 | [github.com/PyCQA/bandit: 1.7.4 → 1.7.9](https://github.com/PyCQA/bandit/compare/1.7.4...1.7.9) 644 | 645 | * chore(pre-commit.ci): auto fixes 646 | 647 | --------- 648 | 649 | Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 650 | 651 | ### Features 652 | 653 | - Add support for GV5121/GV5122/GV5123/GV5125/GV5126 654 | ([#88](https://github.com/Bluetooth-Devices/govee-ble/pull/88), 655 | [`e71ca98`](https://github.com/Bluetooth-Devices/govee-ble/commit/e71ca9897fc2de04adeb3c70a5777e52a3588c04)) 656 | 657 | 658 | ## v0.31.3 (2024-06-24) 659 | 660 | ### Bug Fixes 661 | 662 | - Fix license classifier ([#86](https://github.com/Bluetooth-Devices/govee-ble/pull/86), 663 | [`88408cf`](https://github.com/Bluetooth-Devices/govee-ble/commit/88408cfe3c6d075718e0fdddbf7fed38c27e59f1)) 664 | 665 | 666 | ## v0.31.2 (2024-04-25) 667 | 668 | ### Bug Fixes 669 | 670 | - Ryse smart shades where being detected as an h5106 671 | ([#85](https://github.com/Bluetooth-Devices/govee-ble/pull/85), 672 | [`509977f`](https://github.com/Bluetooth-Devices/govee-ble/commit/509977f0c1e309b496ebbae2f2f930b38548f2b0)) 673 | 674 | ### Testing 675 | 676 | - Add more 5105 tests ([#84](https://github.com/Bluetooth-Devices/govee-ble/pull/84), 677 | [`94bfe57`](https://github.com/Bluetooth-Devices/govee-ble/commit/94bfe57af1d134805aede008459b7dfeb78e0597)) 678 | 679 | 680 | ## v0.31.1 (2024-04-25) 681 | 682 | ### Bug Fixes 683 | 684 | - Show h5075 as h5075 instead of h5075/h5072 685 | ([#83](https://github.com/Bluetooth-Devices/govee-ble/pull/83), 686 | [`8fc22f7`](https://github.com/Bluetooth-Devices/govee-ble/commit/8fc22f7e4183341e02c38667ab830c9edeb27cd3)) 687 | 688 | 689 | ## v0.31.0 (2024-01-31) 690 | 691 | ### Features 692 | 693 | - Add support for H5108 with external probe 694 | ([#82](https://github.com/Bluetooth-Devices/govee-ble/pull/82), 695 | [`46bccd8`](https://github.com/Bluetooth-Devices/govee-ble/commit/46bccd8a487dc736f4e75b6b584d8610e008c306)) 696 | 697 | 698 | ## v0.30.0 (2024-01-31) 699 | 700 | ### Features 701 | 702 | - Add support for h5100 ([#81](https://github.com/Bluetooth-Devices/govee-ble/pull/81), 703 | [`00d9581`](https://github.com/Bluetooth-Devices/govee-ble/commit/00d9581bfb766f9ab95d3034afc45e4f9dcaf58f)) 704 | 705 | 706 | ## v0.29.0 (2024-01-31) 707 | 708 | ### Features 709 | 710 | - Add support for h5105 ([#80](https://github.com/Bluetooth-Devices/govee-ble/pull/80), 711 | [`d1ab246`](https://github.com/Bluetooth-Devices/govee-ble/commit/d1ab246b766df4775ae1c3534b52b66f8f88e39f)) 712 | 713 | 714 | ## v0.28.0 (2024-01-31) 715 | 716 | ### Features 717 | 718 | - Add support for h5103 ([#79](https://github.com/Bluetooth-Devices/govee-ble/pull/79), 719 | [`0c698bb`](https://github.com/Bluetooth-Devices/govee-ble/commit/0c698bbfd3d30233c60fdec0722d41f86904c120)) 720 | 721 | 722 | ## v0.27.3 (2024-01-12) 723 | 724 | ### Bug Fixes 725 | 726 | - Ensure H5106 is not detected as a H5101 727 | ([#77](https://github.com/Bluetooth-Devices/govee-ble/pull/77), 728 | [`0f847ea`](https://github.com/Bluetooth-Devices/govee-ble/commit/0f847ea83473d5c385664e62ebd4771aa4a8ba82)) 729 | 730 | 731 | ## v0.27.2 (2024-01-11) 732 | 733 | ### Bug Fixes 734 | 735 | - Ensure H5106 has a name in passive mode 736 | ([#76](https://github.com/Bluetooth-Devices/govee-ble/pull/76), 737 | [`491977e`](https://github.com/Bluetooth-Devices/govee-ble/commit/491977e12363f25fd543e4663e419c9e0c891bcb)) 738 | 739 | 740 | ## v0.27.1 (2024-01-11) 741 | 742 | ### Bug Fixes 743 | 744 | - Update sensor state data to fix pm25 in library 745 | ([#75](https://github.com/Bluetooth-Devices/govee-ble/pull/75), 746 | [`425d322`](https://github.com/Bluetooth-Devices/govee-ble/commit/425d32230af45990bb5383ee64c8d03a815d64d6)) 747 | 748 | 749 | ## v0.27.0 (2024-01-11) 750 | 751 | ### Features 752 | 753 | - Add support for H5106 ([#74](https://github.com/Bluetooth-Devices/govee-ble/pull/74), 754 | [`1466f9d`](https://github.com/Bluetooth-Devices/govee-ble/commit/1466f9d680d6bca900677eda9fcef2c02150c374)) 755 | 756 | 757 | ## v0.26.0 (2024-01-10) 758 | 759 | ### Features 760 | 761 | - Add support for 5104 and 5174 ([#73](https://github.com/Bluetooth-Devices/govee-ble/pull/73), 762 | [`ce7e266`](https://github.com/Bluetooth-Devices/govee-ble/commit/ce7e266e27afddc46e607ce8cd08f2a941749f69)) 763 | 764 | 765 | ## v0.25.0 (2024-01-10) 766 | 767 | ### Features 768 | 769 | - Add support for H5108 ([#72](https://github.com/Bluetooth-Devices/govee-ble/pull/72), 770 | [`0f52384`](https://github.com/Bluetooth-Devices/govee-ble/commit/0f5238472177402361f3d1a39861c2a9db29307d)) 771 | 772 | 773 | ## v0.24.0 (2023-08-11) 774 | 775 | ### Chores 776 | 777 | - Update python-semantic-release ([#67](https://github.com/Bluetooth-Devices/govee-ble/pull/67), 778 | [`082e358`](https://github.com/Bluetooth-Devices/govee-ble/commit/082e35861194395b9539726e466cc7abee529ba1)) 779 | 780 | ### Features 781 | 782 | - Add support for govee h5055 ([#66](https://github.com/Bluetooth-Devices/govee-ble/pull/66), 783 | [`badd966`](https://github.com/Bluetooth-Devices/govee-ble/commit/badd966b529225f7ce55e97362e0b3c15be5191a)) 784 | 785 | 786 | ## v0.23.0 (2023-02-10) 787 | 788 | ### Bug Fixes 789 | 790 | - Update isort to fix ci ([#62](https://github.com/Bluetooth-Devices/govee-ble/pull/62), 791 | [`9147504`](https://github.com/Bluetooth-Devices/govee-ble/commit/914750424c33fcaa1268d7d36dac1cccd7441ae6)) 792 | 793 | ### Features 794 | 795 | - Add low temperature alarm to h5198 ([#61](https://github.com/Bluetooth-Devices/govee-ble/pull/61), 796 | [`d2b8e0f`](https://github.com/Bluetooth-Devices/govee-ble/commit/d2b8e0f5ddc0faa1bd2699439605601c0ca58f08)) 797 | 798 | 799 | ## v0.22.0 (2023-01-27) 800 | 801 | ### Features 802 | 803 | - Add govee h5198 ([#60](https://github.com/Bluetooth-Devices/govee-ble/pull/60), 804 | [`821a55d`](https://github.com/Bluetooth-Devices/govee-ble/commit/821a55d1162b9d87e2a7745e9e015b925f7bf816)) 805 | 806 | 807 | ## v0.21.1 (2023-01-12) 808 | 809 | ### Bug Fixes 810 | 811 | - Decrease minimum temperature to -30C 812 | ([#57](https://github.com/Bluetooth-Devices/govee-ble/pull/57), 813 | [`c41c9b5`](https://github.com/Bluetooth-Devices/govee-ble/commit/c41c9b5858a469e07cbb6b6666f2bdd4f5eee2c8)) 814 | 815 | Fixes https://github.com/home-assistant/core/issues/85580 816 | 817 | 818 | ## v0.21.0 (2022-12-27) 819 | 820 | ### Features 821 | 822 | - Implement error bit ([#55](https://github.com/Bluetooth-Devices/govee-ble/pull/55), 823 | [`b4b2f82`](https://github.com/Bluetooth-Devices/govee-ble/commit/b4b2f821e8d1dc6e1517ca76d29d124add369eb7)) 824 | 825 | Fixes https://github.com/Bluetooth-Devices/govee-ble/issues/51 826 | 827 | 828 | ## v0.20.0 (2022-12-19) 829 | 830 | ### Features 831 | 832 | - Log data as hex ([#53](https://github.com/Bluetooth-Devices/govee-ble/pull/53), 833 | [`d014bfc`](https://github.com/Bluetooth-Devices/govee-ble/commit/d014bfc9e1ed278c8fe2f25b469941748bac19cb)) 834 | 835 | 836 | ## v0.19.4 (2022-12-18) 837 | 838 | ### Bug Fixes 839 | 840 | - Round temp values ([#52](https://github.com/Bluetooth-Devices/govee-ble/pull/52), 841 | [`e7ec133`](https://github.com/Bluetooth-Devices/govee-ble/commit/e7ec133fa7a884f67b841a5f1f42c7d98946657e)) 842 | 843 | 844 | ## v0.19.3 (2022-12-15) 845 | 846 | ### Bug Fixes 847 | 848 | - Reject impossible temp values take 2 849 | ([#50](https://github.com/Bluetooth-Devices/govee-ble/pull/50), 850 | [`c0a54eb`](https://github.com/Bluetooth-Devices/govee-ble/commit/c0a54eb3e00afe20bacbb930ea8ce251d760d8bc)) 851 | 852 | 853 | ## v0.19.2 (2022-12-15) 854 | 855 | ### Bug Fixes 856 | 857 | - Reject impossible temp values ([#47](https://github.com/Bluetooth-Devices/govee-ble/pull/47), 858 | [`bb8b6e0`](https://github.com/Bluetooth-Devices/govee-ble/commit/bb8b6e00b8c0a2a8779806e6b25330ef50cb41f8)) 859 | 860 | 861 | ## v0.19.1 (2022-09-30) 862 | 863 | ### Bug Fixes 864 | 865 | - Handle another H5181 ([#45](https://github.com/Bluetooth-Devices/govee-ble/pull/45), 866 | [`af2da30`](https://github.com/Bluetooth-Devices/govee-ble/commit/af2da30574db19674ec5e76bfaa5c84adcbbe9f0)) 867 | 868 | 869 | ## v0.19.0 (2022-09-24) 870 | 871 | ### Features 872 | 873 | - Add support for yet another H5183 variant 874 | ([#44](https://github.com/Bluetooth-Devices/govee-ble/pull/44), 875 | [`d699552`](https://github.com/Bluetooth-Devices/govee-ble/commit/d699552bef2c3be13b34899f34e355a54914ffdb)) 876 | 877 | 878 | ## v0.18.0 (2022-09-24) 879 | 880 | ### Features 881 | 882 | - Add support for another H5181 variant 883 | ([#43](https://github.com/Bluetooth-Devices/govee-ble/pull/43), 884 | [`7738d25`](https://github.com/Bluetooth-Devices/govee-ble/commit/7738d25fe6737a2c41d4d1f7af6e3fa41861ba0e)) 885 | 886 | 887 | ## v0.17.3 (2022-09-13) 888 | 889 | ### Bug Fixes 890 | 891 | - Publish ([#41](https://github.com/Bluetooth-Devices/govee-ble/pull/41), 892 | [`40ce706`](https://github.com/Bluetooth-Devices/govee-ble/commit/40ce70653f9cd52eb584253f6893d0f20677d2c7)) 893 | 894 | 895 | ## v0.17.2 (2022-09-05) 896 | 897 | ### Bug Fixes 898 | 899 | - Names are now human readable ([#39](https://github.com/Bluetooth-Devices/govee-ble/pull/39), 900 | [`fefc6b4`](https://github.com/Bluetooth-Devices/govee-ble/commit/fefc6b405e62a063234d12c8d812f9581b24369c)) 901 | 902 | 903 | ## v0.17.1 (2022-08-31) 904 | 905 | ### Bug Fixes 906 | 907 | - Model H5181 var fixes ([#38](https://github.com/Bluetooth-Devices/govee-ble/pull/38), 908 | [`42012bc`](https://github.com/Bluetooth-Devices/govee-ble/commit/42012bc8be9028c62054a7b143ea990ffeb67deb)) 909 | 910 | 911 | ## v0.17.0 (2022-08-30) 912 | 913 | ### Features 914 | 915 | - Add support for additional H5185 firmware 916 | ([#37](https://github.com/Bluetooth-Devices/govee-ble/pull/37), 917 | [`0a5dfa5`](https://github.com/Bluetooth-Devices/govee-ble/commit/0a5dfa5e4e95d79f3f9a5e076355963ba75d34be)) 918 | 919 | 920 | ## v0.16.1 (2022-08-25) 921 | 922 | ### Bug Fixes 923 | 924 | - Use bluetooth-data-tools short_address 925 | ([#36](https://github.com/Bluetooth-Devices/govee-ble/pull/36), 926 | [`e137d93`](https://github.com/Bluetooth-Devices/govee-ble/commit/e137d930d7605a41f7112fd342cfc4bd269dc7da)) 927 | 928 | 929 | ## v0.16.0 (2022-08-16) 930 | 931 | ### Features 932 | 933 | - Add support for H5071 ([#34](https://github.com/Bluetooth-Devices/govee-ble/pull/34), 934 | [`cf7e809`](https://github.com/Bluetooth-Devices/govee-ble/commit/cf7e8095c3f15a5d2ccde2cd14cf294edb4ba379)) 935 | 936 | 937 | ## v0.15.0 (2022-08-16) 938 | 939 | ### Features 940 | 941 | - Implement rounding ([#33](https://github.com/Bluetooth-Devices/govee-ble/pull/33), 942 | [`eeed1aa`](https://github.com/Bluetooth-Devices/govee-ble/commit/eeed1aa231be0df9f3193511124ca2dfeeeaee51)) 943 | 944 | 945 | ## v0.14.1 (2022-08-11) 946 | 947 | ### Bug Fixes 948 | 949 | - Older 5181 firmwares ([#31](https://github.com/Bluetooth-Devices/govee-ble/pull/31), 950 | [`61eac60`](https://github.com/Bluetooth-Devices/govee-ble/commit/61eac6038177b58c07a80882d3cebe9debc25430)) 951 | 952 | 953 | ## v0.14.0 (2022-08-08) 954 | 955 | ### Features 956 | 957 | - Add support for the h5052 ([#30](https://github.com/Bluetooth-Devices/govee-ble/pull/30), 958 | [`625594c`](https://github.com/Bluetooth-Devices/govee-ble/commit/625594c16ad67801cf2a57fa2534900e6ef28310)) 959 | 960 | 961 | ## v0.13.0 (2022-08-08) 962 | 963 | ### Features 964 | 965 | - Add support for the 5184 devices ([#29](https://github.com/Bluetooth-Devices/govee-ble/pull/29), 966 | [`d9d6d6a`](https://github.com/Bluetooth-Devices/govee-ble/commit/d9d6d6a84e7b7647c829be8471915e15fa61ca0d)) 967 | 968 | 969 | ## v0.12.7 (2022-08-07) 970 | 971 | ### Bug Fixes 972 | 973 | - Add 818 to the manufacturer_ids for the gvh5185 974 | ([#28](https://github.com/Bluetooth-Devices/govee-ble/pull/28), 975 | [`f3cfb61`](https://github.com/Bluetooth-Devices/govee-ble/commit/f3cfb61c2d562b801570956901f669c27b0d77fb)) 976 | 977 | 978 | ## v0.12.6 (2022-08-02) 979 | 980 | ### Bug Fixes 981 | 982 | - The GVH5074 is little endian ([#27](https://github.com/Bluetooth-Devices/govee-ble/pull/27), 983 | [`28e626c`](https://github.com/Bluetooth-Devices/govee-ble/commit/28e626c2527c395c507fbe00e7f18a184a3484f0)) 984 | 985 | 986 | ## v0.12.5 (2022-07-30) 987 | 988 | ### Bug Fixes 989 | 990 | - H5179 is little endian and not big endian like the rest 991 | ([#26](https://github.com/Bluetooth-Devices/govee-ble/pull/26), 992 | [`24a0e92`](https://github.com/Bluetooth-Devices/govee-ble/commit/24a0e922f32ef476d51d0b13e90a737dfdc83676)) 993 | 994 | 995 | ## v0.12.4 (2022-07-29) 996 | 997 | ### Bug Fixes 998 | 999 | - Parser for h5182 had the wrong mfgr_id 1000 | ([#25](https://github.com/Bluetooth-Devices/govee-ble/pull/25), 1001 | [`57abb96`](https://github.com/Bluetooth-Devices/govee-ble/commit/57abb962b32994fe4ec8cb938ad89947838b8294)) 1002 | 1003 | 1004 | ## v0.12.3 (2022-07-22) 1005 | 1006 | ### Bug Fixes 1007 | 1008 | - Names for bbq devices ([#24](https://github.com/Bluetooth-Devices/govee-ble/pull/24), 1009 | [`4407ed4`](https://github.com/Bluetooth-Devices/govee-ble/commit/4407ed431f4280ca77b7a31cd4fa930f878aee77)) 1010 | 1011 | 1012 | ## v0.12.2 (2022-07-22) 1013 | 1014 | ### Bug Fixes 1015 | 1016 | - Fixs for bbq sensors ([#23](https://github.com/Bluetooth-Devices/govee-ble/pull/23), 1017 | [`132d04d`](https://github.com/Bluetooth-Devices/govee-ble/commit/132d04d91fc9161ff1a67a34c9b00c46afb2f708)) 1018 | 1019 | 1020 | ## v0.12.1 (2022-07-21) 1021 | 1022 | ### Bug Fixes 1023 | 1024 | - Bump sensor-state-data to fix typing 1025 | ([#22](https://github.com/Bluetooth-Devices/govee-ble/pull/22), 1026 | [`d5cdfc5`](https://github.com/Bluetooth-Devices/govee-ble/commit/d5cdfc506abeb4c81bbb0c2d0c7515f7c81266c5)) 1027 | 1028 | 1029 | ## v0.12.0 (2022-07-21) 1030 | 1031 | ### Features 1032 | 1033 | - Refactor for sensor-state-data 2 ([#21](https://github.com/Bluetooth-Devices/govee-ble/pull/21), 1034 | [`b7fb4dc`](https://github.com/Bluetooth-Devices/govee-ble/commit/b7fb4dcef279e1eeb4b53e47e8f684c3a785e3c2)) 1035 | 1036 | 1037 | ## v0.11.0 (2022-07-20) 1038 | 1039 | ### Features 1040 | 1041 | - Export SensorDescription and SensorValue 1042 | ([#20](https://github.com/Bluetooth-Devices/govee-ble/pull/20), 1043 | [`b61e938`](https://github.com/Bluetooth-Devices/govee-ble/commit/b61e938ce974bf892b2060bc95d6ee808191d1bf)) 1044 | 1045 | 1046 | ## v0.10.2 (2022-07-20) 1047 | 1048 | ### Bug Fixes 1049 | 1050 | - Bump deps ([#19](https://github.com/Bluetooth-Devices/govee-ble/pull/19), 1051 | [`5fc9ece`](https://github.com/Bluetooth-Devices/govee-ble/commit/5fc9ece3d7502bfab84f9f287912f6375549cf49)) 1052 | 1053 | 1054 | ## v0.10.1 (2022-07-19) 1055 | 1056 | ### Bug Fixes 1057 | 1058 | - Bump libs ([#18](https://github.com/Bluetooth-Devices/govee-ble/pull/18), 1059 | [`e818e7c`](https://github.com/Bluetooth-Devices/govee-ble/commit/e818e7c4dc797a571e1d78426f62b940ec60c585)) 1060 | 1061 | 1062 | ## v0.10.0 (2022-07-19) 1063 | 1064 | ### Features 1065 | 1066 | - Export all needed objects ([#17](https://github.com/Bluetooth-Devices/govee-ble/pull/17), 1067 | [`3c5ca7b`](https://github.com/Bluetooth-Devices/govee-ble/commit/3c5ca7b42d20c36bcca650ba15b4b32280751a88)) 1068 | 1069 | 1070 | ## v0.9.1 (2022-07-19) 1071 | 1072 | ### Bug Fixes 1073 | 1074 | - Add missing device classes to bbq probes 1075 | ([#16](https://github.com/Bluetooth-Devices/govee-ble/pull/16), 1076 | [`f2cafd7`](https://github.com/Bluetooth-Devices/govee-ble/commit/f2cafd71dba9894cb7dc9ab6706bd23b77c61366)) 1077 | 1078 | 1079 | ## v0.9.0 (2022-07-19) 1080 | 1081 | ### Features 1082 | 1083 | - Set manu for secondary sensor ([#15](https://github.com/Bluetooth-Devices/govee-ble/pull/15), 1084 | [`ec54d57`](https://github.com/Bluetooth-Devices/govee-ble/commit/ec54d57f25bdff968d9430421b64a751f1b2ce13)) 1085 | 1086 | 1087 | ## v0.8.0 (2022-07-19) 1088 | 1089 | ### Features 1090 | 1091 | - Add set_device_manufacturer ([#14](https://github.com/Bluetooth-Devices/govee-ble/pull/14), 1092 | [`f0203b7`](https://github.com/Bluetooth-Devices/govee-ble/commit/f0203b7c50753127f298e7d7c6977580dccb8cd4)) 1093 | 1094 | 1095 | ## v0.7.0 (2022-07-19) 1096 | 1097 | ### Features 1098 | 1099 | - Add support for B5178 local name variation 1100 | ([#13](https://github.com/Bluetooth-Devices/govee-ble/pull/13), 1101 | [`324b3cd`](https://github.com/Bluetooth-Devices/govee-ble/commit/324b3cd99c833496af7427333e591f23d249ec70)) 1102 | 1103 | 1104 | ## v0.6.0 (2022-07-19) 1105 | 1106 | ### Features 1107 | 1108 | - Do not drop mac from title ([#12](https://github.com/Bluetooth-Devices/govee-ble/pull/12), 1109 | [`cd187ed`](https://github.com/Bluetooth-Devices/govee-ble/commit/cd187ed19b0acf5b7b0c3a91dbc0e13fb321cce5)) 1110 | 1111 | 1112 | ## v0.5.0 (2022-07-19) 1113 | 1114 | ### Features 1115 | 1116 | - Set title for outdoor sensors ([#11](https://github.com/Bluetooth-Devices/govee-ble/pull/11), 1117 | [`1031c78`](https://github.com/Bluetooth-Devices/govee-ble/commit/1031c782865e9b6ec74e38df5f3b4a5345d871ce)) 1118 | 1119 | 1120 | ## v0.4.1 (2022-07-19) 1121 | 1122 | ### Bug Fixes 1123 | 1124 | - Fix device_id for remote sensors ([#10](https://github.com/Bluetooth-Devices/govee-ble/pull/10), 1125 | [`198caf2`](https://github.com/Bluetooth-Devices/govee-ble/commit/198caf26a535f070921ee3e24cc66070d64282d2)) 1126 | 1127 | 1128 | ## v0.4.0 (2022-07-19) 1129 | 1130 | ### Features 1131 | 1132 | - Improve support for remote sensors ([#9](https://github.com/Bluetooth-Devices/govee-ble/pull/9), 1133 | [`bf6eca1`](https://github.com/Bluetooth-Devices/govee-ble/commit/bf6eca1d1f64770fd010475afaeeb642c5e175ff)) 1134 | 1135 | 1136 | ## v0.3.0 (2022-07-19) 1137 | 1138 | ### Features 1139 | 1140 | - Change model ([#8](https://github.com/Bluetooth-Devices/govee-ble/pull/8), 1141 | [`9456bb3`](https://github.com/Bluetooth-Devices/govee-ble/commit/9456bb3ec459e9f2e7d7be4e1bfd670e5cb4fed6)) 1142 | 1143 | 1144 | ## v0.2.1 (2022-07-19) 1145 | 1146 | ### Bug Fixes 1147 | 1148 | - Update sensor-state-data ([#7](https://github.com/Bluetooth-Devices/govee-ble/pull/7), 1149 | [`02b04a9`](https://github.com/Bluetooth-Devices/govee-ble/commit/02b04a91d47337dbdd925cc2c7e037500cd934f2)) 1150 | 1151 | 1152 | ## v0.2.0 (2022-07-19) 1153 | 1154 | ### Features 1155 | 1156 | - Switch to using bluetooth-sensor-state-data 1157 | ([#6](https://github.com/Bluetooth-Devices/govee-ble/pull/6), 1158 | [`8ad3ec5`](https://github.com/Bluetooth-Devices/govee-ble/commit/8ad3ec5f8e7117cf1847be79641b1f706eb9478f)) 1159 | 1160 | 1161 | ## v0.1.1 (2022-07-18) 1162 | 1163 | ### Bug Fixes 1164 | 1165 | - Fix links ([#5](https://github.com/Bluetooth-Devices/govee-ble/pull/5), 1166 | [`455f2d2`](https://github.com/Bluetooth-Devices/govee-ble/commit/455f2d202e80c03bb0e15d1f0385316e3d9dfded)) 1167 | 1168 | 1169 | ## v0.1.0 (2022-07-18) 1170 | 1171 | ### Bug Fixes 1172 | 1173 | - Fix publish process ([#4](https://github.com/Bluetooth-Devices/govee-ble/pull/4), 1174 | [`9c3f892`](https://github.com/Bluetooth-Devices/govee-ble/commit/9c3f89271d1226f05dbe6ec972096c2e822bd2bb)) 1175 | 1176 | ### Features 1177 | 1178 | - Init repo ([#2](https://github.com/Bluetooth-Devices/govee-ble/pull/2), 1179 | [`58fe30c`](https://github.com/Bluetooth-Devices/govee-ble/commit/58fe30ca51b74e3c822bb03e3876eced657915a8)) 1180 | 1181 | 1182 | ## v0.0.2 (2022-07-18) 1183 | 1184 | ### Bug Fixes 1185 | 1186 | - Bump python min to 3.9 1187 | ([`5913902`](https://github.com/Bluetooth-Devices/govee-ble/commit/5913902dd854a5e3fc86e290e76fcb8eef9d1804)) 1188 | 1189 | ### Chores 1190 | 1191 | - Initial commit 1192 | ([`4b17198`](https://github.com/Bluetooth-Devices/govee-ble/commit/4b171988c2acc563cb05f48c98837be78a1dd656)) 1193 | --------------------------------------------------------------------------------