Skip to content

Commit cd1c53a

Browse files
committed
reduce how often we call for errors, update pymammotion to handle bad bluetooth, send commands regardless of mqtt connected state
1 parent cb636b0 commit cd1c53a

3 files changed

Lines changed: 58 additions & 30 deletions

File tree

custom_components/mammotion/coordinator.py

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -283,16 +283,25 @@ async def async_refresh_login(self, exc: Exception | None = None) -> None:
283283
raise ConfigEntryAuthFailed(
284284
f"Login failed for Mammotion account: {exc.reason}"
285285
) from exc
286-
if (
287-
isinstance(exc, SessionExpiredError)
288-
and self.manager.token_manager is not None
289-
):
290-
await self.manager.token_manager.refresh_aliyun_credentials()
291-
elif isinstance(exc, AuthError) and self.manager.token_manager is not None:
292-
await self.manager.token_manager.refresh_mqtt_credentials()
293-
else:
294-
await self.manager.refresh_login(self.account)
295-
self.store_cloud_credentials()
286+
try:
287+
if (
288+
isinstance(exc, SessionExpiredError)
289+
and self.manager.token_manager is not None
290+
):
291+
await self.manager.token_manager.refresh_aliyun_credentials()
292+
elif isinstance(exc, AuthError) and self.manager.token_manager is not None:
293+
await self.manager.token_manager.refresh_mqtt_credentials()
294+
else:
295+
await self.manager.refresh_login(self.account)
296+
self.store_cloud_credentials()
297+
except ReLoginRequiredError:
298+
try:
299+
await self.manager.refresh_login(self.account)
300+
self.store_cloud_credentials()
301+
except LoginFailedError as err:
302+
raise ConfigEntryAuthFailed(
303+
f"Login failed for Mammotion account: {err.reason}"
304+
) from err
296305

297306
async def async_send_and_wait(
298307
self,
@@ -982,13 +991,7 @@ async def async_shutdown(self) -> None:
982991
await super().async_shutdown()
983992

984993
async def _on_state_changed(self, snapshot: Any) -> None:
985-
"""Push updated device data to HA without triggering a full refresh.
986-
987-
Triggering async_request_refresh() here caused a feedback loop: every
988-
incoming report mutates state, which would trigger a refresh, which
989-
sends another get_report_cfg, producing more reports. Pushing the
990-
data update directly keeps entities in sync without re-issuing commands.
991-
"""
994+
"""Push updated device data to HA."""
992995
device = self.manager.get_device_by_name(self.device_name)
993996
if device is not None:
994997
self.async_set_updated_data(self.get_coordinator_data(device))
@@ -1535,26 +1538,51 @@ async def _async_update_data(self) -> MowingDevice:
15351538
if data := await super()._async_update_data():
15361539
return data
15371540
device = self.manager.get_device_by_name(self.device_name)
1538-
try:
1541+
if device.report_data.dev.sys_status in (
1542+
WorkMode.MODE_WORKING,
1543+
WorkMode.MODE_RETURNING,
1544+
WorkMode.MODE_LOCK,
1545+
):
1546+
try:
1547+
await self.async_send_and_wait(
1548+
"read_write_device", "bidire_comm_cmd", rw_id=5, rw=1, context=2
1549+
)
1550+
await self.async_send_and_wait(
1551+
"read_write_device", "bidire_comm_cmd", rw_id=5, rw=1, context=3
1552+
)
1553+
if not device.errors.error_codes:
1554+
http = self.manager.mammotion_http
1555+
if http is not None:
1556+
device.errors.error_codes = await http.get_all_error_codes()
1557+
except DeviceOfflineException:
1558+
return device
1559+
1560+
return device
1561+
1562+
async def _on_sys_status_changed(self, sys_status: WorkMode) -> None:
1563+
"""Handle sys status changed."""
1564+
if sys_status in (
1565+
WorkMode.MODE_WORKING,
1566+
WorkMode.MODE_RETURNING,
1567+
WorkMode.MODE_LOCK,
1568+
WorkMode.MODE_PAUSE,
1569+
):
15391570
await self.async_send_and_wait(
15401571
"read_write_device", "bidire_comm_cmd", rw_id=5, rw=1, context=2
15411572
)
15421573
await self.async_send_and_wait(
15431574
"read_write_device", "bidire_comm_cmd", rw_id=5, rw=1, context=3
15441575
)
1545-
if not device.errors.error_codes:
1546-
http = self.manager.mammotion_http
1547-
if http is not None:
1548-
device.errors.error_codes = await http.get_all_error_codes()
1549-
except DeviceOfflineException:
1550-
return device
1551-
1552-
return device
15531576

15541577
async def _async_setup(self) -> None:
15551578
"""Setup device version coordinator."""
15561579
await super()._async_setup()
15571580
device = self.manager.get_device_by_name(self.device_name)
1581+
if handle := self.manager.mower(self.device_name):
1582+
handle.watch_field(
1583+
lambda s: s.raw.report_data.dev.sys_status,
1584+
self._on_sys_status_changed,
1585+
)
15581586

15591587
try:
15601588
await self.async_send_and_wait(

custom_components/mammotion/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"domain": "mammotion",
33
"name": "Mammotion",
4-
"version": "0.5.11",
4+
"version": "0.5.12",
55
"issue_tracker": "https://github.com/mikey0000/Mammotion-HA/issues",
66
"integration_type": "device",
77
"bluetooth": [
@@ -22,5 +22,5 @@
2222
"documentation": "https://github.com/mikey0000/Mammotion-HA/wiki",
2323
"loggers": ["pymammotion"],
2424
"iot_class": "local_push",
25-
"requirements": ["pymammotion==0.7.61"]
25+
"requirements": ["pymammotion==0.7.62"]
2626
}

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
[tool.poetry]
22
name = "Mammotion-HA"
3-
version = "0.5.11"
3+
version = "0.5.12"
44
description = "Mammotion integration for HACS"
55
authors = ["Michael Arthur <michael@jumblesoft.co.nz>", "jLynx <@jlynx>"]
66
readme = "README.md"
77
package-mode = false
88

99
[tool.poetry.dependencies]
1010
python = "~3.13.2"
11-
pymammotion = "0.7.61"
11+
pymammotion = "0.7.62"
1212
homeassistant = "^2026.1.0"
1313
autotyping = "^24.3.0"
1414
websockets = "^15.0.1"

0 commit comments

Comments
 (0)