11
11
import weakref
12
12
from zoneinfo import ZoneInfo
13
13
14
- from aiohttp import ServerDisconnectedError
14
+ import aiohttp
15
15
from homeassistant .core import callback
16
16
from homeassistant .helpers import device_registry as dr
17
- from homeassistant .helpers .aiohttp_client import async_get_clientsession
18
17
from homeassistant .util import dt as dt_util
19
18
import voluptuous as vol
20
19
@@ -1039,7 +1038,7 @@ async def async_http_request_raw(
1039
1038
self .TRACE_TX ,
1040
1039
)
1041
1040
try :
1042
- response = await http .async_request_message (request )
1041
+ response = await http .async_request_raw (request . json () )
1043
1042
self .device_response_size_min = max (
1044
1043
self .device_response_size_min , len (response .json ())
1045
1044
)
@@ -1104,13 +1103,13 @@ async def async_http_request_raw(
1104
1103
ProtocolSensor .ATTR_HTTP
1105
1104
)
1106
1105
elif namespace is mc .NS_APPLIANCE_CONTROL_UNBIND :
1107
- if isinstance (exception , ServerDisconnectedError ):
1106
+ if isinstance (exception , aiohttp . ServerDisconnectedError ):
1108
1107
# this is expected when issuing the UNBIND
1109
1108
# so this is an indication we're dead
1110
1109
self ._set_offline ()
1111
1110
return None
1112
1111
elif namespace is mc .NS_APPLIANCE_CONTROL_MULTIPLE :
1113
- if isinstance (exception , ServerDisconnectedError ):
1112
+ if isinstance (exception , aiohttp . ServerDisconnectedError ):
1114
1113
# this happens (instead of JSONDecodeError)
1115
1114
# on my msl120. I guess the (older) fw behaves
1116
1115
# differently than those responding incomplete json.
@@ -1129,8 +1128,14 @@ async def async_http_request_raw(
1129
1128
)
1130
1129
return None
1131
1130
1132
- if isinstance (exception , asyncio .TimeoutError ):
1131
+ if isinstance (exception , asyncio .TimeoutError ) or isinstance (
1132
+ exception , aiohttp .ServerTimeoutError
1133
+ ):
1133
1134
return None
1135
+
1136
+ # for any other exception we could guess the device
1137
+ # is stalling a bit so we just wait a bit before re-issuing
1138
+ await asyncio .sleep (0.5 )
1134
1139
else :
1135
1140
return None
1136
1141
@@ -1326,7 +1331,7 @@ async def _async_polling_callback(self, namespace: str):
1326
1331
self ._timezone_next_check = (
1327
1332
epoch + PARAM_TIMEZONE_CHECK_NOTOK_PERIOD
1328
1333
)
1329
- if self .device_timedelta < PARAM_TIMESTAMP_TOLERANCE :
1334
+ if abs ( self .device_timedelta ) < PARAM_TIMESTAMP_TOLERANCE :
1330
1335
with self .exception_warning ("_check_device_timerules" ):
1331
1336
if self ._check_device_timerules ():
1332
1337
# timezone trans not good..fix and check again soon
@@ -1356,7 +1361,9 @@ async def _async_polling_callback(self, namespace: str):
1356
1361
ns_all_response = await self .async_http_request (* ns_all )
1357
1362
1358
1363
if ns_all_response :
1359
- self .polling_strategies [mc .NS_APPLIANCE_SYSTEM_ALL ].response_size = len (ns_all_response .json ())
1364
+ self .polling_strategies [
1365
+ mc .NS_APPLIANCE_SYSTEM_ALL
1366
+ ].response_size = len (ns_all_response .json ())
1360
1367
await self ._async_request_updates (epoch , mc .NS_APPLIANCE_SYSTEM_ALL )
1361
1368
else :
1362
1369
if self ._polling_delay < PARAM_HEARTBEAT_PERIOD :
@@ -1503,11 +1510,7 @@ def _check_protocol(self):
1503
1510
self .sensor_protocol .update_attr_inactive (ProtocolSensor .ATTR_HTTP )
1504
1511
else :
1505
1512
if host := self .host :
1506
- self ._http = MerossHttpClient (
1507
- host ,
1508
- self .key ,
1509
- async_get_clientsession (self .hass ),
1510
- )
1513
+ self ._http = MerossHttpClient (host , self .key )
1511
1514
1512
1515
if conf_protocol is CONF_PROTOCOL_AUTO :
1513
1516
# When using CONF_PROTOCOL_AUTO we try to use our 'preferred' (pref_protocol)
@@ -1570,21 +1573,19 @@ def _receive(self, epoch: float, message: MerossResponse):
1570
1573
# We ignore delays below PARAM_TIMESTAMP_TOLERANCE since
1571
1574
# we'll always be a bit late in processing
1572
1575
self .device_timestamp = header [mc .KEY_TIMESTAMP ]
1573
- device_timedelta = epoch - self .device_timestamp
1574
- if abs (device_timedelta ) > PARAM_TIMESTAMP_TOLERANCE :
1575
- if (
1576
- abs (self .device_timedelta - device_timedelta )
1577
- > PARAM_TIMESTAMP_TOLERANCE
1578
- ):
1579
- # big step so we're not averaging
1580
- self .device_timedelta = device_timedelta
1581
- else : # average the sampled timedelta
1582
- self .device_timedelta = (
1583
- 4 * self .device_timedelta + device_timedelta
1584
- ) / 5
1585
- self ._config_device_timestamp (epoch )
1586
- else :
1587
- self .device_timedelta = 0
1576
+ self .device_timedelta = (
1577
+ 9 * self .device_timedelta + (epoch - self .device_timestamp )
1578
+ ) / 10
1579
+ if abs (self .device_timedelta ) > PARAM_TIMESTAMP_TOLERANCE :
1580
+ if not self ._config_device_timestamp (epoch ):
1581
+ if (epoch - self .device_timedelta_log_epoch ) > 604800 : # 1 week lockout
1582
+ self .device_timedelta_log_epoch = epoch
1583
+ self .log (
1584
+ self .WARNING ,
1585
+ "Incorrect timestamp: %d seconds behind HA (%d on average)" ,
1586
+ int (epoch - self .device_timestamp ),
1587
+ int (self .device_timedelta ),
1588
+ )
1588
1589
1589
1590
if self .isEnabledFor (self .DEBUG ):
1590
1591
# it appears sometimes the devices
@@ -1746,11 +1747,7 @@ def _handle_Appliance_System_All(self, header: dict, payload: dict):
1746
1747
if _http := self ._http :
1747
1748
_http .host = host
1748
1749
else :
1749
- self ._http = MerossHttpClient (
1750
- host ,
1751
- self .key ,
1752
- async_get_clientsession (self .hass ),
1753
- )
1750
+ self ._http = MerossHttpClient (host , self .key )
1754
1751
1755
1752
if self .conf_protocol is CONF_PROTOCOL_AUTO :
1756
1753
if self ._mqtt_active :
@@ -1814,18 +1811,12 @@ def _config_device_timestamp(self, epoch):
1814
1811
# the procedure too often
1815
1812
self .mqtt_request (* request_push (mc .NS_APPLIANCE_SYSTEM_CLOCK ))
1816
1813
self .device_timedelta_config_epoch = epoch
1817
- return
1814
+ return True
1818
1815
if last_config_delay < 30 :
1819
1816
# 30 sec 'deadzone' where we allow the timestamp
1820
1817
# transaction to complete (should really be like few seconds)
1821
- return
1822
- if (epoch - self .device_timedelta_log_epoch ) > 604800 : # 1 week lockout
1823
- self .device_timedelta_log_epoch = epoch
1824
- self .log (
1825
- self .WARNING ,
1826
- "Incorrect timestamp: %d seconds behind HA" ,
1827
- int (self .device_timedelta ),
1828
- )
1818
+ return True
1819
+ return False
1829
1820
1830
1821
def _check_device_timerules (self ) -> bool :
1831
1822
"""
0 commit comments