pysmarlaapi 0.9.3__py3-none-any.whl → 0.10.0__py3-none-any.whl
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.
Potentially problematic release.
This version of pysmarlaapi might be problematic. Click here for more details.
- pysmarlaapi/__init__.py +1 -1
- pysmarlaapi/connection_hub/__init__.py +39 -7
- pysmarlaapi/federwiege/__init__.py +3 -1
- pysmarlaapi/federwiege/services/__init__.py +1 -0
- pysmarlaapi/federwiege/services/analyser_service.py +19 -0
- pysmarlaapi/federwiege/services/info_service.py +18 -0
- pysmarlaapi/federwiege/services/system_service.py +65 -0
- pysmarlaapi/federwiege/types/__init__.py +3 -0
- pysmarlaapi/federwiege/types/send_diag_status.py +8 -0
- pysmarlaapi/federwiege/types/spring_status.py +10 -0
- pysmarlaapi/federwiege/types/update_status.py +8 -0
- {pysmarlaapi-0.9.3.dist-info → pysmarlaapi-0.10.0.dist-info}/METADATA +1 -1
- pysmarlaapi-0.10.0.dist-info/RECORD +22 -0
- pysmarlaapi-0.9.3.dist-info/RECORD +0 -17
- {pysmarlaapi-0.9.3.dist-info → pysmarlaapi-0.10.0.dist-info}/WHEEL +0 -0
- {pysmarlaapi-0.9.3.dist-info → pysmarlaapi-0.10.0.dist-info}/licenses/LICENSE +0 -0
pysmarlaapi/__init__.py
CHANGED
|
@@ -9,11 +9,12 @@ from pysignalr.transport.abstract import ConnectionState
|
|
|
9
9
|
from ..classes import Connection
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
async def event_wait(event, timeout):
|
|
12
|
+
async def event_wait(event, timeout) -> bool:
|
|
13
13
|
try:
|
|
14
14
|
await asyncio.wait_for(event.wait(), timeout)
|
|
15
15
|
except asyncio.TimeoutError:
|
|
16
|
-
return
|
|
16
|
+
return False
|
|
17
|
+
return True
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
# suppress warnings from pysignalr (to avoid missing client method warnings)
|
|
@@ -38,11 +39,13 @@ class ConnectionHub:
|
|
|
38
39
|
event_loop: asyncio.AbstractEventLoop,
|
|
39
40
|
connection: Connection,
|
|
40
41
|
max_delay: int = 256,
|
|
42
|
+
forced_reconnect_interval: int = 86400,
|
|
41
43
|
):
|
|
42
44
|
self.connection: Connection = connection
|
|
43
45
|
self._loop = event_loop
|
|
44
46
|
self._retry_delay = 1 # Initial connection retry delay
|
|
45
47
|
self._max_delay = max_delay
|
|
48
|
+
self._forced_reconnect_interval = forced_reconnect_interval
|
|
46
49
|
|
|
47
50
|
self.logger = logging.getLogger(f"{__package__}[{self.connection.token.serialNumber}]")
|
|
48
51
|
|
|
@@ -51,6 +54,10 @@ class ConnectionHub:
|
|
|
51
54
|
self._running = False
|
|
52
55
|
self._wake = asyncio.Event()
|
|
53
56
|
|
|
57
|
+
self._reconnect_future: asyncio.Future = None
|
|
58
|
+
self._reconnect_lock = asyncio.Lock()
|
|
59
|
+
self._reconnect_cancel_event = asyncio.Event()
|
|
60
|
+
|
|
54
61
|
self.client = None
|
|
55
62
|
self.setup()
|
|
56
63
|
|
|
@@ -85,9 +92,11 @@ class ConnectionHub:
|
|
|
85
92
|
async def on_open_function(self):
|
|
86
93
|
self._retry_delay = 1
|
|
87
94
|
self.logger.info("Connection to server established")
|
|
95
|
+
await self.start_reconnect_job()
|
|
88
96
|
|
|
89
97
|
async def on_close_function(self):
|
|
90
98
|
self.logger.info("Connection to server closed")
|
|
99
|
+
await self.cancel_reconnect_job()
|
|
91
100
|
|
|
92
101
|
async def on_error(self, message):
|
|
93
102
|
self.logger.error("Connection error occurred: %s", str(message))
|
|
@@ -102,8 +111,8 @@ class ConnectionHub:
|
|
|
102
111
|
if not self.running:
|
|
103
112
|
return
|
|
104
113
|
self._running = False
|
|
105
|
-
self.close_connection()
|
|
106
114
|
self.wake_up()
|
|
115
|
+
asyncio.run_coroutine_threadsafe(self.close_connection(), self._loop)
|
|
107
116
|
|
|
108
117
|
async def connection_watcher(self):
|
|
109
118
|
while self.running:
|
|
@@ -115,7 +124,8 @@ class ConnectionHub:
|
|
|
115
124
|
|
|
116
125
|
# Random backoff to avoid simultaneous connection attempts
|
|
117
126
|
jitter = random.uniform(0, 0.5) * self._retry_delay
|
|
118
|
-
|
|
127
|
+
delay = self._retry_delay + jitter
|
|
128
|
+
await event_wait(self._wake, delay)
|
|
119
129
|
self._wake.clear()
|
|
120
130
|
|
|
121
131
|
# Double the delay for the next attempt
|
|
@@ -125,10 +135,32 @@ class ConnectionHub:
|
|
|
125
135
|
def wake_up(self):
|
|
126
136
|
self._wake.set()
|
|
127
137
|
|
|
128
|
-
def close_connection(self):
|
|
129
|
-
|
|
138
|
+
async def close_connection(self):
|
|
139
|
+
await self.cancel_reconnect_job()
|
|
140
|
+
await self.client._transport._ws.close()
|
|
141
|
+
|
|
142
|
+
async def start_reconnect_job(self):
|
|
143
|
+
async with self._reconnect_lock:
|
|
144
|
+
if self._reconnect_future and not self._reconnect_future.done():
|
|
145
|
+
return
|
|
146
|
+
self._reconnect_cancel_event.clear()
|
|
147
|
+
self._reconnect_future = asyncio.create_task(self.reconnect_job())
|
|
148
|
+
|
|
149
|
+
async def cancel_reconnect_job(self):
|
|
150
|
+
async with self._reconnect_lock:
|
|
151
|
+
if not self._reconnect_future or self._reconnect_future.done():
|
|
152
|
+
return
|
|
153
|
+
self._reconnect_cancel_event.set()
|
|
154
|
+
await self._reconnect_future
|
|
155
|
+
|
|
156
|
+
async def reconnect_job(self):
|
|
157
|
+
cancelled = await event_wait(self._reconnect_cancel_event, self._forced_reconnect_interval)
|
|
158
|
+
if cancelled:
|
|
130
159
|
return
|
|
131
|
-
|
|
160
|
+
|
|
161
|
+
# Close connection to trigger a reconnection
|
|
162
|
+
# Make sure that connection stays healthy
|
|
163
|
+
await self.client._transport._ws.close()
|
|
132
164
|
|
|
133
165
|
async def refresh_token(self):
|
|
134
166
|
await self.connection.refresh_token()
|
|
@@ -4,7 +4,8 @@ import threading
|
|
|
4
4
|
from ..classes import Connection
|
|
5
5
|
from ..connection_hub import ConnectionHub
|
|
6
6
|
from .classes import Service
|
|
7
|
-
from .services import AnalyserService, BabywiegeService, InfoService
|
|
7
|
+
from .services import (AnalyserService, BabywiegeService, InfoService,
|
|
8
|
+
SystemService)
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class Federwiege:
|
|
@@ -29,6 +30,7 @@ class Federwiege:
|
|
|
29
30
|
"babywiege": BabywiegeService(self.hub),
|
|
30
31
|
"analyser": AnalyserService(self.hub),
|
|
31
32
|
"info": InfoService(self.hub),
|
|
33
|
+
"system": SystemService(self.hub),
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
self.registered = False
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from ...connection_hub import ConnectionHub
|
|
2
2
|
from ..classes import Property, Service
|
|
3
|
+
from ..types import SpringStatus
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class AnalyserService(Service):
|
|
@@ -9,6 +10,7 @@ class AnalyserService(Service):
|
|
|
9
10
|
self.add_property("oscillation", OscillationProperty(hub))
|
|
10
11
|
self.add_property("activity", ActivityProperty(hub))
|
|
11
12
|
self.add_property("swing_count", SwingCountProperty(hub))
|
|
13
|
+
self.add_property("spring_status", SpringStatusProperty(hub))
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class OscillationProperty(Property[list[int]]):
|
|
@@ -60,3 +62,20 @@ class SwingCountProperty(Property[int]):
|
|
|
60
62
|
|
|
61
63
|
def register(self):
|
|
62
64
|
self.hub.client.on("GetSwingCountCallback", self.on_callback)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class SpringStatusProperty(Property[SpringStatus]):
|
|
68
|
+
|
|
69
|
+
async def on_callback(self, args):
|
|
70
|
+
value = args[0]["value"]
|
|
71
|
+
self.set(value, push=False)
|
|
72
|
+
await self.notify_listeners()
|
|
73
|
+
|
|
74
|
+
def __init__(self, hub: ConnectionHub):
|
|
75
|
+
super().__init__(hub)
|
|
76
|
+
|
|
77
|
+
def pull(self):
|
|
78
|
+
self.hub.send_serialized_data("GetSpringStatus")
|
|
79
|
+
|
|
80
|
+
def register(self):
|
|
81
|
+
self.hub.client.on("GetSpringStatusCallback", self.on_callback)
|
|
@@ -8,6 +8,7 @@ class InfoService(Service):
|
|
|
8
8
|
super().__init__()
|
|
9
9
|
self.add_property("display_name", DisplayNameProperty(hub))
|
|
10
10
|
self.add_property("version", VersionProperty(hub))
|
|
11
|
+
self.add_property("total_swing_time", TotalSwingTimeProperty(hub))
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class DisplayNameProperty(Property[str]):
|
|
@@ -42,3 +43,20 @@ class VersionProperty(Property[str]):
|
|
|
42
43
|
|
|
43
44
|
def register(self):
|
|
44
45
|
self.hub.client.on("GetVersionCallback", self.on_callback)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TotalSwingTimeProperty(Property[int]):
|
|
49
|
+
|
|
50
|
+
async def on_callback(self, args):
|
|
51
|
+
value = args[0]["value"]
|
|
52
|
+
self.set(value, push=False)
|
|
53
|
+
await self.notify_listeners()
|
|
54
|
+
|
|
55
|
+
def __init__(self, hub: ConnectionHub):
|
|
56
|
+
super().__init__(hub)
|
|
57
|
+
|
|
58
|
+
def pull(self):
|
|
59
|
+
self.hub.send_serialized_data("GetTotalSwingTime")
|
|
60
|
+
|
|
61
|
+
def register(self):
|
|
62
|
+
self.hub.client.on("GetTotalSwingTimeCallback", self.on_callback)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from ...connection_hub import ConnectionHub
|
|
2
|
+
from ..classes import Property, Service
|
|
3
|
+
from ..types import SendDiagStatus, UpdateStatus
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SystemService(Service):
|
|
7
|
+
|
|
8
|
+
def __init__(self, hub: ConnectionHub):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self.add_property("firmware_update", FirmwareUpdateProperty(hub))
|
|
11
|
+
self.add_property("firmware_update_status", FirmwareUpdateStatusProperty(hub))
|
|
12
|
+
self.add_property("send_diagnostic_data", SendDiagnosticDataProperty(hub))
|
|
13
|
+
self.add_property("send_diagnostic_data_status", SendDiagnosticDataStatusProperty(hub))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FirmwareUpdateProperty(Property[int]):
|
|
17
|
+
|
|
18
|
+
def __init__(self, hub: ConnectionHub):
|
|
19
|
+
super().__init__(hub)
|
|
20
|
+
|
|
21
|
+
def push(self, value: int):
|
|
22
|
+
self.hub.send_serialized_data("SetFirmwareUpdate", value)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FirmwareUpdateStatusProperty(Property[UpdateStatus]):
|
|
26
|
+
|
|
27
|
+
async def on_callback(self, args):
|
|
28
|
+
value = args[0]["value"]
|
|
29
|
+
self.set(value, push=False)
|
|
30
|
+
await self.notify_listeners()
|
|
31
|
+
|
|
32
|
+
def __init__(self, hub: ConnectionHub):
|
|
33
|
+
super().__init__(hub)
|
|
34
|
+
|
|
35
|
+
def pull(self):
|
|
36
|
+
self.hub.send_serialized_data("GetFirmwareUpdate")
|
|
37
|
+
|
|
38
|
+
def register(self):
|
|
39
|
+
self.hub.client.on("GetFirmwareUpdateCallback", self.on_callback)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SendDiagnosticDataProperty(Property[str]):
|
|
43
|
+
|
|
44
|
+
def __init__(self, hub: ConnectionHub):
|
|
45
|
+
super().__init__(hub)
|
|
46
|
+
|
|
47
|
+
def push(self, value: str):
|
|
48
|
+
self.hub.send_serialized_data("SetSendDiagnosticData", value)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class SendDiagnosticDataStatusProperty(Property[SendDiagStatus]):
|
|
52
|
+
|
|
53
|
+
async def on_callback(self, args):
|
|
54
|
+
value = args[0]["value"]
|
|
55
|
+
self.set(value, push=False)
|
|
56
|
+
await self.notify_listeners()
|
|
57
|
+
|
|
58
|
+
def __init__(self, hub: ConnectionHub):
|
|
59
|
+
super().__init__(hub)
|
|
60
|
+
|
|
61
|
+
def pull(self):
|
|
62
|
+
self.hub.send_serialized_data("GetSendDiagnosticData")
|
|
63
|
+
|
|
64
|
+
def register(self):
|
|
65
|
+
self.hub.client.on("GetSendDiagnosticDataCallback", self.on_callback)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
pysmarlaapi/__init__.py,sha256=zAudM0e9KJckKmuJx89xr-nMMJj0gHfFJGPgdjOAIPA,91
|
|
2
|
+
pysmarlaapi/classes/__init__.py,sha256=N-ZV3Id_t5ciovUlPUGCk5SLLiMUonRoQZWpfOU4ZsM,69
|
|
3
|
+
pysmarlaapi/classes/auth_token.py,sha256=dpo0lBT9Advm3Iyxu-fT9sq078U2OxgXXBuF5gbBZkM,942
|
|
4
|
+
pysmarlaapi/classes/connection.py,sha256=vVC0Ur0KQUb4pNDVuCYnfk-JXs-O-FwYVO-2y1E2g6g,1551
|
|
5
|
+
pysmarlaapi/connection_hub/__init__.py,sha256=Rk-1JOXQGWKuGR3lJbf_svJA7tXAgOn6Un62UvY9mxM,6103
|
|
6
|
+
pysmarlaapi/federwiege/__init__.py,sha256=P3hpgf-okQDEpwCUiLHn1acnenURUorEDVFya9Dvk6M,2020
|
|
7
|
+
pysmarlaapi/federwiege/classes/__init__.py,sha256=DFJJVOKpra40S4ZX_oq2RyMazg6Nx0c8hoPggmj1bXA,60
|
|
8
|
+
pysmarlaapi/federwiege/classes/property.py,sha256=S5Zzo9cXDJMFcQG1vCw1eO-oqeSpQs2YjxWouN_KRkU,1032
|
|
9
|
+
pysmarlaapi/federwiege/classes/service.py,sha256=Y0OQxtQLaHp4qY8Vthj0zRroPoYTiD2WA9ZR96teZTo,632
|
|
10
|
+
pysmarlaapi/federwiege/services/__init__.py,sha256=qhsnybmBF7K1sR2IdfL4FAmAtJGla66NqrMiJrDlCvU,174
|
|
11
|
+
pysmarlaapi/federwiege/services/analyser_service.py,sha256=Fzc4zK-IIVkIllAq32tzf1QkkeYc4SGSU_8YISOW2C0,2249
|
|
12
|
+
pysmarlaapi/federwiege/services/babywiege_service.py,sha256=6u0fSsRoWfv6A0Qad1WLD2yeRHMGnwbKVOJLxEqwzGE,1979
|
|
13
|
+
pysmarlaapi/federwiege/services/info_service.py,sha256=DJNzz7Z6vx2VXhr7CkCuB2CbCY3YCnTy21PvfjGf-bU,1702
|
|
14
|
+
pysmarlaapi/federwiege/services/system_service.py,sha256=88MGFfdyXny8D8lWKMtcu96UX0ZAcC9QER000WC8cgY,1967
|
|
15
|
+
pysmarlaapi/federwiege/types/__init__.py,sha256=XWB_IrNYbIyQjyR_oKAOvHAjGGRLSQqZka0t_oc60ts,125
|
|
16
|
+
pysmarlaapi/federwiege/types/send_diag_status.py,sha256=hxpfNQmZs1YOztxLVnN3Bu50fXwf-hfV6K8GiQlBvkk,120
|
|
17
|
+
pysmarlaapi/federwiege/types/spring_status.py,sha256=cJsWFf2ZG-NvnT3l_CxVJfMFB3Ruv_juTy7Lpb-YEsA,227
|
|
18
|
+
pysmarlaapi/federwiege/types/update_status.py,sha256=YkajOEJ09pY9u4EBxw8ePEjPjYOLdK0i2l41cXbjb8Y,123
|
|
19
|
+
pysmarlaapi-0.10.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
20
|
+
pysmarlaapi-0.10.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
21
|
+
pysmarlaapi-0.10.0.dist-info/METADATA,sha256=x0F0aN-u_aKLLWPP7PF2GGWsr6jMFeLAyH-zL0Aiy9k,1104
|
|
22
|
+
pysmarlaapi-0.10.0.dist-info/RECORD,,
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
pysmarlaapi/__init__.py,sha256=xSrA3ZAl-0UUKk_KVble3F2UoRkGUAanIJvs0ZO7EXI,90
|
|
2
|
-
pysmarlaapi/classes/__init__.py,sha256=N-ZV3Id_t5ciovUlPUGCk5SLLiMUonRoQZWpfOU4ZsM,69
|
|
3
|
-
pysmarlaapi/classes/auth_token.py,sha256=dpo0lBT9Advm3Iyxu-fT9sq078U2OxgXXBuF5gbBZkM,942
|
|
4
|
-
pysmarlaapi/classes/connection.py,sha256=vVC0Ur0KQUb4pNDVuCYnfk-JXs-O-FwYVO-2y1E2g6g,1551
|
|
5
|
-
pysmarlaapi/connection_hub/__init__.py,sha256=k8s4VNO0QeINLycN94Fl5YXr1PcHkfvEI8GWimqTD_A,4776
|
|
6
|
-
pysmarlaapi/federwiege/__init__.py,sha256=7Fl_GnwN6GbS8fhkHdfMhuYFospKnap40pvUtSGIeoE,1933
|
|
7
|
-
pysmarlaapi/federwiege/classes/__init__.py,sha256=DFJJVOKpra40S4ZX_oq2RyMazg6Nx0c8hoPggmj1bXA,60
|
|
8
|
-
pysmarlaapi/federwiege/classes/property.py,sha256=S5Zzo9cXDJMFcQG1vCw1eO-oqeSpQs2YjxWouN_KRkU,1032
|
|
9
|
-
pysmarlaapi/federwiege/classes/service.py,sha256=Y0OQxtQLaHp4qY8Vthj0zRroPoYTiD2WA9ZR96teZTo,632
|
|
10
|
-
pysmarlaapi/federwiege/services/__init__.py,sha256=bJuOsk0lw9WWxB1NZodRTL8Pm_Ra8CuTCxNh33WzxkQ,132
|
|
11
|
-
pysmarlaapi/federwiege/services/analyser_service.py,sha256=xRPvSO5FdwX-gqWLWYQq8zvQSPnkE5Y3d-kG7N3awgg,1695
|
|
12
|
-
pysmarlaapi/federwiege/services/babywiege_service.py,sha256=6u0fSsRoWfv6A0Qad1WLD2yeRHMGnwbKVOJLxEqwzGE,1979
|
|
13
|
-
pysmarlaapi/federwiege/services/info_service.py,sha256=XqMSMU3BusB85V0O93rzliuJCK_H-PE4kXqJX-v7Kc4,1179
|
|
14
|
-
pysmarlaapi-0.9.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
15
|
-
pysmarlaapi-0.9.3.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
16
|
-
pysmarlaapi-0.9.3.dist-info/METADATA,sha256=3iezX1ozOGN0Q9g2Wnff0-w_lJmZlAfYS6avnhjOTmI,1103
|
|
17
|
-
pysmarlaapi-0.9.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|