Skip to content

Commit 851eae6

Browse files
authored
Merge pull request #50 from Alberto97/add_cold_white_support
Add support for cold white in color mode
2 parents 3959c74 + 81a4a1c commit 851eae6

3 files changed

Lines changed: 47 additions & 27 deletions

File tree

tests/test_colours.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,12 @@ def test_colours_rgbw(self):
2626

2727
rgbw = TwinklyColour.from_twinkly_tuple((1, 2, 3, 4))
2828
self.assertEqual(rgbw.as_dict(), {"blue": 4, "green": 3, "red": 2, "white": 1})
29+
30+
def test_colours_rgbww(self):
31+
col = TwinklyColour(1, 2, 3, 4, 5)
32+
self.assertEqual(col.as_twinkly_tuple(), (5, 4, 1, 2, 3))
33+
self.assertEqual(tuple(col), (1, 2, 3, 4, 5))
34+
self.assertEqual(col.as_dict(), {"blue": 3, "green": 2, "red": 1, "white": 4, "cold_white": 5})
35+
36+
rgbw = TwinklyColour.from_twinkly_tuple((1, 2, 3, 4, 5))
37+
self.assertEqual(rgbw.as_dict(), {"blue": 5, "green": 4, "red": 3, "white": 2, "cold_white": 1})

ttls/cli.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,17 @@ async def command_movie(t: Twinkly, args: argparse.Namespace):
113113

114114
async def command_static(t: Twinkly, args: argparse.Namespace):
115115
await t.interview()
116-
# match on r,g,b or r,g,b,w
117-
if m := re.match(r"(\d+),(\d+),(\d+)(?:,(\d+))?", args.colour):
116+
# match on r,g,b, r,g,b,w or r,g,b,w,cw
117+
if m := re.match(r"(\d+),(\d+),(\d+)(?:,(\d+)(?:,(\d+))?)?", args.colour):
118118
r = int(m.group(1))
119119
g = int(m.group(2))
120120
b = int(m.group(3))
121-
# w is optional; convert to int if set
122-
if w := m.group(4):
123-
w = int(w)
124-
c = TwinklyColour(r, g, b, w)
121+
# w and cw are optional; convert to int if set
122+
w = int(m.group(4)) if m.group(4) is not None else None
123+
cw = int(m.group(5)) if m.group(5) is not None else None
124+
c = TwinklyColour(r, g, b, w, cw)
125125
else:
126-
raise ValueError("Colour argument is not in r,g,b or r,g,b,w format")
126+
raise ValueError("Colour argument is not in r,g,b, r,g,b,w or r,g,b,w,cw format")
127127
return await t.set_static_colour(c)
128128

129129

ttls/colours.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from dataclasses import dataclass
22

33
ColourDict = dict[str, int]
4-
ColourTuple = tuple[int, int, int] | tuple[int, int, int, int]
5-
TwinklyColourTuple = tuple[int, int, int] | tuple[int, int, int, int]
4+
ColourTuple = tuple[int, int, int] | tuple[int, int, int, int] | tuple[int, int, int, int, int]
5+
TwinklyColourTuple = tuple[int, int, int] | tuple[int, int, int, int] | tuple[int, int, int, int, int]
66

77

88
@dataclass(frozen=True)
@@ -11,17 +11,26 @@ class TwinklyColour:
1111
green: int
1212
blue: int
1313
white: int | None = None
14+
cold_white: int | None = None
15+
16+
def __post_init__(self):
17+
if self.cold_white is not None and self.white is None:
18+
raise ValueError("cold_white requires white to be set")
1419

1520
def as_twinkly_tuple(self) -> TwinklyColourTuple:
16-
"""Convert TwinklyColour to a tuple as used by Twinkly: (R,G,B) or (W,R,G,B)"""
17-
if self.white is not None:
21+
"""Convert TwinklyColour to a tuple as used by Twinkly: (R,G,B), (W,R,G,B) or (CW,W,R,G,B)"""
22+
if self.cold_white is not None and self.white is not None:
23+
return (self.cold_white, self.white, self.red, self.green, self.blue)
24+
elif self.white is not None:
1825
return (self.white, self.red, self.green, self.blue)
1926
else:
2027
return (self.red, self.green, self.blue)
2128

2229
def as_tuple(self) -> ColourTuple:
23-
"""Convert TwinklyColour to a tuple: (R,G,B) or (R,G,B,W)"""
24-
if self.white is not None:
30+
"""Convert TwinklyColour to a tuple: (R,G,B), (R,G,B,W) or (R,G,B,W,CW)"""
31+
if self.cold_white is not None and self.white is not None:
32+
return (self.red, self.green, self.blue, self.white, self.cold_white)
33+
elif self.white is not None:
2534
return (self.red, self.green, self.blue, self.white)
2635
else:
2736
return (self.red, self.green, self.blue)
@@ -31,20 +40,22 @@ def __iter__(self):
3140

3241
def as_dict(self) -> ColourDict:
3342
"""Convert TwinklyColour to a dict wth color names used by set-led functions."""
34-
if self.white is not None:
35-
return {
36-
"red": self.red,
37-
"green": self.green,
38-
"blue": self.blue,
39-
"white": self.white,
40-
}
41-
else:
42-
return {"red": self.red, "green": self.green, "blue": self.blue}
43+
return {
44+
"red": self.red,
45+
"green": self.green,
46+
"blue": self.blue,
47+
**({"white": self.white} if self.white is not None else {}),
48+
**({"cold_white": self.cold_white} if self.cold_white is not None else {}),
49+
}
4350

4451
@classmethod
4552
def from_twinkly_tuple(cls, t):
46-
if len(t) == 4:
47-
return cls(red=t[1], green=t[2], blue=t[3], white=t[0])
48-
elif len(t) == 3:
49-
return cls(red=t[0], green=t[1], blue=t[2])
50-
raise TypeError("Unknown colour format")
53+
match len(t):
54+
case 5:
55+
return cls(red=t[2], green=t[3], blue=t[4], white=t[1], cold_white=t[0])
56+
case 4:
57+
return cls(red=t[1], green=t[2], blue=t[3], white=t[0])
58+
case 3:
59+
return cls(red=t[0], green=t[1], blue=t[2])
60+
case _:
61+
raise TypeError("Unknown colour format")

0 commit comments

Comments
 (0)