wyzeapy 0.5.30__tar.gz → 0.5.31rc1__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.
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.github/CODEOWNERS +3 -3
- wyzeapy-0.5.31rc1/.github/workflows/auto-assign.yml +22 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.github/workflows/codeql.yml +4 -4
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.github/workflows/lint.yml +3 -3
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.github/workflows/pre-release.yml +3 -3
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.github/workflows/publish.yml +3 -3
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.github/workflows/test.yml +4 -4
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/PKG-INFO +3 -3
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/README.md +3 -3
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/pyproject.toml +4 -4
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/__init__.py +1 -1
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/payload_factory.py +23 -19
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/base_service.py +73 -35
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/camera_service.py +11 -3
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/irrigation_service.py +104 -47
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/tests/test_irrigation_service.py +373 -177
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_camera_service.py +57 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.coveragerc +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.github/dependabot.yml +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.gitignore +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/.reuse/dep5 +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/CHANGELOG.md +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/LICENSES/GPL-3.0-only.txt +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/bin/act +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/index.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/search.js +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/const.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/crypto.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/exceptions.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/payload_factory.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/base_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/bulb_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/camera_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/hms_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/lock_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/sensor_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/switch_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/thermostat_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/update_manager.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services/wall_switch_service.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/services.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/types.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/utils.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy/wyze_auth_lib.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/docs/wyzeapy.html +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/scripts/create_pre_release.sh +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/const.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/crypto.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/exceptions.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/__init__.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/bulb_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/hms_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/lock_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/sensor_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/switch_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/thermostat_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/update_manager.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/services/wall_switch_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/types.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/utils.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/src/wyzeapy/wyze_auth_lib.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/__init__.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_bulb_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_hms_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_lock_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_payload_factory.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_sensor_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_switch_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_thermostat_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_types.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_update_manager.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_utils.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_wall_switch_service.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_wyze_auth_lib.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/tests/test_wyzeapy.py +0 -0
- {wyzeapy-0.5.30 → wyzeapy-0.5.31rc1}/uv.lock +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Lines starting with
|
|
1
|
+
# Lines starting with '#' are comments.
|
|
2
2
|
# Each line is a file pattern followed by one or more owners.
|
|
3
3
|
|
|
4
4
|
# These owners will be the default owners for everything in the repo.
|
|
5
|
-
* @
|
|
5
|
+
* @SecKatie
|
|
6
6
|
|
|
7
7
|
# Order is important. The last matching pattern has the most precedence.
|
|
8
8
|
# So if a pull request only touches javascript files, only these owners
|
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
# *.js @octocat @github/js
|
|
11
11
|
|
|
12
12
|
# You can also use email addresses if you prefer.
|
|
13
|
-
# docs/* docs@example.com
|
|
13
|
+
# docs/* docs@example.com
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Auto Assign Issues
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issues:
|
|
5
|
+
types: [opened]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
assign:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
issues: write
|
|
12
|
+
steps:
|
|
13
|
+
- name: Assign issue to SecKatie
|
|
14
|
+
uses: actions/github-script@v7
|
|
15
|
+
with:
|
|
16
|
+
script: |
|
|
17
|
+
await github.rest.issues.addAssignees({
|
|
18
|
+
owner: context.repo.owner,
|
|
19
|
+
repo: context.repo.repo,
|
|
20
|
+
issue_number: context.issue.number,
|
|
21
|
+
assignees: ['SecKatie']
|
|
22
|
+
});
|
|
@@ -32,17 +32,17 @@ jobs:
|
|
|
32
32
|
|
|
33
33
|
steps:
|
|
34
34
|
- name: Checkout repository
|
|
35
|
-
uses: actions/checkout@
|
|
35
|
+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v3
|
|
36
36
|
|
|
37
37
|
# Initializes the CodeQL tools for scanning.
|
|
38
38
|
- name: Initialize CodeQL
|
|
39
|
-
uses: github/codeql-action/init@
|
|
39
|
+
uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v3
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
|
43
43
|
# If this step fails, then you should remove it and run the build manually (see below)
|
|
44
44
|
- name: Autobuild
|
|
45
|
-
uses: github/codeql-action/autobuild@
|
|
45
|
+
uses: github/codeql-action/autobuild@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v3
|
|
46
46
|
|
|
47
47
|
# Command-line programs to run using the OS shell.
|
|
48
48
|
# See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
@@ -55,5 +55,5 @@ jobs:
|
|
|
55
55
|
# ./location_of_script_within_repo/buildscript.sh
|
|
56
56
|
|
|
57
57
|
- name: Perform CodeQL Analysis
|
|
58
|
-
uses: github/codeql-action/analyze@
|
|
58
|
+
uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v3
|
|
59
59
|
|
|
@@ -11,15 +11,15 @@ jobs:
|
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
|
|
13
13
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
14
|
+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
|
|
15
15
|
|
|
16
16
|
- name: Set up Python
|
|
17
|
-
uses: actions/setup-python@
|
|
17
|
+
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5
|
|
18
18
|
with:
|
|
19
19
|
python-version: '3.11'
|
|
20
20
|
|
|
21
21
|
- name: Install uv
|
|
22
|
-
uses: astral-sh/setup-uv@
|
|
22
|
+
uses: astral-sh/setup-uv@ed21f2f24f8dd64503750218de024bcf64c7250a # v7.1.5
|
|
23
23
|
|
|
24
24
|
- name: Install dependencies
|
|
25
25
|
run: |
|
|
@@ -10,14 +10,14 @@ jobs:
|
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
11
|
|
|
12
12
|
steps:
|
|
13
|
-
- uses: actions/checkout@
|
|
13
|
+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
|
|
14
14
|
|
|
15
|
-
- uses: actions/setup-python@
|
|
15
|
+
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5
|
|
16
16
|
with:
|
|
17
17
|
python-version: "3.12"
|
|
18
18
|
|
|
19
19
|
- name: Install uv
|
|
20
|
-
uses: astral-sh/setup-uv@
|
|
20
|
+
uses: astral-sh/setup-uv@ed21f2f24f8dd64503750218de024bcf64c7250a # v4
|
|
21
21
|
with:
|
|
22
22
|
enable-cache: true
|
|
23
23
|
|
|
@@ -12,14 +12,14 @@ jobs:
|
|
|
12
12
|
id-token: write # Required for trusted publishing
|
|
13
13
|
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
15
|
+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
|
|
16
16
|
|
|
17
|
-
- uses: actions/setup-python@
|
|
17
|
+
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5
|
|
18
18
|
with:
|
|
19
19
|
python-version: "3.12"
|
|
20
20
|
|
|
21
21
|
- name: Install uv
|
|
22
|
-
uses: astral-sh/setup-uv@
|
|
22
|
+
uses: astral-sh/setup-uv@ed21f2f24f8dd64503750218de024bcf64c7250a # v4
|
|
23
23
|
with:
|
|
24
24
|
enable-cache: true
|
|
25
25
|
|
|
@@ -14,15 +14,15 @@ jobs:
|
|
|
14
14
|
python-version: ['3.11', '3.12']
|
|
15
15
|
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
17
|
+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
|
|
18
18
|
|
|
19
19
|
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
-
uses: actions/setup-python@
|
|
20
|
+
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5
|
|
21
21
|
with:
|
|
22
22
|
python-version: ${{ matrix.python-version }}
|
|
23
23
|
|
|
24
24
|
- name: Install uv
|
|
25
|
-
uses: astral-sh/setup-uv@
|
|
25
|
+
uses: astral-sh/setup-uv@ed21f2f24f8dd64503750218de024bcf64c7250a # v7.1.5
|
|
26
26
|
|
|
27
27
|
- name: Install dependencies
|
|
28
28
|
run: |
|
|
@@ -39,7 +39,7 @@ jobs:
|
|
|
39
39
|
coverage xml
|
|
40
40
|
|
|
41
41
|
- name: Upload coverage reports to Codecov
|
|
42
|
-
uses: codecov/codecov-action@
|
|
42
|
+
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v4
|
|
43
43
|
if: matrix.python-version == '3.11'
|
|
44
44
|
with:
|
|
45
45
|
file: ./coverage.xml
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wyzeapy
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.31rc1
|
|
4
4
|
Summary: A library for interacting with Wyze devices
|
|
5
5
|
Author-email: Katie Mulliken <katie@mulliken.net>
|
|
6
6
|
License: GPL-3.0-only
|
|
@@ -9,5 +9,5 @@ Requires-Dist: aiodns<4.0.0,>=3.2.0
|
|
|
9
9
|
Requires-Dist: aiohttp<4.0.0,>=3.11.12
|
|
10
10
|
Requires-Dist: pycryptodome<4.0.0,>=3.21.0
|
|
11
11
|
Provides-Extra: dev
|
|
12
|
-
Requires-Dist: pdoc<
|
|
13
|
-
Requires-Dist: pytest<
|
|
12
|
+
Requires-Dist: pdoc<17.0.0,>=15.0.3; extra == 'dev'
|
|
13
|
+
Requires-Dist: pytest<10.0.0,>=7.0.0; extra == 'dev'
|
|
@@ -23,13 +23,13 @@ from wyzeapy import Wyzeapy
|
|
|
23
23
|
|
|
24
24
|
async def async_main():
|
|
25
25
|
client = await Wyzeapy.create()
|
|
26
|
-
await client.login("EMAIL", "PASSWORD")
|
|
26
|
+
await client.login(email="EMAIL", password="PASSWORD", key_id="KEY_ID", api_key="API_KEY")
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
if __name__ == "__main__":
|
|
30
|
-
|
|
31
|
-
loop.run_until_complete(async_main())
|
|
30
|
+
asyncio.run(async_main())
|
|
32
31
|
```
|
|
32
|
+
Note: Visit the [Wyze developer console](https://developer-api-console.wyze.com/#/apikey/view) to generate an Key Id and Api Key.
|
|
33
33
|
|
|
34
34
|
## Thanks to:
|
|
35
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "wyzeapy"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.31pre1"
|
|
4
4
|
description = "A library for interacting with Wyze devices"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Katie Mulliken", email = "katie@mulliken.net" },
|
|
@@ -15,8 +15,8 @@ dependencies = [
|
|
|
15
15
|
|
|
16
16
|
[project.optional-dependencies]
|
|
17
17
|
dev = [
|
|
18
|
-
"pdoc>=15.0.3,<
|
|
19
|
-
"pytest>=7.0.0,<
|
|
18
|
+
"pdoc>=15.0.3,<17.0.0",
|
|
19
|
+
"pytest>=7.0.0,<10.0.0",
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
[build-system]
|
|
@@ -26,6 +26,6 @@ build-backend = "hatchling.build"
|
|
|
26
26
|
[dependency-groups]
|
|
27
27
|
dev = [
|
|
28
28
|
"ruff>=0.12.3",
|
|
29
|
-
"pytest>=7.0.0,<
|
|
29
|
+
"pytest>=7.0.0,<10.0.0",
|
|
30
30
|
"coverage>=7.9.2",
|
|
31
31
|
]
|
|
@@ -443,7 +443,7 @@ class Wyzeapy:
|
|
|
443
443
|
if self._sensor_service is None:
|
|
444
444
|
self._sensor_service = SensorService(self._auth_lib)
|
|
445
445
|
return self._sensor_service
|
|
446
|
-
|
|
446
|
+
|
|
447
447
|
@property
|
|
448
448
|
async def irrigation_service(self) -> IrrigationService:
|
|
449
449
|
"""Returns an instance of the irrigation service"""
|
|
@@ -51,37 +51,41 @@ def olive_create_get_payload(device_mac: str, keys: str) -> Dict[str, Any]:
|
|
|
51
51
|
|
|
52
52
|
return {"keys": keys, "did": device_mac, "nonce": nonce}
|
|
53
53
|
|
|
54
|
+
|
|
54
55
|
def olive_create_get_payload_irrigation(device_mac: str) -> Dict[str, Any]:
|
|
55
56
|
nonce = int(time.time() * 1000)
|
|
56
57
|
|
|
57
|
-
return {
|
|
58
|
-
'device_id': device_mac,
|
|
59
|
-
'nonce': str(nonce)
|
|
60
|
-
}
|
|
58
|
+
return {"device_id": device_mac, "nonce": str(nonce)}
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
|
|
61
|
+
def olive_create_post_payload_irrigation_stop(
|
|
62
|
+
device_mac: str, action: str
|
|
63
|
+
) -> Dict[str, Any]:
|
|
63
64
|
nonce = int(time.time() * 1000)
|
|
64
65
|
|
|
65
|
-
return {
|
|
66
|
-
'device_id': device_mac,
|
|
67
|
-
'nonce': str(nonce),
|
|
68
|
-
"action": action
|
|
69
|
-
}
|
|
66
|
+
return {"device_id": device_mac, "nonce": str(nonce), "action": action}
|
|
70
67
|
|
|
71
|
-
|
|
68
|
+
|
|
69
|
+
def olive_create_post_payload_irrigation_quickrun(
|
|
70
|
+
device_mac: str, zone_number: int, duration: int
|
|
71
|
+
) -> Dict[str, Any]:
|
|
72
72
|
nonce = int(time.time() * 1000)
|
|
73
73
|
|
|
74
74
|
return {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"zone_runs": [
|
|
78
|
-
{
|
|
79
|
-
"zone_number": zone_number,
|
|
80
|
-
"duration": duration
|
|
81
|
-
}
|
|
82
|
-
]
|
|
75
|
+
"device_id": device_mac,
|
|
76
|
+
"nonce": str(nonce),
|
|
77
|
+
"zone_runs": [{"zone_number": zone_number, "duration": duration}],
|
|
83
78
|
}
|
|
84
79
|
|
|
80
|
+
|
|
81
|
+
def olive_create_get_payload_irrigation_schedule_runs(
|
|
82
|
+
device_mac: str,
|
|
83
|
+
) -> Dict[str, Any]:
|
|
84
|
+
nonce = int(time.time() * 1000)
|
|
85
|
+
|
|
86
|
+
return {"device_id": device_mac, "nonce": str(nonce)}
|
|
87
|
+
|
|
88
|
+
|
|
85
89
|
def olive_create_post_payload(
|
|
86
90
|
device_mac: str, device_model: str, prop_key: str, value: Any
|
|
87
91
|
) -> Dict[str, Any]:
|
|
@@ -39,6 +39,7 @@ from ..payload_factory import (
|
|
|
39
39
|
olive_create_get_payload_irrigation,
|
|
40
40
|
olive_create_post_payload_irrigation_stop,
|
|
41
41
|
olive_create_post_payload_irrigation_quickrun,
|
|
42
|
+
olive_create_get_payload_irrigation_schedule_runs,
|
|
42
43
|
)
|
|
43
44
|
from ..types import PropertyIDs, Device, DeviceMgmtToggleType
|
|
44
45
|
from ..utils import (
|
|
@@ -906,13 +907,13 @@ class BaseService:
|
|
|
906
907
|
payload = olive_create_get_payload_irrigation(device.mac)
|
|
907
908
|
signature = olive_create_signature(payload, self._auth_lib.token.access_token)
|
|
908
909
|
headers = {
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
910
|
+
"Accept-Encoding": "gzip",
|
|
911
|
+
"User-Agent": "myapp",
|
|
912
|
+
"appid": OLIVE_APP_ID,
|
|
913
|
+
"appinfo": APP_INFO,
|
|
914
|
+
"phoneid": PHONE_ID,
|
|
915
|
+
"access_token": self._auth_lib.token.access_token,
|
|
916
|
+
"signature2": signature,
|
|
916
917
|
}
|
|
917
918
|
|
|
918
919
|
response_json = await self._auth_lib.get(url, headers=headers, params=payload)
|
|
@@ -921,50 +922,87 @@ class BaseService:
|
|
|
921
922
|
|
|
922
923
|
return response_json
|
|
923
924
|
|
|
924
|
-
|
|
925
|
-
|
|
925
|
+
async def _stop_running_schedule(
|
|
926
|
+
self, url: str, device: Device, action: str
|
|
927
|
+
) -> Dict[Any, Any]:
|
|
926
928
|
await self._auth_lib.refresh_if_should()
|
|
927
929
|
|
|
928
930
|
payload = olive_create_post_payload_irrigation_stop(device.mac, action)
|
|
929
|
-
signature = olive_create_signature(
|
|
930
|
-
|
|
931
|
+
signature = olive_create_signature(
|
|
932
|
+
json.dumps(payload, separators=(",", ":")),
|
|
933
|
+
self._auth_lib.token.access_token,
|
|
934
|
+
)
|
|
931
935
|
headers = {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
936
|
+
"Accept-Encoding": "gzip",
|
|
937
|
+
"Content-Type": "application/json",
|
|
938
|
+
"User-Agent": "myapp",
|
|
939
|
+
"appid": OLIVE_APP_ID,
|
|
940
|
+
"appinfo": APP_INFO,
|
|
941
|
+
"phoneid": PHONE_ID,
|
|
942
|
+
"access_token": self._auth_lib.token.access_token,
|
|
943
|
+
"signature2": signature,
|
|
940
944
|
}
|
|
941
945
|
|
|
942
|
-
payload_str = json.dumps(payload, separators=(
|
|
943
|
-
response_json = await self._auth_lib.post(
|
|
946
|
+
payload_str = json.dumps(payload, separators=(",", ":"))
|
|
947
|
+
response_json = await self._auth_lib.post(
|
|
948
|
+
url, headers=headers, data=payload_str
|
|
949
|
+
)
|
|
944
950
|
|
|
945
951
|
check_for_errors_iot(self, response_json)
|
|
946
952
|
|
|
947
953
|
return response_json
|
|
948
954
|
|
|
949
|
-
async def _start_zone(
|
|
955
|
+
async def _start_zone(
|
|
956
|
+
self, url: str, device: Device, zone_number: int, duration: int
|
|
957
|
+
) -> Dict[Any, Any]:
|
|
950
958
|
await self._auth_lib.refresh_if_should()
|
|
951
959
|
|
|
952
|
-
payload = olive_create_post_payload_irrigation_quickrun(
|
|
953
|
-
|
|
954
|
-
|
|
960
|
+
payload = olive_create_post_payload_irrigation_quickrun(
|
|
961
|
+
device.mac, zone_number, duration
|
|
962
|
+
)
|
|
963
|
+
signature = olive_create_signature(
|
|
964
|
+
json.dumps(payload, separators=(",", ":")),
|
|
965
|
+
self._auth_lib.token.access_token,
|
|
966
|
+
)
|
|
955
967
|
headers = {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
968
|
+
"Accept-Encoding": "gzip",
|
|
969
|
+
"Content-Type": "application/json",
|
|
970
|
+
"User-Agent": "myapp",
|
|
971
|
+
"appid": OLIVE_APP_ID,
|
|
972
|
+
"appinfo": APP_INFO,
|
|
973
|
+
"phoneid": PHONE_ID,
|
|
974
|
+
"access_token": self._auth_lib.token.access_token,
|
|
975
|
+
"signature2": signature,
|
|
964
976
|
}
|
|
965
977
|
|
|
966
|
-
payload_str = json.dumps(payload, separators=(
|
|
967
|
-
response_json = await self._auth_lib.post(
|
|
978
|
+
payload_str = json.dumps(payload, separators=(",", ":"))
|
|
979
|
+
response_json = await self._auth_lib.post(
|
|
980
|
+
url, headers=headers, data=payload_str
|
|
981
|
+
)
|
|
982
|
+
|
|
983
|
+
check_for_errors_iot(self, response_json)
|
|
984
|
+
|
|
985
|
+
return response_json
|
|
986
|
+
|
|
987
|
+
async def _get_schedule_runs(
|
|
988
|
+
self, url: str, device: Device, limit: int = 2
|
|
989
|
+
) -> Dict[Any, Any]:
|
|
990
|
+
await self._auth_lib.refresh_if_should()
|
|
991
|
+
|
|
992
|
+
payload = olive_create_get_payload_irrigation_schedule_runs(device.mac)
|
|
993
|
+
payload["limit"] = limit
|
|
994
|
+
signature = olive_create_signature(payload, self._auth_lib.token.access_token)
|
|
995
|
+
headers = {
|
|
996
|
+
"Accept-Encoding": "gzip",
|
|
997
|
+
"User-Agent": "myapp",
|
|
998
|
+
"appid": OLIVE_APP_ID,
|
|
999
|
+
"appinfo": APP_INFO,
|
|
1000
|
+
"phoneid": PHONE_ID,
|
|
1001
|
+
"access_token": self._auth_lib.token.access_token,
|
|
1002
|
+
"signature2": signature,
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
response_json = await self._auth_lib.get(url, headers=headers, params=payload)
|
|
968
1006
|
|
|
969
1007
|
check_for_errors_iot(self, response_json)
|
|
970
1008
|
|
|
@@ -88,8 +88,10 @@ class CameraService(BaseService):
|
|
|
88
88
|
if property is PropertyIDs.CAMERA_SIREN:
|
|
89
89
|
camera.siren = value == "1"
|
|
90
90
|
if property is PropertyIDs.ACCESSORY:
|
|
91
|
+
# Bulb Cam (HL_BC): '1' = ON, '2' = OFF
|
|
92
|
+
# Other cameras with accessories: same logic
|
|
91
93
|
camera.floodlight = value == "1"
|
|
92
|
-
if camera.device_params
|
|
94
|
+
if camera.device_params.get("dongle_product_model") == "HL_CGDC":
|
|
93
95
|
camera.garage = (
|
|
94
96
|
value == "1"
|
|
95
97
|
) # 1 = open, 2 = closed by automation or smart platform (Alexa, Google Home, Rules), 0 = closed by app
|
|
@@ -186,7 +188,7 @@ class CameraService(BaseService):
|
|
|
186
188
|
else:
|
|
187
189
|
await self._run_action(camera, "siren_off")
|
|
188
190
|
|
|
189
|
-
# Also controls lamp socket and
|
|
191
|
+
# Also controls lamp socket, BCP spotlight, and Bulb Cam light
|
|
190
192
|
async def floodlight_on(self, camera: Camera):
|
|
191
193
|
if camera.product_model == "AN_RSCW":
|
|
192
194
|
await self._run_action_devicemgmt(
|
|
@@ -196,10 +198,13 @@ class CameraService(BaseService):
|
|
|
196
198
|
await self._run_action_devicemgmt(
|
|
197
199
|
camera, "floodlight", "1"
|
|
198
200
|
) # Some camera models use a diffrent api
|
|
201
|
+
elif camera.product_model == "HL_BC":
|
|
202
|
+
# Bulb Cam uses run_action with floodlight_on action
|
|
203
|
+
await self._run_action(camera, "floodlight_on")
|
|
199
204
|
else:
|
|
200
205
|
await self._set_property(camera, PropertyIDs.ACCESSORY.value, "1")
|
|
201
206
|
|
|
202
|
-
# Also controls lamp socket and
|
|
207
|
+
# Also controls lamp socket, BCP spotlight, and Bulb Cam light
|
|
203
208
|
async def floodlight_off(self, camera: Camera):
|
|
204
209
|
if camera.product_model == "AN_RSCW":
|
|
205
210
|
await self._run_action_devicemgmt(
|
|
@@ -209,6 +214,9 @@ class CameraService(BaseService):
|
|
|
209
214
|
await self._run_action_devicemgmt(
|
|
210
215
|
camera, "floodlight", "0"
|
|
211
216
|
) # Some camera models use a diffrent api
|
|
217
|
+
elif camera.product_model == "HL_BC":
|
|
218
|
+
# Bulb Cam uses run_action with floodlight_off action
|
|
219
|
+
await self._run_action(camera, "floodlight_off")
|
|
212
220
|
else:
|
|
213
221
|
await self._set_property(camera, PropertyIDs.ACCESSORY.value, "2")
|
|
214
222
|
|