lifx-async 4.3.5__py3-none-any.whl → 4.3.6__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.
- lifx/network/connection.py +35 -34
- {lifx_async-4.3.5.dist-info → lifx_async-4.3.6.dist-info}/METADATA +1 -1
- {lifx_async-4.3.5.dist-info → lifx_async-4.3.6.dist-info}/RECORD +5 -5
- {lifx_async-4.3.5.dist-info → lifx_async-4.3.6.dist-info}/WHEEL +0 -0
- {lifx_async-4.3.5.dist-info → lifx_async-4.3.6.dist-info}/licenses/LICENSE +0 -0
lifx/network/connection.py
CHANGED
|
@@ -22,7 +22,6 @@ from lifx.exceptions import (
|
|
|
22
22
|
LifxConnectionError,
|
|
23
23
|
LifxProtocolError,
|
|
24
24
|
LifxTimeoutError,
|
|
25
|
-
LifxUnsupportedCommandError,
|
|
26
25
|
)
|
|
27
26
|
from lifx.network.message import create_message, parse_message
|
|
28
27
|
from lifx.network.transport import UdpTransport
|
|
@@ -443,13 +442,12 @@ class DeviceConnection:
|
|
|
443
442
|
LifxConnectionError: If connection is not open
|
|
444
443
|
LifxProtocolError: If response correlation validation fails
|
|
445
444
|
LifxTimeoutError: If no response after all retries
|
|
446
|
-
LifxUnsupportedCommandError: If device doesn't support command
|
|
447
445
|
"""
|
|
448
446
|
if not self._is_open or self._transport is None:
|
|
449
|
-
raise LifxConnectionError("Connection not open")
|
|
447
|
+
raise LifxConnectionError("Connection not open") # pragma: no cover
|
|
450
448
|
|
|
451
449
|
if timeout is None:
|
|
452
|
-
timeout = self.timeout
|
|
450
|
+
timeout = self.timeout # pragma: no cover
|
|
453
451
|
|
|
454
452
|
if max_retries is None:
|
|
455
453
|
max_retries = self.max_retries
|
|
@@ -597,12 +595,6 @@ class DeviceConnection:
|
|
|
597
595
|
f"got {header.sequence}, max expected {max_expected}"
|
|
598
596
|
)
|
|
599
597
|
|
|
600
|
-
# Check for StateUnhandled
|
|
601
|
-
if header.pkt_type == _STATE_UNHANDLED_PKT_TYPE:
|
|
602
|
-
raise LifxUnsupportedCommandError(
|
|
603
|
-
"Request unsupported by device: received StateUnhandled"
|
|
604
|
-
)
|
|
605
|
-
|
|
606
598
|
# Yield response (can be from any retry attempt)
|
|
607
599
|
has_yielded = True
|
|
608
600
|
last_response_time = time.monotonic()
|
|
@@ -640,7 +632,7 @@ class DeviceConnection:
|
|
|
640
632
|
request: Any,
|
|
641
633
|
timeout: float | None = None,
|
|
642
634
|
max_retries: int | None = None,
|
|
643
|
-
) -> AsyncGenerator[
|
|
635
|
+
) -> AsyncGenerator[bool, None]:
|
|
644
636
|
"""Internal implementation of request_ack_stream with retry logic.
|
|
645
637
|
|
|
646
638
|
This is an async generator that sends a request requiring acknowledgement
|
|
@@ -652,18 +644,17 @@ class DeviceConnection:
|
|
|
652
644
|
max_retries: Maximum retries
|
|
653
645
|
|
|
654
646
|
Yields:
|
|
655
|
-
|
|
647
|
+
True for successful ACK, False if device returned StateUnhandled
|
|
656
648
|
|
|
657
649
|
Raises:
|
|
658
650
|
LifxConnectionError: If connection is not open
|
|
659
651
|
LifxTimeoutError: If no ack after all retries
|
|
660
|
-
LifxUnsupportedCommandError: If device doesn't support command
|
|
661
652
|
"""
|
|
662
653
|
if not self._is_open or self._transport is None:
|
|
663
|
-
raise LifxConnectionError("Connection not open")
|
|
654
|
+
raise LifxConnectionError("Connection not open") # pragma: no cover
|
|
664
655
|
|
|
665
656
|
if timeout is None:
|
|
666
|
-
timeout = self.timeout
|
|
657
|
+
timeout = self.timeout # pragma: no cover
|
|
667
658
|
|
|
668
659
|
if max_retries is None:
|
|
669
660
|
max_retries = self.max_retries
|
|
@@ -729,14 +720,13 @@ class DeviceConnection:
|
|
|
729
720
|
f"{Serial.from_protocol(header.target).to_string()})"
|
|
730
721
|
)
|
|
731
722
|
|
|
732
|
-
# Check for StateUnhandled
|
|
723
|
+
# Check for StateUnhandled - return False to indicate unsupported
|
|
733
724
|
if header.pkt_type == _STATE_UNHANDLED_PKT_TYPE:
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
)
|
|
725
|
+
yield False
|
|
726
|
+
return
|
|
737
727
|
|
|
738
728
|
# ACK received successfully
|
|
739
|
-
yield
|
|
729
|
+
yield True
|
|
740
730
|
return
|
|
741
731
|
|
|
742
732
|
except TimeoutError as e:
|
|
@@ -791,14 +781,14 @@ class DeviceConnection:
|
|
|
791
781
|
timeout: Request timeout in seconds
|
|
792
782
|
|
|
793
783
|
Yields:
|
|
794
|
-
Unpacked response packet instances
|
|
795
|
-
|
|
784
|
+
Unpacked response packet instances (including StateUnhandled if device
|
|
785
|
+
doesn't support the command)
|
|
786
|
+
For SET packets: yields True (acknowledgement) or False (StateUnhandled)
|
|
796
787
|
|
|
797
788
|
Raises:
|
|
798
789
|
LifxTimeoutError: If request times out
|
|
799
790
|
LifxProtocolError: If response invalid
|
|
800
791
|
LifxConnectionError: If connection fails
|
|
801
|
-
LifxUnsupportedCommandError: If command not supported
|
|
802
792
|
|
|
803
793
|
Example:
|
|
804
794
|
```python
|
|
@@ -808,11 +798,16 @@ class DeviceConnection:
|
|
|
808
798
|
label = state.label # Already decoded to string
|
|
809
799
|
break
|
|
810
800
|
|
|
811
|
-
# SET request yields True (acknowledgement)
|
|
812
|
-
async for
|
|
801
|
+
# SET request yields True (acknowledgement) or False (StateUnhandled)
|
|
802
|
+
async for result in conn.request_stream(
|
|
813
803
|
packets.Light.SetColor(color=hsbk, duration=1000)
|
|
814
804
|
):
|
|
815
|
-
|
|
805
|
+
if result:
|
|
806
|
+
# Acknowledgement received
|
|
807
|
+
pass
|
|
808
|
+
else:
|
|
809
|
+
# Device doesn't support this command
|
|
810
|
+
pass
|
|
816
811
|
break
|
|
817
812
|
|
|
818
813
|
# Multi-response GET - stream all responses
|
|
@@ -875,9 +870,12 @@ class DeviceConnection:
|
|
|
875
870
|
|
|
876
871
|
elif packet_kind == "SET":
|
|
877
872
|
# Request acknowledgement
|
|
878
|
-
async for
|
|
873
|
+
async for ack_result in self._request_ack_stream_impl(
|
|
874
|
+
packet, timeout=timeout
|
|
875
|
+
):
|
|
879
876
|
# Log the request/ack cycle
|
|
880
877
|
request_values = packet.as_dict
|
|
878
|
+
reply_packet = "Acknowledgement" if ack_result else "StateUnhandled"
|
|
881
879
|
_LOGGER.debug(
|
|
882
880
|
{
|
|
883
881
|
"class": "DeviceConnection",
|
|
@@ -887,7 +885,7 @@ class DeviceConnection:
|
|
|
887
885
|
"values": request_values,
|
|
888
886
|
},
|
|
889
887
|
"reply": {
|
|
890
|
-
"packet":
|
|
888
|
+
"packet": reply_packet,
|
|
891
889
|
"values": {},
|
|
892
890
|
},
|
|
893
891
|
"serial": self.serial,
|
|
@@ -895,7 +893,7 @@ class DeviceConnection:
|
|
|
895
893
|
}
|
|
896
894
|
)
|
|
897
895
|
|
|
898
|
-
yield
|
|
896
|
+
yield ack_result
|
|
899
897
|
return
|
|
900
898
|
|
|
901
899
|
else:
|
|
@@ -934,7 +932,7 @@ class DeviceConnection:
|
|
|
934
932
|
yield response_packet
|
|
935
933
|
return
|
|
936
934
|
else:
|
|
937
|
-
raise
|
|
935
|
+
raise LifxProtocolError(
|
|
938
936
|
f"Cannot auto-handle packet kind: {packet_kind}"
|
|
939
937
|
)
|
|
940
938
|
else:
|
|
@@ -961,14 +959,14 @@ class DeviceConnection:
|
|
|
961
959
|
timeout: Request timeout in seconds
|
|
962
960
|
|
|
963
961
|
Returns:
|
|
964
|
-
Single unpacked response packet
|
|
965
|
-
|
|
962
|
+
Single unpacked response packet (including StateUnhandled if device
|
|
963
|
+
doesn't support the command)
|
|
964
|
+
For SET packets: True (acknowledgement) or False (StateUnhandled)
|
|
966
965
|
|
|
967
966
|
Raises:
|
|
968
967
|
LifxTimeoutError: If no response within timeout
|
|
969
968
|
LifxProtocolError: If response invalid
|
|
970
969
|
LifxConnectionError: If connection fails
|
|
971
|
-
LifxUnsupportedCommandError: If command not supported
|
|
972
970
|
|
|
973
971
|
Example:
|
|
974
972
|
```python
|
|
@@ -977,10 +975,13 @@ class DeviceConnection:
|
|
|
977
975
|
color = HSBK.from_protocol(state.color)
|
|
978
976
|
label = state.label # Already decoded to string
|
|
979
977
|
|
|
980
|
-
# SET request returns True
|
|
978
|
+
# SET request returns True or False
|
|
981
979
|
success = await conn.request(
|
|
982
980
|
packets.Light.SetColor(color=hsbk, duration=1000)
|
|
983
981
|
)
|
|
982
|
+
if not success:
|
|
983
|
+
# Device doesn't support this command (returned StateUnhandled)
|
|
984
|
+
pass
|
|
984
985
|
```
|
|
985
986
|
"""
|
|
986
987
|
async for response in self.request_stream(packet, timeout):
|
|
@@ -20,7 +20,7 @@ lifx/effects/models.py,sha256=MS5D-cxD0Ar8XhqbqKAc9q2sk38IP1vPkYwd8V7jCr8,2446
|
|
|
20
20
|
lifx/effects/pulse.py,sha256=t5eyjfFWG1xT-RXKghRqHYJ9CG_50tPu4jsDapJZ2mw,8721
|
|
21
21
|
lifx/effects/state_manager.py,sha256=iDfYowiCN5IJqcR1s-pM0mQEJpe-RDsMcOOSMmtPVDE,8983
|
|
22
22
|
lifx/network/__init__.py,sha256=uSyA8r8qISG7qXUHbX8uk9A2E8rvDADgCcf94QIZ9so,499
|
|
23
|
-
lifx/network/connection.py,sha256=
|
|
23
|
+
lifx/network/connection.py,sha256=hM7BxpG4udLCMWV18trbgbV_yjPsX5e_V4boCf8eZYs,38278
|
|
24
24
|
lifx/network/discovery.py,sha256=FoFoZcw3dtJs1daESiZiNXytanKQsMTdF9PjOxEgHM0,23804
|
|
25
25
|
lifx/network/message.py,sha256=jCLC9v0tbBi54g5CaHLFM_nP1Izu8kJmo2tt23HHBbA,2600
|
|
26
26
|
lifx/network/transport.py,sha256=8QS0YV32rdP0EDiPEwuvZXbplRWL08pmjKybd87mkZ0,11070
|
|
@@ -40,7 +40,7 @@ lifx/theme/canvas.py,sha256=4h7lgN8iu_OdchObGDgbxTqQLCb-FRKC-M-YCWef_i4,8048
|
|
|
40
40
|
lifx/theme/generators.py,sha256=L0X6_iApLx6XDboGlYunaVsl6nvUCqMfn23VQmRkyCk,6125
|
|
41
41
|
lifx/theme/library.py,sha256=tKlKZNqJp8lRGDnilWyDm_Qr1vCRGGwuvWVS82anNpQ,21326
|
|
42
42
|
lifx/theme/theme.py,sha256=qMEx_8E41C0Cc6f083XHiAXEglTv4YlXW0UFsG1rQKg,5521
|
|
43
|
-
lifx_async-4.3.
|
|
44
|
-
lifx_async-4.3.
|
|
45
|
-
lifx_async-4.3.
|
|
46
|
-
lifx_async-4.3.
|
|
43
|
+
lifx_async-4.3.6.dist-info/METADATA,sha256=ieTQiM2W8wpfpxTTpl2GwBCdV_9BK36iaK695yKnYac,2609
|
|
44
|
+
lifx_async-4.3.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
45
|
+
lifx_async-4.3.6.dist-info/licenses/LICENSE,sha256=eBz48GRA3gSiWn3rYZAz2Ewp35snnhV9cSqkVBq7g3k,1832
|
|
46
|
+
lifx_async-4.3.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|