diff --git a/.vscode/settings.json b/.vscode/settings.json
index e52f483..587f9ed 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -12,7 +12,6 @@
},
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
- "lint"
},
"python.analysis.autoImportCompletions": true,
"python.analysis.packageIndexDepths": [
@@ -34,6 +33,7 @@
"**/.mypy_cache": true,
"**/.pytest_cache": true,
"**/.ruff_cache": true,
+ "**/dist": true,
},
"extensions.ignoreRecommendations": false
}
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..f708d3d
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,31 @@
+Copyright 2024 David Buezas, Lennard Beers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------- Other Licenses -------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2016 Markus Peter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 968d3d2..39fccf7 100644
--- a/README.md
+++ b/README.md
@@ -22,13 +22,13 @@ A modernized temporary replacement for the native Home Assistant component.
4. Click `Add`
5. Close `Custom Repositories` modal
6. Click `+ EXPLORE & DOWNLOAD REPOSITORIES`
-7. Search for `dbuezas_eq3btsmart`
+7. Search for `eq3btsmart`
8. Click `Download`
9. Restart _Home Assistant_
### Option 2: Manual copy
-1. Copy the `dbuezas_eq3btsmart` folder inside `custom_components` of this repo to `/config/custom_components` in your Home Assistant instance
+1. Copy the `eq3btsmart` folder inside `custom_components` of this repo to `/config/custom_components` in your Home Assistant instance
2. Restart _Home Assistant_
## Adding devices
@@ -40,7 +40,7 @@ A modernized temporary replacement for the native Home Assistant component.
-or click `+ ADD INTEGRATION` and search for `dbuezas_eq3btsmart`
+or click `+ ADD INTEGRATION` and search for `eq3btsmart`
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/.pre-commit-config.yaml b/custom_components/dbuezas_eq3btsmart/python_eq3bt/.pre-commit-config.yaml
deleted file mode 100644
index cb8cdd2..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/.pre-commit-config.yaml
+++ /dev/null
@@ -1,37 +0,0 @@
-repos:
- - repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.3.0
- hooks:
- - id: trailing-whitespace
- - id: end-of-file-fixer
- - id: check-docstring-first
- - id: check-yaml
- - id: debug-statements
- - id: check-ast
-
- - repo: https://github.com/asottile/pyupgrade
- rev: v2.35.0
- hooks:
- - id: pyupgrade
- args: ["--py37-plus"]
-
- - repo: https://github.com/python/black
- rev: 22.6.0
- hooks:
- - id: black
-
- - repo: https://gitlab.com/pycqa/flake8
- rev: 3.9.2
- hooks:
- - id: flake8
-
- - repo: https://github.com/pre-commit/mirrors-isort
- rev: v5.10.1
- hooks:
- - id: isort
- additional_dependencies: [toml]
-
- - repo: https://github.com/pre-commit/mirrors-mypy
- rev: v0.961
- hooks:
- - id: mypy
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/CHANGELOG b/custom_components/dbuezas_eq3btsmart/python_eq3bt/CHANGELOG
deleted file mode 100644
index 51daa0a..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/CHANGELOG
+++ /dev/null
@@ -1,225 +0,0 @@
-Changelog
-=========
-
-0.2 (2022-07-13)
-----------------
-
-- Add publish to pypi workflow (#54) [Teemu R]
-
-- Add bleak backend and make it default (#53) [Teemu R]
-
-- Wrap backend exceptions inside BackendException (#52) [Teemu R]
-
-- Add mac property to thermostat class (#51) [Teemu R]
-
-- Update README, pyproject.toml (#49) [Teemu R]
-
-- Support gattlib as an alternative btle library (#48) [Helmut Grohne]
-
-- Use poetry, add pre-commit hooks & mass format to modern standards,
- add CI (#47) [Teemu R]
-
-
-0.1.12 (2021-11-13)
--------------------
-
-- Add bt interface selection (#44) [Hummel95]
-
-0.1.11 (2019-05-27)
--------------------
-
-- Decoding presets in status messages (#33) [Matthias Erll]
-
-- Adding device serial number and firmware (#31) [Matthias Erll]
-
-- Context.invoke() -> Context.forward() (#28) [Till]
-
-- Require python 3.4 or newer in setup.py, closes #23. [Teemu Rytilahti]
-
-
-0.1.10 (2018-11-09))
-------------------------
-- Context.invoke() -> Context.forward() (#28) [Till]
-- Require python 3.4 or newer in setup.py, closes #23. [Teemu Rytilahti]
-
-
-0.1.9 (2018-02-18)
-------------------------
-
-- Update to the new construct API (#20) [Arkadiusz Bulski]
-
-
-0.1.8 (2018-01-20)
-------------------
-
-- Update to work with the newest construct release, bump version. [Teemu
- Rytilahti]
-
-- Update schedule example, fixes #15. [Teemu Rytilahti]
-
-- Do not suppress exceptions from bluepy, but log them to debug logger
- and raise exceptions for users to handle. [Teemu Rytilahti]
-
-- Install flake8 and pylint, which are required for the travis build.
- [Teemu Rytilahti]
-
-0.1.7 (2017-10-06)
-------------------------
-- Fixed setting schedule not working (#9) [horsitis
-
-0.1.6 (2017-04-01)
-------------------------
-
-- Version 0.1.6. [Teemu Rytilahti]
-
-- Use debug logging for the first round of connection error. [Teemu
- Rytilahti]
-
-- Disallow running with python versions older than 3.4. [Teemu
- Rytilahti]
-
- The library _may_ still be python2 compatible though for now,
- but this is unsupported and should not be relied on.
-
-- On/Off/Manual mode fixes (#6) [Janne Grunau]
-
- * Handle On/Off mode correctly
-
- * Set temperature in [EQ3BT_MIN_TEMP, EQ3BT_MAX_TEMP] for manual mode
-
- * simplify mode setter function
-
-- Be less noisy on connection errors. [Teemu Rytilahti]
-
-- Require and validate mac address at the cli (#4) [Klemens Schölhorn]
-
-- Add missing structures.py. this was already in pypi package, so no
- harm done. [Teemu Rytilahti]
-
-
-0.1.5 (2017-01-28)
-------------------------
-
-- Version 0.1.5. [Teemu Rytilahti]
-
-- Fix manual on/off handling, cleanup the code for next release. [Teemu
- Rytilahti]
-
-- Make Thermostat testable. [Teemu Rytilahti]
-
-- Use less magic constants and more structures, fix manual mode setting.
- [Teemu Rytilahti]
-
-- Fix setup.py typo. [Teemu Rytilahti]
-
-- Eq3cli: add away command. [Teemu Rytilahti]
-
-- Restructuring with construct for more readable code. [Teemu Rytilahti]
-
- * add set_away(away_ends, temperature) for enabling and disabling away mode
-
-- Add hound-ci config. [Teemu Rytilahti]
-
-
-0.1.4 (2017-01-15)
-------------------
-
-- Version 0.1.4. [Teemu Rytilahti]
-
-- Add away_end property. [Teemu Rytilahti]
-
-- Add changelog. [Teemu Rytilahti]
-
-0.1.3 (2017-01-15)
-------------------
-
-- Make eq3bt a module. [Teemu Rytilahti]
-
-- Update README. [Teemu Rytilahti]
-
-- Add scheduling and offset functionality. [Teemu Rytilahti]
-
-- Connection: pretty print messaging in hex. [Teemu Rytilahti]
-
-- Setup.py: fix console script location. [Teemu Rytilahti]
-
-0.1.2 (2017-01-14)
-------------------
-
-- Fix packaging, add click dependency, bump to 0.1.2. [Teemu Rytilahti]
-
-- Bump bluepy requirement to 1.0.5. [Teemu Rytilahti]
-
-0.1 (2017-01-14)
-----------------
-
-- Restructure bluepy_devices to python-eq3bt. [Teemu Rytilahti]
-
- * Complete restructure of the library. All unnecessary and problematic parts are dropped.
- * General cleaning up, making flake8 and pylint happy.
- * Updated and documented cli tool, named eq3cli
-
-- Add contextmanager for connection to simplify connecting and
- disconnecting. Calling writes on device will build and tear down the
- connection automatically. [Teemu Rytilahti]
-
-- Eq3btsmart: do not try to connect on init, allows adding the component
- to homeassistant even if the device is not connectable at the moment.
- [Teemu Rytilahti]
-
-- Add eq3cli tool. [Teemu Rytilahti]
-
- Included command-line tool can be used to control the device.
- All current functionality is available through it, check updated README.md for usage.
-
-- Add logger to ease debugging. [Teemu Rytilahti]
-
-- Increase version to 0.3.0 for the enhaced eq3btsmart support. [Janne
- Grunau]
-
-- Eq3btsmart: and support for the comfort and eco temperature presets.
- [Janne Grunau]
-
-- Eq3btsmart: add a property for the low battery warning. [Janne Grunau]
-
-- Eq3btsmart: add support for the thermostat's operating lock. [Janne
- Grunau]
-
-- Eq3btsmart: add window open mode configuration. [Janne Grunau]
-
-- Eq3btsmart: and property to check window open state. [Janne Grunau]
-
-- Eq3btsmart: report valve state. [Janne Grunau]
-
-- Eq3btsmart: control the supported modes of the thermostat. [Janne
- Grunau]
-
- The away mode is not really useful yet.
-
-- Eq3btsmart: verify that temperatures are in min/max range. [Janne
- Grunau]
-
-- Eq3btsmart: fix the minimal and maximal temperatures. [Janne Grunau]
-
- 4.5 and 30 degree celsius have special meanings and can't be set
- in 'auto' mode. 4.5 means off (valve closed even if the temperature
- below 4.5 degress). 30 means on (valve permanently open even if the
- temperature exceeds 30 degrees).
-
-- Eq3btsmart: the update request needs to include the full time. [Janne
- Grunau]
-
- Otherwise the thermostat can set a random time. Also fixes the format of
- the set time request.
-
-- Initial update in eq3btsmart.py. [Markus Peter]
-
-- +travis. [Markus Peter]
-
-- Update README.md. [Markus Peter]
-
-- Create README.md. [Markus Peter]
-
-- Initial Commit Version 0.2.0. [Markus Peter]
-
-- Initial commit. [Markus Peter]
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/LICENSE b/custom_components/dbuezas_eq3btsmart/python_eq3bt/LICENSE
deleted file mode 100644
index bef487a..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2016 Markus Peter
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/README.md b/custom_components/dbuezas_eq3btsmart/python_eq3bt/README.md
deleted file mode 100644
index ea65792..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/README.md
+++ /dev/null
@@ -1,204 +0,0 @@
-# python-eq3bt
-
-Python library and a command line tool for EQ3 Bluetooth smart thermostats, uses bleak (default), bluepy or gattlib for BTLE communication.
-
-# Features
-
-* Reading device status: locked, low battery, valve state, window open, target temperature, active mode
-* Writing settings: target temperature, auto mode presets, temperature offset
-* Setting the active mode: auto, manual, boost, away
-* Reading the device serial number and firmware version
-* Reading presets and temperature offset in more recent firmware versions.
-
-## Not (yet) supported
-
-* No easy-to-use interface for setting schedules.
-
-# Installation
-
-```bash
-pip install python-eq3bt
-```
-
-# Command-line Usage
-
-To test all available functionality a cli tool inside utils can be used:
-```
-$ eq3cli --help
-Usage: eq3cli [OPTIONS] COMMAND [ARGS]...
-
- Tool to query and modify the state of EQ3 BT smart thermostat.
-
-Options:
- --mac TEXT [required]
- --interface TEXT
- --debug / --normal
- --backend [bleak|bluepy|gattlib]
- --help Show this message and exit.
-
-Commands:
- away Enables or disables the away mode.
- boost Gets or sets the boost mode.
- device Displays basic device information.
- locked Gets or sets the lock.
- low-battery Gets the low battery status.
- mode Gets or sets the active mode.
- offset Sets the temperature offset [-3,5 3,5]
- presets Sets the preset temperatures for auto mode.
- schedule Gets the schedule from the thermostat.
- state Prints out all available information.
- temp Gets or sets the target temperature.
- valve-state Gets the state of the valve.
- window-open Gets and sets the window open settings.
-```
-
-EQ3_MAC environment variable can be used to define mac to avoid typing it:
-```bash
-export EQ3_MAC=XX:XX
-```
-
-Without parameters current state of the device is printed out.
-```bash
-$ eq3cli
-
-[00:1A:22:XX:XX:XX] Target 17.0 (mode: auto dst, away: no)
-Locked: False
-Batter low: False
-Window open: False
-Window open temp: 12.0
-Window open time: 0:15:00
-Boost: False
-Current target temp: 17.0
-Current comfort temp: 20.0
-Current eco temp: 17.0
-Current mode: auto dst locked
-Valve: 0
-```
-
-Getting & setting values.
-```bash
-$ eq3cli temp
-
-Current target temp: 17.0
-
-eq3cli temp --target 20
-
-Current target temp: 17.0
-Setting target temp: 20.0
-```
-
-# Pairing
-
-If you have thermostat with firmware version 1.20+ pairing may be needed. Below simple procedure to do that.
-
-```
-Press and hold wheel on thermostat until Pair will be displayed. Remember or write it.
-
-$ sudo bluetoothctl
-[bluetooth]# power on
-[bluetooth]# agent on
-[bluetooth]# default-agent
-[bluetooth]# scan on
-[bluetooth]# scan off
-[bluetooth]# pair 00:1A:22:06:A7:83
-[agent] Enter passkey (number in 0-999999):
-[bluetooth]# trust 00:1A:22:06:A7:83
-[bluetooth]# disconnect 00:1A:22:06:A7:83
-[bluetooth]# exit
-
-Optional steps:
-[bluetooth]# devices - to list all bluetooth devices
-[bluetooth]# info 00:1A:22:06:A7:83
-Device 00:1A:22:06:A7:83 (public)
- Name: CC-RT-BLE
- Alias: CC-RT-BLE
- Paired: yes
- Trusted: yes
- Blocked: no
- Connected: no
- LegacyPairing: no
- UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
- UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
- UUID: Device Information (0000180a-0000-1000-8000-00805f9b34fb)
- UUID: Vendor specific (3e135142-654f-9090-134a-a6ff5bb77046)
- UUID: Vendor specific (9e5d1e47-5c13-43a0-8635-82ad38a1386f)
- ManufacturerData Key: 0x0000
- ManufacturerData Value:
- 00 00 00 00 00 00 00 00 00 .........
-```
-
-Be aware that sometimes if you pair your device then mobile application (calor BT) can't connect with thermostat and vice versa.
-
-
-# Library Usage
-
-```
-from eq3bt import Thermostat
-
-thermostat = Thermostat('AB:CD:EF:12:23:45')
-thermostat.update() # fetches data from the thermostat
-
-print(thermostat)
-```
-
-
-
-## Fetching schedule
-
-The schedule is queried per day basis and the cached information can be
-accessed through `schedule` property..
-
-```
-from eq3bt import Thermostat
-
-thermostat = Thermostat('AB:CD:EF:12:34:45')
-thermostat.query_schedule(0)
-print(thermostat.schedule)
-```
-
-## Setting schedule
-
-The 'base_temp' and 'next_change_at' paramater define the first period for that 'day' (the period from midnight up till next_change_at).
-
-The schedule can be set on a per day basis like follows:
-
-```
-from datetime import time
-from eq3bt import Thermostat
-from eq3bt import HOUR_24_PLACEHOLDER as END_OF_DAY
-
-thermostat = Thermostat('12:34:56:78:9A:BC')
-thermostat.set_schedule(
- dict(
- cmd="write",
- day="sun",
- base_temp=18,
- next_change_at=time(8, 0),
- hours=[
- dict(target_temp=23, next_change_at=time(20, 0)),
- dict(target_temp=18, next_change_at=END_OF_DAY),
- dict(target_temp=23, next_change_at=END_OF_DAY),
- dict(target_temp=23, next_change_at=END_OF_DAY),
- dict(target_temp=23, next_change_at=END_OF_DAY),
- dict(target_temp=23, next_change_at=END_OF_DAY)
- ]
- )
-)
-```
-
-# Contributing
-
-Feel free to open pull requests to improve the library!
-
-This project uses github actions to enforce code formatting using tools like black, isort, flake8, and mypy.
-You can run these checks locally either by executing `pre-commit run -a` or using `tox` which also runs the test suite.
-
-
-# History
-
-This library is a simplified version of bluepy_devices from Markus Peter (https://github.com/bimbar/bluepy_devices.git) with support for more features and robuster device handling.
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/__init__.py b/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/__init__.py
deleted file mode 100644
index ea19f33..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# flake8: noqa
-from .structures import *
-
-
-class BackendException(Exception):
- """Exception to wrap backend exceptions."""
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/device example.txt b/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/device example.txt
deleted file mode 100644
index f5f79cd..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/device example.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-devices[self._i][0] = {
- "path": "/org/bluez/hci1/dev_00_1A_22_11_D7_93",
- "props": {
- "Address": "00:1A:22:11:D7:93",
- "AddressType": "public",
- "Name": "CC-RT-BLE",
- "Alias": "CC-RT-BLE",
- "Paired": True,
- "Trusted": True,
- "Blocked": False,
- "LegacyPairing": False,
- "Connected": False,
- "UUIDs": [
- "00001800-0000-1000-8000-00805f9b34fb",
- "00001801-0000-1000-8000-00805f9b34fb",
- "0000180a-0000-1000-8000-00805f9b34fb",
- "3e135142-654f-9090-134a-a6ff5bb77046",
- "9e5d1e47-5c13-43a0-8635-82ad38a1386f",
- ],
- "Adapter": "/org/bluez/hci1",
- "ManufacturerData": {0: bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00")},
- "ServicesResolved": False,
- "RSSI": -67,
- },
-}
-devices[self._i][1] = AdvertisementData(
- local_name="CC-RT-BLE",
- manufacturer_data={0: b"\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- service_uuids=[
- "00001800-0000-1000-8000-00805f9b34fb",
- "00001801-0000-1000-8000-00805f9b34fb",
- "0000180a-0000-1000-8000-00805f9b34fb",
- "3e135142-654f-9090-134a-a6ff5bb77046",
- "9e5d1e47-5c13-43a0-8635-82ad38a1386f",
- ],
- rssi=-73,
-)
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/tests/test_thermostat.py b/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/tests/test_thermostat.py
deleted file mode 100644
index abf1bf7..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/tests/test_thermostat.py
+++ /dev/null
@@ -1,197 +0,0 @@
-import codecs
-from datetime import datetime, timedelta
-from unittest import TestCase
-
-import pytest
-from eq3bt import TemperatureException, Thermostat
-from eq3bt.eq3btsmart import PROP_ID_QUERY, PROP_INFO_QUERY, PROP_NTFY_HANDLE, Mode
-
-ID_RESPONSE = b"01780000807581626163606067659e"
-STATUS_RESPONSES = {
- "auto": b"020100000428",
- "manual": b"020101000428",
- "window": b"020110000428",
- "away": b"0201020004231d132e03",
- "boost": b"020104000428",
- "low_batt": b"020180000428",
- "valve_at_22": b"020100160428",
- "presets": b"020100000422000000001803282207",
-}
-
-
-class FakeConnection:
- def __init__(self, _iface, mac):
- self._callbacks = {}
- self._res = "auto"
-
- def set_callback(self, handle, cb):
- self._callbacks[handle] = cb
-
- def set_status(self, key):
- if key in STATUS_RESPONSES:
- self._res = key
- else:
- raise ValueError("Invalid key for status test response.")
-
- def make_request(self, handle, value, timeout=1, with_response=True):
- """Write a GATT Command without callback - not utf-8."""
- if with_response:
- cb = self._callbacks.get(PROP_NTFY_HANDLE)
-
- if value[0] == PROP_ID_QUERY:
- data = ID_RESPONSE
- elif value[0] == PROP_INFO_QUERY:
- data = STATUS_RESPONSES[self._res]
- else:
- return
- cb(codecs.decode(data, "hex"))
-
-
-class TestThermostat(TestCase):
- def setUp(self):
- self.thermostat = Thermostat(
- _mac=None, _iface=None, connection_cls=FakeConnection
- )
-
- def test__verify_temperature(self):
- with self.assertRaises(TemperatureException):
- self.thermostat._verify_temperature(-1)
- with self.assertRaises(TemperatureException):
- self.thermostat._verify_temperature(35)
-
- self.thermostat._verify_temperature(8)
- self.thermostat._verify_temperature(25)
-
- @pytest.mark.skip()
- def test_parse_schedule(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_handle_notification(self):
- self.fail()
-
- def test_query_id(self):
- self.thermostat.query_id()
- self.assertEqual(self.thermostat.firmware_version, 120)
- self.assertEqual(self.thermostat.device_serial, "PEQ2130075")
-
- def test_update(self):
- th = self.thermostat
-
- th._conn.set_status("auto")
- th.update()
- self.assertEqual(th.valve_state, 0)
- self.assertEqual(th.mode, Mode.Auto)
- self.assertEqual(th.target_temperature, 20.0)
- self.assertFalse(th.locked)
- self.assertFalse(th.low_battery)
- self.assertFalse(th.boost)
- self.assertFalse(th.window_open)
-
- th._conn.set_status("manual")
- th.update()
- self.assertTrue(th.mode, Mode.Manual)
-
- th._conn.set_status("away")
- th.update()
- self.assertEqual(th.mode, Mode.Away)
- self.assertEqual(th.target_temperature, 17.5)
- self.assertEqual(th.away_end, datetime(2019, 3, 29, 23, 00))
-
- th._conn.set_status("boost")
- th.update()
- self.assertTrue(th.boost)
- self.assertEqual(th.mode, Mode.Boost)
-
- def test_presets(self):
- th = self.thermostat
- self.thermostat._conn.set_status("presets")
- self.thermostat.update()
- self.assertEqual(th.window_open_temperature, 12.0)
- self.assertEqual(th.window_open_time, timedelta(minutes=15.0))
- self.assertEqual(th.comfort_temperature, 20.0)
- self.assertEqual(th.eco_temperature, 17.0)
- self.assertEqual(th.temperature_offset, 0)
-
- @pytest.mark.skip()
- def test_query_schedule(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_schedule(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_set_schedule(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_target_temperature(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_mode(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_mode_readable(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_boost(self):
- self.fail()
-
- def test_valve_state(self):
- th = self.thermostat
- th._conn.set_status("valve_at_22")
- th.update()
- self.assertEqual(th.valve_state, 22)
-
- def test_window_open(self):
- th = self.thermostat
- th._conn.set_status("window")
- th.update()
- self.assertTrue(th.window_open)
-
- @pytest.mark.skip()
- def test_window_open_config(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_locked(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_low_battery(self):
- th = self.thermostat
- th._conn.set_status("low_batt")
- th.update()
- self.assertTrue(th.low_battery)
-
- @pytest.mark.skip()
- def test_temperature_offset(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_activate_comfort(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_activate_eco(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_min_temp(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_max_temp(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_away_end(self):
- self.fail()
-
- @pytest.mark.skip()
- def test_decode_mode(self):
- self.fail()
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/poetry.lock b/custom_components/dbuezas_eq3btsmart/python_eq3bt/poetry.lock
deleted file mode 100644
index 034f375..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/poetry.lock
+++ /dev/null
@@ -1,640 +0,0 @@
-[[package]]
-name = "atomicwrites"
-version = "1.4.1"
-description = "Atomic file writes."
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-
-[[package]]
-name = "attrs"
-version = "21.4.0"
-description = "Classes Without Boilerplate"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-
-[package.extras]
-dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
-docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
-tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
-tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
-
-[[package]]
-name = "bleak"
-version = "0.14.3"
-description = "Bluetooth Low Energy platform Agnostic Klient"
-category = "main"
-optional = false
-python-versions = "*"
-
-[package.dependencies]
-bleak-winrt = {version = ">=1.1.1", markers = "platform_system == \"Windows\""}
-dbus-next = {version = "*", markers = "platform_system == \"Linux\""}
-pyobjc-core = {version = "*", markers = "platform_system == \"Darwin\""}
-pyobjc-framework-CoreBluetooth = {version = "*", markers = "platform_system == \"Darwin\""}
-pyobjc-framework-libdispatch = {version = "*", markers = "platform_system == \"Darwin\""}
-
-[[package]]
-name = "bleak-winrt"
-version = "1.1.1"
-description = "Python WinRT bindings for Bleak"
-category = "main"
-optional = false
-python-versions = "*"
-
-[[package]]
-name = "bluepy"
-version = "1.3.0"
-description = "Python module for interfacing with BLE devices through Bluez"
-category = "main"
-optional = true
-python-versions = "*"
-
-[[package]]
-name = "certifi"
-version = "2022.6.15"
-description = "Python package for providing Mozilla's CA Bundle."
-category = "dev"
-optional = false
-python-versions = ">=3.6"
-
-[[package]]
-name = "cfgv"
-version = "3.3.1"
-description = "Validate configuration and produce human readable error messages."
-category = "dev"
-optional = false
-python-versions = ">=3.6.1"
-
-[[package]]
-name = "charset-normalizer"
-version = "2.1.0"
-description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-category = "dev"
-optional = false
-python-versions = ">=3.6.0"
-
-[package.extras]
-unicode_backport = ["unicodedata2"]
-
-[[package]]
-name = "click"
-version = "8.1.3"
-description = "Composable command line interface toolkit"
-category = "main"
-optional = false
-python-versions = ">=3.7"
-
-[package.dependencies]
-colorama = {version = "*", markers = "platform_system == \"Windows\""}
-importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
-
-[[package]]
-name = "codecov"
-version = "2.1.12"
-description = "Hosted coverage reports for GitHub, Bitbucket and Gitlab"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-
-[package.dependencies]
-coverage = "*"
-requests = ">=2.7.9"
-
-[[package]]
-name = "colorama"
-version = "0.4.5"
-description = "Cross-platform colored terminal text."
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-
-[[package]]
-name = "construct"
-version = "2.10.68"
-description = "A powerful declarative symmetric parser/builder for binary data"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[package.extras]
-extras = ["arrow", "cloudpickle", "enum34", "lz4", "numpy", "ruamel.yaml"]
-
-[[package]]
-name = "coverage"
-version = "6.4.1"
-description = "Code coverage measurement for Python"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[package.dependencies]
-tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
-
-[package.extras]
-toml = ["tomli"]
-
-[[package]]
-name = "dbus-next"
-version = "0.2.3"
-description = "A zero-dependency DBus library for Python with asyncio support"
-category = "main"
-optional = false
-python-versions = ">=3.6.0"
-
-[[package]]
-name = "distlib"
-version = "0.3.4"
-description = "Distribution utilities"
-category = "dev"
-optional = false
-python-versions = "*"
-
-[[package]]
-name = "filelock"
-version = "3.7.1"
-description = "A platform independent file lock."
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[package.extras]
-docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"]
-testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"]
-
-[[package]]
-name = "gattlib"
-version = "0.20201113"
-description = "Library to access Bluetooth LE devices"
-category = "main"
-optional = true
-python-versions = "*"
-
-[[package]]
-name = "identify"
-version = "2.5.1"
-description = "File identification library for Python"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[package.extras]
-license = ["ukkonen"]
-
-[[package]]
-name = "idna"
-version = "3.3"
-description = "Internationalized Domain Names in Applications (IDNA)"
-category = "dev"
-optional = false
-python-versions = ">=3.5"
-
-[[package]]
-name = "importlib-metadata"
-version = "4.12.0"
-description = "Read metadata from Python packages"
-category = "main"
-optional = false
-python-versions = ">=3.7"
-
-[package.dependencies]
-typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
-zipp = ">=0.5"
-
-[package.extras]
-docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
-perf = ["ipython"]
-testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
-
-[[package]]
-name = "iniconfig"
-version = "1.1.1"
-description = "iniconfig: brain-dead simple config-ini parsing"
-category = "dev"
-optional = false
-python-versions = "*"
-
-[[package]]
-name = "nodeenv"
-version = "1.7.0"
-description = "Node.js virtual environment builder"
-category = "dev"
-optional = false
-python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
-
-[[package]]
-name = "packaging"
-version = "21.3"
-description = "Core utilities for Python packages"
-category = "dev"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
-
-[[package]]
-name = "platformdirs"
-version = "2.5.2"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[package.extras]
-docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
-test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
-
-[[package]]
-name = "pluggy"
-version = "1.0.0"
-description = "plugin and hook calling mechanisms for python"
-category = "dev"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
-
-[package.extras]
-dev = ["pre-commit", "tox"]
-testing = ["pytest", "pytest-benchmark"]
-
-[[package]]
-name = "pre-commit"
-version = "2.19.0"
-description = "A framework for managing and maintaining multi-language pre-commit hooks."
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[package.dependencies]
-cfgv = ">=2.0.0"
-identify = ">=1.0.0"
-importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
-nodeenv = ">=0.11.1"
-pyyaml = ">=5.1"
-toml = "*"
-virtualenv = ">=20.0.8"
-
-[[package]]
-name = "py"
-version = "1.11.0"
-description = "library with cross-python path, ini-parsing, io, code, log facilities"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-
-[[package]]
-name = "pyobjc-core"
-version = "8.5"
-description = "Python<->ObjC Interoperability Module"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[[package]]
-name = "pyobjc-framework-cocoa"
-version = "8.5"
-description = "Wrappers for the Cocoa frameworks on macOS"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-pyobjc-core = ">=8.5"
-
-[[package]]
-name = "pyobjc-framework-corebluetooth"
-version = "8.5"
-description = "Wrappers for the framework CoreBluetooth on macOS"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-pyobjc-core = ">=8.5"
-pyobjc-framework-Cocoa = ">=8.5"
-
-[[package]]
-name = "pyobjc-framework-libdispatch"
-version = "8.5"
-description = "Wrappers for libdispatch on macOS"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-pyobjc-core = ">=8.5"
-
-[[package]]
-name = "pyparsing"
-version = "3.0.9"
-description = "pyparsing module - Classes and methods to define and execute parsing grammars"
-category = "dev"
-optional = false
-python-versions = ">=3.6.8"
-
-[package.extras]
-diagrams = ["railroad-diagrams", "jinja2"]
-
-[[package]]
-name = "pytest"
-version = "7.1.2"
-description = "pytest: simple powerful testing with Python"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[package.dependencies]
-atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
-attrs = ">=19.2.0"
-colorama = {version = "*", markers = "sys_platform == \"win32\""}
-importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
-iniconfig = "*"
-packaging = "*"
-pluggy = ">=0.12,<2.0"
-py = ">=1.8.2"
-tomli = ">=1.0.0"
-
-[package.extras]
-testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
-
-[[package]]
-name = "pytest-cov"
-version = "3.0.0"
-description = "Pytest plugin for measuring coverage."
-category = "dev"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-coverage = {version = ">=5.2.1", extras = ["toml"]}
-pytest = ">=4.6"
-
-[package.extras]
-testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
-
-[[package]]
-name = "pyyaml"
-version = "6.0"
-description = "YAML parser and emitter for Python"
-category = "dev"
-optional = false
-python-versions = ">=3.6"
-
-[[package]]
-name = "requests"
-version = "2.28.1"
-description = "Python HTTP for Humans."
-category = "dev"
-optional = false
-python-versions = ">=3.7, <4"
-
-[package.dependencies]
-certifi = ">=2017.4.17"
-charset-normalizer = ">=2,<3"
-idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<1.27"
-
-[package.extras]
-socks = ["PySocks (>=1.5.6,!=1.5.7)"]
-use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
-
-[[package]]
-name = "six"
-version = "1.16.0"
-description = "Python 2 and 3 compatibility utilities"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
-
-[[package]]
-name = "toml"
-version = "0.10.2"
-description = "Python Library for Tom's Obvious, Minimal Language"
-category = "dev"
-optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-
-[[package]]
-name = "tomli"
-version = "2.0.1"
-description = "A lil' TOML parser"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[[package]]
-name = "tox"
-version = "3.25.1"
-description = "tox is a generic virtualenv management and test command line tool"
-category = "dev"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-
-[package.dependencies]
-colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""}
-filelock = ">=3.0.0"
-importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
-packaging = ">=14"
-pluggy = ">=0.12.0"
-py = ">=1.4.17"
-six = ">=1.14.0"
-toml = ">=0.9.4"
-virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7"
-
-[package.extras]
-docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"]
-testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)", "psutil (>=5.6.1)", "pathlib2 (>=2.3.3)"]
-
-[[package]]
-name = "typing-extensions"
-version = "4.3.0"
-description = "Backported and Experimental Type Hints for Python 3.7+"
-category = "main"
-optional = false
-python-versions = ">=3.7"
-
-[[package]]
-name = "urllib3"
-version = "1.26.10"
-description = "HTTP library with thread-safe connection pooling, file post, and more."
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4"
-
-[package.extras]
-brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"]
-secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
-socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
-
-[[package]]
-name = "virtualenv"
-version = "20.15.1"
-description = "Virtual Python Environment builder"
-category = "dev"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-
-[package.dependencies]
-distlib = ">=0.3.1,<1"
-filelock = ">=3.2,<4"
-importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
-platformdirs = ">=2,<3"
-six = ">=1.9.0,<2"
-
-[package.extras]
-docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"]
-testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"]
-
-[[package]]
-name = "zipp"
-version = "3.8.0"
-description = "Backport of pathlib-compatible object wrapper for zip files"
-category = "main"
-optional = false
-python-versions = ">=3.7"
-
-[package.extras]
-docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
-testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
-
-[extras]
-bluepy = ["bluepy"]
-gattlib = ["gattlib"]
-
-[metadata]
-lock-version = "1.1"
-python-versions = "^3.7"
-content-hash = "21ec4141f11f1c8ae25544a03f436e718b35884212e0f916887e2685907ee555"
-
-[metadata.files]
-atomicwrites = []
-attrs = [
- {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
- {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
-]
-bleak = []
-bleak-winrt = []
-bluepy = [
- {file = "bluepy-1.3.0.tar.gz", hash = "sha256:2a71edafe103565fb990256ff3624c1653036a837dfc90e1e32b839f83971cec"},
-]
-certifi = []
-cfgv = [
- {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
- {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
-]
-charset-normalizer = []
-click = []
-codecov = [
- {file = "codecov-2.1.12-py2.py3-none-any.whl", hash = "sha256:585dc217dc3d8185198ceb402f85d5cb5dbfa0c5f350a5abcdf9e347776a5b47"},
- {file = "codecov-2.1.12-py3.8.egg", hash = "sha256:782a8e5352f22593cbc5427a35320b99490eb24d9dcfa2155fd99d2b75cfb635"},
- {file = "codecov-2.1.12.tar.gz", hash = "sha256:a0da46bb5025426da895af90938def8ee12d37fcbcbbbc15b6dc64cf7ebc51c1"},
-]
-colorama = []
-construct = [
- {file = "construct-2.10.68.tar.gz", hash = "sha256:7b2a3fd8e5f597a5aa1d614c3bd516fa065db01704c72a1efaaeec6ef23d8b45"},
-]
-coverage = []
-dbus-next = []
-distlib = [
- {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"},
- {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
-]
-filelock = []
-gattlib = [
- {file = "gattlib-0.20201113.tar.gz", hash = "sha256:1e3d92d07bdaad7574aabc3fd36aea5ef1fae4339e521a162fe2341a9a33fcb5"},
-]
-identify = []
-idna = [
- {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
- {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
-]
-importlib-metadata = []
-iniconfig = [
- {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
- {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
-]
-nodeenv = []
-packaging = [
- {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
- {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
-]
-platformdirs = []
-pluggy = [
- {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
- {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
-]
-pre-commit = []
-py = [
- {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
- {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
-]
-pyobjc-core = []
-pyobjc-framework-cocoa = []
-pyobjc-framework-corebluetooth = []
-pyobjc-framework-libdispatch = []
-pyparsing = []
-pytest = []
-pytest-cov = [
- {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
- {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
-]
-pyyaml = [
- {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
- {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
- {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
- {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
- {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
- {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
- {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
- {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
- {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
- {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
- {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
- {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
- {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
- {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
- {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
- {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
- {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
- {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
-]
-requests = []
-six = [
- {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
- {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
-]
-toml = [
- {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
- {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
-]
-tomli = [
- {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
- {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
-]
-tox = []
-typing-extensions = []
-urllib3 = []
-virtualenv = []
-zipp = [
- {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"},
- {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"},
-]
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/pyproject.toml b/custom_components/dbuezas_eq3btsmart/python_eq3bt/pyproject.toml
deleted file mode 100644
index ba9fceb..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/pyproject.toml
+++ /dev/null
@@ -1,49 +0,0 @@
-[tool.poetry]
-name = "python-eq3bt"
-version = "0.2"
-description = "EQ3 bluetooth thermostat support library"
-license = "MIT"
-authors = ["Teemu R. ", "Markus Peter "]
-repository = "https://github.com/rytilahti/python-eq3bt"
-readme = "README.md"
-packages = [
- { include = "eq3bt" }
-]
-include = ["CHANGELOG"]
-
-[tool.poetry.scripts]
-eq3cli = "eq3bt.eq3cli:cli"
-
-[tool.poetry.dependencies]
-python = "^3.7"
-click = "*"
-construct = "*"
-bleak = "*"
-gattlib = { version = "*", optional = true }
-bluepy = { version = ">=1.0.5", optional = true }
-
-[tool.poetry.extras]
-gattlib = ["gattlib"]
-bluepy = ["bluepy"]
-
-[tool.poetry.dev-dependencies]
-pytest = "*"
-pre-commit = "*"
-toml = "*"
-tox = "*"
-codecov = "*"
-pytest-cov = "*"
-
-
-[tool.isort]
-multi_line_output = 3
-include_trailing_comma = true
-force_grid_wrap = 0
-use_parentheses = true
-line_length = 88
-known_first_party = "eq3bt"
-known_third_party = ["click", "pytest"]
-
-[build-system]
-requires = ["poetry-core>=1.0.0"]
-build-backend = "poetry.core.masonry.api"
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/tox.ini b/custom_components/dbuezas_eq3btsmart/python_eq3bt/tox.ini
deleted file mode 100644
index ac5dffb..0000000
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/tox.ini
+++ /dev/null
@@ -1,22 +0,0 @@
-[tox]
-envlist = lint,tests
-skip_missing_interpreters = True
-isolated_build = True
-
-[flake8]
-ignore = E501
-
-[testenv:lint]
-deps=
- pre-commit
-basepython = python3
-ignore_errors = True
-commands =
- pre-commit run -a
-
-[testenv:tests]
-deps=
- pytest
- construct
-commands =
- pytest eq3bt
diff --git a/custom_components/dbuezas_eq3btsmart/__init__.py b/custom_components/eq3btsmart/__init__.py
similarity index 97%
rename from custom_components/dbuezas_eq3btsmart/__init__.py
rename to custom_components/eq3btsmart/__init__.py
index 6116508..79bbb3e 100644
--- a/custom_components/dbuezas_eq3btsmart/__init__.py
+++ b/custom_components/eq3btsmart/__init__.py
@@ -3,6 +3,7 @@
import logging
+from eq3btsmart import Thermostat
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
@@ -14,7 +15,6 @@
DEFAULT_STAY_CONNECTED,
DOMAIN,
)
-from .python_eq3bt.eq3bt.eq3btsmart import Thermostat
PLATFORMS = [
Platform.CLIMATE,
diff --git a/custom_components/dbuezas_eq3btsmart/binary_sensor.py b/custom_components/eq3btsmart/binary_sensor.py
similarity index 84%
rename from custom_components/dbuezas_eq3btsmart/binary_sensor.py
rename to custom_components/eq3btsmart/binary_sensor.py
index de7ab30..0285b16 100644
--- a/custom_components/dbuezas_eq3btsmart/binary_sensor.py
+++ b/custom_components/eq3btsmart/binary_sensor.py
@@ -1,15 +1,18 @@
import json
import logging
-from homeassistant.components.binary_sensor import BinarySensorEntity
-from homeassistant.config_entries import ConfigEntry
+from eq3btsmart import Thermostat
+from homeassistant.components.binary_sensor import (
+ BinarySensorDeviceClass,
+ BinarySensorEntity,
+)
+from homeassistant.config_entries import ConfigEntry, UndefinedType
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import CONF_DEBUG_MODE, DOMAIN
-from .python_eq3bt.eq3bt.eq3btsmart import Thermostat
_LOGGER = logging.getLogger(__name__)
@@ -42,8 +45,10 @@ def __init__(self, _thermostat: Thermostat):
self._attr_has_entity_name = True
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
@@ -61,7 +66,7 @@ def __init__(self, _thermostat: Thermostat):
self._attr_name = "Busy"
@property
- def is_on(self):
+ def is_on(self) -> bool:
return self._thermostat._conn._lock.locked()
@@ -77,10 +82,10 @@ def __init__(self, _thermostat: Thermostat):
_thermostat._conn.register_connection_callback(self.schedule_update_ha_state)
self._attr_entity_category = EntityCategory.DIAGNOSTIC
self._attr_name = "Connected"
- self._attr_device_class = "connectivity"
+ self._attr_device_class = BinarySensorDeviceClass.CONNECTIVITY
@property
- def extra_state_attributes(self):
+ def extra_state_attributes(self) -> dict[str, str] | None:
"""Return the device specific state attributes."""
if (device := self._thermostat._conn._ble_device) is None:
return None
@@ -92,7 +97,7 @@ def extra_state_attributes(self):
return json.loads(json.dumps(details["props"], default=json_serial))
@property
- def is_on(self):
+ def is_on(self) -> bool:
if self._thermostat._conn._conn is None:
return False
return self._thermostat._conn._conn.is_connected
@@ -103,7 +108,7 @@ def __init__(self, _thermostat: Thermostat):
super().__init__(_thermostat)
_thermostat.register_update_callback(self.schedule_update_ha_state)
self._attr_name = "Battery"
- self._attr_device_class = "battery"
+ self._attr_device_class = BinarySensorDeviceClass.BATTERY
self._attr_entity_category = EntityCategory.DIAGNOSTIC
@property
@@ -116,7 +121,7 @@ def __init__(self, _thermostat: Thermostat):
super().__init__(_thermostat)
_thermostat.register_update_callback(self.schedule_update_ha_state)
self._attr_name = "Window Open"
- self._attr_device_class = "window"
+ self._attr_device_class = BinarySensorDeviceClass.WINDOW
@property
def is_on(self):
diff --git a/custom_components/dbuezas_eq3btsmart/button.py b/custom_components/eq3btsmart/button.py
similarity index 90%
rename from custom_components/dbuezas_eq3btsmart/button.py
rename to custom_components/eq3btsmart/button.py
index cea9f6c..d3879bc 100644
--- a/custom_components/dbuezas_eq3btsmart/button.py
+++ b/custom_components/eq3btsmart/button.py
@@ -2,20 +2,18 @@
import logging
import voluptuous as vol
+from eq3btsmart import Thermostat
+from eq3btsmart.const import EQ3BT_MAX_TEMP, EQ3BT_MIN_TEMP, HOUR_24_PLACEHOLDER
from homeassistant.components.button import ButtonEntity
-from homeassistant.config_entries import ConfigEntry
+from homeassistant.config_entries import ConfigEntry, UndefinedType
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import entity_platform
from homeassistant.helpers.device_registry import format_mac
-from homeassistant.helpers.entity import DeviceInfo, EntityCategory
+from homeassistant.helpers.entity import DeviceInfo, Entity, EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import CONF_DEBUG_MODE, DOMAIN
-from .python_eq3bt.eq3bt.eq3btsmart import EQ3BT_MAX_TEMP, EQ3BT_MIN_TEMP, Thermostat
-from .python_eq3bt.eq3bt.structures import (
- HOUR_24_PLACEHOLDER,
-)
_LOGGER = logging.getLogger(__name__)
@@ -27,8 +25,11 @@ def v_assert(bool, error):
if not bool:
raise vol.Invalid(error)
- time = lambda i: value.get(f"next_change_at_{i}")
- temp = lambda i: value.get(f"target_temp_{i}")
+ def time(i):
+ return value.get(f"next_change_at_{i}")
+
+ def temp(i):
+ return value.get(f"target_temp_{i}")
v_assert(temp(0), f"Missing target_temp_{0}")
if time(0):
@@ -80,7 +81,7 @@ async def async_setup_entry(
"""Add sensors for passed config_entry in HA."""
eq3 = hass.data[DOMAIN][config_entry.entry_id]
debug_mode = config_entry.options.get(CONF_DEBUG_MODE, False)
- new_devices = [FetchScheduleButton(eq3)]
+ new_devices: list[Entity] = [FetchScheduleButton(eq3)]
async_add_entities(new_devices)
if debug_mode:
@@ -104,8 +105,10 @@ def __init__(self, _thermostat: Thermostat):
self._attr_has_entity_name = True
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
diff --git a/custom_components/dbuezas_eq3btsmart/climate.py b/custom_components/eq3btsmart/climate.py
similarity index 91%
rename from custom_components/dbuezas_eq3btsmart/climate.py
rename to custom_components/eq3btsmart/climate.py
index d2bcb1a..9237d92 100644
--- a/custom_components/dbuezas_eq3btsmart/climate.py
+++ b/custom_components/eq3btsmart/climate.py
@@ -1,12 +1,15 @@
-"""Support for dbuezas_eQ-3 Bluetooth Smart thermostats."""
+"""Support for eQ-3 Bluetooth Smart thermostats."""
from __future__ import annotations
import asyncio
import logging
from datetime import timedelta
+from typing import Callable
import voluptuous as vol
+from eq3btsmart import Thermostat
+from eq3btsmart.const import EQ3BT_MAX_TEMP, EQ3BT_OFF_TEMP, Mode
from homeassistant.components.climate import ClimateEntity, HVACMode
from homeassistant.components.climate.const import (
ATTR_HVAC_MODE,
@@ -43,12 +46,6 @@
Preset,
TargetTemperatureSelector,
)
-from .python_eq3bt.eq3bt.eq3btsmart import (
- EQ3BT_MAX_TEMP,
- EQ3BT_OFF_TEMP,
- Mode,
- Thermostat,
-)
_LOGGER = logging.getLogger(__name__)
DEVICE_SCHEMA = vol.Schema({vol.Required(CONF_MAC): cv.string})
@@ -105,10 +102,10 @@ def __init__(
self._conf_current_temp_selector = conf_current_temp_selector
self._conf_target_temp_selector = conf_target_temp_selector
self._conf_external_temp_sensor = conf_external_temp_sensor
- self._target_temperature_to_set = None
+ self._target_temperature_to_set: float | None = None
self._is_setting_temperature = False
self._is_available = False
- self._cancel_timer = None
+ self._cancel_timer: Callable[[], None] | None = None
# This is the main entity of the device and should use the device name.
# See https://developers.home-assistant.io/docs/core/entity#has_entity_name-true-mandatory-for-new-integrations
self._attr_has_entity_name = True
@@ -138,11 +135,12 @@ async def async_will_remove_from_hass(self) -> None:
if self._cancel_timer:
self._cancel_timer()
- async def _async_scan_loop(self, now=None):
+ async def _async_scan_loop(self, now=None) -> None:
await self.async_scan()
if self._platform_state != EntityPlatformState.REMOVED:
+ delay = timedelta(minutes=self._scan_interval)
self._cancel_timer = async_call_later(
- self.hass, timedelta(minutes=self._scan_interval), self._async_scan_loop
+ self.hass, delay, self._async_scan_loop
)
@callback
@@ -166,7 +164,7 @@ def available(self) -> bool:
return self._is_available
@property
- def hvac_action(self) -> str | None:
+ def hvac_action(self) -> HVACAction | None:
"""Return the current running hvac operation."""
if self._thermostat.mode == Mode.Off:
return HVACAction.OFF
@@ -175,7 +173,7 @@ def hvac_action(self) -> str | None:
return HVACAction.HEATING
@property
- def current_temperature(self):
+ def current_temperature(self) -> float | None:
"""Can not report temperature, so return target_temperature."""
if self._conf_current_temp_selector == CurrentTemperatureSelector.NOTHING:
return None
@@ -195,9 +193,10 @@ def current_temperature(self):
return float(state.state)
except ValueError:
pass
+ return None
@property
- def target_temperature(self):
+ def target_temperature(self) -> float | None:
"""Return the temperature we try to reach."""
match self._conf_target_temp_selector:
case TargetTemperatureSelector.TARGET:
@@ -205,14 +204,15 @@ def target_temperature(self):
case TargetTemperatureSelector.LAST_REPORTED:
return self._thermostat.target_temperature
- async def async_set_temperature(self, **kwargs):
+ async def async_set_temperature(self, **kwargs) -> None:
"""Set new target temperature."""
# We can also set the HVAC mode when setting the temperature.
# This needs to be done before changing the temperature because
# changing the mode might change the temperature.
if ATTR_HVAC_MODE in kwargs:
mode = kwargs.get(ATTR_HVAC_MODE)
- assert mode != None
+ if mode is None:
+ return
# Setting the mode to off while change the tempreature doesn't make sense.
if mode != HVACMode.OFF:
await self.async_set_hvac_mode(mode)
@@ -242,21 +242,21 @@ async def async_set_temperature(self, **kwargs):
self._target_temperature_to_set = previous_temperature
self.async_schedule_update_ha_state()
- async def async_set_temperature_now(self):
+ async def async_set_temperature_now(self) -> None:
await self._thermostat.async_set_target_temperature(
self._target_temperature_to_set
)
self._is_setting_temperature = False
@property
- def hvac_mode(self):
+ def hvac_mode(self) -> HVACMode | None:
"""Return the current operation mode."""
- if self._thermostat.mode == None:
+ if self._thermostat.mode is None:
return None
return EQ_TO_HA_HVAC[self._thermostat.mode]
- async def async_set_hvac_mode(self, hvac_mode):
+ async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
"""Set operation mode."""
if hvac_mode == HVACMode.OFF:
self._target_temperature_to_set = EQ3BT_OFF_TEMP
@@ -269,7 +269,7 @@ async def async_set_hvac_mode(self, hvac_mode):
await self._thermostat.async_set_mode(HA_TO_EQ_HVAC[hvac_mode])
@property
- def preset_mode(self):
+ def preset_mode(self) -> str | None:
"""Return the current preset mode, e.g., home, away, temp.
Requires SUPPORT_PRESET_MODE.
"""
@@ -289,7 +289,7 @@ def preset_mode(self):
return Preset.OPEN
return PRESET_NONE
- async def async_set_preset_mode(self, preset_mode):
+ async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set new preset mode."""
match preset_mode:
case Preset.BOOST:
@@ -333,7 +333,7 @@ def device_info(self) -> DeviceInfo:
connections={(CONNECTION_BLUETOOTH, self._thermostat.mac)},
)
- async def async_scan(self):
+ async def async_scan(self) -> None:
"""Update the data from the thermostat."""
try:
await self._thermostat.async_update()
diff --git a/custom_components/dbuezas_eq3btsmart/config_flow.py b/custom_components/eq3btsmart/config_flow.py
similarity index 96%
rename from custom_components/dbuezas_eq3btsmart/config_flow.py
rename to custom_components/eq3btsmart/config_flow.py
index ed81bdf..e0fc745 100644
--- a/custom_components/dbuezas_eq3btsmart/config_flow.py
+++ b/custom_components/eq3btsmart/config_flow.py
@@ -42,11 +42,13 @@ def __init__(self):
"""Initialize the EQ3One flow."""
self.discovery_info = None
- async def async_step_user(self, user_input=None):
+ async def async_step_user(
+ self, user_input: dict[str, Any] | None = None
+ ) -> FlowResult:
"""Handle a flow initialized by the user."""
_LOGGER.debug("async_step_user: %s", user_input)
- errors = {}
+ errors: dict[str, str] | None = {}
if user_input is None:
return self.async_show_form(
step_id="user",
@@ -63,7 +65,9 @@ async def async_step_user(self, user_input=None):
self._abort_if_unique_id_configured(updates=user_input)
return self.async_create_entry(title=user_input[CONF_NAME], data=user_input)
- async def async_step_bluetooth(self, discovery_info: BluetoothServiceInfoBleak):
+ async def async_step_bluetooth(
+ self, discovery_info: BluetoothServiceInfoBleak
+ ) -> FlowResult:
"""Handle bluetooth discovery."""
await self.async_set_unique_id(format_mac(discovery_info.address))
self._abort_if_unique_id_configured()
@@ -86,7 +90,7 @@ async def async_step_bluetooth(self, discovery_info: BluetoothServiceInfoBleak):
)
return await self.async_step_init()
- async def async_step_init(self, user_input=None):
+ async def async_step_init(self, user_input: dict[str, Any] | None = None):
"""Handle a flow start."""
if self.discovery_info is None:
# mainly to shut up the type checker
diff --git a/custom_components/dbuezas_eq3btsmart/const.py b/custom_components/eq3btsmart/const.py
similarity index 93%
rename from custom_components/dbuezas_eq3btsmart/const.py
rename to custom_components/eq3btsmart/const.py
index 6d15c65..d4037f0 100644
--- a/custom_components/dbuezas_eq3btsmart/const.py
+++ b/custom_components/eq3btsmart/const.py
@@ -1,11 +1,8 @@
"""Constants for EQ3 Bluetooth Smart Radiator Valves."""
from enum import Enum
+from eq3btsmart.const import Mode
from homeassistant.components.climate import HVACMode
-
-from .python_eq3bt.eq3bt.eq3btsmart import Mode
-
-DOMAIN = "dbuezas_eq3btsmart"
from homeassistant.components.climate.const import (
PRESET_AWAY,
PRESET_BOOST,
@@ -13,7 +10,9 @@
PRESET_ECO,
)
-EQ_TO_HA_HVAC = {
+DOMAIN = "eq3btsmart"
+
+EQ_TO_HA_HVAC: dict[Mode, HVACMode] = {
Mode.Unknown: HVACMode.HEAT,
Mode.Off: HVACMode.OFF,
Mode.On: HVACMode.HEAT,
diff --git a/custom_components/dbuezas_eq3btsmart/lock.py b/custom_components/eq3btsmart/lock.py
similarity index 79%
rename from custom_components/dbuezas_eq3btsmart/lock.py
rename to custom_components/eq3btsmart/lock.py
index cb6d297..9f79c87 100644
--- a/custom_components/dbuezas_eq3btsmart/lock.py
+++ b/custom_components/eq3btsmart/lock.py
@@ -1,14 +1,14 @@
import logging
+from eq3btsmart import Thermostat
from homeassistant.components.lock import LockEntity
-from homeassistant.config_entries import ConfigEntry
+from homeassistant.config_entries import ConfigEntry, UndefinedType
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
-from .python_eq3bt.eq3bt.eq3btsmart import Thermostat
_LOGGER = logging.getLogger(__name__)
@@ -32,8 +32,10 @@ def __init__(self, _thermostat: Thermostat):
self._attr_has_entity_name = True
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
@@ -49,12 +51,12 @@ def __init__(self, _thermostat: Thermostat):
_thermostat.register_update_callback(self.schedule_update_ha_state)
self._attr_name = "Locked"
- async def async_lock(self, **kwargs):
+ async def async_lock(self, **kwargs) -> None:
await self._thermostat.async_set_locked(True)
- async def async_unlock(self, **kwargs):
+ async def async_unlock(self, **kwargs) -> None:
await self._thermostat.async_set_locked(False)
@property
- def is_locked(self):
+ def is_locked(self) -> bool | None:
return self._thermostat.locked
diff --git a/custom_components/dbuezas_eq3btsmart/manifest.json b/custom_components/eq3btsmart/manifest.json
similarity index 67%
rename from custom_components/dbuezas_eq3btsmart/manifest.json
rename to custom_components/eq3btsmart/manifest.json
index 1c896c3..79921ad 100644
--- a/custom_components/dbuezas_eq3btsmart/manifest.json
+++ b/custom_components/eq3btsmart/manifest.json
@@ -1,11 +1,11 @@
{
- "domain": "dbuezas_eq3btsmart",
- "name": "eQ-3 Bluetooth Smart Thermostats (dbuezas)",
+ "domain": "eq3btsmart",
+ "name": "eQ-3 Bluetooth Smart Thermostats",
"documentation": "https://github.com/dbuezas/eq3btsmart",
"issue_tracker": "https://github.com/dbuezas/eq3btsmart/issues",
- "requirements": ["construct==2.10.56"],
+ "requirements": ["eq3btsmart==0.0.0"],
"dependencies": ["bluetooth"],
- "codeowners": ["@dbuezas", "@rytilahti", "@lkempf"],
+ "codeowners": ["@dbuezas", "@eulemitkeule", "@rytilahti", "@lkempf"],
"iot_class": "local_polling",
"loggers": ["bleak", "eq3bt"],
"version": "6.2.1",
diff --git a/custom_components/dbuezas_eq3btsmart/number.py b/custom_components/eq3btsmart/number.py
similarity index 79%
rename from custom_components/dbuezas_eq3btsmart/number.py
rename to custom_components/eq3btsmart/number.py
index e311783..2de4aa2 100644
--- a/custom_components/dbuezas_eq3btsmart/number.py
+++ b/custom_components/eq3btsmart/number.py
@@ -1,21 +1,27 @@
import logging
from datetime import timedelta
-from homeassistant.components.number import NumberEntity, NumberMode, RestoreNumber
-from homeassistant.config_entries import ConfigEntry
+from eq3btsmart import Thermostat
+from eq3btsmart.const import (
+ EQ3BT_MAX_OFFSET,
+ EQ3BT_MAX_TEMP,
+ EQ3BT_MIN_OFFSET,
+ EQ3BT_MIN_TEMP,
+)
+from homeassistant.components.number import (
+ NumberDeviceClass,
+ NumberEntity,
+ NumberMode,
+ RestoreNumber,
+)
+from homeassistant.config_entries import ConfigEntry, UndefinedType
+from homeassistant.const import UnitOfTemperature, UnitOfTime
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
-from .python_eq3bt.eq3bt.eq3btsmart import (
- EQ3BT_MAX_OFFSET,
- EQ3BT_MAX_TEMP,
- EQ3BT_MIN_OFFSET,
- EQ3BT_MIN_TEMP,
- Thermostat,
-)
_LOGGER = logging.getLogger(__name__)
@@ -45,8 +51,8 @@ def __init__(self, _thermostat: Thermostat):
_thermostat.register_update_callback(self.schedule_update_ha_state)
self._thermostat = _thermostat
self._attr_has_entity_name = True
- self._attr_device_class = "temperature"
- self._attr_native_unit_of_measurement = "°C"
+ self._attr_device_class = NumberDeviceClass.TEMPERATURE
+ self._attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
self._attr_native_min_value = EQ3BT_MIN_TEMP
self._attr_native_max_value = EQ3BT_MAX_TEMP
@@ -54,8 +60,10 @@ def __init__(self, _thermostat: Thermostat):
self._attr_mode = NumberMode.BOX
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
@@ -71,12 +79,16 @@ def __init__(self, _thermostat: Thermostat):
self._attr_name = "Comfort"
@property
- def native_value(self):
+ def native_value(self) -> float | None:
return self._thermostat.comfort_temperature
async def async_set_native_value(self, value: float) -> None:
await self._thermostat.async_update() # to ensure the other temp is up to date
other = self._thermostat.eco_temperature
+
+ if other is None:
+ return
+
await self._thermostat.async_temperature_presets(comfort=value, eco=other)
@@ -86,12 +98,16 @@ def __init__(self, _thermostat: Thermostat):
self._attr_name = "Eco"
@property
- def native_value(self):
+ def native_value(self) -> float | None:
return self._thermostat.eco_temperature
async def async_set_native_value(self, value: float) -> None:
await self._thermostat.async_update() # to ensure the other temp is up to date
other = self._thermostat.comfort_temperature
+
+ if other is None:
+ return
+
await self._thermostat.async_temperature_presets(comfort=other, eco=value)
@@ -103,7 +119,7 @@ def __init__(self, _thermostat: Thermostat):
self._attr_native_max_value = EQ3BT_MAX_OFFSET
@property
- def native_value(self):
+ def native_value(self) -> float | None:
return self._thermostat.temperature_offset
async def async_set_native_value(self, value: float) -> None:
@@ -116,11 +132,15 @@ def __init__(self, _thermostat: Thermostat):
self._attr_name = "Window Open"
@property
- def native_value(self):
+ def native_value(self) -> float | None:
return self._thermostat.window_open_temperature
async def async_set_native_value(self, value: float) -> None:
await self._thermostat.async_update() # to ensure the other value is up to date
+
+ if self._thermostat.window_open_time is None:
+ return
+
await self._thermostat.async_window_open_config(
temperature=value, duration=self._thermostat.window_open_time
)
@@ -136,11 +156,13 @@ def __init__(self, _thermostat: Thermostat):
self._attr_native_min_value = 0
self._attr_native_max_value = 60
self._attr_native_step = 5
- self._attr_native_unit_of_measurement = "minutes"
+ self._attr_native_unit_of_measurement = UnitOfTime.MINUTES
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
@@ -150,13 +172,18 @@ def device_info(self) -> DeviceInfo:
)
@property
- def native_value(self):
+ def native_value(self) -> float | None:
if self._thermostat.window_open_time is None:
return None
+
return self._thermostat.window_open_time.total_seconds() / 60
async def async_set_native_value(self, value: float) -> None:
await self._thermostat.async_update() # to ensure the other value is up to date
+
+ if self._thermostat.window_open_temperature is None:
+ return
+
await self._thermostat.async_window_open_config(
temperature=self._thermostat.window_open_temperature,
duration=timedelta(minutes=value),
@@ -172,11 +199,13 @@ def __init__(self, _thermostat: Thermostat):
self._attr_native_min_value = 0.5
self._attr_native_max_value = 1000000
self._attr_native_step = 0.5
- self._attr_native_unit_of_measurement = "hours"
+ self._attr_native_unit_of_measurement = UnitOfTime.HOURS
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
@@ -189,7 +218,7 @@ async def async_added_to_hass(self) -> None:
"""Restore last state."""
data = await self.async_get_last_number_data()
- if data and data.native_value != None:
+ if data and data.native_value is not None:
self._thermostat.default_away_hours = data.native_value
async def async_set_native_value(self, value: float) -> None:
@@ -206,8 +235,10 @@ def __init__(self, _thermostat: Thermostat):
self._attr_name = "Away"
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
@@ -219,7 +250,7 @@ def device_info(self) -> DeviceInfo:
async def async_added_to_hass(self) -> None:
"""Restore last state."""
data = await self.async_get_last_number_data()
- if data and data.native_value != None:
+ if data and data.native_value is not None:
self._thermostat.default_away_temp = data.native_value
async def async_set_native_value(self, value: float) -> None:
diff --git a/custom_components/eq3btsmart/ruff.toml b/custom_components/eq3btsmart/ruff.toml
new file mode 100644
index 0000000..963784a
--- /dev/null
+++ b/custom_components/eq3btsmart/ruff.toml
@@ -0,0 +1,2 @@
+[lint.isort]
+known-third-party = ["eq3btsmart"]
diff --git a/custom_components/dbuezas_eq3btsmart/sensor.py b/custom_components/eq3btsmart/sensor.py
similarity index 82%
rename from custom_components/dbuezas_eq3btsmart/sensor.py
rename to custom_components/eq3btsmart/sensor.py
index 1d024ce..1ce8fb8 100644
--- a/custom_components/dbuezas_eq3btsmart/sensor.py
+++ b/custom_components/eq3btsmart/sensor.py
@@ -1,8 +1,12 @@
import asyncio
import logging
+from datetime import datetime
+from eq3btsmart import Thermostat
+from homeassistant.components.homekit import SensorDeviceClass
from homeassistant.components.sensor import SensorEntity
-from homeassistant.config_entries import ConfigEntry
+from homeassistant.config_entries import ConfigEntry, UndefinedType
+from homeassistant.const import PERCENTAGE, SIGNAL_STRENGTH_DECIBELS_MILLIWATT
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import format_mac
@@ -10,7 +14,6 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import CONF_DEBUG_MODE, DOMAIN
-from .python_eq3bt.eq3bt.eq3btsmart import Thermostat
_LOGGER = logging.getLogger(__name__)
@@ -47,8 +50,10 @@ def __init__(self, _thermostat: Thermostat):
self._attr_has_entity_name = True
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
@@ -64,10 +69,10 @@ def __init__(self, _thermostat: Thermostat):
_thermostat.register_update_callback(self.schedule_update_ha_state)
self._attr_name = "Valve"
self._attr_icon = "mdi:pipe-valve"
- self._attr_native_unit_of_measurement = "%"
+ self._attr_native_unit_of_measurement = PERCENTAGE
@property
- def state(self):
+ def state(self) -> int | None:
return self._thermostat.valve_state
@@ -76,11 +81,14 @@ def __init__(self, _thermostat: Thermostat):
super().__init__(_thermostat)
_thermostat.register_update_callback(self.schedule_update_ha_state)
self._attr_name = "Away until"
- self._attr_device_class = "date"
+ self._attr_device_class = SensorDeviceClass.DATE
@property
- def native_value(self):
- return self._thermostat.away_end if self._thermostat.away else None
+ def native_value(self) -> datetime | None:
+ if self._thermostat.away_end is None:
+ return None
+
+ return self._thermostat.away_end
class RssiSensor(Base):
@@ -88,11 +96,11 @@ def __init__(self, _thermostat: Thermostat):
super().__init__(_thermostat)
_thermostat._conn.register_connection_callback(self.schedule_update_ha_state)
self._attr_name = "Rssi"
- self._attr_native_unit_of_measurement = "dBm"
+ self._attr_native_unit_of_measurement = SIGNAL_STRENGTH_DECIBELS_MILLIWATT
self._attr_entity_category = EntityCategory.DIAGNOSTIC
@property
- def state(self):
+ def state(self) -> int | None:
return self._thermostat._conn.rssi
@@ -104,7 +112,7 @@ def __init__(self, _thermostat: Thermostat):
self._attr_entity_category = EntityCategory.DIAGNOSTIC
@property
- def state(self):
+ def state(self) -> str | None:
return self._thermostat.device_serial
@@ -118,7 +126,7 @@ def __init__(self, _thermostat: Thermostat):
async def async_added_to_hass(self) -> None:
asyncio.get_event_loop().create_task(self.fetch_serial())
- async def fetch_serial(self):
+ async def fetch_serial(self) -> None:
try:
await self._thermostat.async_query_id()
except Exception as e:
@@ -144,7 +152,7 @@ async def fetch_serial(self):
)
@property
- def state(self):
+ def state(self) -> str | None:
return self._thermostat.firmware_version
@@ -155,7 +163,7 @@ def __init__(self, _thermostat: Thermostat):
self._attr_entity_category = EntityCategory.DIAGNOSTIC
@property
- def state(self):
+ def state(self) -> str | None:
return self._thermostat.mac
@@ -167,7 +175,7 @@ def __init__(self, _thermostat: Thermostat):
self._attr_entity_category = EntityCategory.DIAGNOSTIC
@property
- def state(self):
+ def state(self) -> int:
return self._thermostat._conn.retries
@@ -179,8 +187,8 @@ def __init__(self, _thermostat: Thermostat):
self._attr_entity_category = EntityCategory.DIAGNOSTIC
@property
- def state(self):
- if self._thermostat._conn._conn == None:
+ def state(self) -> str | None:
+ if self._thermostat._conn._conn is None:
return None
if not hasattr(self._thermostat._conn._conn._backend, "_device_path"):
diff --git a/custom_components/dbuezas_eq3btsmart/services.yaml b/custom_components/eq3btsmart/services.yaml
similarity index 89%
rename from custom_components/dbuezas_eq3btsmart/services.yaml
rename to custom_components/eq3btsmart/services.yaml
index 5b8fdf5..713bd43 100644
--- a/custom_components/dbuezas_eq3btsmart/services.yaml
+++ b/custom_components/eq3btsmart/services.yaml
@@ -2,7 +2,7 @@ set_away_until:
name: Set Away until
target:
device:
- integration: dbuezas_eq3btsmart
+ integration: eq3btsmart
model: CC-RT-BLE-EQ
fields:
away_until:
@@ -26,7 +26,7 @@ set_schedule:
name: Set EQ3 Schedule
target:
device:
- integration: dbuezas_eq3btsmart
+ integration: eq3btsmart
model: CC-RT-BLE-EQ
fields:
days:
@@ -36,7 +36,7 @@ set_schedule:
select:
mode: list
multiple: true
- options:
+ options:
- label: Monday
value: mon
- label: Tuesday
@@ -70,35 +70,35 @@ set_schedule:
selector: &time_selector
time:
- target_temp_1:
+ target_temp_1:
name: "Then change to"
required: false
example: 21
default: 21
selector: *temp_selector
- next_change_at_1:
+ next_change_at_1:
name: Until
example: "09:00:00"
default: "09:00:00"
selector: *time_selector
- target_temp_2:
+ target_temp_2:
name: "Then change to"
example: 17
default: 17
selector: *temp_selector
- next_change_at_2:
+ next_change_at_2:
name: Until
example: "17:00:00"
default: "17:00:00"
selector: *time_selector
- target_temp_3:
+ target_temp_3:
name: "Then change to"
example: 21
default: 21
selector: *temp_selector
- next_change_at_3:
+ next_change_at_3:
name: Until
example: "23:00:00"
default: "23:00:00"
@@ -109,16 +109,16 @@ set_schedule:
example: 17
default: 17
selector: *temp_selector
- next_change_at_4:
+ next_change_at_4:
name: Until
default: "23:00:00"
selector: *time_selector
-
+
target_temp_5:
name: "Then change to"
default: 17
selector: *temp_selector
- next_change_at_5:
+ next_change_at_5:
name: Until
default: "23:00:00"
selector: *time_selector
@@ -126,4 +126,4 @@ set_schedule:
target_temp_6:
name: "Then change to"
default: 17
- selector: *temp_selector
\ No newline at end of file
+ selector: *temp_selector
diff --git a/custom_components/dbuezas_eq3btsmart/switch.py b/custom_components/eq3btsmart/switch.py
similarity index 81%
rename from custom_components/dbuezas_eq3btsmart/switch.py
rename to custom_components/eq3btsmart/switch.py
index f758e8c..6905e51 100644
--- a/custom_components/dbuezas_eq3btsmart/switch.py
+++ b/custom_components/eq3btsmart/switch.py
@@ -1,8 +1,11 @@
import logging
+from typing import Any
import voluptuous as vol
+from eq3btsmart import Thermostat
+from eq3btsmart.const import EQ3BT_MAX_TEMP, EQ3BT_OFF_TEMP
from homeassistant.components.switch import SwitchEntity
-from homeassistant.config_entries import ConfigEntry
+from homeassistant.config_entries import ConfigEntry, UndefinedType
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import entity_platform
@@ -11,11 +14,6 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import CONF_DEBUG_MODE, DOMAIN
-from .python_eq3bt.eq3bt.eq3btsmart import (
- EQ3BT_MAX_TEMP,
- EQ3BT_OFF_TEMP,
- Thermostat,
-)
_LOGGER = logging.getLogger(__name__)
@@ -57,8 +55,10 @@ def __init__(self, _thermostat: Thermostat):
self._attr_has_entity_name = True
@property
- def unique_id(self) -> str:
- assert self.name
+ def unique_id(self) -> str | None:
+ if self.name is None or isinstance(self.name, UndefinedType):
+ return None
+
return format_mac(self._thermostat.mac) + "_" + self.name
@property
@@ -67,9 +67,6 @@ def device_info(self) -> DeviceInfo:
identifiers={(DOMAIN, self._thermostat.mac)},
)
- async def set_away_until(self, away_until, temperature: float) -> None:
- pass
-
class AwaySwitch(Base):
def __init__(self, _thermostat: Thermostat):
@@ -78,14 +75,14 @@ def __init__(self, _thermostat: Thermostat):
self._attr_name = "Away"
self._attr_icon = "mdi:lock"
- async def async_turn_on(self):
+ async def async_turn_on(self, **kwargs: Any) -> None:
await self._thermostat.async_set_away(True)
- async def async_turn_off(self):
+ async def async_turn_off(self, **kwargs: Any) -> None:
await self._thermostat.async_set_away(False)
@property
- def is_on(self):
+ def is_on(self) -> bool | None:
return self._thermostat.away
async def set_away_until(self, away_until, temperature: float) -> None:
@@ -99,14 +96,14 @@ def __init__(self, _thermostat: Thermostat):
self._attr_name = "Boost"
self._attr_icon = "mdi:speedometer"
- async def async_turn_on(self):
+ async def async_turn_on(self, **kwargs: Any) -> None:
await self._thermostat.async_set_boost(True)
- async def async_turn_off(self):
+ async def async_turn_off(self, **kwargs: Any) -> None:
await self._thermostat.async_set_boost(False)
@property
- def is_on(self):
+ def is_on(self) -> bool | None:
return self._thermostat.boost
@@ -119,15 +116,15 @@ def __init__(self, _thermostat: Thermostat):
self._attr_assumed_state = True
self._attr_entity_category = EntityCategory.DIAGNOSTIC
- async def async_turn_on(self):
+ async def async_turn_on(self, **kwargs: Any) -> None:
await self._thermostat._conn.async_make_request("ONLY CONNECT")
- async def async_turn_off(self):
+ async def async_turn_off(self, **kwargs: Any) -> None:
if self._thermostat._conn._conn:
await self._thermostat._conn._conn.disconnect()
@property
- def is_on(self):
+ def is_on(self) -> bool | None:
if self._thermostat._conn._conn is None:
return None
return self._thermostat._conn._conn.is_connected
diff --git a/custom_components/dbuezas_eq3btsmart/translations/en.json b/custom_components/eq3btsmart/translations/en.json
similarity index 100%
rename from custom_components/dbuezas_eq3btsmart/translations/en.json
rename to custom_components/eq3btsmart/translations/en.json
diff --git a/eq3btsmart/__init__.py b/eq3btsmart/__init__.py
new file mode 100644
index 0000000..5786d31
--- /dev/null
+++ b/eq3btsmart/__init__.py
@@ -0,0 +1,2 @@
+from eq3btsmart.bleakconnection import BleakConnection as BleakConnection
+from eq3btsmart.thermostat import Thermostat as Thermostat
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/bleakconnection.py b/eq3btsmart/bleakconnection.py
similarity index 86%
rename from custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/bleakconnection.py
rename to eq3btsmart/bleakconnection.py
index 66d96a2..e1aca0d 100644
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/bleakconnection.py
+++ b/eq3btsmart/bleakconnection.py
@@ -1,11 +1,7 @@
-"""
-Bleak connection backend.
-This creates a new event loop that is used to integrate bleak's
-asyncio functions to synchronous architecture of python-eq3bt.
-"""
+"""Bleak connection backend."""
import asyncio
import logging
-from typing import cast
+from typing import Callable, cast
from bleak import BleakClient
from bleak.backends.characteristic import BleakGATTCharacteristic
@@ -14,20 +10,18 @@
from homeassistant.components import bluetooth
from homeassistant.core import HomeAssistant
-from ...const import Adapter
-from . import BackendException
-
-REQUEST_TIMEOUT = 5
-RETRY_BACK_OFF_FACTOR = 0.25
-RETRIES = 14
-
-# Handles in linux and BTProxy are off by 1. Using UUIDs instead for consistency
-PROP_WRITE_UUID = "3fa4585a-ce4a-3bad-db4b-b8df8179ea09"
-PROP_NTFY_UUID = "d0e8434d-cd29-0996-af41-6c90f4e0eb2a"
+from eq3btsmart.const import (
+ PROP_NTFY_UUID,
+ PROP_WRITE_UUID,
+ REQUEST_TIMEOUT,
+ RETRIES,
+ RETRY_BACK_OFF_FACTOR,
+ Adapter,
+)
+from eq3btsmart.exceptions import BackendException
# bleak backends are very loud on debug, this reduces the log spam when using --debug
# logging.getLogger("bleak.backends").setLevel(logging.WARNING)
-
_LOGGER = logging.getLogger(__name__)
@@ -52,22 +46,22 @@ def __init__(
self._callback = callback
self._notify_event = asyncio.Event()
self._terminate_event = asyncio.Event()
- self.rssi = None
+ self.rssi: int | None = None
self._lock = asyncio.Lock()
self._conn: BleakClient | None = None
self._ble_device: BLEDevice | None = None
- self._connection_callbacks = []
+ self._connection_callbacks: list[Callable] = []
self.retries = 0
self._round_robin = 0
- def register_connection_callback(self, callback) -> None:
+ def register_connection_callback(self, callback: Callable) -> None:
self._connection_callbacks.append(callback)
def _on_connection_event(self) -> None:
for callback in self._connection_callbacks:
callback()
- def shutdown(self):
+ def shutdown(self) -> None:
_LOGGER.debug(
"[%s] closing connections",
self._name,
@@ -75,18 +69,18 @@ def shutdown(self):
self._terminate_event.set()
self._notify_event.set()
- async def throw_if_terminating(self):
+ async def throw_if_terminating(self) -> None:
if self._terminate_event.is_set():
if self._conn:
await self._conn.disconnect()
raise Exception("Connection cancelled by shutdown")
- async def async_get_connection(self):
+ async def async_get_connection(self) -> BleakClient:
if self._adapter == Adapter.AUTO:
self._ble_device = bluetooth.async_ble_device_from_address(
self._hass, self._mac, connectable=True
)
- if self._ble_device == None:
+ if self._ble_device is None:
raise Exception("Device not found")
self._conn = await establish_connection(
@@ -140,7 +134,9 @@ async def async_get_connection(self):
raise BackendException("Can't connect")
return self._conn
- async def on_notification(self, handle: BleakGATTCharacteristic, data: bytearray):
+ async def on_notification(
+ self, handle: BleakGATTCharacteristic, data: bytearray
+ ) -> None:
"""Handle Callback from a Bluetooth (GATT) request."""
if PROP_NTFY_UUID == handle.uuid:
self._notify_event.set()
@@ -153,7 +149,7 @@ async def on_notification(self, handle: BleakGATTCharacteristic, data: bytearray
handle.uuid,
)
- async def async_make_request(self, value, retries=RETRIES):
+ async def async_make_request(self, value, retries=RETRIES) -> None:
"""Write a GATT Command with callback - not utf-8."""
async with self._lock: # only one concurrent request per thermostat
try:
@@ -162,7 +158,7 @@ async def async_make_request(self, value, retries=RETRIES):
self.retries = 0
self._on_connection_event()
- async def _async_make_request_try(self, value, retries):
+ async def _async_make_request_try(self, value, retries) -> None:
self.retries = 0
while True:
self.retries += 1
diff --git a/eq3btsmart/const.py b/eq3btsmart/const.py
new file mode 100644
index 0000000..c2d3fb7
--- /dev/null
+++ b/eq3btsmart/const.py
@@ -0,0 +1,59 @@
+"""Constants for the eq3btsmart library."""
+
+from enum import Enum, IntEnum
+
+PROP_ID_QUERY = 0
+PROP_ID_RETURN = 1
+PROP_INFO_QUERY = 3
+PROP_INFO_RETURN = 2
+PROP_COMFORT_ECO_CONFIG = 0x11
+PROP_OFFSET = 0x13
+PROP_WINDOW_OPEN_CONFIG = 0x14
+PROP_SCHEDULE_SET = 0x10
+PROP_SCHEDULE_QUERY = 0x20
+PROP_SCHEDULE_RETURN = 0x21
+
+PROP_MODE_WRITE = 0x40
+PROP_TEMPERATURE_WRITE = 0x41
+PROP_COMFORT = 0x43
+PROP_ECO = 0x44
+PROP_BOOST = 0x45
+PROP_LOCK = 0x80
+
+NAME_TO_DAY = {"sat": 0, "sun": 1, "mon": 2, "tue": 3, "wed": 4, "thu": 5, "fri": 6}
+NAME_TO_CMD = {"write": PROP_SCHEDULE_SET, "response": PROP_SCHEDULE_RETURN}
+HOUR_24_PLACEHOLDER = 1234
+
+EQ3BT_AWAY_TEMP = 12.0
+EQ3BT_MIN_TEMP = 5.0
+EQ3BT_MAX_TEMP = 29.5
+EQ3BT_OFF_TEMP = 4.5
+EQ3BT_ON_TEMP = 30.0
+EQ3BT_MIN_OFFSET = -3.5
+EQ3BT_MAX_OFFSET = 3.5
+
+# Handles in linux and BTProxy are off by 1. Using UUIDs instead for consistency
+PROP_WRITE_UUID = "3fa4585a-ce4a-3bad-db4b-b8df8179ea09"
+PROP_NTFY_UUID = "d0e8434d-cd29-0996-af41-6c90f4e0eb2a"
+
+REQUEST_TIMEOUT = 5
+RETRY_BACK_OFF_FACTOR = 0.25
+RETRIES = 14
+
+DEFAULT_AWAY_HOURS = 30 * 24
+DEFAULT_AWAY_TEMP = 12
+
+
+class Mode(IntEnum):
+ """Thermostat modes."""
+
+ Unknown = 0
+ Off = 0
+ On = 1
+ Auto = 2
+ Manual = 3
+
+
+class Adapter(str, Enum):
+ AUTO = "AUTO"
+ LOCAL = "LOCAL"
diff --git a/eq3btsmart/exceptions.py b/eq3btsmart/exceptions.py
new file mode 100644
index 0000000..2ff6a0a
--- /dev/null
+++ b/eq3btsmart/exceptions.py
@@ -0,0 +1,9 @@
+"""Exceptions for the eq3btsmart library."""
+
+
+class TemperatureException(Exception):
+ """Temperature out of range error."""
+
+
+class BackendException(Exception):
+ """Exception to wrap backend exceptions."""
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/structures.py b/eq3btsmart/structures.py
similarity index 90%
rename from custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/structures.py
rename to eq3btsmart/structures.py
index 9297980..4a5fc61 100644
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/structures.py
+++ b/eq3btsmart/structures.py
@@ -14,14 +14,13 @@
Struct,
)
-PROP_ID_RETURN = 1
-PROP_INFO_RETURN = 2
-PROP_SCHEDULE_SET = 0x10
-PROP_SCHEDULE_RETURN = 0x21
-
-NAME_TO_DAY = {"sat": 0, "sun": 1, "mon": 2, "tue": 3, "wed": 4, "thu": 5, "fri": 6}
-NAME_TO_CMD = {"write": PROP_SCHEDULE_SET, "response": PROP_SCHEDULE_RETURN}
-HOUR_24_PLACEHOLDER = 1234
+from eq3btsmart.const import (
+ HOUR_24_PLACEHOLDER,
+ NAME_TO_CMD,
+ NAME_TO_DAY,
+ PROP_ID_RETURN,
+ PROP_INFO_RETURN,
+)
class TimeAdapter(Adapter):
@@ -131,15 +130,15 @@ def _decode(self, obj, context, path):
"cmd" / Const(PROP_INFO_RETURN, Int8ub),
Const(0x01, Int8ub),
"mode" / ModeFlags,
- "valve" / Int8ub, # type: ignore
+ "valve" / Int8ub,
Const(0x04, Int8ub),
"target_temp" / TempAdapter(Int8ub),
"away"
- / IfThenElse( # noqa: W503
+ / IfThenElse(
lambda ctx: ctx.mode.AWAY, AwayDataAdapter(Bytes(4)), Optional(Bytes(4))
),
"presets"
- / Optional( # noqa: W503
+ / Optional(
Struct(
"window_open_temp" / TempAdapter(Int8ub),
"window_open_time" / WindowOpenTimeAdapter(Int8ub),
@@ -154,7 +153,7 @@ def _decode(self, obj, context, path):
"cmd" / Enum(Int8ub, **NAME_TO_CMD),
"day" / Enum(Int8ub, **NAME_TO_DAY),
"hours"
- / GreedyRange( # noqa: W503
+ / GreedyRange(
Struct(
"target_temp" / TempAdapter(Int8ub),
"next_change_at" / TimeAdapter(Int8ub),
@@ -164,7 +163,7 @@ def _decode(self, obj, context, path):
DeviceId = "DeviceId" / Struct(
"cmd" / Const(PROP_ID_RETURN, Int8ub),
- "version" / Int8ub, # type: ignore
+ "version" / Int8ub,
Int8ub,
Int8ub,
"serial" / DeviceSerialAdapter(Bytes(10)),
diff --git a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/eq3btsmart.py b/eq3btsmart/thermostat.py
similarity index 65%
rename from custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/eq3btsmart.py
rename to eq3btsmart/thermostat.py
index 5eea1d6..baf09b5 100644
--- a/custom_components/dbuezas_eq3btsmart/python_eq3bt/eq3bt/eq3btsmart.py
+++ b/eq3btsmart/thermostat.py
@@ -11,58 +11,44 @@
import logging
import struct
from datetime import datetime, timedelta
-from enum import IntEnum
+from typing import Any, Callable
-from construct import Byte
+from construct import Byte, Container
from homeassistant.core import HomeAssistant
-from .structures import AwayDataAdapter, DeviceId, Schedule, Status
+from eq3btsmart.bleakconnection import BleakConnection
+from eq3btsmart.const import (
+ DEFAULT_AWAY_HOURS,
+ DEFAULT_AWAY_TEMP,
+ EQ3BT_MAX_OFFSET,
+ EQ3BT_MAX_TEMP,
+ EQ3BT_MIN_OFFSET,
+ EQ3BT_MIN_TEMP,
+ EQ3BT_OFF_TEMP,
+ EQ3BT_ON_TEMP,
+ PROP_BOOST,
+ PROP_COMFORT,
+ PROP_COMFORT_ECO_CONFIG,
+ PROP_ECO,
+ PROP_ID_QUERY,
+ PROP_ID_RETURN,
+ PROP_INFO_QUERY,
+ PROP_INFO_RETURN,
+ PROP_LOCK,
+ PROP_MODE_WRITE,
+ PROP_OFFSET,
+ PROP_SCHEDULE_QUERY,
+ PROP_SCHEDULE_RETURN,
+ PROP_TEMPERATURE_WRITE,
+ PROP_WINDOW_OPEN_CONFIG,
+ Mode,
+)
+from eq3btsmart.exceptions import TemperatureException
+from eq3btsmart.structures import AwayDataAdapter, DeviceId, Schedule, Status
_LOGGER = logging.getLogger(__name__)
-PROP_ID_QUERY = 0
-PROP_ID_RETURN = 1
-PROP_INFO_QUERY = 3
-PROP_INFO_RETURN = 2
-PROP_COMFORT_ECO_CONFIG = 0x11
-PROP_OFFSET = 0x13
-PROP_WINDOW_OPEN_CONFIG = 0x14
-PROP_SCHEDULE_QUERY = 0x20
-PROP_SCHEDULE_RETURN = 0x21
-PROP_MODE_WRITE = 0x40
-PROP_TEMPERATURE_WRITE = 0x41
-PROP_COMFORT = 0x43
-PROP_ECO = 0x44
-PROP_BOOST = 0x45
-PROP_LOCK = 0x80
-
-EQ3BT_AWAY_TEMP = 12.0
-EQ3BT_MIN_TEMP = 5.0
-EQ3BT_MAX_TEMP = 29.5
-EQ3BT_OFF_TEMP = 4.5
-EQ3BT_ON_TEMP = 30.0
-EQ3BT_MIN_OFFSET = -3.5
-EQ3BT_MAX_OFFSET = 3.5
-
-
-class Mode(IntEnum):
- """Thermostat modes."""
-
- Unknown = 0
- Off = 0
- On = 1
- Auto = 2
- Manual = 3
-
-
-class TemperatureException(Exception):
- """Temperature out of range error."""
-
- pass
-
-
-# pylint: disable=too-many-instance-attributes
class Thermostat:
"""Representation of a EQ3 Bluetooth Smart thermostat."""
@@ -77,16 +63,13 @@ def __init__(
"""Initialize the thermostat."""
self.name = name
- self._status = None
- self._presets = None
- self._device_data = None
- self._schedule = {}
- self.default_away_hours: float = 30 * 24
- self.default_away_temp: float = 12
-
- from .bleakconnection import BleakConnection
-
- self._on_update_callbacks = []
+ self._status: Container[Any] | None = None
+ self._presets: Container[Any] | None = None
+ self._device_data: Container[Any] | None = None
+ self._schedule: dict[str, Container[Any]] = {}
+ self.default_away_hours: float = DEFAULT_AWAY_HOURS
+ self.default_away_temp: float = DEFAULT_AWAY_TEMP
+ self._on_update_callbacks: list[Callable] = []
self._conn = BleakConnection(
mac=mac,
name=name,
@@ -96,13 +79,13 @@ def __init__(
callback=self.handle_notification,
)
- def register_update_callback(self, on_update):
+ def register_update_callback(self, on_update: Callable) -> None:
self._on_update_callbacks.append(on_update)
- def shutdown(self):
+ def shutdown(self) -> None:
self._conn.shutdown()
- def _verify_temperature(self, temp):
+ def _verify_temperature(self, temp: float) -> None:
"""Verifies that the temperature is valid.
:raises TemperatureException: On invalid temperature.
"""
@@ -113,23 +96,26 @@ def _verify_temperature(self, temp):
)
)
- def parse_schedule(self, data):
+ def parse_schedule(self, data) -> Container[Any]:
"""Parses the device sent schedule."""
sched = Schedule.parse(data)
- if sched == None:
+ if sched is None:
raise Exception("Parsed empty schedule data")
_LOGGER.debug("[%s] Got schedule data for day '%s'", self.name, sched.day)
return sched
- def handle_notification(self, data: bytearray):
+ def handle_notification(self, data: bytearray) -> None:
"""Handle Callback from a Bluetooth (GATT) request."""
_LOGGER.debug("[%s] Received notification from the device.", self.name)
updated = True
if data[0] == PROP_INFO_RETURN and data[1] == 1:
_LOGGER.debug("[%s] Got status: %s", self.name, codecs.encode(data, "hex"))
self._status = Status.parse(data)
- assert self._status
+
+ if self._status is None:
+ raise Exception("Parsed empty status data")
+
self._presets = self._status.presets
_LOGGER.debug("[%s] Parsed status: %s", self.name, self._status)
@@ -153,14 +139,14 @@ def handle_notification(self, data: bytearray):
for callback in self._on_update_callbacks:
callback()
- async def async_query_id(self):
+ async def async_query_id(self) -> None:
"""Query device identification information, e.g. the serial number."""
_LOGGER.debug("[%s] Querying id..", self.name)
value = struct.pack("B", PROP_ID_QUERY)
await self._conn.async_make_request(value)
_LOGGER.debug("[%s] Finished Querying id..", self.name)
- async def async_update(self):
+ async def async_update(self) -> None:
"""Update the data from the thermostat. Always sets the current time."""
_LOGGER.debug("[%s] Querying the device..", self.name)
time = datetime.now()
@@ -177,7 +163,7 @@ async def async_update(self):
await self._conn.async_make_request(value)
- async def async_query_schedule(self, day):
+ async def async_query_schedule(self, day: int) -> None:
_LOGGER.debug("[%s] Querying schedule..", self.name)
if day < 0 or day > 6:
@@ -188,13 +174,13 @@ async def async_query_schedule(self, day):
await self._conn.async_make_request(value)
@property
- def schedule(self):
+ def schedule(self) -> dict[str, Container[Any]]:
"""Returns previously fetched schedule.
:return: Schedule structure or None if not fetched.
"""
return self._schedule
- async def async_set_schedule(self, day, hours):
+ async def async_set_schedule(self, day, hours) -> None:
_LOGGER.debug(
"[%s] Setting schedule day=[%s], hours=[%s]", self.name, day, hours
)
@@ -215,12 +201,15 @@ async def async_set_schedule(self, day, hours):
callback()
@property
- def target_temperature(self):
+ def target_temperature(self) -> float:
"""Return the temperature we try to reach."""
return self._status.target_temp if self._status else -1
- async def async_set_target_temperature(self, temperature):
+ async def async_set_target_temperature(self, temperature: float | None) -> None:
"""Set new target temperature."""
+ if temperature is None:
+ return
+
dev_temp = int(temperature * 2)
if temperature == EQ3BT_OFF_TEMP or temperature == EQ3BT_ON_TEMP:
dev_temp |= 0x40
@@ -232,9 +221,9 @@ async def async_set_target_temperature(self, temperature):
await self._conn.async_make_request(value)
@property
- def mode(self):
+ def mode(self) -> Mode:
"""Return the current operation mode"""
- if self._status == None:
+ if self._status is None:
return Mode.Unknown
if self.target_temperature == EQ3BT_OFF_TEMP:
return Mode.Off
@@ -244,32 +233,46 @@ def mode(self):
return Mode.Manual
return Mode.Auto
- async def async_set_mode(self, mode):
+ async def async_set_mode(self, mode: Mode) -> None:
"""Set the operation mode."""
_LOGGER.debug("[%s] Setting new mode: %s", self.name, mode)
- if mode == Mode.Off:
- return await self.async_set_target_temperature(EQ3BT_OFF_TEMP)
- if mode == Mode.On:
- return await self.async_set_target_temperature(EQ3BT_ON_TEMP)
- if mode == Mode.Auto:
- return await self._async_set_mode(0)
- if mode == Mode.Manual:
- temperature = max(
- min(self.target_temperature, EQ3BT_MAX_TEMP), EQ3BT_MIN_TEMP
- )
- return await self._async_set_mode(0x40 | int(temperature * 2))
+ match mode:
+ case Mode.Off:
+ await self.async_set_target_temperature(EQ3BT_OFF_TEMP)
+ case Mode.On:
+ await self.async_set_target_temperature(EQ3BT_ON_TEMP)
+ case Mode.Auto:
+ await self._async_set_mode(0)
+ case Mode.Manual:
+ temperature = max(
+ min(self.target_temperature, EQ3BT_MAX_TEMP), EQ3BT_MIN_TEMP
+ )
+ await self._async_set_mode(0x40 | int(temperature * 2))
@property
def away(self) -> bool | None:
- """Returns True if the thermostat is in boost mode."""
- return self._status and self._status.mode.AWAY # type: ignore
+ """Returns True if the thermostat is in away mode."""
+
+ if self._status is None:
+ return None
+
+ return self.away_end is not None
@property
def away_end(self) -> datetime | None:
- return self._status and self._status.away # type: ignore
+ """Returns the end datetime of the away mode."""
+ if self._status is None:
+ return None
+
+ if not isinstance(self._status.away, datetime):
+ return None
+
+ return self._status.away
- async def async_set_away_until(self, away_end: datetime, temperature: float):
+ async def async_set_away_until(
+ self, away_end: datetime, temperature: float
+ ) -> None:
"""Sets away mode with default temperature."""
# rounding
@@ -279,12 +282,12 @@ async def async_set_away_until(self, away_end: datetime, temperature: float):
_LOGGER.debug(
"[%s] Setting away until %s, temp %s", self.name, away_end, temperature
)
- adapter = AwayDataAdapter(Byte[4]) # type: ignore
+ adapter = AwayDataAdapter(Byte[4])
packed = adapter.build(away_end)
await self._async_set_mode(0x80 | int(temperature * 2), packed)
- async def async_set_away(self, away: bool):
+ async def async_set_away(self, away: bool) -> None:
"""Sets away mode with default temperature."""
if not away:
_LOGGER.debug("[%s] Disabling away, going to auto mode.", self.name)
@@ -294,7 +297,7 @@ async def async_set_away(self, away: bool):
await self.async_set_away_until(away_end, self.default_away_temp)
- async def _async_set_mode(self, mode, payload=None):
+ async def _async_set_mode(self, mode: int, payload: bytes | None = None) -> None:
value = struct.pack("BB", PROP_MODE_WRITE, mode)
if payload:
value += payload
@@ -303,26 +306,40 @@ async def _async_set_mode(self, mode, payload=None):
@property
def boost(self) -> bool | None:
"""Returns True if the thermostat is in boost mode."""
- return self._status and self._status.mode.BOOST # type: ignore
- async def async_set_boost(self, boost):
+ if self._status is None:
+ return None
+
+ return self._status.mode.BOOST
+
+ async def async_set_boost(self, boost: bool) -> None:
"""Sets boost mode."""
_LOGGER.debug("[%s] Setting boost mode: %s", self.name, boost)
- value = struct.pack("BB", PROP_BOOST, bool(boost))
+ value = struct.pack("BB", PROP_BOOST, boost)
await self._conn.async_make_request(value)
@property
def valve_state(self) -> int | None:
"""Returns the valve state. Probably reported as percent open."""
- return self._status and self._status.valve # type: ignore
+
+ if self._status is None:
+ return None
+
+ return self._status.valve
@property
def window_open(self) -> bool | None:
"""Returns True if the thermostat reports a open window
(detected by sudden drop of temperature)"""
- return self._status and self._status.mode.WINDOW # type: ignore
- async def async_window_open_config(self, temperature, duration):
+ if self._status is None:
+ return False
+
+ return self._status.mode.WINDOW
+
+ async def async_window_open_config(
+ self, temperature: float, duration: timedelta
+ ) -> None:
"""Configures the window open behavior. The duration is specified in
5 minute increments."""
_LOGGER.debug(
@@ -344,37 +361,57 @@ async def async_window_open_config(self, temperature, duration):
await self._conn.async_make_request(value)
@property
- def window_open_temperature(self):
+ def window_open_temperature(self) -> float | None:
"""The temperature to set when an open window is detected."""
- return self._presets and self._presets.window_open_temp
+
+ if self._presets is None:
+ return None
+
+ return self._presets.window_open_temp
@property
def window_open_time(self) -> timedelta | None:
"""Timeout to reset the thermostat after an open window is detected."""
- return self._presets and self._presets.window_open_time # type: ignore
+
+ if self._presets is None:
+ return None
+
+ return self._presets.window_open_time
@property
def dst(self) -> bool | None:
"""Returns True if the thermostat is in Daylight Saving Time."""
- return self._status and self._status.mode.DST # type: ignore
+
+ if self._status is None:
+ return None
+
+ return self._status.mode.DST
@property
def locked(self) -> bool | None:
"""Returns True if the thermostat is locked."""
- return self._status and self._status.mode.LOCKED # type: ignore
- async def async_set_locked(self, lock):
+ if self._status is None:
+ return None
+
+ return self._status.mode.LOCKED
+
+ async def async_set_locked(self, lock: bool) -> None:
"""Locks or unlocks the thermostat."""
_LOGGER.debug("[%s] Setting the lock: %s", self.name, lock)
- value = struct.pack("BB", PROP_LOCK, bool(lock))
+ value = struct.pack("BB", PROP_LOCK, lock)
await self._conn.async_make_request(value)
@property
def low_battery(self) -> bool | None:
"""Returns True if the thermostat reports a low battery."""
- return self._status and self._status.mode.LOW_BATTERY # type: ignore
- async def async_temperature_presets(self, comfort, eco):
+ if self._status is None:
+ return None
+
+ return self._status.mode.LOW_BATTERY
+
+ async def async_temperature_presets(self, comfort: float, eco: float) -> None:
"""Set the thermostats preset temperatures comfort (sun) and
eco (moon)."""
_LOGGER.debug(
@@ -391,21 +428,33 @@ async def async_temperature_presets(self, comfort, eco):
await self._conn.async_make_request(value)
@property
- def comfort_temperature(self):
+ def comfort_temperature(self) -> float | None:
"""Returns the comfort temperature preset of the thermostat."""
- return self._presets and self._presets.comfort_temp
+
+ if self._presets is None:
+ return None
+
+ return self._presets.comfort_temp
@property
- def eco_temperature(self):
+ def eco_temperature(self) -> float | None:
"""Returns the eco temperature preset of the thermostat."""
- return self._presets and self._presets.eco_temp
+
+ if self._presets is None:
+ return None
+
+ return self._presets.eco_temp
@property
- def temperature_offset(self):
+ def temperature_offset(self) -> float | None:
"""Returns the thermostat's temperature offset."""
- return self._presets and self._presets.offset
- async def async_set_temperature_offset(self, offset):
+ if self._presets is None:
+ return None
+
+ return self._presets.offset
+
+ async def async_set_temperature_offset(self, offset: float) -> None:
"""Sets the thermostat's temperature offset."""
_LOGGER.debug("[%s] Setting offset: %s", self.name, offset)
# [-3,5 .. 0 .. 3,5 ]
@@ -422,12 +471,12 @@ async def async_set_temperature_offset(self, offset):
value = struct.pack("BB", PROP_OFFSET, values[offset])
await self._conn.async_make_request(value)
- async def async_activate_comfort(self):
+ async def async_activate_comfort(self) -> None:
"""Activates the comfort temperature."""
value = struct.pack("B", PROP_COMFORT)
await self._conn.async_make_request(value)
- async def async_activate_eco(self):
+ async def async_activate_eco(self) -> None:
"""Activates the comfort temperature."""
value = struct.pack("B", PROP_ECO)
await self._conn.async_make_request(value)
@@ -435,14 +484,23 @@ async def async_activate_eco(self):
@property
def firmware_version(self) -> str | None:
"""Return the firmware version."""
- return self._device_data and self._device_data.version # type: ignore
+
+ if self._device_data is None:
+ return None
+
+ return self._device_data.version
@property
def device_serial(self) -> str | None:
"""Return the device serial number."""
- return self._device_data and self._device_data.serial # type: ignore
+
+ if self._device_data is None:
+ return None
+
+ return self._device_data.serial
@property
- def mac(self):
+ def mac(self) -> str:
"""Return the mac address."""
+
return self._conn._mac
diff --git a/hacs.json b/hacs.json
index bd4ba40..c3edd01 100644
--- a/hacs.json
+++ b/hacs.json
@@ -1,5 +1,5 @@
{
- "name": "dbuezas_eq3btsmart",
+ "name": "eq3btsmart",
"homeassistant": "2023.1.1",
"render_readme": true
}
diff --git a/poetry.lock b/poetry.lock
index 1e6d025..78e00a5 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,16 +1,5 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
-[[package]]
-name = "aiofiles"
-version = "23.2.1"
-description = "File support for asyncio."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "aiofiles-23.2.1-py3-none-any.whl", hash = "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107"},
- {file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"},
-]
-
[[package]]
name = "aiohttp"
version = "3.9.1"
@@ -136,18 +125,18 @@ aiohttp = ">=3.8.5,<3.10"
[[package]]
name = "aiohttp-zlib-ng"
-version = "0.1.3"
+version = "0.1.1"
description = "Enable zlib_ng on aiohttp"
optional = false
python-versions = ">=3.8,<4.0"
files = [
- {file = "aiohttp_zlib_ng-0.1.3-py3-none-any.whl", hash = "sha256:d3f8aec04bda08467d1d0ad16a5ff4b31d1eb87534d43b24d8a183d4fc963e63"},
- {file = "aiohttp_zlib_ng-0.1.3.tar.gz", hash = "sha256:2aafeb911de5075b1374736c7830b5d203988937d25b015e89c22390f4a6856a"},
+ {file = "aiohttp_zlib_ng-0.1.1-py3-none-any.whl", hash = "sha256:05a4f69b1f02cb9a790c366e1417ed7a95e23a55123acc2216a47b8f9d27226f"},
+ {file = "aiohttp_zlib_ng-0.1.1.tar.gz", hash = "sha256:8f3a9a9b4e8bfa9c3cfa7fb619b1268d6e986a66e452de067a81017717bb6962"},
]
[package.dependencies]
aiohttp = ">=3.8.5"
-zlib-ng = ">=0.3.0"
+zlib-ng = ">=0.2.0"
[[package]]
name = "aiosignal"
@@ -297,22 +286,6 @@ typing-extensions = {version = ">=4.7.0", markers = "python_version < \"3.12\""}
"winrt-Windows.Foundation.Collections" = {version = "2.0.0b1", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""}
"winrt-Windows.Storage.Streams" = {version = "2.0.0b1", markers = "platform_system == \"Windows\" and python_version >= \"3.12\""}
-[[package]]
-name = "bleak-retry-connector"
-version = "3.4.0"
-description = "A connector for Bleak Clients that handles transient connection failures"
-optional = false
-python-versions = ">=3.10,<3.13"
-files = [
- {file = "bleak_retry_connector-3.4.0-py3-none-any.whl", hash = "sha256:5f6c26efa03d3ae94c55045b99079fc27f1a9480cf4c8f6d6f027a36bf15cf66"},
- {file = "bleak_retry_connector-3.4.0.tar.gz", hash = "sha256:71f30928180b74f0381e0752f681d18d8de888faa9c81c78cd17123718909ea0"},
-]
-
-[package.dependencies]
-bleak = ">=0.21.0"
-bluetooth-adapters = {version = ">=0.15.2", markers = "platform_system == \"Linux\""}
-dbus-fast = {version = ">=1.14.0", markers = "platform_system == \"Linux\""}
-
[[package]]
name = "bleak-winrt"
version = "1.2.0"
@@ -333,106 +306,6 @@ files = [
{file = "bleak_winrt-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:63130c11acfe75c504a79c01f9919e87f009f5e742bfc7b7a5c2a9c72bf591a7"},
]
-[[package]]
-name = "bluetooth-adapters"
-version = "0.17.0"
-description = "Tools to enumerate and find Bluetooth Adapters"
-optional = false
-python-versions = ">=3.9,<3.13"
-files = [
- {file = "bluetooth_adapters-0.17.0-py3-none-any.whl", hash = "sha256:24a8d485e77289f037494fe52877b5c20051feb4747f0173b768a66d8e2b13c4"},
- {file = "bluetooth_adapters-0.17.0.tar.gz", hash = "sha256:6a82ec713a4a5eccb870d7e9ff98e4002bbae885e1ab0f98f5056fc68db22325"},
-]
-
-[package.dependencies]
-aiohttp = ">=3.8.1"
-bleak = ">=0.21.1"
-dbus-fast = ">=1.21.0"
-mac-vendor-lookup = ">=0.1.12"
-usb-devices = ">=0.4.5"
-
-[package.extras]
-docs = ["Sphinx (>=5,<8)", "myst-parser (>=0.18,<2.1)", "sphinx-rtd-theme (>=1,<3)"]
-
-[[package]]
-name = "bluetooth-auto-recovery"
-version = "1.3.0"
-description = "Recover bluetooth adapters that are in an stuck state"
-optional = false
-python-versions = ">=3.9,<4.0"
-files = [
- {file = "bluetooth_auto_recovery-1.3.0-py3-none-any.whl", hash = "sha256:f804c59f1302830f9343f96bf0d150e6e51983e951ecd7ffe6f28d2286932717"},
- {file = "bluetooth_auto_recovery-1.3.0.tar.gz", hash = "sha256:36ebf08e7cf44e35c15175323aed91e1bf2418792a4c3f76165d16d0f437614b"},
-]
-
-[package.dependencies]
-bluetooth-adapters = ">=0.16.0"
-btsocket = ">=0.2.0"
-PyRIC = ">=0.1.6.3"
-usb-devices = ">=0.4.1"
-
-[package.extras]
-docs = ["Sphinx (>=5.0,<6.0)", "myst-parser (>=0.18,<0.19)", "sphinx-rtd-theme (>=1.0,<2.0)"]
-
-[[package]]
-name = "bluetooth-data-tools"
-version = "1.19.0"
-description = "Tools for converting bluetooth data and packets"
-optional = false
-python-versions = ">=3.10,<4.0"
-files = [
- {file = "bluetooth_data_tools-1.19.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:cc9130b92fe5a11ba91b4632cb5b5c5bdf9dfe8c4741f610ae277c971c226a11"},
- {file = "bluetooth_data_tools-1.19.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c0137966b6a1e3b95b50fa81b64c53d87ab41ab53d9aab69bad4113c7311afc"},
- {file = "bluetooth_data_tools-1.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c98115130a41122360b799aa7b3492ccea45bb5095ac16bb7b727111737ea5ce"},
- {file = "bluetooth_data_tools-1.19.0-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:a3de1c93f210bcae0048fa0ebc96b097613eddcbea5b05824df8b8fc90d343f8"},
- {file = "bluetooth_data_tools-1.19.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1b57bfbb878decfda85816b0744d6a18c82a353f6531ef5b5037a4088865c7de"},
- {file = "bluetooth_data_tools-1.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:252fa800bfc22de0cc19e491e99e155305a47788cff6c31d56450f6137c74f6b"},
- {file = "bluetooth_data_tools-1.19.0-cp310-cp310-win32.whl", hash = "sha256:541adf9b8a093c4333f7c4b99e2662ec7c38a9dde8b2561d5e280da06573707a"},
- {file = "bluetooth_data_tools-1.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:74843706ad65dbc0c32cf4ce073e266353f48970ab0a6ae2edda1969fbb318d1"},
- {file = "bluetooth_data_tools-1.19.0-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:2e36ec53e6264faa9a75e8b704ce8f274ab0ba336ce3e5b7a279c254b2231bc2"},
- {file = "bluetooth_data_tools-1.19.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ebd2783c1f487d2c991f4f2ed399ea452fdee605e4de4417f353a5bee494b82"},
- {file = "bluetooth_data_tools-1.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:238db5bf2f19872c1318fcc35a4efc48961065ff7c227a0d239b220de1576d80"},
- {file = "bluetooth_data_tools-1.19.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bae1f9a2a1a89c5268c796d32c6a000d783ad9fc73fa9a271a287c6eaa1ecd97"},
- {file = "bluetooth_data_tools-1.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9763c3d3df14d16884775d61f034499afa4a32b8538cb6f2c71630ef6967295b"},
- {file = "bluetooth_data_tools-1.19.0-cp311-cp311-win32.whl", hash = "sha256:d23997cc3d849bfdf85ef42645b999054e4913a320ad10e77ca7557806008768"},
- {file = "bluetooth_data_tools-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:4b73b3509497d642404c8efc2b42de3b34d06172a88dbeacc6f8ebc1de1e550f"},
- {file = "bluetooth_data_tools-1.19.0-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:8371aeb50cef225a17df9a013277b3363ca59a53097cec5cb1ec89dea8323c3c"},
- {file = "bluetooth_data_tools-1.19.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:586bdeca2e24a41ceddad7fa02a3ed7a9c865f13ee95e8231b6a56c0a07e3e87"},
- {file = "bluetooth_data_tools-1.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56f6f822f2d69a620151f2a0bb9ad8502e5c59f84cff473befe545709bd952b5"},
- {file = "bluetooth_data_tools-1.19.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c6f4c95590c1524bf1cb3e543ee48760965b9eb5a2944b90e82f42200fce759"},
- {file = "bluetooth_data_tools-1.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:72188dd239728d6845d759671733d6b4cbf37face2adfd844fdcf431fce4103f"},
- {file = "bluetooth_data_tools-1.19.0-cp312-cp312-win32.whl", hash = "sha256:30acd97edc15d97eacae205b2c495371d7ae8cd878b3d72424286935ebd7d857"},
- {file = "bluetooth_data_tools-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:ce08ad5d2ce7ea624388bf5263c2688c356fae45c583d7331439b489f4191f01"},
- {file = "bluetooth_data_tools-1.19.0-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:8e81410105a4b753fb4afc6a881fa666c0dcba70fb38fe26835f4bf8baa71cd4"},
- {file = "bluetooth_data_tools-1.19.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c183ed080682cd4ab9f84205d648c46b9d65d41f4d9bbd65dc3a4787c07e633c"},
- {file = "bluetooth_data_tools-1.19.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e6dde7df8f61f13bb2e6bff29a93a190f31a858d753c48986c66c9aa3bdd3c2"},
- {file = "bluetooth_data_tools-1.19.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6e5d1546c3a2d400d78c70ededc49c4f7b418386b4b1f68611871ec3a39a8c85"},
- {file = "bluetooth_data_tools-1.19.0.tar.gz", hash = "sha256:5b58349126efbb38d61222267cf85bf1766f832cc5744a59e70a1a2653e477d9"},
-]
-
-[package.dependencies]
-cryptography = ">=41.0.3"
-
-[package.extras]
-docs = ["Sphinx (>=5.0,<6.0)", "myst-parser (>=0.18,<0.19)", "sphinx-rtd-theme (>=1.0,<2.0)"]
-
-[[package]]
-name = "btsocket"
-version = "0.2.0"
-description = "Python library for BlueZ Bluetooth Management API"
-optional = false
-python-versions = "*"
-files = [
- {file = "btsocket-0.2.0-py2.py3-none-any.whl", hash = "sha256:0d33893039284fa3a496dd31cb15227e1cf07f0d42d3843d3284b522cccf575a"},
- {file = "btsocket-0.2.0.tar.gz", hash = "sha256:6862250b7e0973d2beea9e49d3b5ced324d80e5003a0350856879e537ba777a8"},
-]
-
-[package.extras]
-dev = ["bumpversion", "coverage", "pycodestyle", "pygments", "sphinx", "sphinx-rtd-theme", "twine"]
-docs = ["pygments", "sphinx", "sphinx-rtd-theme"]
-rel = ["bumpversion", "twine"]
-test = ["coverage", "pycodestyle"]
-
[[package]]
name = "certifi"
version = "2023.11.17"
@@ -672,6 +545,34 @@ files = [
{file = "ciso8601-2.3.0.tar.gz", hash = "sha256:19e3fbd786d8bec3358eac94d8774d365b694b604fd1789244b87083f66c8900"},
]
+[[package]]
+name = "construct"
+version = "2.10.68"
+description = "A powerful declarative symmetric parser/builder for binary data"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "construct-2.10.68.tar.gz", hash = "sha256:7b2a3fd8e5f597a5aa1d614c3bd516fa065db01704c72a1efaaeec6ef23d8b45"},
+]
+
+[package.extras]
+extras = ["arrow", "cloudpickle", "enum34", "lz4", "numpy", "ruamel.yaml"]
+
+[[package]]
+name = "construct-typing"
+version = "0.6.2"
+description = "Extension for the python package 'construct' that adds typing features"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "construct-typing-0.6.2.tar.gz", hash = "sha256:948e998cfc003681dc34f2d071c3a688cf35b805cbe107febbc488ef967ccba1"},
+ {file = "construct_typing-0.6.2-py3-none-any.whl", hash = "sha256:ebea6989ac622d0c4eb457092cef0c7bfbcfa110bd018670fea7064d0bc09e47"},
+]
+
+[package.dependencies]
+construct = "2.10.68"
+typing-extensions = ">=4.6.0"
+
[[package]]
name = "cryptography"
version = "41.0.7"
@@ -884,79 +785,33 @@ files = [
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
]
-[[package]]
-name = "habluetooth"
-version = "2.2.0"
-description = "High availability Bluetooth"
-optional = false
-python-versions = ">=3.10,<3.13"
-files = [
- {file = "habluetooth-2.2.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:e3fa525f7c895a5f082d0e6fc2babf6a347b04d34463263ebbf7ceaad33a4daf"},
- {file = "habluetooth-2.2.0-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b7fa4b34eb7f57dcbb8762ce9c59f2bfd06c8f697c08ee27afacf6dfd49d7f59"},
- {file = "habluetooth-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f289708788ff7735ad32e63fde7827f435a25166eef84193fbd2f1d082a14ad"},
- {file = "habluetooth-2.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:076d1dd9240a983d6ea60ced98dba5e55015ac039462e639cb3c5bcbae101a9e"},
- {file = "habluetooth-2.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f0de72d1ec3295be2176b6972a4e3cf9c6ed1627d59ad85d3485feffee073d9c"},
- {file = "habluetooth-2.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1bc811aba8d0524df4574f17d0b9c3418068ab0c132060f85c3cce8577e49dbd"},
- {file = "habluetooth-2.2.0-cp310-cp310-win32.whl", hash = "sha256:472f374e23f49dcff7b2b4b0ff63b891300a217d475cd84addc7579e751cb474"},
- {file = "habluetooth-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:7d9113009de74e1bfa4ebf85ee325d375a1bbb6f224b4b3680791564071444e2"},
- {file = "habluetooth-2.2.0-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:6f9e1a6d7dbc3d7bead822db6fc9bb585a2d4b91523d306d119ad408a68ac056"},
- {file = "habluetooth-2.2.0-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:e9d369b1e1c7502d818f9bebb77e0dd7a1e358f8b6bafbf5e480c293e0ad06b3"},
- {file = "habluetooth-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab8dfc0e1532610347a07fef2a5b29dee217c42b4daca3a070d2f36d2c552240"},
- {file = "habluetooth-2.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f3c27f62fc529ed40698e4676a36eff92880d72d3159df464d611c1319678aeb"},
- {file = "habluetooth-2.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a2f117f44e9bee89ec9e971f05873ac5ad69b3728330a628000155b8a4b54a67"},
- {file = "habluetooth-2.2.0-cp311-cp311-win32.whl", hash = "sha256:6bb73712dd88181485c15bfd3ee13d279e455a13196e09f9b112fc93de07f338"},
- {file = "habluetooth-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:ea02b9b2d09fc7f0e1174860314ab0ced8d9b93377d49406c7bbafc1d5bf458a"},
- {file = "habluetooth-2.2.0-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b110797a071dc6cb23e63f0fad1b596b8d857f437347bb2763e284c9e9703b36"},
- {file = "habluetooth-2.2.0-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:1be517372c3788fe3eb47ec3b6588da961b7811e522a1aa960f504583132ffc3"},
- {file = "habluetooth-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afbd0564b6bb38dd0ec90ea3b63d159c05d917d1cade95367fc561549e5ba59"},
- {file = "habluetooth-2.2.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:596f0cc9dd7dedc2e93a7ed39fd81cbecd32af0fb4b704e6c8aa657ff936e030"},
- {file = "habluetooth-2.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f7a4132da52987c28866133ebecae9e3f1d4c15bb6f3e01f481e3f58995d881a"},
- {file = "habluetooth-2.2.0-cp312-cp312-win32.whl", hash = "sha256:e10fcefa939466d2f936b9c1f3a986c7c6bccae0186def292516fc3c6eda139b"},
- {file = "habluetooth-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:134562a06bb16a2c8b8a99dd0d0b1d88388478d6a5eb9e8f3826d76c01f65de8"},
- {file = "habluetooth-2.2.0-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:13d81dcdc63be75d932c70e6b62a0faf1dea4c616be4852ed9ee4c4b69d0dc6e"},
- {file = "habluetooth-2.2.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:c0dae2dbec2dbd52ece439d8967613625bd0f3fb17007e97d3da893fc1c18b8b"},
- {file = "habluetooth-2.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:971654936dfcd07003cd954ba28f5f947af59c55af07951c1bd9866894db5c8d"},
- {file = "habluetooth-2.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:42570c9459564ce14aa008dcd6f2d2722bb987a301d391e25de0a71a01ae0383"},
- {file = "habluetooth-2.2.0.tar.gz", hash = "sha256:003dcb6394b06ecb76b622e07ef0d66570c5bf55307cc54a0b0886c4fe174802"},
-]
-
-[package.dependencies]
-bleak = ">=0.21.1"
-bleak-retry-connector = ">=3.3.0"
-bluetooth-adapters = ">=0.16.1"
-bluetooth-auto-recovery = ">=1.2.3"
-bluetooth-data-tools = ">=1.16.0"
-
[[package]]
name = "home-assistant-bluetooth"
-version = "1.12.0"
+version = "1.10.4"
description = "Home Assistant Bluetooth Models and Helpers"
optional = false
-python-versions = ">=3.11,<3.13"
+python-versions = ">=3.9,<4.0"
files = [
- {file = "home_assistant_bluetooth-1.12.0-py3-none-any.whl", hash = "sha256:9b3cea07e50f0521d805a3fef102a338aaeb532576f100844a155b890ac97381"},
- {file = "home_assistant_bluetooth-1.12.0.tar.gz", hash = "sha256:9cac369fea11f67c1165df527f918a8c56630cbccb3c5cbe24b72f06aeb9f59b"},
+ {file = "home_assistant_bluetooth-1.10.4-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:7c3434bdec5dcfe733d3e7c56d4a24418fcd03718dc2e7707c9133d1e48145a8"},
+ {file = "home_assistant_bluetooth-1.10.4.tar.gz", hash = "sha256:21216b6be9d028bc232b9188ac4dce773798c6b4e47482cc3524bfc5f82515e3"},
]
-[package.dependencies]
-habluetooth = ">=0.11.0"
-
[[package]]
name = "homeassistant"
-version = "2024.1.3"
+version = "2023.12.4"
description = "Open-source home automation platform running on Python 3."
optional = false
python-versions = ">=3.11.0"
files = [
- {file = "homeassistant-2024.1.3-py3-none-any.whl", hash = "sha256:4f54b3dec0539eca5e2fa09f9a510222af82ce041f8aebdbd5f5732e558f3783"},
- {file = "homeassistant-2024.1.3.tar.gz", hash = "sha256:323d3469392e9a6b0fa54b50e62506f71389e2b6ba49fbbcba4970ae8317a32d"},
+ {file = "homeassistant-2023.12.4-py3-none-any.whl", hash = "sha256:0a521e712d126a88febe747cd4215838774c0954a518c8c314d0fde5082834be"},
+ {file = "homeassistant-2023.12.4.tar.gz", hash = "sha256:75e6b43da702cc25a1321da0c3f915247c180a84fbcc9e76a9341b1e6a9cc14f"},
]
[package.dependencies]
aiohttp = "3.9.1"
aiohttp-cors = "0.7.0"
aiohttp-fast-url-dispatcher = "0.3.0"
-aiohttp-zlib-ng = "0.1.3"
+aiohttp-zlib-ng = "0.1.1"
astral = "2.2"
atomicwrites-homeassistant = "1.4.1"
attrs = "23.1.0"
@@ -965,11 +820,11 @@ bcrypt = "4.0.1"
certifi = ">=2021.5.30"
ciso8601 = "2.3.0"
cryptography = "41.0.7"
-home-assistant-bluetooth = "1.12.0"
-httpx = "0.26.0"
+home-assistant-bluetooth = "1.10.4"
+httpx = "0.25.0"
ifaddr = "0.2.0"
Jinja2 = "3.1.2"
-lru-dict = "1.3.0"
+lru-dict = "1.2.0"
orjson = "3.9.9"
packaging = ">=23.1"
pip = ">=21.3.1"
@@ -978,63 +833,61 @@ pyOpenSSL = "23.2.0"
python-slugify = "4.0.1"
PyYAML = "6.0.1"
requests = "2.31.0"
-typing-extensions = ">=4.9.0,<5.0"
+typing-extensions = ">=4.8.0,<5.0"
ulid-transform = "0.9.0"
-urllib3 = ">=1.26.5,<2"
voluptuous = "0.13.1"
voluptuous-serialize = "2.6.0"
-yarl = "1.9.4"
+yarl = "1.9.2"
[[package]]
name = "homeassistant-stubs"
-version = "2024.1.3"
+version = "2023.12.4"
description = "PEP 484 typing stubs for Home Assistant Core"
optional = false
-python-versions = ">=3.11,<3.13"
+python-versions = ">=3.11,<4.0"
files = [
- {file = "homeassistant_stubs-2024.1.3-py3-none-any.whl", hash = "sha256:98879043e2f2e216097ca7200d83057b44764515ea2c0c9514dd52ea21841b09"},
- {file = "homeassistant_stubs-2024.1.3.tar.gz", hash = "sha256:20c660f341bc2d567379bd4cdb541ed6951534188e342bb502ce646c7c7c1cd4"},
+ {file = "homeassistant_stubs-2023.12.4-py3-none-any.whl", hash = "sha256:2e8083149cefa771c45279d5893a67cb932a39f3410a7f1ed5322ce5675d041d"},
+ {file = "homeassistant_stubs-2023.12.4.tar.gz", hash = "sha256:778867d768e5d9767e75525ffe48978fa3188b65b3af5efa17e404b85feedced"},
]
[package.dependencies]
-homeassistant = "2024.1.3"
+homeassistant = "2023.12.4"
[[package]]
name = "httpcore"
-version = "1.0.2"
+version = "0.18.0"
description = "A minimal low-level HTTP client."
optional = false
python-versions = ">=3.8"
files = [
- {file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"},
- {file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"},
+ {file = "httpcore-0.18.0-py3-none-any.whl", hash = "sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced"},
+ {file = "httpcore-0.18.0.tar.gz", hash = "sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9"},
]
[package.dependencies]
+anyio = ">=3.0,<5.0"
certifi = "*"
h11 = ">=0.13,<0.15"
+sniffio = "==1.*"
[package.extras]
-asyncio = ["anyio (>=4.0,<5.0)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
-trio = ["trio (>=0.22.0,<0.23.0)"]
[[package]]
name = "httpx"
-version = "0.26.0"
+version = "0.25.0"
description = "The next generation HTTP client."
optional = false
python-versions = ">=3.8"
files = [
- {file = "httpx-0.26.0-py3-none-any.whl", hash = "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd"},
- {file = "httpx-0.26.0.tar.gz", hash = "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf"},
+ {file = "httpx-0.25.0-py3-none-any.whl", hash = "sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100"},
+ {file = "httpx-0.25.0.tar.gz", hash = "sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875"},
]
[package.dependencies]
-anyio = "*"
certifi = "*"
-httpcore = "==1.*"
+httpcore = ">=0.18.0,<0.19.0"
idna = "*"
sniffio = "*"
@@ -1099,114 +952,98 @@ i18n = ["Babel (>=2.7)"]
[[package]]
name = "lru-dict"
-version = "1.3.0"
+version = "1.2.0"
description = "An Dict like LRU container."
optional = false
-python-versions = ">=3.8"
+python-versions = "*"
files = [
- {file = "lru-dict-1.3.0.tar.gz", hash = "sha256:54fd1966d6bd1fcde781596cb86068214edeebff1db13a2cea11079e3fd07b6b"},
- {file = "lru_dict-1.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4073333894db9840f066226d50e6f914a2240711c87d60885d8c940b69a6673f"},
- {file = "lru_dict-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0ad6361e4dd63b47b2fc8eab344198f37387e1da3dcfacfee19bafac3ec9f1eb"},
- {file = "lru_dict-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c637ab54b8cd9802fe19b260261e38820d748adf7606e34045d3c799b6dde813"},
- {file = "lru_dict-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fce5f95489ca1fc158cc9fe0f4866db9cec82c2be0470926a9080570392beaf"},
- {file = "lru_dict-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2bf2e24cf5f19c3ff69bf639306e83dced273e6fa775b04e190d7f5cd16f794"},
- {file = "lru_dict-1.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e90059f7701bef3c4da073d6e0434a9c7dc551d5adce30e6b99ef86b186f4b4a"},
- {file = "lru_dict-1.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ecb7ae557239c64077e9b26a142eb88e63cddb104111a5122de7bebbbd00098"},
- {file = "lru_dict-1.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6af36166d22dba851e06a13e35bbf33845d3dd88872e6aebbc8e3e7db70f4682"},
- {file = "lru_dict-1.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ee38d420c77eed548df47b7d74b5169a98e71c9e975596e31ab808e76d11f09"},
- {file = "lru_dict-1.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0e1845024c31e6ff246c9eb5e6f6f1a8bb564c06f8a7d6d031220044c081090b"},
- {file = "lru_dict-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3ca5474b1649555d014be1104e5558a92497509021a5ba5ea6e9b492303eb66b"},
- {file = "lru_dict-1.3.0-cp310-cp310-win32.whl", hash = "sha256:ebb03a9bd50c2ed86d4f72a54e0aae156d35a14075485b2127c4b01a3f4a63fa"},
- {file = "lru_dict-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:04cda617f4e4c27009005d0a8185ef02829b14b776d2791f5c994cc9d668bc24"},
- {file = "lru_dict-1.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:20c595764695d20bdc3ab9b582e0cc99814da183544afb83783a36d6741a0dac"},
- {file = "lru_dict-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d9b30a8f50c3fa72a494eca6be5810a1b5c89e4f0fda89374f0d1c5ad8d37d51"},
- {file = "lru_dict-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9710737584650a4251b9a566cbb1a86f83437adb209c9ba43a4e756d12faf0d7"},
- {file = "lru_dict-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b84c321ae34f2f40aae80e18b6fa08b31c90095792ab64bb99d2e385143effaa"},
- {file = "lru_dict-1.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eed24272b4121b7c22f234daed99899817d81d671b3ed030c876ac88bc9dc890"},
- {file = "lru_dict-1.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd13af06dab7c6ee92284fd02ed9a5613a07d5c1b41948dc8886e7207f86dfd"},
- {file = "lru_dict-1.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1efc59bfba6aac33684d87b9e02813b0e2445b2f1c444dae2a0b396ad0ed60c"},
- {file = "lru_dict-1.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfaf75ac574447afcf8ad998789071af11d2bcf6f947643231f692948839bd98"},
- {file = "lru_dict-1.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c95f8751e2abd6f778da0399c8e0239321d560dbc58cb063827123137d213242"},
- {file = "lru_dict-1.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:abd0c284b26b5c4ee806ca4f33ab5e16b4bf4d5ec9e093e75a6f6287acdde78e"},
- {file = "lru_dict-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a47740652b25900ac5ce52667b2eade28d8b5fdca0ccd3323459df710e8210a"},
- {file = "lru_dict-1.3.0-cp311-cp311-win32.whl", hash = "sha256:a690c23fc353681ed8042d9fe8f48f0fb79a57b9a45daea2f0be1eef8a1a4aa4"},
- {file = "lru_dict-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:efd3f4e0385d18f20f7ea6b08af2574c1bfaa5cb590102ef1bee781bdfba84bc"},
- {file = "lru_dict-1.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c279068f68af3b46a5d649855e1fb87f5705fe1f744a529d82b2885c0e1fc69d"},
- {file = "lru_dict-1.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:350e2233cfee9f326a0d7a08e309372d87186565e43a691b120006285a0ac549"},
- {file = "lru_dict-1.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4eafb188a84483b3231259bf19030859f070321b00326dcb8e8c6cbf7db4b12f"},
- {file = "lru_dict-1.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73593791047e36b37fdc0b67b76aeed439fcea80959c7d46201240f9ec3b2563"},
- {file = "lru_dict-1.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1958cb70b9542773d6241974646e5410e41ef32e5c9e437d44040d59bd80daf2"},
- {file = "lru_dict-1.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc1cd3ed2cee78a47f11f3b70be053903bda197a873fd146e25c60c8e5a32cd6"},
- {file = "lru_dict-1.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82eb230d48eaebd6977a92ddaa6d788f14cf4f4bcf5bbffa4ddfd60d051aa9d4"},
- {file = "lru_dict-1.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5ad659cbc349d0c9ba8e536b5f40f96a70c360f43323c29f4257f340d891531c"},
- {file = "lru_dict-1.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ba490b8972531d153ac0d4e421f60d793d71a2f4adbe2f7740b3c55dce0a12f1"},
- {file = "lru_dict-1.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:c0131351b8a7226c69f1eba5814cbc9d1d8daaf0fdec1ae3f30508e3de5262d4"},
- {file = "lru_dict-1.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0e88dba16695f17f41701269fa046197a3fd7b34a8dba744c8749303ddaa18df"},
- {file = "lru_dict-1.3.0-cp312-cp312-win32.whl", hash = "sha256:6ffaf595e625b388babc8e7d79b40f26c7485f61f16efe76764e32dce9ea17fc"},
- {file = "lru_dict-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf9da32ef2582434842ab6ba6e67290debfae72771255a8e8ab16f3e006de0aa"},
- {file = "lru_dict-1.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c265f16c936a8ff3bb4b8a4bda0be94c15ec28b63e99fdb1439c1ffe4cd437db"},
- {file = "lru_dict-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:784ca9d3b0730b3ec199c0a58f66264c63dd5d438119c739c349a6a9be8e5f6e"},
- {file = "lru_dict-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e13b2f58f647178470adaa14603bb64cc02eeed32601772ccea30e198252883c"},
- {file = "lru_dict-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ffbce5c2e80f57937679553c8f27e61ec327c962bf7ea0b15f1d74277fd5363"},
- {file = "lru_dict-1.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7969cb034b3ccc707aff877c73c225c32d7e2a7981baa8f92f5dd4d468fe8c33"},
- {file = "lru_dict-1.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca9ab676609cce85dd65d91c275e47da676d13d77faa72de286fbea30fbaa596"},
- {file = "lru_dict-1.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27c078b5d75989952acbf9b77e14c3dadc468a4aafe85174d548afbc5efc38b"},
- {file = "lru_dict-1.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6123aefe97762ad74215d05320a7f389f196f0594c8813534284d4eafeca1a96"},
- {file = "lru_dict-1.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cd869cadba9a63e1e7fe2dced4a5747d735135b86016b0a63e8c9e324ab629ac"},
- {file = "lru_dict-1.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:40a8daddc29c7edb09dfe44292cf111f1e93a8344349778721d430d336b50505"},
- {file = "lru_dict-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a03170e4152836987a88dcebde61aaeb73ab7099a00bb86509d45b3fe424230"},
- {file = "lru_dict-1.3.0-cp38-cp38-win32.whl", hash = "sha256:3b4f121afe10f5a82b8e317626eb1e1c325b3f104af56c9756064cd833b1950b"},
- {file = "lru_dict-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:1470f5828c7410e16c24b5150eb649647986e78924816e6fb0264049dea14a2b"},
- {file = "lru_dict-1.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a3c9f746a9917e784fffcedeac4c8c47a3dbd90cbe13b69e9140182ad97ce4b7"},
- {file = "lru_dict-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2789296819525a1f3204072dfcf3df6db8bcf69a8fc740ffd3de43a684ea7002"},
- {file = "lru_dict-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:170b66d29945391460351588a7bd8210a95407ae82efe0b855e945398a1d24ea"},
- {file = "lru_dict-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:774ca88501a9effe8797c3db5a6685cf20978c9cb0fe836b6813cfe1ca60d8c9"},
- {file = "lru_dict-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:df2e119c6ae412d2fd641a55f8a1e2e51f45a3de3449c18b1b86c319ab79e0c4"},
- {file = "lru_dict-1.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28aa1ea42a7e48174bf513dc2416fea7511a547961e678dc6f5670ca987c18cb"},
- {file = "lru_dict-1.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9537e1cee6fa582cb68f2fb9ce82d51faf2ccc0a638b275d033fdcb1478eb80b"},
- {file = "lru_dict-1.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:64545fca797fe2c68c5168efb5f976c6e1459e058cab02445207a079180a3557"},
- {file = "lru_dict-1.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a193a14c66cfc0c259d05dddc5e566a4b09e8f1765e941503d065008feebea9d"},
- {file = "lru_dict-1.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:3cb1de0ce4137b060abaafed8474cc0ebd12cedd88aaa7f7b3ebb1ddfba86ae0"},
- {file = "lru_dict-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8551ccab1349d4bebedab333dfc8693c74ff728f4b565fe15a6bf7d296bd7ea9"},
- {file = "lru_dict-1.3.0-cp39-cp39-win32.whl", hash = "sha256:6cb0be5e79c3f34d69b90d8559f0221e374b974b809a22377122c4b1a610ff67"},
- {file = "lru_dict-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9f725f2a0bdf1c18735372d5807af4ea3b77888208590394d4660e3d07971f21"},
- {file = "lru_dict-1.3.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f8f7824db5a64581180ab9d09842e6dd9fcdc46aac9cb592a0807cd37ea55680"},
- {file = "lru_dict-1.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acd04b7e7b0c0c192d738df9c317093335e7282c64c9d1bb6b7ebb54674b4e24"},
- {file = "lru_dict-1.3.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5c20f236f27551e3f0adbf1a987673fb1e9c38d6d284502cd38f5a3845ef681"},
- {file = "lru_dict-1.3.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca3703ff03b03a1848c563bc2663d0ad813c1cd42c4d9cf75b623716d4415d9a"},
- {file = "lru_dict-1.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a9fb71ba262c6058a0017ce83d343370d0a0dbe2ae62c2eef38241ec13219330"},
- {file = "lru_dict-1.3.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f5b88a7c39e307739a3701194993455968fcffe437d1facab93546b1b8a334c1"},
- {file = "lru_dict-1.3.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2682bfca24656fb7a643621520d57b7fe684ed5fa7be008704c1235d38e16a32"},
- {file = "lru_dict-1.3.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96fc87ddf569181827458ec5ad8fa446c4690cffacda66667de780f9fcefd44d"},
- {file = "lru_dict-1.3.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcec98e2c7da7631f0811730303abc4bdfe70d013f7a11e174a2ccd5612a7c59"},
- {file = "lru_dict-1.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6bba2863060caeaedd8386b0c8ee9a7ce4d57a7cb80ceeddf440b4eff2d013ba"},
- {file = "lru_dict-1.3.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c497fb60279f1e1d7dfbe150b1b069eaa43f7e172dab03f206282f4994676c5"},
- {file = "lru_dict-1.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d9509d817a47597988615c1a322580c10100acad10c98dfcf3abb41e0e5877f"},
- {file = "lru_dict-1.3.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0213ab4e3d9a8d386c18e485ad7b14b615cb6f05df6ef44fb2a0746c6ea9278b"},
- {file = "lru_dict-1.3.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b50fbd69cd3287196796ab4d50e4cc741eb5b5a01f89d8e930df08da3010c385"},
- {file = "lru_dict-1.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5247d1f011f92666010942434020ddc5a60951fefd5d12a594f0e5d9f43e3b3b"},
+ {file = "lru-dict-1.2.0.tar.gz", hash = "sha256:13c56782f19d68ddf4d8db0170041192859616514c706b126d0df2ec72a11bd7"},
+ {file = "lru_dict-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:de906e5486b5c053d15b7731583c25e3c9147c288ac8152a6d1f9bccdec72641"},
+ {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604d07c7604b20b3130405d137cae61579578b0e8377daae4125098feebcb970"},
+ {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:203b3e78d03d88f491fa134f85a42919020686b6e6f2d09759b2f5517260c651"},
+ {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:020b93870f8c7195774cbd94f033b96c14f51c57537969965c3af300331724fe"},
+ {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1184d91cfebd5d1e659d47f17a60185bbf621635ca56dcdc46c6a1745d25df5c"},
+ {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fc42882b554a86e564e0b662da47b8a4b32fa966920bd165e27bb8079a323bc1"},
+ {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:18ee88ada65bd2ffd483023be0fa1c0a6a051ef666d1cd89e921dcce134149f2"},
+ {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:756230c22257597b7557eaef7f90484c489e9ba78e5bb6ab5a5bcfb6b03cb075"},
+ {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c4da599af36618881748b5db457d937955bb2b4800db891647d46767d636c408"},
+ {file = "lru_dict-1.2.0-cp310-cp310-win32.whl", hash = "sha256:35a142a7d1a4fd5d5799cc4f8ab2fff50a598d8cee1d1c611f50722b3e27874f"},
+ {file = "lru_dict-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:6da5b8099766c4da3bf1ed6e7d7f5eff1681aff6b5987d1258a13bd2ed54f0c9"},
+ {file = "lru_dict-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b20b7c9beb481e92e07368ebfaa363ed7ef61e65ffe6e0edbdbaceb33e134124"},
+ {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22147367b296be31cc858bf167c448af02435cac44806b228c9be8117f1bfce4"},
+ {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a3091abeb95e707f381a8b5b7dc8e4ee016316c659c49b726857b0d6d1bd7a"},
+ {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:877801a20f05c467126b55338a4e9fa30e2a141eb7b0b740794571b7d619ee11"},
+ {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d3336e901acec897bcd318c42c2b93d5f1d038e67688f497045fc6bad2c0be7"},
+ {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8dafc481d2defb381f19b22cc51837e8a42631e98e34b9e0892245cc96593deb"},
+ {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:87bbad3f5c3de8897b8c1263a9af73bbb6469fb90e7b57225dad89b8ef62cd8d"},
+ {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:25f9e0bc2fe8f41c2711ccefd2871f8a5f50a39e6293b68c3dec576112937aad"},
+ {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ae301c282a499dc1968dd633cfef8771dd84228ae9d40002a3ea990e4ff0c469"},
+ {file = "lru_dict-1.2.0-cp311-cp311-win32.whl", hash = "sha256:c9617583173a29048e11397f165501edc5ae223504a404b2532a212a71ecc9ed"},
+ {file = "lru_dict-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6b7a031e47421d4b7aa626b8c91c180a9f037f89e5d0a71c4bb7afcf4036c774"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ea2ac3f7a7a2f32f194c84d82a034e66780057fd908b421becd2f173504d040e"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd46c94966f631a81ffe33eee928db58e9fbee15baba5923d284aeadc0e0fa76"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:086ce993414f0b28530ded7e004c77dc57c5748fa6da488602aa6e7f79e6210e"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df25a426446197488a6702954dcc1de511deee20c9db730499a2aa83fddf0df1"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c53b12b89bd7a6c79f0536ff0d0a84fdf4ab5f6252d94b24b9b753bd9ada2ddf"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f9484016e6765bd295708cccc9def49f708ce07ac003808f69efa386633affb9"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d0f7ec902a0097ac39f1922c89be9eaccf00eb87751e28915320b4f72912d057"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:981ef3edc82da38d39eb60eae225b88a538d47b90cce2e5808846fd2cf64384b"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e25b2e90a032dc248213af7f3f3e975e1934b204f3b16aeeaeaff27a3b65e128"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-win32.whl", hash = "sha256:59f3df78e94e07959f17764e7fa7ca6b54e9296953d2626a112eab08e1beb2db"},
+ {file = "lru_dict-1.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:de24b47159e07833aeab517d9cb1c3c5c2d6445cc378b1c2f1d8d15fb4841d63"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d0dd4cd58220351233002f910e35cc01d30337696b55c6578f71318b137770f9"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a87bdc291718bbdf9ea4be12ae7af26cbf0706fa62c2ac332748e3116c5510a7"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05fb8744f91f58479cbe07ed80ada6696ec7df21ea1740891d4107a8dd99a970"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00f6e8a3fc91481b40395316a14c94daa0f0a5de62e7e01a7d589f8d29224052"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b172fce0a0ffc0fa6d282c14256d5a68b5db1e64719c2915e69084c4b6bf555"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e707d93bae8f0a14e6df1ae8b0f076532b35f00e691995f33132d806a88e5c18"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b9ec7a4a0d6b8297102aa56758434fb1fca276a82ed7362e37817407185c3abb"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f404dcc8172da1f28da9b1f0087009578e608a4899b96d244925c4f463201f2a"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1171ad3bff32aa8086778be4a3bdff595cc2692e78685bcce9cb06b96b22dcc2"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-win32.whl", hash = "sha256:0c316dfa3897fabaa1fe08aae89352a3b109e5f88b25529bc01e98ac029bf878"},
+ {file = "lru_dict-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5919dd04446bc1ee8d6ecda2187deeebfff5903538ae71083e069bc678599446"},
+ {file = "lru_dict-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fbf36c5a220a85187cacc1fcb7dd87070e04b5fc28df7a43f6842f7c8224a388"},
+ {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:712e71b64da181e1c0a2eaa76cd860265980cd15cb0e0498602b8aa35d5db9f8"},
+ {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f54908bf91280a9b8fa6a8c8f3c2f65850ce6acae2852bbe292391628ebca42f"},
+ {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3838e33710935da2ade1dd404a8b936d571e29268a70ff4ca5ba758abb3850df"},
+ {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5d5a5f976b39af73324f2b793862859902ccb9542621856d51a5993064f25e4"},
+ {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8bda3a9afd241ee0181661decaae25e5336ce513ac268ab57da737eacaa7871f"},
+ {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bd2cd1b998ea4c8c1dad829fc4fa88aeed4dee555b5e03c132fc618e6123f168"},
+ {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b55753ee23028ba8644fd22e50de7b8f85fa60b562a0fafaad788701d6131ff8"},
+ {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7e51fa6a203fa91d415f3b2900e5748ec8e06ad75777c98cc3aeb3983ca416d7"},
+ {file = "lru_dict-1.2.0-cp38-cp38-win32.whl", hash = "sha256:cd6806313606559e6c7adfa0dbeb30fc5ab625f00958c3d93f84831e7a32b71e"},
+ {file = "lru_dict-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d90a70c53b0566084447c3ef9374cc5a9be886e867b36f89495f211baabd322"},
+ {file = "lru_dict-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3ea7571b6bf2090a85ff037e6593bbafe1a8598d5c3b4560eb56187bcccb4dc"},
+ {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:287c2115a59c1c9ed0d5d8ae7671e594b1206c36ea9df2fca6b17b86c468ff99"},
+ {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5ccfd2291c93746a286c87c3f895165b697399969d24c54804ec3ec559d4e43"},
+ {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b710f0f4d7ec4f9fa89dfde7002f80bcd77de8024017e70706b0911ea086e2ef"},
+ {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5345bf50e127bd2767e9fd42393635bbc0146eac01f6baf6ef12c332d1a6a329"},
+ {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:291d13f85224551913a78fe695cde04cbca9dcb1d84c540167c443eb913603c9"},
+ {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d5bb41bc74b321789803d45b124fc2145c1b3353b4ad43296d9d1d242574969b"},
+ {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0facf49b053bf4926d92d8d5a46fe07eecd2af0441add0182c7432d53d6da667"},
+ {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:987b73a06bcf5a95d7dc296241c6b1f9bc6cda42586948c9dabf386dc2bef1cd"},
+ {file = "lru_dict-1.2.0-cp39-cp39-win32.whl", hash = "sha256:231d7608f029dda42f9610e5723614a35b1fff035a8060cf7d2be19f1711ace8"},
+ {file = "lru_dict-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:71da89e134747e20ed5b8ad5b4ee93fc5b31022c2b71e8176e73c5a44699061b"},
+ {file = "lru_dict-1.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:21b3090928c7b6cec509e755cc3ab742154b33660a9b433923bd12c37c448e3e"},
+ {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaecd7085212d0aa4cd855f38b9d61803d6509731138bf798a9594745953245b"},
+ {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ead83ac59a29d6439ddff46e205ce32f8b7f71a6bd8062347f77e232825e3d0a"},
+ {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:312b6b2a30188586fe71358f0f33e4bac882d33f5e5019b26f084363f42f986f"},
+ {file = "lru_dict-1.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b30122e098c80e36d0117810d46459a46313421ce3298709170b687dc1240b02"},
+ {file = "lru_dict-1.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f010cfad3ab10676e44dc72a813c968cd586f37b466d27cde73d1f7f1ba158c2"},
+ {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20f5f411f7751ad9a2c02e80287cedf69ae032edd321fe696e310d32dd30a1f8"},
+ {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afdadd73304c9befaed02eb42f5f09fdc16288de0a08b32b8080f0f0f6350aa6"},
+ {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7ab0c10c4fa99dc9e26b04e6b62ac32d2bcaea3aad9b81ec8ce9a7aa32b7b1b"},
+ {file = "lru_dict-1.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:edad398d5d402c43d2adada390dd83c74e46e020945ff4df801166047013617e"},
+ {file = "lru_dict-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:91d577a11b84387013815b1ad0bb6e604558d646003b44c92b3ddf886ad0f879"},
+ {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb12f19cdf9c4f2d9aa259562e19b188ff34afab28dd9509ff32a3f1c2c29326"},
+ {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e4c85aa8844bdca3c8abac3b7f78da1531c74e9f8b3e4890c6e6d86a5a3f6c0"},
+ {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c6acbd097b15bead4de8e83e8a1030bb4d8257723669097eac643a301a952f0"},
+ {file = "lru_dict-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b6613daa851745dd22b860651de930275be9d3e9373283a2164992abacb75b62"},
]
[package.extras]
test = ["pytest"]
-[[package]]
-name = "mac-vendor-lookup"
-version = "0.1.12"
-description = "Find the vendor for a given MAC address"
-optional = false
-python-versions = "<4, >=3.5"
-files = [
- {file = "mac_vendor_lookup-0.1.12-py3-none-any.whl", hash = "sha256:aeec6eac01b07e6558d889b51f475a1e1e938e09cab409a069ab6a43b13cba58"},
-]
-
-[package.dependencies]
-aiofiles = "*"
-aiohttp = "*"
-
-[package.extras]
-test = ["coverage", "pytest"]
-
[[package]]
name = "markupsafe"
version = "2.1.3"
@@ -1654,16 +1491,6 @@ cryptography = ">=38.0.0,<40.0.0 || >40.0.0,<40.0.1 || >40.0.1,<42"
docs = ["sphinx (!=5.2.0,!=5.2.0.post0)", "sphinx-rtd-theme"]
test = ["flaky", "pretend", "pytest (>=3.0.1)"]
-[[package]]
-name = "pyric"
-version = "0.1.6.3"
-description = "Python Wireless Library"
-optional = false
-python-versions = "*"
-files = [
- {file = "PyRIC-0.1.6.3.tar.gz", hash = "sha256:b539b01cafebd2406c00097f94525ea0f8ecd1dd92f7731f43eac0ef16c2ccc9"},
-]
-
[[package]]
name = "python-slugify"
version = "4.0.1"
@@ -1874,30 +1701,19 @@ files = [
[[package]]
name = "urllib3"
-version = "1.26.18"
+version = "2.1.0"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+python-versions = ">=3.8"
files = [
- {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"},
- {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"},
+ {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"},
+ {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"},
]
[package.extras]
-brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
-secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
-socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
-
-[[package]]
-name = "usb-devices"
-version = "0.4.5"
-description = "Tools for mapping, describing, and resetting USB devices"
-optional = false
-python-versions = ">=3.9,<4.0"
-files = [
- {file = "usb_devices-0.4.5-py3-none-any.whl", hash = "sha256:8a415219ef1395e25aa0bddcad484c88edf9673acdeae8a07223ca7222a01dcf"},
- {file = "usb_devices-0.4.5.tar.gz", hash = "sha256:9b5c7606df2bc791c6c45b7f76244a0cbed83cb6fa4c68791a143c03345e195d"},
-]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "virtualenv"
@@ -2179,101 +1995,85 @@ all = ["winrt-Windows.Foundation.Collections[all] (==2.0.0-beta.1)", "winrt-Wind
[[package]]
name = "yarl"
-version = "1.9.4"
+version = "1.9.2"
description = "Yet another URL library"
optional = false
python-versions = ">=3.7"
files = [
- {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"},
- {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"},
- {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"},
- {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"},
- {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"},
- {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"},
- {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"},
- {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"},
- {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"},
- {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"},
- {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"},
- {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"},
- {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"},
- {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"},
- {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"},
- {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"},
- {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"},
- {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"},
- {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"},
- {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"},
- {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"},
- {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"},
- {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"},
- {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"},
- {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"},
- {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"},
- {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"},
- {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"},
- {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"},
- {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"},
+ {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"},
+ {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"},
+ {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"},
+ {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"},
+ {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"},
+ {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"},
+ {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"},
+ {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"},
+ {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"},
+ {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"},
+ {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"},
+ {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"},
+ {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"},
+ {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"},
+ {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"},
+ {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"},
+ {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"},
+ {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"},
+ {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"},
+ {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"},
+ {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"},
+ {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"},
+ {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"},
+ {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"},
+ {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"},
+ {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"},
+ {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"},
+ {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"},
+ {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"},
+ {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"},
+ {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"},
+ {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"},
+ {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"},
+ {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"},
+ {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"},
+ {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"},
+ {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"},
+ {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"},
+ {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"},
+ {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"},
+ {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"},
+ {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"},
+ {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"},
+ {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"},
+ {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"},
+ {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"},
+ {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"},
+ {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"},
+ {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"},
+ {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"},
+ {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"},
+ {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"},
+ {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"},
+ {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"},
+ {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"},
+ {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"},
+ {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"},
+ {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"},
+ {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"},
+ {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"},
+ {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"},
+ {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"},
+ {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"},
+ {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"},
+ {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"},
+ {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"},
+ {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"},
+ {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"},
+ {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"},
+ {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"},
+ {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"},
+ {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"},
+ {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"},
+ {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"},
]
[package.dependencies]
@@ -2335,4 +2135,4 @@ files = [
[metadata]
lock-version = "2.0"
python-versions = ">=3.11,<3.13"
-content-hash = "9d8fdf861ef5cac372e08a86853a61cceaa79b201e221e94bd456d4aef504f54"
+content-hash = "4f1c7cd12b29dfc7a6e32a43ee39b0f1c0f0ffeb0c872e13538c20bf5ce8ba75"
diff --git a/pyproject.toml b/pyproject.toml
index 5e2fd30..914971e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,17 +4,23 @@ version = "0.0.0"
description = ""
authors = ["David Buezas, Lennard Beers"]
readme = "README.md"
+repository = "https://github.com/dbuezas/eq3btsmart"
+packages = [
+ { include = "eq3btsmart" }
+]
[tool.poetry.dependencies]
python = ">=3.11,<3.13"
-
+bleak = "^0.21.1"
+construct = "^2.10.68"
+construct-typing = "^0.6.2"
+homeassistant = "^2023.1.1"
[tool.poetry.group.dev.dependencies]
ruff = "^0.1.13"
mypy = "^1.8.0"
pre-commit = "^3.6.0"
-homeassistant = "^2024.1.3"
-homeassistant-stubs = "^2024.1.3"
+homeassistant-stubs = "^2023.1.1"
voluptuous-stubs = "^0.1.1"
[build-system]