pyvesync 3.0.0b3__tar.gz → 3.0.0b4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyvesync-3.0.0b3/src/pyvesync.egg-info → pyvesync-3.0.0b4}/PKG-INFO +18 -1
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/README.md +17 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/pyproject.toml +1 -1
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/purifier_base.py +1 -1
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/switch_base.py +1 -1
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/const.py +1 -1
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/vesyncbulb.py +1 -1
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/vesyncfan.py +14 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/vesynchumidifier.py +2 -2
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/vesyncoutlet.py +2 -2
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/vesyncswitch.py +2 -4
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/vesync_models.py +10 -23
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/vesync.py +5 -5
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4/src/pyvesync.egg-info}/PKG-INFO +18 -1
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/LICENSE +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/MANIFEST.in +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/requirements.txt +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/setup.cfg +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/setup.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/__init__.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/__init__.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/bulb_base.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/fan_base.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/fryer_base.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/humidifier_base.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/outlet_base.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/thermostat_base.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/base_devices/vesyncbasedevice.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/device_container.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/device_map.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/__init__.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/vesynckitchen.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/vesyncpurifier.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/devices/vesyncthermostat.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/__init__.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/base_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/bulb_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/bypass_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/fan_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/fryer_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/home_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/humidifier_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/outlet_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/purifier_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/switch_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/models/thermostat_models.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/utils/__init__.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/utils/colors.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/utils/device_mixins.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/utils/enum_utils.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/utils/errors.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/utils/helpers.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/utils/logs.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync/vesynchome.py +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync.egg-info/SOURCES.txt +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync.egg-info/dependency_links.txt +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync.egg-info/requires.txt +0 -0
- {pyvesync-3.0.0b3 → pyvesync-3.0.0b4}/src/pyvesync.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyvesync
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0b4
|
|
4
4
|
Summary: pyvesync is a library to manage Etekcity Devices, Cosori Air Fryers, and Levoit Air Purifiers run on the VeSync app.
|
|
5
5
|
Author: Mark Perdue
|
|
6
6
|
Author-email: Joe Trabulsy <webdjoe@gmail.com>
|
|
@@ -525,3 +525,20 @@ After:
|
|
|
525
525
|
All [contributions](CONTRIBUTING.md) are welcome.
|
|
526
526
|
|
|
527
527
|
This project is licensed under [MIT](LICENSE).
|
|
528
|
+
|
|
529
|
+
## Contributors
|
|
530
|
+
|
|
531
|
+
This is an open source project and cannot exist without the contributions of its community. Thank you to all the contributors who have helped make this project better!
|
|
532
|
+
|
|
533
|
+
A special thanks for helping with V3 go live:
|
|
534
|
+
|
|
535
|
+
| [<img src="https://github.com/cdninja.png" width="60px;"/><br /><sub><a href="https://github.com/cdninja">cdninja</a></sub>](https://github.com/cdninja) | [<img src="https://github.com/sapuseven.png" width="60px;"/><br /><sub><a href="https://github.com/sapuseven">sapuseven</a></sub>](https://github.com/sapuseven) | [<img src="https://github.com/sdrapha.png" width="60px;"/><br /><sub><a href="https://github.com/sdrapha">sdrapha</a></sub>](https://github.com/sdrapha) |
|
|
536
|
+
| :------- | :------- | :------- |
|
|
537
|
+
|
|
538
|
+
And to all of those that contributed to the project:
|
|
539
|
+
|
|
540
|
+
<a href="https://github.com/webdjoe/pyvesync/graphs/contributors">
|
|
541
|
+
<img src="https://contrib.rocks/image?repo=webdjoe/pyvesync" />
|
|
542
|
+
</a>
|
|
543
|
+
|
|
544
|
+
Made with [contrib.rocks](https://contrib.rocks).
|
|
@@ -494,3 +494,20 @@ After:
|
|
|
494
494
|
All [contributions](CONTRIBUTING.md) are welcome.
|
|
495
495
|
|
|
496
496
|
This project is licensed under [MIT](LICENSE).
|
|
497
|
+
|
|
498
|
+
## Contributors
|
|
499
|
+
|
|
500
|
+
This is an open source project and cannot exist without the contributions of its community. Thank you to all the contributors who have helped make this project better!
|
|
501
|
+
|
|
502
|
+
A special thanks for helping with V3 go live:
|
|
503
|
+
|
|
504
|
+
| [<img src="https://github.com/cdninja.png" width="60px;"/><br /><sub><a href="https://github.com/cdninja">cdninja</a></sub>](https://github.com/cdninja) | [<img src="https://github.com/sapuseven.png" width="60px;"/><br /><sub><a href="https://github.com/sapuseven">sapuseven</a></sub>](https://github.com/sapuseven) | [<img src="https://github.com/sdrapha.png" width="60px;"/><br /><sub><a href="https://github.com/sdrapha">sdrapha</a></sub>](https://github.com/sdrapha) |
|
|
505
|
+
| :------- | :------- | :------- |
|
|
506
|
+
|
|
507
|
+
And to all of those that contributed to the project:
|
|
508
|
+
|
|
509
|
+
<a href="https://github.com/webdjoe/pyvesync/graphs/contributors">
|
|
510
|
+
<img src="https://contrib.rocks/image?repo=webdjoe/pyvesync" />
|
|
511
|
+
</a>
|
|
512
|
+
|
|
513
|
+
Made with [contrib.rocks](https://contrib.rocks).
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyvesync"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.0.0b4"
|
|
8
8
|
description = "pyvesync is a library to manage Etekcity Devices, Cosori Air Fryers, and Levoit Air Purifiers run on the VeSync app."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -125,7 +125,7 @@ class PurifierState(DeviceState):
|
|
|
125
125
|
@air_quality_level.setter
|
|
126
126
|
def air_quality_level(self, value: int | None) -> None:
|
|
127
127
|
"""Set air quality level."""
|
|
128
|
-
if isinstance(value,
|
|
128
|
+
if isinstance(value, int):
|
|
129
129
|
self._air_quality_level = AirQualityLevel.from_int(value)
|
|
130
130
|
|
|
131
131
|
def set_air_quality_level(self, value: int | str | None) -> None:
|
|
@@ -102,7 +102,7 @@ class VeSyncSwitch(VeSyncBaseToggleDevice):
|
|
|
102
102
|
"""Etekcity Switch Base Class.
|
|
103
103
|
|
|
104
104
|
Abstract Base Class for Etekcity Switch Devices, inheriting from
|
|
105
|
-
pyvesync.vesyncbasedevice.VeSyncBaseDevice. Should not be instantiated directly,
|
|
105
|
+
pyvesync.base_devices.vesyncbasedevice.VeSyncBaseDevice. Should not be instantiated directly,
|
|
106
106
|
subclassed by VeSyncWallSwitch and VeSyncDimmerSwitch.
|
|
107
107
|
|
|
108
108
|
Attributes:
|
|
@@ -45,7 +45,7 @@ DEFAULT_TZ = "America/New_York"
|
|
|
45
45
|
DEFAULT_REGION = "US"
|
|
46
46
|
APP_VERSION = "5.6.60"
|
|
47
47
|
APP_ID = ''.join(choices(string.ascii_lowercase + string.digits, k=8)) # noqa: S311
|
|
48
|
-
PHONE_BRAND = "
|
|
48
|
+
PHONE_BRAND = "pyvesync"
|
|
49
49
|
PHONE_OS = "Android"
|
|
50
50
|
# MOBILE_ID = "1234567890123456"
|
|
51
51
|
MOBILE_ID = str(randint(1000000000000000, 9999999999999999)) # noqa: S311
|
|
@@ -15,7 +15,7 @@ from __future__ import annotations
|
|
|
15
15
|
import logging
|
|
16
16
|
from collections.abc import Mapping
|
|
17
17
|
from typing import TYPE_CHECKING
|
|
18
|
-
from
|
|
18
|
+
from typing_extensions import deprecated
|
|
19
19
|
from pyvesync.base_devices import VeSyncBulb
|
|
20
20
|
from pyvesync.const import DeviceStatus, ConnectionStatus
|
|
21
21
|
from pyvesync.models.base_models import DefaultValues
|
|
@@ -125,6 +125,20 @@ class VeSyncTowerFan(BypassV2Mixin, VeSyncFanBase):
|
|
|
125
125
|
self.state.connection_status = ConnectionStatus.ONLINE
|
|
126
126
|
return True
|
|
127
127
|
|
|
128
|
+
async def toggle_switch(self, toggle: bool | None = None) -> bool:
|
|
129
|
+
payload_data = {
|
|
130
|
+
'powerSwitch': int(toggle),
|
|
131
|
+
'switchIdx': 0,
|
|
132
|
+
}
|
|
133
|
+
r_dict = await self.call_bypassv2_api("setSwitch", payload_data)
|
|
134
|
+
r = Helpers.process_dev_response(logger, "toggle_switch", self, r_dict)
|
|
135
|
+
if r is None:
|
|
136
|
+
return False
|
|
137
|
+
|
|
138
|
+
self.state.device_status = DeviceStatus.from_bool(toggle)
|
|
139
|
+
self.state.connection_status = ConnectionStatus.ONLINE
|
|
140
|
+
return True
|
|
141
|
+
|
|
128
142
|
async def toggle_oscillation(self, toggle: bool) -> bool:
|
|
129
143
|
payload_data = {
|
|
130
144
|
"oscillationSwitch": int(toggle)
|
|
@@ -246,7 +246,7 @@ class VeSyncHumid200300S(BypassV2Mixin, VeSyncHumidifier):
|
|
|
246
246
|
self.device_name, self.device_type)
|
|
247
247
|
return False
|
|
248
248
|
|
|
249
|
-
if Validators.validate_zero_to_hundred(brightness):
|
|
249
|
+
if not Validators.validate_zero_to_hundred(brightness):
|
|
250
250
|
logger.debug("Brightness value must be set between 0 and 100")
|
|
251
251
|
return False
|
|
252
252
|
|
|
@@ -666,7 +666,7 @@ class VeSyncHumid1000S(VeSyncHumid200300S):
|
|
|
666
666
|
|
|
667
667
|
self._set_state(r_model)
|
|
668
668
|
|
|
669
|
-
@deprecated("Use
|
|
669
|
+
@deprecated("Use toggle_display() instead.")
|
|
670
670
|
async def set_display(self, toggle: bool) -> bool:
|
|
671
671
|
"""Toggle display on/off.
|
|
672
672
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
import logging
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
|
-
from
|
|
6
|
+
from typing_extensions import deprecated
|
|
7
7
|
|
|
8
8
|
from pyvesync.utils.helpers import Helpers, Timer
|
|
9
9
|
from pyvesync.utils.logs import LibraryLogger
|
|
@@ -620,7 +620,7 @@ class VeSyncOutdoorPlug(BypassV1Mixin, VeSyncOutlet):
|
|
|
620
620
|
if int(self.sub_device_no) == int(outlet.subDeviceNo):
|
|
621
621
|
self.state.device_status = outlet.subDeviceStatus
|
|
622
622
|
|
|
623
|
-
@deprecated(
|
|
623
|
+
@deprecated("Use toggle_switch(toggle: bool | None) instead")
|
|
624
624
|
async def toggle(self, status: str) -> bool:
|
|
625
625
|
"""Deprecated, use toggle_switch() instead."""
|
|
626
626
|
toggle = status != DeviceStatus.ON
|
|
@@ -25,7 +25,7 @@ from dataclasses import asdict
|
|
|
25
25
|
import logging
|
|
26
26
|
# from abc import ABCMeta, abstractmethod
|
|
27
27
|
from typing import TYPE_CHECKING
|
|
28
|
-
from
|
|
28
|
+
from typing_extensions import deprecated
|
|
29
29
|
|
|
30
30
|
from pyvesync.base_devices.switch_base import VeSyncSwitch
|
|
31
31
|
from pyvesync.utils.colors import Color
|
|
@@ -265,9 +265,7 @@ class VeSyncDimmerSwitch(BypassV1Mixin, VeSyncSwitch):
|
|
|
265
265
|
self.state.indicator_status = result.indicatorlightStatus
|
|
266
266
|
self.state.device_status = result.deviceStatus
|
|
267
267
|
|
|
268
|
-
@deprecated(
|
|
269
|
-
reason="switch_toggle() deprecated, use toggle_switch(toggle: bool | None = None)"
|
|
270
|
-
)
|
|
268
|
+
@deprecated("switch_toggle() deprecated, use toggle_switch(toggle: bool | None = None)")
|
|
271
269
|
async def switch_toggle(self, status: str) -> bool:
|
|
272
270
|
"""Toggle switch status."""
|
|
273
271
|
return await self.toggle_switch(status == DeviceStatus.ON)
|
|
@@ -206,7 +206,7 @@ def _flatten_device_prop(d: dict[str, Any]) -> dict[str, Any]:
|
|
|
206
206
|
d['connectionStatus'] = device_prop['connectionStatus']
|
|
207
207
|
if device_prop.get('wifiMac') is not None:
|
|
208
208
|
d['macID'] = device_prop['wifiMac']
|
|
209
|
-
|
|
209
|
+
d.pop("deviceProp", None)
|
|
210
210
|
return d
|
|
211
211
|
|
|
212
212
|
|
|
@@ -230,38 +230,25 @@ class ResponseDeviceDetailsModel(ResponseBaseModel):
|
|
|
230
230
|
type: str
|
|
231
231
|
uuid: str | None
|
|
232
232
|
configModule: str
|
|
233
|
-
macID: str
|
|
234
|
-
mode: str
|
|
235
|
-
speed: str | None
|
|
236
|
-
currentFirmVersion: str
|
|
237
|
-
subDeviceType: str | None
|
|
238
|
-
subDeviceList:
|
|
239
|
-
extension:
|
|
233
|
+
macID: str = ""
|
|
234
|
+
mode: str = ""
|
|
235
|
+
speed: str | None = None
|
|
236
|
+
currentFirmVersion: str | None = None
|
|
237
|
+
subDeviceType: str | None = None
|
|
238
|
+
subDeviceList: str | None = None
|
|
239
|
+
extension: InternalDeviceListExtension | None = None
|
|
240
240
|
subDeviceNo: int | None = None
|
|
241
241
|
deviceStatus: str = "off"
|
|
242
242
|
connectionStatus: str = "offline"
|
|
243
243
|
productType: str | None = None
|
|
244
|
-
# deviceProp: InitVar[None | InternalDevicePropModel] = None
|
|
245
|
-
|
|
246
|
-
# def __post_init__(self, deviceProp: None | IntRespDevicePropModel) -> None:
|
|
247
|
-
# """Set productType based on deviceType."""
|
|
248
|
-
# if deviceProp is not None:
|
|
249
|
-
# if deviceProp.powerSwitch == 1:
|
|
250
|
-
# self.deviceStatus = "on"
|
|
251
|
-
# elif deviceProp.powerSwitch == 0:
|
|
252
|
-
# self.deviceStatus = "off"
|
|
253
|
-
# if isinstance(deviceProp.connectionStatus, str) and \
|
|
254
|
-
# self.connectionStatus != deviceProp.connectionStatus:
|
|
255
|
-
# self.connectionStatus = deviceProp.connectionStatus
|
|
256
244
|
|
|
257
245
|
@classmethod
|
|
258
246
|
def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]:
|
|
259
247
|
"""Perform device_list pre-deserialization processes.
|
|
260
248
|
|
|
261
249
|
This performs the following:
|
|
262
|
-
- Flattens the deviceProp field into deviceStatus and
|
|
263
|
-
- Sets
|
|
264
|
-
- Sets cid to uuid or macID if null
|
|
250
|
+
- Flattens the `deviceProp` field into `deviceStatus`, `connectionStatus` and `macID`
|
|
251
|
+
- Sets `cid` to `uuid` or `macID` if null
|
|
265
252
|
"""
|
|
266
253
|
super().__pre_deserialize__(d)
|
|
267
254
|
d = _flatten_device_prop(d)
|
|
@@ -79,7 +79,9 @@ class VeSync: # pylint: disable=function-redefined
|
|
|
79
79
|
password: str,
|
|
80
80
|
country_code: str = DEFAULT_REGION,
|
|
81
81
|
session: ClientSession | None = None,
|
|
82
|
-
time_zone: str = DEFAULT_TZ
|
|
82
|
+
time_zone: str = DEFAULT_TZ,
|
|
83
|
+
debug: bool = False,
|
|
84
|
+
redact: bool = True) -> None:
|
|
83
85
|
"""Initialize VeSync Manager.
|
|
84
86
|
|
|
85
87
|
This class is used as the manager for all VeSync objects, all methods and
|
|
@@ -138,10 +140,8 @@ class VeSync: # pylint: disable=function-redefined
|
|
|
138
140
|
"""
|
|
139
141
|
self.session = session
|
|
140
142
|
self._close_session = False
|
|
141
|
-
self._debug =
|
|
142
|
-
self.
|
|
143
|
-
if self._redact:
|
|
144
|
-
self.redact = self.redact
|
|
143
|
+
self._debug = debug
|
|
144
|
+
self.redact = redact
|
|
145
145
|
self.username: str = username
|
|
146
146
|
self.password: str = password
|
|
147
147
|
self._token: str | None = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyvesync
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0b4
|
|
4
4
|
Summary: pyvesync is a library to manage Etekcity Devices, Cosori Air Fryers, and Levoit Air Purifiers run on the VeSync app.
|
|
5
5
|
Author: Mark Perdue
|
|
6
6
|
Author-email: Joe Trabulsy <webdjoe@gmail.com>
|
|
@@ -525,3 +525,20 @@ After:
|
|
|
525
525
|
All [contributions](CONTRIBUTING.md) are welcome.
|
|
526
526
|
|
|
527
527
|
This project is licensed under [MIT](LICENSE).
|
|
528
|
+
|
|
529
|
+
## Contributors
|
|
530
|
+
|
|
531
|
+
This is an open source project and cannot exist without the contributions of its community. Thank you to all the contributors who have helped make this project better!
|
|
532
|
+
|
|
533
|
+
A special thanks for helping with V3 go live:
|
|
534
|
+
|
|
535
|
+
| [<img src="https://github.com/cdninja.png" width="60px;"/><br /><sub><a href="https://github.com/cdninja">cdninja</a></sub>](https://github.com/cdninja) | [<img src="https://github.com/sapuseven.png" width="60px;"/><br /><sub><a href="https://github.com/sapuseven">sapuseven</a></sub>](https://github.com/sapuseven) | [<img src="https://github.com/sdrapha.png" width="60px;"/><br /><sub><a href="https://github.com/sdrapha">sdrapha</a></sub>](https://github.com/sdrapha) |
|
|
536
|
+
| :------- | :------- | :------- |
|
|
537
|
+
|
|
538
|
+
And to all of those that contributed to the project:
|
|
539
|
+
|
|
540
|
+
<a href="https://github.com/webdjoe/pyvesync/graphs/contributors">
|
|
541
|
+
<img src="https://contrib.rocks/image?repo=webdjoe/pyvesync" />
|
|
542
|
+
</a>
|
|
543
|
+
|
|
544
|
+
Made with [contrib.rocks](https://contrib.rocks).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|