Skip to content

Commit aebbc06

Browse files
authored
Merge pull request #7 from JnyJny/features/phase1-foundation
Phase 1: Foundation improvements for busylight-core refactoring
2 parents 0dd8f69 + d114171 commit aebbc06

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+767
-347
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,4 @@ cython_debug/
199199
.claude/
200200

201201
tst.py
202+
plan.md

src/busylight_core/__init__.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@
3636
BlinkStickSquare,
3737
BlinkStickStrip,
3838
)
39-
from .vendors.compulab import Fit_StatUSB
40-
from .vendors.embrava import Blynclight, Blynclight_Mini, Blynclight_Plus
39+
from .vendors.compulab import FitStatUSB
40+
from .vendors.embrava import Blynclight, BlynclightMini, BlynclightPlus
4141
from .vendors.epos import Busylight
42-
from .vendors.kuando import Busylight_Alpha, Busylight_Omega
42+
from .vendors.kuando import BusylightAlpha, BusylightOmega
4343
from .vendors.luxafor import Bluetooth, BusyTag, Flag, Mute, Orb
44-
from .vendors.muteme import MuteMe, MuteMe_Mini, MuteSync
45-
from .vendors.plantronics import Status_Indicator
44+
from .vendors.muteme import MuteMe, MuteMeMini, MuteSync
45+
from .vendors.plantronics import StatusIndicator
4646
from .vendors.thingm import Blink1
4747

4848
__all__ = [
@@ -55,13 +55,13 @@
5555
"BlinkStickStrip",
5656
"Bluetooth",
5757
"Blynclight",
58-
"Blynclight_Mini",
59-
"Blynclight_Plus",
58+
"BlynclightMini",
59+
"BlynclightPlus",
6060
"BusyTag",
6161
"Busylight",
62-
"Busylight_Alpha",
63-
"Busylight_Omega",
64-
"Fit_StatUSB",
62+
"BusylightAlpha",
63+
"BusylightOmega",
64+
"FitStatUSB",
6565
"Flag",
6666
"Hardware",
6767
"HardwareUnsupportedError",
@@ -70,11 +70,11 @@
7070
"LightUnavailableError",
7171
"Mute",
7272
"MuteMe",
73-
"MuteMe_Mini",
73+
"MuteMeMini",
7474
"MuteSync",
7575
"NoLightsFoundError",
7676
"Orb",
77-
"Status_Indicator",
77+
"StatusIndicator",
7878
]
7979

8080
logger.disable("busylight_core")
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""Agile Innovative vendor base class."""
2+
3+
from busylight_core.light import Light
4+
5+
6+
class AgileInnovativeBase(Light):
7+
"""Base class for Agile Innovative devices.
8+
9+
Provides common functionality for all Agile Innovative devices,
10+
primarily the BlinkStick product line.
11+
"""
12+
13+
@staticmethod
14+
def vendor() -> str:
15+
"""Return the vendor name for Agile Innovative devices."""
16+
return "Agile Innovative"

src/busylight_core/vendors/agile_innovative/blinkstick_base.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
"""Base BlinkStick Implementation"""
22

3-
from busylight_core import Light
4-
53
from ._blinkstick import State
4+
from .agile_innovative_base import AgileInnovativeBase
65

76

8-
class BlinkStickBase(Light):
7+
class BlinkStickBase(AgileInnovativeBase):
98
"""Base BlinkStick Implementation
109
1110
Subclasses should provide a claims classmethod and a state
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""CompuLab Fit-statUSB Support"""
22

3-
from .fit_statusb import Fit_StatUSB
3+
from .fit_statusb import FitStatUSB
44

5-
__all__ = ["Fit_StatUSB"]
5+
__all__ = ["FitStatUSB"]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""CompuLab vendor base class."""
2+
3+
from busylight_core.light import Light
4+
5+
6+
class CompuLabBase(Light):
7+
"""Base class for CompuLab devices.
8+
9+
Provides common functionality for all CompuLab devices,
10+
primarily the fit-statUSB product line.
11+
"""
12+
13+
@staticmethod
14+
def vendor() -> str:
15+
"""Return the vendor name for CompuLab devices."""
16+
return "CompuLab"

src/busylight_core/vendors/compulab/fit_statusb.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
from typing import ClassVar
44

5-
from busylight_core.light import Light
65
from busylight_core.mixins import ColorableMixin
76

7+
from .compulab_base import CompuLabBase
88

9-
class Fit_StatUSB(ColorableMixin, Light):
9+
10+
class FitStatUSB(ColorableMixin, CompuLabBase):
1011
"""CompuLab fit-statUSB status light controller.
1112
1213
The fit-statUSB is a USB-connected RGB LED device that communicates
@@ -17,10 +18,6 @@ class Fit_StatUSB(ColorableMixin, Light):
1718
(0x2047, 0x03DF): "fit-statUSB",
1819
}
1920

20-
@staticmethod
21-
def vendor() -> str:
22-
"""Return the vendor name for this device."""
23-
return "CompuLab"
2421

2522
def __bytes__(self) -> bytes:
2623
buf = f"B#{self.red:02x}{self.green:02x}{self.blue:02x}\n"
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"""Embrava Blynclight Support"""
22

33
from .blynclight import Blynclight
4-
from .blynclight_mini import Blynclight_Mini
5-
from .blynclight_plus import Blynclight_Plus
4+
from .blynclight_mini import BlynclightMini
5+
from .blynclight_plus import BlynclightPlus
66

77
__all__ = [
88
"Blynclight",
9-
"Blynclight_Mini",
10-
"Blynclight_Plus",
9+
"BlynclightMini",
10+
"BlynclightPlus",
1111
]
Lines changed: 3 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
"""Embrava Blynclight Support"""
22

3-
from functools import cached_property
43
from typing import ClassVar
54

6-
from busylight_core.light import Light
5+
from .embrava_base import EmbravaBase
76

8-
from ._blynclight import FlashSpeed, State
97

10-
11-
class Blynclight(Light):
8+
class Blynclight(EmbravaBase):
129
"""Embrava Blynclight status light controller.
1310
1411
The Blynclight is a USB-connected RGB LED device with additional features
@@ -19,102 +16,4 @@ class Blynclight(Light):
1916
(0x2C0D, 0x0001): "Blynclight",
2017
(0x2C0D, 0x000C): "Blynclight",
2118
(0x0E53, 0x2516): "Blynclight",
22-
}
23-
24-
@cached_property
25-
def state(self) -> State:
26-
"""The device state manager."""
27-
return State()
28-
29-
def __bytes__(self) -> bytes:
30-
if not self.is_lit:
31-
self.state.off = True
32-
self.state.flash = False
33-
self.state.dim = False
34-
35-
return bytes([0, *bytes(self.state), 0xFF, 0x22])
36-
37-
def on(self, color: tuple[int, int, int], led: int = 0) -> None:
38-
"""Turn on the Blynclight with the specified color.
39-
40-
:param value: RGB color tuple (red, green, blue)
41-
"""
42-
with self.batch_update():
43-
self.color = color
44-
45-
@property
46-
def color(self) -> tuple[int, int, int]:
47-
"""Tuple of RGB color values."""
48-
return (self.state.red, self.state.green, self.state.blue)
49-
50-
@color.setter
51-
def color(self, value: tuple[int, int, int]) -> None:
52-
self.state.red, self.state.green, self.state.blue = value
53-
54-
def dim(self) -> None:
55-
"""Set the light to dim mode (reduced brightness)."""
56-
with self.batch_update():
57-
self.state.dim = True
58-
59-
def bright(self) -> None:
60-
"""Set the light to bright mode (full brightness)."""
61-
with self.batch_update():
62-
self.state.dim = False
63-
64-
def play_sound(
65-
self,
66-
music: int = 0,
67-
volume: int = 1,
68-
repeat: bool = False,
69-
) -> None:
70-
"""Play a sound on the Blynclight device.
71-
72-
:param music: Music track number to play (0-7)
73-
:param volume: Volume level (0-3)
74-
:param repeat: Whether the music repeats
75-
"""
76-
with self.batch_update():
77-
self.state.repeat = repeat
78-
self.state.play = True
79-
self.state.music = music
80-
self.state.mute = False
81-
self.state.volume = volume
82-
83-
def stop_sound(self) -> None:
84-
"""Stop playing any currently playing sound."""
85-
with self.batch_update():
86-
self.state.play = False
87-
88-
def mute(self) -> None:
89-
"""Mute the device sound output."""
90-
with self.batch_update():
91-
self.state.mute = True
92-
93-
def unmute(self) -> None:
94-
"""Unmute the device sound output."""
95-
with self.batch_update():
96-
self.state.mute = False
97-
98-
def flash(self, color: tuple[int, int, int], speed: FlashSpeed = None) -> None:
99-
"""Flash the light with the specified color and speed.
100-
101-
:param color: RGB color tuple to flash
102-
:param speed: Flashing speed (default is slow)
103-
104-
"""
105-
speed = speed or FlashSpeed.slow
106-
107-
with self.batch_update():
108-
self.color = color
109-
self.state.flash = True
110-
self.state.speed = speed.value
111-
112-
def stop_flashing(self) -> None:
113-
"""Stop the flashing pattern and return to solid color."""
114-
with self.batch_update():
115-
self.state.flash = False
116-
117-
def reset(self) -> None:
118-
"""Reset the device to its default state (off, no sound)."""
119-
self.state.reset()
120-
self.update()
19+
}

src/busylight_core/vendors/embrava/blynclight_mini.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
from typing import ClassVar
44

5-
from .blynclight import Blynclight
5+
from .embrava_base import EmbravaBase
66

77

8-
class Blynclight_Mini(Blynclight):
8+
class BlynclightMini(EmbravaBase):
99
"""Embrava Blynclight Mini status light controller.
1010
1111
A smaller version of the Blynclight with the same functionality

0 commit comments

Comments
 (0)