deebot-client 3.0.3.dev0__tar.gz → 4.0.0__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.
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.devcontainer.json +4 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/workflows/ci.yml +2 -2
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/workflows/python-publish.yml +1 -1
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.pre-commit-config.yaml +8 -11
- {deebot-client-3.0.3.dev0/deebot_client.egg-info → deebot-client-4.0.0}/PKG-INFO +4 -4
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/README.md +3 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/api_client.py +5 -7
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/authentication.py +9 -9
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/capabilities.py +8 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/command.py +71 -7
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/__init__.py +15 -2
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/battery.py +3 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/charge.py +3 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/charge_state.py +8 -8
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/clean.py +12 -13
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/clean_count.py +5 -5
- deebot-client-4.0.0/deebot_client/commands/json/common.py +105 -0
- deebot-client-4.0.0/deebot_client/commands/json/efficiency.py +40 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/error.py +5 -4
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/fan_speed.py +5 -4
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/life_span.py +4 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/map.py +39 -37
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/network.py +2 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/pos.py +7 -5
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/stats.py +3 -3
- deebot-client-4.0.0/deebot_client/commands/json/voice_assistant_state.py +19 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/volume.py +10 -8
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/water_info.py +13 -8
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/work_mode.py +5 -4
- deebot-client-4.0.0/deebot_client/commands/xml/__init__.py +1 -0
- deebot-client-3.0.3.dev0/deebot_client/vacuum_bot.py → deebot-client-4.0.0/deebot_client/device.py +16 -14
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/event_bus.py +7 -7
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/events/__init__.py +12 -3
- deebot-client-4.0.0/deebot_client/events/efficiency_mode.py +20 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/events/map.py +3 -4
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/events/water_info.py +3 -3
- deebot-client-4.0.0/deebot_client/hardware/deebot/85nbtp.py +193 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/hardware/deebot/fallback.py +3 -1
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/hardware/deebot/p1jij8.py +3 -1
- deebot-client-4.0.0/deebot_client/hardware/deebot/p95mgv.py +220 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/hardware/deebot/vi829v.py +3 -1
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/hardware/deebot/yna5xi.py +3 -1
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/logging_filter.py +4 -4
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/map.py +7 -6
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/models.py +11 -8
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/mqtt_client.py +9 -7
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/util.py +15 -10
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0/deebot_client.egg-info}/PKG-INFO +4 -4
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client.egg-info/SOURCES.txt +11 -2
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/pyproject.toml +24 -46
- deebot-client-4.0.0/requirements-test.txt +12 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/__init__.py +34 -6
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_advanced_mode.py +5 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_carpet.py +3 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_charge.py +6 -4
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_clean.py +10 -10
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_clean_log.py +5 -1
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_clean_preference.py +3 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_common.py +12 -13
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_continuous_cleaning.py +3 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_custom.py +10 -4
- deebot-client-4.0.0/tests/commands/json/test_efficiency.py +40 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_life_span.py +29 -6
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_map.py +22 -23
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_mulitmap_state.py +5 -3
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_true_detect.py +5 -3
- deebot-client-4.0.0/tests/commands/json/test_voice_assistant_state.py +22 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_water_info.py +10 -4
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/conftest.py +0 -12
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/fixtures/base.py +11 -7
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/hardware/test_init.py +48 -2
- deebot-client-4.0.0/tests/messages/json/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/messages/test_messages.py +2 -2
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/test_authentication.py +1 -1
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/test_command.py +5 -2
- deebot-client-3.0.3.dev0/tests/test_vacuum_bot.py → deebot-client-4.0.0/tests/test_device.py +7 -7
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/test_event_bus.py +38 -26
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/test_mqtt_client.py +50 -17
- deebot-client-3.0.3.dev0/deebot_client/commands/json/common.py +0 -151
- deebot-client-3.0.3.dev0/requirements-test.txt +0 -13
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.codecov.yml +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.coveragerc +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.gitattributes +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/FUNDING.yml +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/dependabot.yml +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/release-drafter.yml +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/workflows/codeql-analysis.yml +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.github/workflows/release-drafter.yml +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.gitignore +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.prettierrc.js +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/.yamllint +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/LICENSE.txt +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/advanced_mode.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/carpet.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/clean_logs.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/clean_preference.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/const.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/continuous_cleaning.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/custom.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/multimap_state.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/play_sound.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/relocation.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/true_detect.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/xml/common.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/const.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/events/base.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/events/fan_speed.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/events/network.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/events/work_mode.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/exceptions.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/hardware/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/hardware/deebot/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/message.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/messages/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/messages/json/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/messages/json/battery.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/messages/json/stats.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/py.typed +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client.egg-info/dependency_links.txt +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client.egg-info/requires.txt +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client.egg-info/top_level.txt +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/mypy.ini +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/pytest.ini +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/requirements-dev.txt +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/requirements.txt +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/scripts/check_getLogger.sh +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/scripts/run-in-env.sh +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/setup.cfg +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_battery.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_charge_state.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_clean_count.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_fan_speed.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_network.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_volume.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/commands/json/test_work_mode.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/events/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/events/test_water_info.py +0 -0
- {deebot-client-3.0.3.dev0/tests/hardware → deebot-client-4.0.0/tests/fixtures}/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/fixtures/mqtt_server.py +0 -0
- {deebot-client-3.0.3.dev0/tests/messages/json → deebot-client-4.0.0/tests/hardware}/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/helpers/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/helpers/tasks.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/messages/__init__.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/messages/json/test_battery.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/messages/json/test_stats.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/messages/test_get_messages.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/test_map.py +0 -0
- {deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/tests/test_util.py +0 -0
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Configure properties specific to VS Code.
|
|
6
6
|
"vscode": {
|
|
7
7
|
"extensions": [
|
|
8
|
+
"charliermarsh.ruff",
|
|
8
9
|
"eamodio.gitlens",
|
|
9
10
|
"github.vscode-pull-request-github",
|
|
10
11
|
"ms-python.python",
|
|
@@ -15,6 +16,9 @@
|
|
|
15
16
|
],
|
|
16
17
|
// Set *default* container specific settings.json values on container create.
|
|
17
18
|
"settings": {
|
|
19
|
+
"[python]": {
|
|
20
|
+
"editor.defaultFormatter": "charliermarsh.ruff"
|
|
21
|
+
},
|
|
18
22
|
"editor.formatOnPaste": false,
|
|
19
23
|
"editor.formatOnSave": true,
|
|
20
24
|
"editor.formatOnType": true,
|
|
@@ -18,7 +18,7 @@ jobs:
|
|
|
18
18
|
- uses: "actions/checkout@v4"
|
|
19
19
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
20
20
|
id: python
|
|
21
|
-
uses: actions/setup-python@
|
|
21
|
+
uses: actions/setup-python@v5.0.0
|
|
22
22
|
with:
|
|
23
23
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
24
24
|
cache: "pip"
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
- uses: "actions/checkout@v4"
|
|
43
43
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
44
44
|
id: python
|
|
45
|
-
uses: actions/setup-python@
|
|
45
|
+
uses: actions/setup-python@v5.0.0
|
|
46
46
|
with:
|
|
47
47
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
48
48
|
cache: "pip"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
ci:
|
|
2
|
+
autofix_prs: false
|
|
2
3
|
skip:
|
|
3
4
|
# This steps run in the ci workflow. Keep in sync
|
|
4
5
|
- mypy
|
|
@@ -10,23 +11,19 @@ default_language_version:
|
|
|
10
11
|
|
|
11
12
|
repos:
|
|
12
13
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
13
|
-
rev: v0.1.
|
|
14
|
+
rev: v0.1.6
|
|
14
15
|
hooks:
|
|
15
16
|
- id: ruff
|
|
16
17
|
args:
|
|
17
18
|
- --fix
|
|
19
|
+
# - --unsafe-fixes
|
|
20
|
+
- id: ruff-format
|
|
18
21
|
- repo: https://github.com/asottile/pyupgrade
|
|
19
22
|
rev: v3.15.0
|
|
20
23
|
hooks:
|
|
21
24
|
- id: pyupgrade
|
|
22
25
|
args:
|
|
23
26
|
- --py311-plus
|
|
24
|
-
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
25
|
-
rev: 23.10.0
|
|
26
|
-
hooks:
|
|
27
|
-
- id: black
|
|
28
|
-
args:
|
|
29
|
-
- --quiet
|
|
30
27
|
- repo: https://github.com/codespell-project/codespell
|
|
31
28
|
rev: v2.2.6
|
|
32
29
|
hooks:
|
|
@@ -48,16 +45,16 @@ repos:
|
|
|
48
45
|
args: [--branch, main, --branch, dev]
|
|
49
46
|
- id: requirements-txt-fixer
|
|
50
47
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
|
51
|
-
rev: v3.0
|
|
48
|
+
rev: v3.1.0
|
|
52
49
|
hooks:
|
|
53
50
|
- id: prettier
|
|
54
51
|
additional_dependencies:
|
|
55
|
-
- prettier@3.0
|
|
56
|
-
- prettier-plugin-sort-json@3.0
|
|
52
|
+
- prettier@3.1.0
|
|
53
|
+
- prettier-plugin-sort-json@3.1.0
|
|
57
54
|
exclude_types:
|
|
58
55
|
- python
|
|
59
56
|
- repo: https://github.com/adrienverge/yamllint.git
|
|
60
|
-
rev: v1.
|
|
57
|
+
rev: v1.33.0
|
|
61
58
|
hooks:
|
|
62
59
|
- id: yamllint
|
|
63
60
|
- repo: local
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: deebot-client
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: Deebot client library in python 3
|
|
5
5
|
Author-email: Robert Resch <robert@resch.dev>
|
|
6
6
|
License: GPL-3.0
|
|
@@ -24,7 +24,7 @@ Requires-Dist: defusedxml
|
|
|
24
24
|
Requires-Dist: numpy<2.0,>=1.23.2
|
|
25
25
|
Requires-Dist: Pillow<11.0,>=10.0.1
|
|
26
26
|
|
|
27
|
-
# Client Library for Deebot Vacuums
|
|
27
|
+
# Client Library for Deebot devices (Vacuums)
|
|
28
28
|
|
|
29
29
|
[](https://pypi.org/project/deebot-client)
|
|
30
30
|
<a href="https://www.buymeacoffee.com/edenhaus" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-black.png" width="150px" height="35px" alt="Buy Me A Coffee" style="height: 35px !important;width: 150px !important;" ></a>
|
|
@@ -57,7 +57,7 @@ from deebot_client.events import BatteryEvent
|
|
|
57
57
|
from deebot_client.models import Configuration
|
|
58
58
|
from deebot_client.mqtt_client import MqttClient, MqttConfiguration
|
|
59
59
|
from deebot_client.util import md5
|
|
60
|
-
from deebot_client.
|
|
60
|
+
from deebot_client.device import Device
|
|
61
61
|
|
|
62
62
|
device_id = md5(str(time.time()))
|
|
63
63
|
account_id = "your email or phonenumber (cn)"
|
|
@@ -78,7 +78,7 @@ async def main():
|
|
|
78
78
|
|
|
79
79
|
devices_ = await api_client.get_devices()
|
|
80
80
|
|
|
81
|
-
bot =
|
|
81
|
+
bot = Device(devices_[0], authenticator)
|
|
82
82
|
|
|
83
83
|
mqtt_config = MqttConfiguration(config=config)
|
|
84
84
|
mqtt = MqttClient(mqtt_config, authenticator)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Client Library for Deebot Vacuums
|
|
1
|
+
# Client Library for Deebot devices (Vacuums)
|
|
2
2
|
|
|
3
3
|
[](https://pypi.org/project/deebot-client)
|
|
4
4
|
<a href="https://www.buymeacoffee.com/edenhaus" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-black.png" width="150px" height="35px" alt="Buy Me A Coffee" style="height: 35px !important;width: 150px !important;" ></a>
|
|
@@ -31,7 +31,7 @@ from deebot_client.events import BatteryEvent
|
|
|
31
31
|
from deebot_client.models import Configuration
|
|
32
32
|
from deebot_client.mqtt_client import MqttClient, MqttConfiguration
|
|
33
33
|
from deebot_client.util import md5
|
|
34
|
-
from deebot_client.
|
|
34
|
+
from deebot_client.device import Device
|
|
35
35
|
|
|
36
36
|
device_id = md5(str(time.time()))
|
|
37
37
|
account_id = "your email or phonenumber (cn)"
|
|
@@ -52,7 +52,7 @@ async def main():
|
|
|
52
52
|
|
|
53
53
|
devices_ = await api_client.get_devices()
|
|
54
54
|
|
|
55
|
-
bot =
|
|
55
|
+
bot = Device(devices_[0], authenticator)
|
|
56
56
|
|
|
57
57
|
mqtt_config = MqttConfiguration(config=config)
|
|
58
58
|
mqtt = MqttClient(mqtt_config, authenticator)
|
|
@@ -15,7 +15,7 @@ _LOGGER = get_logger(__name__)
|
|
|
15
15
|
class ApiClient:
|
|
16
16
|
"""Api client."""
|
|
17
17
|
|
|
18
|
-
def __init__(self, authenticator: Authenticator):
|
|
18
|
+
def __init__(self, authenticator: Authenticator) -> None:
|
|
19
19
|
self._authenticator = authenticator
|
|
20
20
|
|
|
21
21
|
async def get_devices(self) -> list[DeviceInfo]:
|
|
@@ -38,9 +38,8 @@ class ApiClient:
|
|
|
38
38
|
_LOGGER.debug("Skipping device as it is not supported: %s", device)
|
|
39
39
|
return devices
|
|
40
40
|
_LOGGER.error("Failed to get devices: %s", resp)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
41
|
+
msg = f"failure {resp.get('error', '')} ({resp.get('errno', '')}) on getting devices"
|
|
42
|
+
raise ApiError(msg)
|
|
44
43
|
|
|
45
44
|
async def get_product_iot_map(self) -> dict[str, Any]:
|
|
46
45
|
"""Get product iot map."""
|
|
@@ -55,6 +54,5 @@ class ApiClient:
|
|
|
55
54
|
result[entry["classid"]] = entry["product"]
|
|
56
55
|
return result
|
|
57
56
|
_LOGGER.error("Failed to get product iot map")
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
57
|
+
msg = f"failure {resp['error']} ({resp['errno']}) on getting product iot map"
|
|
58
|
+
raise ApiError(msg)
|
|
@@ -51,7 +51,7 @@ class _AuthClient:
|
|
|
51
51
|
config: Configuration,
|
|
52
52
|
account_id: str,
|
|
53
53
|
password_hash: str,
|
|
54
|
-
):
|
|
54
|
+
) -> None:
|
|
55
55
|
self._config = config
|
|
56
56
|
self._account_id = account_id
|
|
57
57
|
self._password_hash = password_hash
|
|
@@ -107,7 +107,7 @@ class _AuthClient:
|
|
|
107
107
|
content_type = res.headers.get(hdrs.CONTENT_TYPE, "").lower()
|
|
108
108
|
json = await res.json(content_type=content_type)
|
|
109
109
|
_LOGGER.debug("got %s", json)
|
|
110
|
-
#
|
|
110
|
+
# TODO better error handling # pylint: disable=fixme
|
|
111
111
|
if json["code"] == "0000":
|
|
112
112
|
data: dict[str, Any] = json["data"]
|
|
113
113
|
return data
|
|
@@ -115,9 +115,8 @@ class _AuthClient:
|
|
|
115
115
|
raise InvalidAuthenticationError
|
|
116
116
|
|
|
117
117
|
_LOGGER.error("call to %s failed with %s", url, json)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)
|
|
118
|
+
msg = f"failure code {json['code']} ({json['msg']}) for call {url}"
|
|
119
|
+
raise AuthenticationError(msg)
|
|
121
120
|
|
|
122
121
|
async def __call_login_api(
|
|
123
122
|
self, account_id: str, password_hash: str
|
|
@@ -204,9 +203,10 @@ class _AuthClient:
|
|
|
204
203
|
continue
|
|
205
204
|
|
|
206
205
|
_LOGGER.error("call to %s failed with %s", _PATH_USERS_USER, resp)
|
|
207
|
-
|
|
206
|
+
msg = (
|
|
208
207
|
f"failure {resp['error']} ({resp['errno']}) for call {_PATH_USERS_USER}"
|
|
209
208
|
)
|
|
209
|
+
raise AuthenticationError(msg)
|
|
210
210
|
|
|
211
211
|
raise AuthenticationError("failed to login with token")
|
|
212
212
|
|
|
@@ -302,7 +302,7 @@ class Authenticator:
|
|
|
302
302
|
config: Configuration,
|
|
303
303
|
account_id: str,
|
|
304
304
|
password_hash: str,
|
|
305
|
-
):
|
|
305
|
+
) -> None:
|
|
306
306
|
self._auth_client = _AuthClient(
|
|
307
307
|
config,
|
|
308
308
|
account_id,
|
|
@@ -317,7 +317,7 @@ class Authenticator:
|
|
|
317
317
|
self._refresh_handle: asyncio.TimerHandle | None = None
|
|
318
318
|
self._tasks: set[asyncio.Future[Any]] = set()
|
|
319
319
|
|
|
320
|
-
async def authenticate(self, force: bool = False) -> Credentials:
|
|
320
|
+
async def authenticate(self, *, force: bool = False) -> Credentials:
|
|
321
321
|
"""Authenticate on ecovacs servers."""
|
|
322
322
|
async with self._lock:
|
|
323
323
|
if (
|
|
@@ -379,7 +379,7 @@ class Authenticator:
|
|
|
379
379
|
|
|
380
380
|
async def async_refresh() -> None:
|
|
381
381
|
try:
|
|
382
|
-
await self.authenticate(True)
|
|
382
|
+
await self.authenticate(force=True)
|
|
383
383
|
except Exception: # pylint: disable=broad-except
|
|
384
384
|
_LOGGER.exception("An exception occurred during refreshing token")
|
|
385
385
|
|
|
@@ -4,8 +4,7 @@ from dataclasses import dataclass, field, fields, is_dataclass
|
|
|
4
4
|
from types import MappingProxyType
|
|
5
5
|
from typing import TYPE_CHECKING, Any, Generic, TypeVar
|
|
6
6
|
|
|
7
|
-
from deebot_client.command import Command
|
|
8
|
-
from deebot_client.commands.json.common import SetCommand
|
|
7
|
+
from deebot_client.command import Command, SetCommand
|
|
9
8
|
from deebot_client.events import (
|
|
10
9
|
AdvancedModeEvent,
|
|
11
10
|
AvailabilityEvent,
|
|
@@ -35,12 +34,14 @@ from deebot_client.events import (
|
|
|
35
34
|
StatsEvent,
|
|
36
35
|
TotalStatsEvent,
|
|
37
36
|
TrueDetectEvent,
|
|
37
|
+
VoiceAssistantStateEvent,
|
|
38
38
|
VolumeEvent,
|
|
39
39
|
WaterAmount,
|
|
40
40
|
WaterInfoEvent,
|
|
41
41
|
WorkMode,
|
|
42
42
|
WorkModeEvent,
|
|
43
43
|
)
|
|
44
|
+
from deebot_client.events.efficiency_mode import EfficiencyMode, EfficiencyModeEvent
|
|
44
45
|
from deebot_client.models import CleanAction, CleanMode
|
|
45
46
|
|
|
46
47
|
if TYPE_CHECKING:
|
|
@@ -121,7 +122,7 @@ class CapabilityClean:
|
|
|
121
122
|
action: CapabilityCleanAction
|
|
122
123
|
continuous: CapabilitySetEnable[ContinuousCleaningEvent]
|
|
123
124
|
count: CapabilitySet[CleanCountEvent, int] | None = None
|
|
124
|
-
log: CapabilityEvent[CleanLogEvent]
|
|
125
|
+
log: CapabilityEvent[CleanLogEvent] | None = None
|
|
125
126
|
preference: CapabilitySetEnable[CleanPreferenceEvent] | None = None
|
|
126
127
|
work_mode: CapabilitySetTypes[WorkModeEvent, WorkMode] | None = None
|
|
127
128
|
|
|
@@ -169,7 +170,11 @@ class CapabilitySettings:
|
|
|
169
170
|
|
|
170
171
|
advanced_mode: CapabilitySetEnable[AdvancedModeEvent]
|
|
171
172
|
carpet_auto_fan_boost: CapabilitySetEnable[CarpetAutoFanBoostEvent]
|
|
173
|
+
efficiency_mode: (
|
|
174
|
+
CapabilitySetTypes[EfficiencyModeEvent, EfficiencyMode] | None
|
|
175
|
+
) = None
|
|
172
176
|
true_detect: CapabilitySetEnable[TrueDetectEvent] | None = None
|
|
177
|
+
voice_assistant: CapabilitySetEnable[VoiceAssistantStateEvent] | None = None
|
|
173
178
|
volume: CapabilitySet[VolumeEvent, int]
|
|
174
179
|
|
|
175
180
|
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
3
|
import asyncio
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
+
from types import MappingProxyType
|
|
5
6
|
from typing import Any, final
|
|
6
7
|
|
|
8
|
+
from deebot_client.events import AvailabilityEvent
|
|
7
9
|
from deebot_client.exceptions import DeebotError
|
|
8
10
|
|
|
9
11
|
from .authentication import Authenticator
|
|
10
12
|
from .const import PATH_API_IOT_DEVMANAGER, REQUEST_HEADERS, DataType
|
|
11
13
|
from .event_bus import EventBus
|
|
12
14
|
from .logging_filter import get_logger
|
|
13
|
-
from .message import HandlingResult, HandlingState
|
|
15
|
+
from .message import HandlingResult, HandlingState, MessageBody
|
|
14
16
|
from .models import DeviceInfo
|
|
15
17
|
|
|
16
18
|
_LOGGER = get_logger(__name__)
|
|
@@ -53,7 +55,7 @@ class Command(ABC):
|
|
|
53
55
|
@classmethod
|
|
54
56
|
@abstractmethod
|
|
55
57
|
def data_type(cls) -> DataType:
|
|
56
|
-
"""Data type."""
|
|
58
|
+
"""Data type."""
|
|
57
59
|
|
|
58
60
|
@abstractmethod
|
|
59
61
|
def _get_payload(self) -> dict[str, Any] | list[Any] | str:
|
|
@@ -189,6 +191,49 @@ class Command(ABC):
|
|
|
189
191
|
return hash(self.name) + hash(self._args)
|
|
190
192
|
|
|
191
193
|
|
|
194
|
+
class CommandWithMessageHandling(Command, MessageBody, ABC):
|
|
195
|
+
"""Command, which handle response by itself."""
|
|
196
|
+
|
|
197
|
+
_is_available_check: bool = False
|
|
198
|
+
|
|
199
|
+
def _handle_response(
|
|
200
|
+
self, event_bus: EventBus, response: dict[str, Any]
|
|
201
|
+
) -> CommandResult:
|
|
202
|
+
"""Handle response from a command.
|
|
203
|
+
|
|
204
|
+
:return: A message response
|
|
205
|
+
"""
|
|
206
|
+
if response.get("ret") == "ok":
|
|
207
|
+
data = response.get("resp", response)
|
|
208
|
+
result = self.handle(event_bus, data)
|
|
209
|
+
return CommandResult(result.state, result.args)
|
|
210
|
+
|
|
211
|
+
if errno := response.get("errno", None):
|
|
212
|
+
match errno:
|
|
213
|
+
case 4200:
|
|
214
|
+
# bot offline
|
|
215
|
+
_LOGGER.info(
|
|
216
|
+
'Device is offline. Could not execute command "%s"', self.name
|
|
217
|
+
)
|
|
218
|
+
event_bus.notify(AvailabilityEvent(available=False))
|
|
219
|
+
return CommandResult(HandlingState.FAILED)
|
|
220
|
+
case 500:
|
|
221
|
+
if self._is_available_check:
|
|
222
|
+
_LOGGER.info(
|
|
223
|
+
'No response received for command "%s" during availability-check.',
|
|
224
|
+
self.name,
|
|
225
|
+
)
|
|
226
|
+
else:
|
|
227
|
+
_LOGGER.warning(
|
|
228
|
+
'No response received for command "%s". This can happen if the device has network issues or does not support the command',
|
|
229
|
+
self.name,
|
|
230
|
+
)
|
|
231
|
+
return CommandResult(HandlingState.FAILED)
|
|
232
|
+
|
|
233
|
+
_LOGGER.warning('Command "%s" was not successfully.', self.name)
|
|
234
|
+
return CommandResult(HandlingState.ANALYSE)
|
|
235
|
+
|
|
236
|
+
|
|
192
237
|
@dataclass
|
|
193
238
|
class InitParam:
|
|
194
239
|
"""Init param."""
|
|
@@ -200,7 +245,7 @@ class InitParam:
|
|
|
200
245
|
class CommandMqttP2P(Command, ABC):
|
|
201
246
|
"""Command which can handle mqtt p2p messages."""
|
|
202
247
|
|
|
203
|
-
_mqtt_params:
|
|
248
|
+
_mqtt_params: MappingProxyType[str, InitParam | None]
|
|
204
249
|
|
|
205
250
|
@abstractmethod
|
|
206
251
|
def handle_mqtt_p2p(self, event_bus: EventBus, response: dict[str, Any]) -> None:
|
|
@@ -230,10 +275,29 @@ def _pop_or_raise(name: str, type_: type, data: dict[str, Any]) -> Any:
|
|
|
230
275
|
try:
|
|
231
276
|
value = data.pop(name)
|
|
232
277
|
except KeyError as err:
|
|
233
|
-
|
|
278
|
+
msg = f'"{name}" is missing in {data}'
|
|
279
|
+
raise DeebotError(msg) from err
|
|
234
280
|
try:
|
|
235
281
|
return type_(value)
|
|
236
282
|
except ValueError as err:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
283
|
+
msg = f'Could not convert "{value}" of {name} into {type_}'
|
|
284
|
+
raise DeebotError(msg) from err
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class SetCommand(CommandWithMessageHandling, CommandMqttP2P, ABC):
|
|
288
|
+
"""Base set command.
|
|
289
|
+
|
|
290
|
+
Command needs to be linked to the "get" command, for handling (updating) the sensors.
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
@property
|
|
294
|
+
@abstractmethod
|
|
295
|
+
def get_command(self) -> type[CommandWithMessageHandling]:
|
|
296
|
+
"""Return the corresponding "get" command."""
|
|
297
|
+
raise NotImplementedError # pragma: no cover
|
|
298
|
+
|
|
299
|
+
def handle_mqtt_p2p(self, event_bus: EventBus, response: dict[str, Any]) -> None:
|
|
300
|
+
"""Handle response received over the mqtt channel "p2p"."""
|
|
301
|
+
result = self.handle(event_bus, response)
|
|
302
|
+
if result.state == HandlingState.SUCCESS and isinstance(self._args, dict):
|
|
303
|
+
self.get_command.handle(event_bus, self._args)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Json commands module."""
|
|
2
2
|
from deebot_client.command import Command, CommandMqttP2P
|
|
3
3
|
|
|
4
4
|
from .advanced_mode import GetAdvancedMode, SetAdvancedMode
|
|
@@ -12,6 +12,7 @@ from .clean_logs import GetCleanLogs
|
|
|
12
12
|
from .clean_preference import GetCleanPreference, SetCleanPreference
|
|
13
13
|
from .common import JsonCommand
|
|
14
14
|
from .continuous_cleaning import GetContinuousCleaning, SetContinuousCleaning
|
|
15
|
+
from .efficiency import GetEfficiencyMode, SetEfficiencyMode
|
|
15
16
|
from .error import GetError
|
|
16
17
|
from .fan_speed import GetFanSpeed, SetFanSpeed
|
|
17
18
|
from .life_span import GetLifeSpan, ResetLifeSpan
|
|
@@ -30,6 +31,7 @@ from .pos import GetPos
|
|
|
30
31
|
from .relocation import SetRelocationState
|
|
31
32
|
from .stats import GetStats, GetTotalStats
|
|
32
33
|
from .true_detect import GetTrueDetect, SetTrueDetect
|
|
34
|
+
from .voice_assistant_state import GetVoiceAssistantState, SetVoiceAssistantState
|
|
33
35
|
from .volume import GetVolume, SetVolume
|
|
34
36
|
from .water_info import GetWaterInfo, SetWaterInfo
|
|
35
37
|
from .work_mode import GetWorkMode, SetWorkMode
|
|
@@ -52,6 +54,8 @@ __all__ = [
|
|
|
52
54
|
"GetCleanLogs",
|
|
53
55
|
"GetContinuousCleaning",
|
|
54
56
|
"SetContinuousCleaning",
|
|
57
|
+
"GetEfficiencyMode",
|
|
58
|
+
"SetEfficiencyMode",
|
|
55
59
|
"GetError",
|
|
56
60
|
"GetFanSpeed",
|
|
57
61
|
"SetFanSpeed",
|
|
@@ -73,6 +77,8 @@ __all__ = [
|
|
|
73
77
|
"GetTotalStats",
|
|
74
78
|
"GetTrueDetect",
|
|
75
79
|
"SetTrueDetect",
|
|
80
|
+
"GetVoiceAssistantState",
|
|
81
|
+
"SetVoiceAssistantState",
|
|
76
82
|
"GetVolume",
|
|
77
83
|
"SetVolume",
|
|
78
84
|
"GetWaterInfo",
|
|
@@ -111,6 +117,9 @@ _COMMANDS: list[type[JsonCommand]] = [
|
|
|
111
117
|
GetContinuousCleaning,
|
|
112
118
|
SetContinuousCleaning,
|
|
113
119
|
|
|
120
|
+
GetEfficiencyMode,
|
|
121
|
+
SetEfficiencyMode,
|
|
122
|
+
|
|
114
123
|
GetError,
|
|
115
124
|
|
|
116
125
|
GetFanSpeed,
|
|
@@ -143,6 +152,9 @@ _COMMANDS: list[type[JsonCommand]] = [
|
|
|
143
152
|
GetTrueDetect,
|
|
144
153
|
SetTrueDetect,
|
|
145
154
|
|
|
155
|
+
GetVoiceAssistantState,
|
|
156
|
+
SetVoiceAssistantState,
|
|
157
|
+
|
|
146
158
|
GetVolume,
|
|
147
159
|
SetVolume,
|
|
148
160
|
|
|
@@ -155,7 +167,8 @@ _COMMANDS: list[type[JsonCommand]] = [
|
|
|
155
167
|
# fmt: on
|
|
156
168
|
|
|
157
169
|
COMMANDS: dict[str, type[Command]] = {
|
|
158
|
-
cmd.name: cmd
|
|
170
|
+
cmd.name: cmd # type: ignore[misc]
|
|
171
|
+
for cmd in _COMMANDS
|
|
159
172
|
}
|
|
160
173
|
|
|
161
174
|
COMMANDS_WITH_MQTT_P2P_HANDLING: dict[str, type[CommandMqttP2P]] = {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"""Battery commands."""
|
|
2
2
|
from deebot_client.messages.json import OnBattery
|
|
3
3
|
|
|
4
|
-
from .common import
|
|
4
|
+
from .common import JsonCommandWithMessageHandling
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class GetBattery(OnBattery,
|
|
7
|
+
class GetBattery(OnBattery, JsonCommandWithMessageHandling):
|
|
8
8
|
"""Get battery command."""
|
|
9
9
|
|
|
10
10
|
name = "getBattery"
|
|
11
11
|
|
|
12
|
-
def __init__(self, is_available_check: bool = False) -> None:
|
|
12
|
+
def __init__(self, *, is_available_check: bool = False) -> None:
|
|
13
13
|
super().__init__()
|
|
14
14
|
self._is_available_check = is_available_check
|
|
@@ -5,7 +5,7 @@ from deebot_client.event_bus import EventBus
|
|
|
5
5
|
from deebot_client.events import StateEvent
|
|
6
6
|
from deebot_client.logging_filter import get_logger
|
|
7
7
|
from deebot_client.message import HandlingResult
|
|
8
|
-
from deebot_client.models import
|
|
8
|
+
from deebot_client.models import State
|
|
9
9
|
|
|
10
10
|
from .common import ExecuteCommand
|
|
11
11
|
from .const import CODE
|
|
@@ -29,12 +29,12 @@ class Charge(ExecuteCommand):
|
|
|
29
29
|
"""
|
|
30
30
|
code = int(body.get(CODE, -1))
|
|
31
31
|
if code == 0:
|
|
32
|
-
event_bus.notify(StateEvent(
|
|
32
|
+
event_bus.notify(StateEvent(State.RETURNING))
|
|
33
33
|
return HandlingResult.success()
|
|
34
34
|
|
|
35
35
|
if code == 30007:
|
|
36
36
|
# bot is already charging
|
|
37
|
-
event_bus.notify(StateEvent(
|
|
37
|
+
event_bus.notify(StateEvent(State.DOCKED))
|
|
38
38
|
return HandlingResult.success()
|
|
39
39
|
|
|
40
40
|
return super()._handle_body(event_bus, body)
|
{deebot-client-3.0.3.dev0 → deebot-client-4.0.0}/deebot_client/commands/json/charge_state.py
RENAMED
|
@@ -4,13 +4,13 @@ from typing import Any
|
|
|
4
4
|
from deebot_client.event_bus import EventBus
|
|
5
5
|
from deebot_client.events import StateEvent
|
|
6
6
|
from deebot_client.message import HandlingResult, MessageBodyDataDict
|
|
7
|
-
from deebot_client.models import
|
|
7
|
+
from deebot_client.models import State
|
|
8
8
|
|
|
9
|
-
from .common import
|
|
9
|
+
from .common import JsonCommandWithMessageHandling
|
|
10
10
|
from .const import CODE
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class GetChargeState(
|
|
13
|
+
class GetChargeState(JsonCommandWithMessageHandling, MessageBodyDataDict):
|
|
14
14
|
"""Get charge state command."""
|
|
15
15
|
|
|
16
16
|
name = "getChargeState"
|
|
@@ -24,7 +24,7 @@ class GetChargeState(CommandWithMessageHandling, MessageBodyDataDict):
|
|
|
24
24
|
:return: A message response
|
|
25
25
|
"""
|
|
26
26
|
if data.get("isCharging") == 1:
|
|
27
|
-
event_bus.notify(StateEvent(
|
|
27
|
+
event_bus.notify(StateEvent(State.DOCKED))
|
|
28
28
|
return HandlingResult.success()
|
|
29
29
|
|
|
30
30
|
@classmethod
|
|
@@ -33,17 +33,17 @@ class GetChargeState(CommandWithMessageHandling, MessageBodyDataDict):
|
|
|
33
33
|
# Call this also if code is not in the body
|
|
34
34
|
return super()._handle_body(event_bus, body)
|
|
35
35
|
|
|
36
|
-
status:
|
|
36
|
+
status: State | None = None
|
|
37
37
|
if body.get("msg", None) == "fail":
|
|
38
38
|
if body["code"] == "30007": # Already charging
|
|
39
|
-
status =
|
|
39
|
+
status = State.DOCKED
|
|
40
40
|
elif body["code"] in ("3", "5"):
|
|
41
41
|
# 3 -> Bot in stuck state, example dust bin out
|
|
42
42
|
# 5 -> Busy with another command
|
|
43
|
-
status =
|
|
43
|
+
status = State.ERROR
|
|
44
44
|
|
|
45
45
|
if status:
|
|
46
|
-
event_bus.notify(StateEvent(
|
|
46
|
+
event_bus.notify(StateEvent(State.DOCKED))
|
|
47
47
|
return HandlingResult.success()
|
|
48
48
|
|
|
49
49
|
return HandlingResult.analyse()
|
|
@@ -7,9 +7,9 @@ from deebot_client.event_bus import EventBus
|
|
|
7
7
|
from deebot_client.events import StateEvent
|
|
8
8
|
from deebot_client.logging_filter import get_logger
|
|
9
9
|
from deebot_client.message import HandlingResult, MessageBodyDataDict
|
|
10
|
-
from deebot_client.models import CleanAction, CleanMode, DeviceInfo,
|
|
10
|
+
from deebot_client.models import CleanAction, CleanMode, DeviceInfo, State
|
|
11
11
|
|
|
12
|
-
from .common import
|
|
12
|
+
from .common import ExecuteCommand, JsonCommandWithMessageHandling
|
|
13
13
|
|
|
14
14
|
_LOGGER = get_logger(__name__)
|
|
15
15
|
|
|
@@ -30,12 +30,12 @@ class Clean(ExecuteCommand):
|
|
|
30
30
|
if state and isinstance(self._args, dict):
|
|
31
31
|
if (
|
|
32
32
|
self._args["act"] == CleanAction.RESUME.value
|
|
33
|
-
and state.state !=
|
|
33
|
+
and state.state != State.PAUSED
|
|
34
34
|
):
|
|
35
35
|
self._args = self.__get_args(CleanAction.START)
|
|
36
36
|
elif (
|
|
37
37
|
self._args["act"] == CleanAction.START.value
|
|
38
|
-
and state.state ==
|
|
38
|
+
and state.state == State.PAUSED
|
|
39
39
|
):
|
|
40
40
|
self._args = self.__get_args(CleanAction.RESUME)
|
|
41
41
|
|
|
@@ -62,7 +62,7 @@ class CleanArea(Clean):
|
|
|
62
62
|
self._args["count"] = cleanings
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
class GetCleanInfo(
|
|
65
|
+
class GetCleanInfo(JsonCommandWithMessageHandling, MessageBodyDataDict):
|
|
66
66
|
"""Get clean info command."""
|
|
67
67
|
|
|
68
68
|
name = "getCleanInfo"
|
|
@@ -75,20 +75,19 @@ class GetCleanInfo(CommandWithMessageHandling, MessageBodyDataDict):
|
|
|
75
75
|
|
|
76
76
|
:return: A message response
|
|
77
77
|
"""
|
|
78
|
-
|
|
79
|
-
status: VacuumState | None = None
|
|
78
|
+
status: State | None = None
|
|
80
79
|
state = data.get("state")
|
|
81
80
|
if data.get("trigger") == "alert":
|
|
82
|
-
status =
|
|
81
|
+
status = State.ERROR
|
|
83
82
|
elif state == "clean":
|
|
84
83
|
clean_state = data.get("cleanState", {})
|
|
85
84
|
motion_state = clean_state.get("motionState")
|
|
86
85
|
if motion_state == "working":
|
|
87
|
-
status =
|
|
86
|
+
status = State.CLEANING
|
|
88
87
|
elif motion_state == "pause":
|
|
89
|
-
status =
|
|
88
|
+
status = State.PAUSED
|
|
90
89
|
elif motion_state == "goCharging":
|
|
91
|
-
status =
|
|
90
|
+
status = State.RETURNING
|
|
92
91
|
|
|
93
92
|
clean_type = clean_state.get("type")
|
|
94
93
|
content = clean_state.get("content", {})
|
|
@@ -103,9 +102,9 @@ class GetCleanInfo(CommandWithMessageHandling, MessageBodyDataDict):
|
|
|
103
102
|
_LOGGER.debug("Last custom area values (x1,y1,x2,y2): %s", area_values)
|
|
104
103
|
|
|
105
104
|
elif state == "goCharging":
|
|
106
|
-
status =
|
|
105
|
+
status = State.RETURNING
|
|
107
106
|
elif state == "idle":
|
|
108
|
-
status =
|
|
107
|
+
status = State.IDLE
|
|
109
108
|
|
|
110
109
|
if status:
|
|
111
110
|
event_bus.notify(StateEvent(status))
|