Different color for each figure
This commit is contained in:
parent
7a1ed75998
commit
bb5d3e1870
|
@ -1,5 +1,6 @@
|
|||
from dataclasses import dataclass
|
||||
import struct
|
||||
import colorsys
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -9,8 +10,8 @@ class ColorRGBW:
|
|||
b: float
|
||||
w: float
|
||||
|
||||
def repr(self):
|
||||
return f"ColorRGBW({self.r}, {self.g}, {self.b}, {self.w}"
|
||||
def __repr__(self):
|
||||
return f"#({self.r}, {self.g}, {self.b}, {self.w})"
|
||||
|
||||
def as_bytes(self) -> bytes:
|
||||
assert self.is_valid(), "Trying to send invalid " + repr(self)
|
||||
|
@ -28,6 +29,14 @@ class ColorHSV:
|
|||
s: float
|
||||
v: float
|
||||
|
||||
@staticmethod
|
||||
def fromRGB(rgb):
|
||||
conv = colorsys.rgb_to_hsv(rgb.r, rgb.g, rgb.b)
|
||||
return ColorHSV(conv[0] * 360, conv[1], conv[2])
|
||||
|
||||
def __repr__(self):
|
||||
return f"ColorHSV({self.h}, {self.s}, {self.v})"
|
||||
|
||||
def as_bytes(self) -> bytes:
|
||||
return struct.pack("<fff", self.h, self.s, self.v)
|
||||
|
||||
|
@ -47,6 +56,9 @@ class EffectStaticConfig:
|
|||
begin: int = 0
|
||||
end: int = 0
|
||||
|
||||
def __repr__(self):
|
||||
return f"EffectStaticConfig {str(self.color)}, beg: {self.begin}, end {self.end}"
|
||||
|
||||
def as_bytes(self) -> bytes:
|
||||
return self.color.as_bytes() + struct.pack("<HH", self.begin, self.end)
|
||||
|
||||
|
@ -68,6 +80,9 @@ class EffectAlexaSwipeConfig:
|
|||
self.bell_curve_width_in_leds, self.start_position,
|
||||
self.forward) + self.primary_color.as_bytes() + self.secondary_color.as_bytes()
|
||||
|
||||
def __repr__(self):
|
||||
return f"EffectAlexaSwipe primary {str(self.primary_color)}, {str(self.secondary_color)}"
|
||||
|
||||
|
||||
@dataclass
|
||||
class EffectRandomTwoColorInterpolationConfig:
|
||||
|
@ -80,9 +95,14 @@ class EffectRandomTwoColorInterpolationConfig:
|
|||
color2: ColorHSV = ColorHSV(192, 1, 1)
|
||||
|
||||
def as_bytes(self) -> bytes:
|
||||
c1 = ColorHSV.fromRGB(self.color1) if isinstance(self.color1, ColorRGBW) else self.color1
|
||||
c2 = ColorHSV.fromRGB(self.color2) if isinstance(self.color2, ColorRGBW) else self.color2
|
||||
return struct.pack("<i?i??", self.cycle_durations_ms, self.start_with_existing,
|
||||
self.num_segments, self.hue1_random,
|
||||
self.hue2_random) + self.color1.as_bytes() + self.color2.as_bytes()
|
||||
self.hue2_random) + c1.as_bytes() + c2.as_bytes()
|
||||
|
||||
def __repr__(self):
|
||||
return f"RandTwoColor {str(self.color1)}, {str(self.color2)}, segments {self.num_segments}"
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -101,4 +121,7 @@ class EffectSwipeAndChange:
|
|||
change: EffectRandomTwoColorInterpolationConfig = EffectRandomTwoColorInterpolationConfig()
|
||||
|
||||
def as_bytes(self) -> bytes:
|
||||
return self.swipe.as_bytes() + self.change.as_bytes()
|
||||
return self.swipe.as_bytes() + self.change.as_bytes()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Swipe and Change: \n {str(self.swipe)}\n {str(self.change)}"
|
|
@ -3,7 +3,7 @@ import serial_asyncio
|
|||
from led_cmds import (ColorRGBW, ColorHSV, EffectStaticConfig,
|
||||
EffectRandomTwoColorInterpolationConfig, EffectAlexaSwipeConfig,
|
||||
EffectSwipeAndChange)
|
||||
from host_driver import MusicMouseProtocol, RfidTokenRead, RotaryEncoderEvent, ButtonEvent
|
||||
from host_driver import MusicMouseProtocol, RfidTokenRead, RotaryEncoderEvent, ButtonEvent, TouchButton, TouchButtonPress, TouchButtonRelease
|
||||
from player import AudioPlayer
|
||||
from glob import glob
|
||||
import os
|
||||
|
@ -11,6 +11,8 @@ import os
|
|||
MUSIC_FOLDER = "/home/martin/code/musicmouse/espmusicmouse/host_driver/music"
|
||||
|
||||
audio_player = AudioPlayer()
|
||||
current_figure = None
|
||||
last_figure = None
|
||||
|
||||
rfid_token_map = {
|
||||
bytes.fromhex("88041174e9"): "elefant",
|
||||
|
@ -21,24 +23,45 @@ rfid_token_map = {
|
|||
bytes.fromhex("8804bc7444"): "hund",
|
||||
}
|
||||
|
||||
|
||||
def parse_hex_color(color_str: str):
|
||||
if isinstance(color_str, ColorRGBW):
|
||||
return color_str
|
||||
color_str = color_str.lstrip('#')
|
||||
t = tuple(int(color_str[i:i + 2], 16) / 255 for i in (0, 2, 4))
|
||||
return ColorRGBW(*t, 0)
|
||||
|
||||
|
||||
class FigureColorCfg:
|
||||
def __init__(self, primary, secondary, background, accent):
|
||||
self.primary = parse_hex_color(primary)
|
||||
self.secondary = parse_hex_color(secondary)
|
||||
self.background = parse_hex_color(background)
|
||||
self.accent = parse_hex_color(accent)
|
||||
|
||||
|
||||
color_cfg = {
|
||||
"elefant": FigureColorCfg("#ffff00", "#00c8ff", "#094b46", "#c20099"),
|
||||
"fuchs": FigureColorCfg("#F4D35E", "#F95738", "#F95738", "#083d77"),
|
||||
"omnom": FigureColorCfg("#005102", "#3bc405", "#005102", "#3bc405"),
|
||||
"eichhoernchen": FigureColorCfg("#ff0ada", "#4BC6B9", "#69045a", "#4BC6B9"),
|
||||
"hund": FigureColorCfg("#ffff00", "#00c8ff", "#094b46", "#c20099"),
|
||||
"eule": FigureColorCfg("#e5a200", "#f8e300", ColorRGBW(0, 0, 0, 0.2), ColorRGBW(0, 0, 0, 1)),
|
||||
}
|
||||
|
||||
playlists = {
|
||||
fig: audio_player.create_playlist(sorted(glob(os.path.join(MUSIC_FOLDER, fig, "*.mp3"))))
|
||||
for fig in rfid_token_map.values()
|
||||
}
|
||||
|
||||
mouse_leds = {
|
||||
'right_foot': (0, 6),
|
||||
'left_foot': (6, 6 + 6),
|
||||
'left_ear': (6 + 6, 6 + 6 + 16),
|
||||
'right_ear': (6 + 6 + 16, 6 + 6 + 16 + 17),
|
||||
TouchButton.RIGHT_FOOT: (0, 6),
|
||||
TouchButton.LEFT_FOOT: (6, 6 + 6),
|
||||
TouchButton.LEFT_EAR: (6 + 6, 6 + 6 + 16),
|
||||
TouchButton.RIGHT_EAR: (6 + 6 + 16, 6 + 6 + 16 + 17),
|
||||
}
|
||||
|
||||
|
||||
def set_mouse_leds(protocol, position: str, color: ColorRGBW):
|
||||
start, end = mouse_leds[position]
|
||||
protocol.led_ring_effect(EffectStaticConfig(color, start, end))
|
||||
|
||||
|
||||
def on_music_end_callback(protocol):
|
||||
eff = EffectAlexaSwipeConfig()
|
||||
eff.forward = False
|
||||
|
@ -46,35 +69,47 @@ def on_music_end_callback(protocol):
|
|||
protocol.mouse_led_effect(EffectStaticConfig(ColorRGBW(0, 0, 0, 0)))
|
||||
|
||||
|
||||
def on_firmware_msg(protocol: MusicMouseProtocol, message):
|
||||
print("Got message", message)
|
||||
if isinstance(message, RfidTokenRead) and message.id == bytes.fromhex("0000000000"):
|
||||
def on_rfid(protocol, tagid):
|
||||
global current_figure, last_figure
|
||||
|
||||
if tagid == bytes.fromhex("0000000000"):
|
||||
# Off
|
||||
if audio_player.is_playing():
|
||||
eff = EffectAlexaSwipeConfig()
|
||||
eff.forward = False
|
||||
ring_eff = EffectAlexaSwipeConfig()
|
||||
ring_eff.forward = False
|
||||
else:
|
||||
eff = EffectStaticConfig(ColorRGBW(0, 0, 0, 0))
|
||||
protocol.led_ring_effect(eff)
|
||||
ring_eff = EffectStaticConfig(ColorRGBW(0, 0, 0, 0))
|
||||
protocol.led_ring_effect(ring_eff)
|
||||
protocol.mouse_led_effect(EffectStaticConfig(ColorRGBW(0, 0, 0, 0)))
|
||||
audio_player.pause()
|
||||
elif isinstance(message, RfidTokenRead) and message.id in rfid_token_map:
|
||||
eff = EffectSwipeAndChange()
|
||||
eff.swipe.primary_color = ColorRGBW(1, 1, 0, 0)
|
||||
figure = rfid_token_map[message.id]
|
||||
|
||||
if figure == "eule":
|
||||
eff.swipe.primary_color = ColorRGBW(0.96, 0.7, 0, 0)
|
||||
eff.swipe.secondary_color = ColorRGBW(0.96, 0.7, 0, 0)
|
||||
eff.swipe.swipe_speed = 180
|
||||
eff.swipe.bell_curve_width_in_leds = 6
|
||||
last_figure = current_figure
|
||||
else:
|
||||
figure = rfid_token_map[tagid]
|
||||
current_figure = figure
|
||||
ccfg = color_cfg[figure]
|
||||
ring_eff = EffectSwipeAndChange()
|
||||
ring_eff.swipe.primary_color = ccfg.primary
|
||||
ring_eff.swipe.secondary_color = ccfg.secondary
|
||||
ring_eff.change.color1 = ccfg.primary
|
||||
ring_eff.change.color2 = ccfg.secondary
|
||||
protocol.led_ring_effect(ring_eff)
|
||||
|
||||
mouse_eff = EffectStaticConfig(ccfg.background)
|
||||
protocol.mouse_led_effect(mouse_eff)
|
||||
|
||||
protocol.led_ring_effect(eff)
|
||||
protocol.mouse_led_effect(
|
||||
EffectStaticConfig(ColorRGBW(18 / 255 / 2, 156 / 255 / 2, 140 / 255 / 2, 0)))
|
||||
print(figure)
|
||||
if figure in playlists:
|
||||
audio_player.set_playlist(playlists[figure])
|
||||
audio_player.play_from_start()
|
||||
if last_figure == current_figure:
|
||||
audio_player.play()
|
||||
else:
|
||||
audio_player.play_from_start()
|
||||
|
||||
|
||||
def on_firmware_msg(protocol: MusicMouseProtocol, message):
|
||||
print("FW msg:", message)
|
||||
if isinstance(message, RfidTokenRead):
|
||||
on_rfid(protocol, message.id)
|
||||
elif isinstance(message, RotaryEncoderEvent):
|
||||
if audio_player.is_playing():
|
||||
if message.direction == 2:
|
||||
|
@ -86,6 +121,14 @@ def on_firmware_msg(protocol: MusicMouseProtocol, message):
|
|||
audio_player.previous()
|
||||
elif message.button == "right" and message.event == "pressed":
|
||||
audio_player.next()
|
||||
elif isinstance(message, TouchButtonPress):
|
||||
ccfg = color_cfg[current_figure]
|
||||
protocol.mouse_led_effect(EffectStaticConfig(ccfg.accent,
|
||||
*mouse_leds[message.touch_button]))
|
||||
elif isinstance(message, TouchButtonRelease):
|
||||
ccfg = color_cfg[current_figure]
|
||||
color = ccfg.background if audio_player.is_playing() else ColorRGBW(0, 0, 0, 0)
|
||||
protocol.mouse_led_effect(EffectStaticConfig(color, *mouse_leds[message.touch_button]))
|
||||
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
|
|
@ -113,11 +113,11 @@ class AudioPlayer:
|
|||
def _callback(self, event, *args, **kwargs):
|
||||
|
||||
if True: # event.type == vlc.EventType.MediaPlayerEndReached:
|
||||
print("End reached")
|
||||
#print("End reached")
|
||||
if self.on_playlist_end_callback:
|
||||
self.on_playlist_end_callback()
|
||||
print("Callback from VLC", event, args, kwargs)
|
||||
print(event.meta_type, event.obj, event.type)
|
||||
#print("Callback from VLC", event, args, kwargs)
|
||||
#print(event.meta_type, event.obj, event.type)
|
||||
|
||||
def change_volume(self, amount=1):
|
||||
vol = self.media_player.audio_get_volume() + amount
|
||||
|
|
Loading…
Reference in New Issue