python-dali 0.14__py3-none-any.whl → 0.16__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.
- dali/driver/serial.py +36 -16
- dali/tests/test_serial_driver.py +50 -1
- {python_dali-0.14.dist-info → python_dali-0.16.dist-info}/METADATA +2 -2
- {python_dali-0.14.dist-info → python_dali-0.16.dist-info}/RECORD +9 -9
- {python_dali-0.14.dist-info → python_dali-0.16.dist-info}/WHEEL +1 -1
- {python_dali-0.14.dist-info → python_dali-0.16.dist-info}/licenses/COPYING +0 -0
- {python_dali-0.14.dist-info → python_dali-0.16.dist-info}/licenses/COPYING.LESSER +0 -0
- {python_dali-0.14.dist-info → python_dali-0.16.dist-info}/licenses/LICENSE +0 -0
- {python_dali-0.14.dist-info → python_dali-0.16.dist-info}/top_level.txt +0 -0
dali/driver/serial.py
CHANGED
|
@@ -660,18 +660,30 @@ class DriverLubaRs232(DriverSerialBase):
|
|
|
660
660
|
)
|
|
661
661
|
if confirm.error_code is not None:
|
|
662
662
|
raise TransmissionError(confirm.error_code)
|
|
663
|
+
if (
|
|
664
|
+
hasattr(confirm.message, "frame")
|
|
665
|
+
and confirm.message.frame != tx.frame
|
|
666
|
+
):
|
|
667
|
+
# A confirmation for a different frame can only be a
|
|
668
|
+
# stale one for an earlier send whose confirmation
|
|
669
|
+
# arrived after it had already timed out: sends are
|
|
670
|
+
# serialised under '_tx_lock', so nothing later is in
|
|
671
|
+
# flight yet. Drop it and keep waiting for this frame's
|
|
672
|
+
# own confirmation, otherwise every subsequent send
|
|
673
|
+
# inherits the one-off mismatch and the stream never
|
|
674
|
+
# resynchronises.
|
|
675
|
+
_LOG.warning(
|
|
676
|
+
"Discarding stale LUBA confirmation for '%s' "
|
|
677
|
+
"while awaiting '%s'",
|
|
678
|
+
confirm.message,
|
|
679
|
+
tx,
|
|
680
|
+
)
|
|
681
|
+
continue
|
|
663
682
|
if hasattr(confirm.message, "frame"):
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
)
|
|
669
|
-
else:
|
|
670
|
-
_LOG.error(
|
|
671
|
-
"Expected LUBA device to confirm transmission "
|
|
672
|
-
f"of message '{tx}', but got a confirmation "
|
|
673
|
-
f"for '{confirm.message}'"
|
|
674
|
-
)
|
|
683
|
+
_LOG.trace(
|
|
684
|
+
f"LUBA device reports message '{tx}' sent, "
|
|
685
|
+
f"with ID {confirm.tx_id}"
|
|
686
|
+
)
|
|
675
687
|
else:
|
|
676
688
|
_LOG.debug(
|
|
677
689
|
f"Unable to decode message id {confirm.tx_id}, but "
|
|
@@ -1317,7 +1329,13 @@ class DriverLubaRs232(DriverSerialBase):
|
|
|
1317
1329
|
self._transport: Optional[serialx.SerialTransport] = None
|
|
1318
1330
|
self._protocol: Optional[DriverLubaRs232.LubaProtocol] = None
|
|
1319
1331
|
|
|
1320
|
-
async def connect(
|
|
1332
|
+
async def connect(
|
|
1333
|
+
self, *, scan_dev_inst: bool = False, apply_settings: bool = True
|
|
1334
|
+
) -> None:
|
|
1335
|
+
# ``apply_settings=False`` connects without writing the device settings,
|
|
1336
|
+
# leaving the interface's hardware configuration (including its bus-power
|
|
1337
|
+
# state) untouched. Use it to probe a discovered interface read-only so
|
|
1338
|
+
# the probe cannot depower a bus the integrated supply is already driving.
|
|
1321
1339
|
if self.is_connected:
|
|
1322
1340
|
_LOG.warning(
|
|
1323
1341
|
f"'connect()' called but luba232 driver already connected"
|
|
@@ -1346,8 +1364,9 @@ class DriverLubaRs232(DriverSerialBase):
|
|
|
1346
1364
|
for attempt in range(1, DriverLubaRs232.handshake_attempts + 1):
|
|
1347
1365
|
try:
|
|
1348
1366
|
await self._protocol.send_device_info_query()
|
|
1349
|
-
|
|
1350
|
-
|
|
1367
|
+
if apply_settings:
|
|
1368
|
+
self._protocol.bus_power = self.bus_power
|
|
1369
|
+
await self._protocol.send_device_settings()
|
|
1351
1370
|
break
|
|
1352
1371
|
except (asyncio.TimeoutError, TimeoutError):
|
|
1353
1372
|
if attempt >= DriverLubaRs232.handshake_attempts:
|
|
@@ -1366,8 +1385,9 @@ class DriverLubaRs232(DriverSerialBase):
|
|
|
1366
1385
|
|
|
1367
1386
|
# After switching on the integrated power supply the bus voltage takes
|
|
1368
1387
|
# a moment to rise; sending DALI frames before then fails, so wait for
|
|
1369
|
-
# the bus to be powered before scanning.
|
|
1370
|
-
|
|
1388
|
+
# the bus to be powered before scanning. Skipped when the settings were
|
|
1389
|
+
# not applied, as the bus-power state was then left untouched.
|
|
1390
|
+
if apply_settings and self.bus_power:
|
|
1371
1391
|
await self._wait_for_bus_power()
|
|
1372
1392
|
|
|
1373
1393
|
# Scan the bus for control devices, and create a mapping of addresses
|
dali/tests/test_serial_driver.py
CHANGED
|
@@ -6,11 +6,12 @@ from unittest.mock import AsyncMock, MagicMock
|
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
8
|
|
|
9
|
-
from dali.address import DeviceShort, InstanceNumber
|
|
9
|
+
from dali.address import DeviceShort, GearShort, InstanceNumber
|
|
10
10
|
from dali.command import NumericResponse
|
|
11
11
|
from dali.device.general import QueryInstanceType
|
|
12
12
|
from dali.device.helpers import check_bad_rsp
|
|
13
13
|
from dali.driver.serial import _DALI_FRAMING_ERROR, DriverLubaRs232
|
|
14
|
+
from dali.gear.general import QueryActualLevel
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
@pytest.mark.asyncio
|
|
@@ -93,6 +94,25 @@ async def test_connect_retries_handshake_on_timeout(monkeypatch):
|
|
|
93
94
|
assert protocol.reset_luba_response.call_count == 2
|
|
94
95
|
|
|
95
96
|
|
|
97
|
+
@pytest.mark.asyncio
|
|
98
|
+
async def test_connect_without_applying_settings_leaves_hardware_untouched(
|
|
99
|
+
monkeypatch,
|
|
100
|
+
):
|
|
101
|
+
"""connect(apply_settings=False) must not write the device settings.
|
|
102
|
+
|
|
103
|
+
A read-only probe of a discovered interface must not overwrite the
|
|
104
|
+
hardware configuration, otherwise it could depower a bus the integrated
|
|
105
|
+
supply is already driving.
|
|
106
|
+
"""
|
|
107
|
+
driver, protocol = _connecting_driver(monkeypatch, [None])
|
|
108
|
+
|
|
109
|
+
await driver.connect(apply_settings=False)
|
|
110
|
+
|
|
111
|
+
assert driver.is_connected
|
|
112
|
+
assert protocol.send_device_info_query.await_count == 1
|
|
113
|
+
assert protocol.send_device_settings.await_count == 0
|
|
114
|
+
|
|
115
|
+
|
|
96
116
|
@pytest.mark.asyncio
|
|
97
117
|
async def test_connect_raises_after_exhausting_handshake_attempts(monkeypatch):
|
|
98
118
|
"""When every handshake attempt times out, connect must give up and raise."""
|
|
@@ -149,6 +169,35 @@ async def test_connect_reopens_the_port_after_a_lost_transport(monkeypatch):
|
|
|
149
169
|
assert driver._protocol is replacement
|
|
150
170
|
|
|
151
171
|
|
|
172
|
+
@pytest.mark.asyncio
|
|
173
|
+
async def test_send_dali_command_resyncs_after_stale_confirmation(caplog):
|
|
174
|
+
"""A stale confirmation must not desync every following transmission.
|
|
175
|
+
|
|
176
|
+
A weak bus can let a send's confirmation arrive after it timed out; the
|
|
177
|
+
next send then finds that stale confirmation queued ahead of its own. It
|
|
178
|
+
must be discarded and the matching one awaited, so the stream recovers
|
|
179
|
+
instead of every later frame inheriting the one-off mismatch.
|
|
180
|
+
"""
|
|
181
|
+
protocol = DriverLubaRs232.LubaProtocol()
|
|
182
|
+
protocol.transport = MagicMock()
|
|
183
|
+
protocol.rx_idle.set()
|
|
184
|
+
|
|
185
|
+
command = QueryActualLevel(GearShort(0))
|
|
186
|
+
stale = QueryActualLevel(GearShort(1))
|
|
187
|
+
protocol._queue_tx_conf.put_nowait(
|
|
188
|
+
protocol.LubaMsgTxConf(tx_id=1, message=stale)
|
|
189
|
+
)
|
|
190
|
+
protocol._queue_tx_conf.put_nowait(
|
|
191
|
+
protocol.LubaMsgTxConf(tx_id=2, message=command)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
with caplog.at_level(logging.WARNING, logger="dali.driver"):
|
|
195
|
+
await protocol.send_dali_command(command)
|
|
196
|
+
|
|
197
|
+
assert protocol._queue_tx_conf.empty()
|
|
198
|
+
assert any("stale LUBA confirmation" in r.getMessage() for r in caplog.records)
|
|
199
|
+
|
|
200
|
+
|
|
152
201
|
@pytest.mark.asyncio
|
|
153
202
|
async def test_reset_luba_response_drains_all(caplog):
|
|
154
203
|
"""Stale LUBA command replies must be cleared before a handshake retry."""
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-dali
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16
|
|
4
4
|
Summary: Interface to DALI lighting systems
|
|
5
5
|
Home-page: https://github.com/sde1000/python-dali
|
|
6
6
|
Author: Stephen Early
|
|
7
7
|
Author-email: steve@assorted.org.uk
|
|
8
|
-
License:
|
|
8
|
+
License: LGPL-3.0-or-later
|
|
9
9
|
Classifier: Development Status :: 3 - Alpha
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -18,7 +18,7 @@ dali/driver/base.py,sha256=Jd_0PrkVg84CdkVLmGBr5IyK5Sm7N68tqNDdPFRB7-0,3891
|
|
|
18
18
|
dali/driver/daliserver.py,sha256=YbaTv8glbsPWtXy-m-zakxsPwZBu5FsuXxtVPfE1n78,3120
|
|
19
19
|
dali/driver/hasseb.py,sha256=dQDrkxdpXlXlxmoShsoYOpvXpGzSLqZ8eqG-HMKIGOI,9376
|
|
20
20
|
dali/driver/hid.py,sha256=CyBkCZeyDFumzvfTUeTB3xIjALZkg6dugd3G4DYIeig,33591
|
|
21
|
-
dali/driver/serial.py,sha256=
|
|
21
|
+
dali/driver/serial.py,sha256=qk58G_6nEONZqS2MRX_A0XmhwBxyy8W4tE_E4z05tCw,82883
|
|
22
22
|
dali/driver/trace_logging.py,sha256=qfkEdgVQsu-dXYKsmPXb6j7VRC6O1JJovuU8ca-KEMs,2366
|
|
23
23
|
dali/driver/tridonic.py,sha256=H-j0u-7oP36uKxm-KdCO35AFuoyVzKu_jQs31jeDW6Y,10889
|
|
24
24
|
dali/driver/unipi.py,sha256=arQ-o8zI-PtyvnyRa6f6kPKYswFtFvvdoKfCNRxTAiY,7399
|
|
@@ -54,11 +54,11 @@ dali/tests/test_frame.py,sha256=qd9LzN5ie9zFMTeqzTW5CIsLeuR4n0U4ZqybuG-s4Ck,6035
|
|
|
54
54
|
dali/tests/test_general_sensor.py,sha256=jQqsjzUJa9rbX5pt1K9oavDiFXzMvqclx7qZ7FHrUos,1818
|
|
55
55
|
dali/tests/test_memory.py,sha256=CGcoyhyd_pVC9C4yY0D7X83RIGs8RzYcDX32VuJvd3A,29526
|
|
56
56
|
dali/tests/test_sequences.py,sha256=VaGy1WbUAXFRh-RU6v0OIOHKAhFwVh4KqU7O0N28zF8,4314
|
|
57
|
-
dali/tests/test_serial_driver.py,sha256=
|
|
58
|
-
python_dali-0.
|
|
59
|
-
python_dali-0.
|
|
60
|
-
python_dali-0.
|
|
61
|
-
python_dali-0.
|
|
62
|
-
python_dali-0.
|
|
63
|
-
python_dali-0.
|
|
64
|
-
python_dali-0.
|
|
57
|
+
dali/tests/test_serial_driver.py,sha256=rB6PBi-2tJsi9NLo2iTxAg2oD0z2epv9L-YFcUai5gY,9351
|
|
58
|
+
python_dali-0.16.dist-info/licenses/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
|
59
|
+
python_dali-0.16.dist-info/licenses/COPYING.LESSER,sha256=2n6rt7r999OuXp8iOqW9we7ORaxWncIbOwN1ILRGR2g,7651
|
|
60
|
+
python_dali-0.16.dist-info/licenses/LICENSE,sha256=HVcO3iFdIg-1DaBsl4fgk3swO0aZDktmHBZPIhhn_5o,168
|
|
61
|
+
python_dali-0.16.dist-info/METADATA,sha256=cBWW6vSNaCpu-RrUmZp-tw3y0kr3AMgKeO72tnxwhU4,6198
|
|
62
|
+
python_dali-0.16.dist-info/WHEEL,sha256=a-udL2m4V_6Yn8b-uKzWb12RjRxwwMo6ohYFM24tpaY,91
|
|
63
|
+
python_dali-0.16.dist-info/top_level.txt,sha256=VlSHNdAIGn5irB2PYMRKK0POsLocy-YusWmK3GwHViI,5
|
|
64
|
+
python_dali-0.16.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|