lifx-async 4.6.1__py3-none-any.whl → 4.7.1__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/devices/matrix.py CHANGED
@@ -699,6 +699,7 @@ class MatrixLight(Light):
699
699
  source_fb: int = 1,
700
700
  target_fb: int = 0,
701
701
  duration: float = 0.0,
702
+ length: int = 1,
702
703
  ) -> None:
703
704
  """Copy frame buffer (for tiles with >64 zones).
704
705
 
@@ -710,6 +711,7 @@ class MatrixLight(Light):
710
711
  source_fb: Source frame buffer index (usually 1)
711
712
  target_fb: Target frame buffer index (usually 0)
712
713
  duration: time in seconds to transition if target_fb is 0
714
+ length: Number of tiles to update starting from tile_index (default 1)
713
715
 
714
716
  Example:
715
717
  >>> # For 16x8 tile (128 zones):
@@ -739,12 +741,18 @@ class MatrixLight(Light):
739
741
  >>> await matrix.copy_frame_buffer(
740
742
  ... tile_index=0, source_fb=1, target_fb=0, duration=2.0
741
743
  ... )
744
+
745
+ >>> # For a chain of 5 tiles, update all simultaneously:
746
+ >>> await matrix.copy_frame_buffer(
747
+ ... tile_index=0, source_fb=1, target_fb=0, length=5
748
+ ... )
742
749
  """
743
750
  _LOGGER.debug(
744
- "Copying frame buffer %d -> %d for tile %d on %s",
751
+ "Copying frame buffer %d -> %d for tile %d (length=%d) on %s",
745
752
  source_fb,
746
753
  target_fb,
747
754
  tile_index,
755
+ length,
748
756
  self.label or self.serial,
749
757
  )
750
758
 
@@ -761,7 +769,7 @@ class MatrixLight(Light):
761
769
  await self.connection.send_packet(
762
770
  packets.Tile.CopyFrameBuffer(
763
771
  tile_index=tile_index,
764
- length=1,
772
+ length=length,
765
773
  src_fb_index=source_fb,
766
774
  dst_fb_index=target_fb,
767
775
  src_x=0,
lifx/devices/multizone.py CHANGED
@@ -604,6 +604,8 @@ class MultiZoneLight(Light):
604
604
  colors: list[HSBK],
605
605
  duration: float = 0.0,
606
606
  apply: ExtendedAppReq = ExtendedAppReq.APPLY,
607
+ *,
608
+ fast: bool = False,
607
609
  ) -> None:
608
610
  """Set colors for multiple zones efficiently (up to 82 zones per call).
609
611
 
@@ -615,12 +617,15 @@ class MultiZoneLight(Light):
615
617
  colors: List of HSBK colors to set (max 82)
616
618
  duration: Transition duration in seconds (default 0.0)
617
619
  apply: Application mode (default APPLY)
620
+ fast: If True, send fire-and-forget without waiting for response.
621
+ Use for high-frequency animations (>20 updates/second).
618
622
 
619
623
  Raises:
620
624
  ValueError: If colors list is too long or zone index is invalid
621
625
  LifxDeviceNotFoundError: If device is not connected
622
- LifxTimeoutError: If device does not respond
626
+ LifxTimeoutError: If device does not respond (only when fast=False)
623
627
  LifxUnsupportedCommandError: If device doesn't support this command
628
+ (only when fast=False)
624
629
 
625
630
  Example:
626
631
  ```python
@@ -630,6 +635,11 @@ class MultiZoneLight(Light):
630
635
  for i in range(10)
631
636
  ]
632
637
  await light.set_extended_color_zones(0, colors)
638
+
639
+ # High-speed animation loop
640
+ for frame in animation_frames:
641
+ await light.set_extended_color_zones(0, frame, fast=True)
642
+ await asyncio.sleep(0.033) # ~30 FPS
633
643
  ```
634
644
  """
635
645
  if zone_index < 0:
@@ -637,7 +647,9 @@ class MultiZoneLight(Light):
637
647
  if len(colors) > 82:
638
648
  raise ValueError(f"Too many colors: {len(colors)} (max 82 per request)")
639
649
  if len(colors) == 0:
640
- raise ValueError("Colors list cannot be empty") # Convert to protocol HSBK
650
+ raise ValueError("Colors list cannot be empty")
651
+
652
+ # Convert to protocol HSBK
641
653
  protocol_colors = [color.to_protocol() for color in colors]
642
654
 
643
655
  # Pad to 82 colors if needed
@@ -647,17 +659,25 @@ class MultiZoneLight(Light):
647
659
  # Convert duration to milliseconds
648
660
  duration_ms = int(duration * 1000)
649
661
 
650
- # Send request
651
- result = await self.connection.request(
652
- packets.MultiZone.SetExtendedColorZones(
653
- duration=duration_ms,
654
- apply=apply,
655
- index=zone_index,
656
- colors_count=len(colors),
657
- colors=protocol_colors,
658
- ),
662
+ packet = packets.MultiZone.SetExtendedColorZones(
663
+ duration=duration_ms,
664
+ apply=apply,
665
+ index=zone_index,
666
+ colors_count=len(colors),
667
+ colors=protocol_colors,
659
668
  )
660
- self._raise_if_unhandled(result)
669
+
670
+ if fast:
671
+ # Fire-and-forget: no ack, no response, no waiting
672
+ await self.connection.send_packet(
673
+ packet,
674
+ ack_required=False,
675
+ res_required=False,
676
+ )
677
+ else:
678
+ # Standard: wait for response and check for errors
679
+ result = await self.connection.request(packet)
680
+ self._raise_if_unhandled(result)
661
681
 
662
682
  _LOGGER.debug(
663
683
  {
@@ -678,6 +698,7 @@ class MultiZoneLight(Light):
678
698
  ],
679
699
  "duration": duration_ms,
680
700
  "apply": apply.name,
701
+ "fast": fast,
681
702
  },
682
703
  }
683
704
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lifx-async
3
- Version: 4.6.1
3
+ Version: 4.7.1
4
4
  Summary: A modern, type-safe, async Python library for controlling LIFX lights
5
5
  Author-email: Avi Miller <me@dje.li>
6
6
  Maintainer-email: Avi Miller <me@dje.li>
@@ -10,8 +10,8 @@ lifx/devices/ceiling.py,sha256=qXZeTGAnPbKpnMyEOI2DsffC9HddmWzsW_Q_Fnkpwkw,33087
10
10
  lifx/devices/hev.py,sha256=T5hvt2q_vdgPBvThx_-M7n5pZu9pL0y9Fs3Zz_KL0NM,15588
11
11
  lifx/devices/infrared.py,sha256=ePk9qxX_s-hv5gQMvio1Vv8FYiCd68HF0ySbWgSrvuU,8130
12
12
  lifx/devices/light.py,sha256=gk92lhViUWINGaxDWbs4qn8Stnn2fGCfRkC5Kk0Q-hI,34087
13
- lifx/devices/matrix.py,sha256=AVNM2071NFtPg3Eq7kZ3asRGus36He02iDDvIa8RaQ0,41951
14
- lifx/devices/multizone.py,sha256=8OJ6zP5xgSCmlMQDj2mLUZ352EMkbYMbDZ1X-Cux7AU,32786
13
+ lifx/devices/matrix.py,sha256=TcfVvqFCIhGXjOtaQEARQCXe9XqSFDZ4wEQdRZBiQpA,42301
14
+ lifx/devices/multizone.py,sha256=zQj0qKxWccHAmkIpqIcGzZsKjCQL-_bAquz78o0Izng,33570
15
15
  lifx/effects/__init__.py,sha256=4DF31yp7RJic5JoltMlz5dCtF5KQobU6NOUtLUKkVKE,1509
16
16
  lifx/effects/base.py,sha256=YO0Hbg2VYHKPtfYnWxmrtzYoPGOi9BUXhn8HVFKv5IM,10283
17
17
  lifx/effects/colorloop.py,sha256=kuuyENJS2irAN8vZAFsDa2guQdDbmmc4PJNiyZTfFPE,15840
@@ -42,7 +42,7 @@ lifx/theme/canvas.py,sha256=4h7lgN8iu_OdchObGDgbxTqQLCb-FRKC-M-YCWef_i4,8048
42
42
  lifx/theme/generators.py,sha256=nq3Yvntq_h-eFHbmmow3LcAdA_hEbRRaP5mv9Bydrjk,6435
43
43
  lifx/theme/library.py,sha256=tKlKZNqJp8lRGDnilWyDm_Qr1vCRGGwuvWVS82anNpQ,21326
44
44
  lifx/theme/theme.py,sha256=qMEx_8E41C0Cc6f083XHiAXEglTv4YlXW0UFsG1rQKg,5521
45
- lifx_async-4.6.1.dist-info/METADATA,sha256=bjtJ7SbLYx_SKkUzvEZqWaPJqqGrDG8aiLyqim1AbSE,2609
46
- lifx_async-4.6.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
47
- lifx_async-4.6.1.dist-info/licenses/LICENSE,sha256=eBz48GRA3gSiWn3rYZAz2Ewp35snnhV9cSqkVBq7g3k,1832
48
- lifx_async-4.6.1.dist-info/RECORD,,
45
+ lifx_async-4.7.1.dist-info/METADATA,sha256=Zrtws6NJBuCkoGw4dUBUJ6IPG2c5JW_BLJeKALgYY6U,2609
46
+ lifx_async-4.7.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
47
+ lifx_async-4.7.1.dist-info/licenses/LICENSE,sha256=eBz48GRA3gSiWn3rYZAz2Ewp35snnhV9cSqkVBq7g3k,1832
48
+ lifx_async-4.7.1.dist-info/RECORD,,