Changes on device
This commit is contained in:
parent
da9373e74d
commit
59060d6636
|
@ -60,10 +60,10 @@ class RfidTokenRead:
|
||||||
|
|
||||||
class RotaryEncoderEvent:
|
class RotaryEncoderEvent:
|
||||||
def __init__(self, msg_content: bytes):
|
def __init__(self, msg_content: bytes):
|
||||||
self.position, self.direction = struct.unpack("<iB", msg_content)
|
self.position, self.increment, self.direction = struct.unpack("<iiB", msg_content)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"Rotary event: pos {self.position}, dir {self.direction}"
|
return f"Rotary event: pos {self.position}, incr {self.increment}, dir {self.direction}"
|
||||||
|
|
||||||
|
|
||||||
class TouchButtonPress:
|
class TouchButtonPress:
|
||||||
|
|
|
@ -6,7 +6,7 @@ import serial_asyncio
|
||||||
from led_cmds import (ColorRGBW, ColorHSV, EffectStaticConfig,
|
from led_cmds import (ColorRGBW, ColorHSV, EffectStaticConfig,
|
||||||
EffectRandomTwoColorInterpolationConfig, EffectAlexaSwipeConfig,
|
EffectRandomTwoColorInterpolationConfig, EffectAlexaSwipeConfig,
|
||||||
EffectSwipeAndChange, EffectReverseSwipe)
|
EffectSwipeAndChange, EffectReverseSwipe)
|
||||||
from host_driver import MusicMouseProtocol, RfidTokenRead, RotaryEncoderEvent, ButtonEvent, TouchButton, TouchButtonPress, TouchButtonRelease
|
from host_driver import MusicMouseProtocol, RfidTokenRead, RotaryEncoderEvent, ButtonEvent, TouchButton, TouchButtonPress, TouchButtonRelease, mouse_leds_index_ranges
|
||||||
from player import AudioPlayer
|
from player import AudioPlayer
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
@ -44,6 +44,10 @@ def load_config(config_path):
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
|
def hass_service(hass, domain, service, **kwargs):
|
||||||
|
asyncio.create_task(hass.call_service(domain, service, kwargs))
|
||||||
|
|
||||||
|
|
||||||
class MusicMouseState:
|
class MusicMouseState:
|
||||||
def __init__(self, protocol: MusicMouseProtocol):
|
def __init__(self, protocol: MusicMouseProtocol):
|
||||||
self.current_figure: str = None
|
self.current_figure: str = None
|
||||||
|
@ -80,11 +84,17 @@ class MusicMouseState:
|
||||||
|
|
||||||
|
|
||||||
class Controller:
|
class Controller:
|
||||||
def __init__(self, protocol, cfg):
|
def __init__(self, protocol, hass, cfg):
|
||||||
self.cfg = cfg
|
self.cfg = cfg
|
||||||
self.audio_player = AudioPlayer(cfg["general"]["alsa_device"])
|
self.audio_player = AudioPlayer(cfg["general"]["alsa_device"])
|
||||||
|
self.audio_player.set_volume(50)
|
||||||
self.mmstate = MusicMouseState(protocol)
|
self.mmstate = MusicMouseState(protocol)
|
||||||
|
self.protocol = protocol
|
||||||
|
self.hass = hass
|
||||||
|
|
||||||
|
vol_min = self.cfg["general"].get("min_volume", None)
|
||||||
|
vol_max = self.cfg["general"].get("max_volume", None)
|
||||||
|
self.audio_player.set_volume_limits(vol_min, vol_max)
|
||||||
protocol.register_message_callback(self.on_firmware_msg)
|
protocol.register_message_callback(self.on_firmware_msg)
|
||||||
|
|
||||||
self.audio_player.on_playlist_end_callback = self._run_off_animation
|
self.audio_player.on_playlist_end_callback = self._run_off_animation
|
||||||
|
@ -105,7 +115,7 @@ class Controller:
|
||||||
self.mmstate.figure_removed()
|
self.mmstate.figure_removed()
|
||||||
elif tagid in self._rfid_to_figure_name:
|
elif tagid in self._rfid_to_figure_name:
|
||||||
figure = self._rfid_to_figure_name[tagid]
|
figure = self._rfid_to_figure_name[tagid]
|
||||||
primary_color, secondary_color, *rest = self.cfg["figures"]["colors"]
|
primary_color, secondary_color, *rest = self.cfg["figures"][figure]["colors"]
|
||||||
self._start_animation(primary_color, secondary_color)
|
self._start_animation(primary_color, secondary_color)
|
||||||
self.mmstate.button_leds(self.cfg["general"].get("button_leds_brightness", 0.5))
|
self.mmstate.button_leds(self.cfg["general"].get("button_leds_brightness", 0.5))
|
||||||
|
|
||||||
|
@ -125,7 +135,8 @@ class Controller:
|
||||||
if isinstance(message, RfidTokenRead):
|
if isinstance(message, RfidTokenRead):
|
||||||
self.handle_rfid_event(message.id)
|
self.handle_rfid_event(message.id)
|
||||||
elif isinstance(message, RotaryEncoderEvent):
|
elif isinstance(message, RotaryEncoderEvent):
|
||||||
volume_increment = self.cfg["general"].get("volume_increment", 2)
|
volume_increment = self.cfg["general"].get("volume_increment", 2) * abs(
|
||||||
|
message.increment)
|
||||||
if message.direction == 2:
|
if message.direction == 2:
|
||||||
self.audio_player.change_volume(volume_increment)
|
self.audio_player.change_volume(volume_increment)
|
||||||
elif message.direction == 1:
|
elif message.direction == 1:
|
||||||
|
@ -135,35 +146,59 @@ class Controller:
|
||||||
self.audio_player.previous()
|
self.audio_player.previous()
|
||||||
elif message.button == "right" and message.event == "pressed":
|
elif message.button == "right" and message.event == "pressed":
|
||||||
self.audio_player.next()
|
self.audio_player.next()
|
||||||
elif False and isinstance(message, TouchButtonPress):
|
elif message.button == "rotary" and message.event == "pressed":
|
||||||
if current_figure:
|
hass_service(self.hass, "light", "toggle", entity_id="light.kinderzimmer_fluter")
|
||||||
ccfg = color_cfg[current_figure]
|
elif isinstance(message, TouchButtonPress):
|
||||||
protocol.mouse_led_effect(
|
figure = self.mmstate.current_figure
|
||||||
EffectStaticConfig(ccfg.accent, *mouse_leds[message.touch_button]))
|
if figure and self.audio_player.is_playing():
|
||||||
#if message.touch_button == TouchButton.RIGHT_FOOT:
|
primary_color, secondary_color, bg, accent = self.cfg["figures"][figure]["colors"]
|
||||||
# asyncio.create_task(
|
self.protocol.mouse_led_effect(
|
||||||
# hass.call_service("switch", "toggle", {"entity_id": "switch.tasmota06"}))
|
EffectStaticConfig(accent, *mouse_leds_index_ranges[message.touch_button]))
|
||||||
# asyncio.create_task(
|
|
||||||
# hass.call_service("light", "turn_on", {"entity_id": "light.arbeitszimmer_fluter"}))
|
|
||||||
#elif message.touch_button == TouchButton.LEFT_FOOT:
|
|
||||||
# asyncio.create_task(
|
|
||||||
# hass.call_service("light", "turn_off", {"entity_id": "light.arbeitszimmer_fluter"}))
|
|
||||||
|
|
||||||
elif False and isinstance(message, TouchButtonRelease):
|
colors = {
|
||||||
if current_figure:
|
TouchButton.RIGHT_FOOT: {
|
||||||
ccfg = color_cfg[current_figure]
|
'rgb_color': [235, 255, 67]
|
||||||
|
},
|
||||||
|
TouchButton.LEFT_FOOT: {
|
||||||
|
'color_temp': 469
|
||||||
|
},
|
||||||
|
TouchButton.RIGHT_EAR: {
|
||||||
|
'rgb_color': [101, 49, 255]
|
||||||
|
},
|
||||||
|
TouchButton.LEFT_EAR: {
|
||||||
|
'rgb_color': [255, 74, 254]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
hass_service(self.hass,
|
||||||
|
"light",
|
||||||
|
"turn_on",
|
||||||
|
entity_id="light.kinderzimmer_fluter",
|
||||||
|
**colors[message.touch_button])
|
||||||
|
#if message.touch_button == TouchButton.RIGHT_FOOT:
|
||||||
|
# asyncio.create_task(
|
||||||
|
# self.hass.call_service("switch", "toggle", {"entity_id": "switch.tasmota06"}))
|
||||||
|
# asyncio.create_task(
|
||||||
|
# self.hass.call_service("light", "turn_on", {"entity_id": "light.arbeitszimmer_fluter"}))
|
||||||
|
#elif message.touch_button == TouchButton.LEFT_FOOT:
|
||||||
|
# asyncio.create_task(
|
||||||
|
# self.hass.call_service("light", "turn_off", {"entity_id": "light.arbeitszimmer_fluter"}))
|
||||||
|
|
||||||
|
elif isinstance(message, TouchButtonRelease):
|
||||||
|
figure = self.mmstate.current_figure
|
||||||
eff_change = EffectRandomTwoColorInterpolationConfig()
|
eff_change = EffectRandomTwoColorInterpolationConfig()
|
||||||
eff_static = EffectStaticConfig(ColorRGBW(0, 0, 0, 0),
|
eff_static = EffectStaticConfig(ColorRGBW(0, 0, 0, 0),
|
||||||
*mouse_leds[message.touch_button])
|
*mouse_leds_index_ranges[message.touch_button])
|
||||||
if audio_player.is_playing():
|
if self.audio_player.is_playing():
|
||||||
eff_static.color = ccfg.primary
|
primary_color, secondary_color, bg, accent = self.cfg["figures"][figure]["colors"]
|
||||||
protocol.mouse_led_effect(eff_static)
|
eff_static.color = primary_color
|
||||||
|
self.protocol.mouse_led_effect(eff_static)
|
||||||
|
|
||||||
if audio_player.is_playing():
|
if self.audio_player.is_playing():
|
||||||
eff_change.color1 = ccfg.primary
|
primary_color, secondary_color, bg, accent = self.cfg["figures"][figure]["colors"]
|
||||||
eff_change.color2 = ccfg.secondary
|
eff_change.color1 = primary_color
|
||||||
|
eff_change.color2 = secondary_color
|
||||||
eff_change.start_with_existing = True
|
eff_change.start_with_existing = True
|
||||||
protocol.mouse_led_effect(eff_change)
|
self.protocol.mouse_led_effect(eff_change)
|
||||||
|
|
||||||
def _start_animation(self, primary_color, secondary_color):
|
def _start_animation(self, primary_color, secondary_color):
|
||||||
ring_eff = EffectSwipeAndChange()
|
ring_eff = EffectSwipeAndChange()
|
||||||
|
@ -193,13 +228,17 @@ class Controller:
|
||||||
|
|
||||||
def main(config_path):
|
def main(config_path):
|
||||||
cfg = load_config(config_path)
|
cfg = load_config(config_path)
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
hass = HomeAssistantClient(cfg["general"]["hass_url"], cfg["general"]["hass_token"], loop)
|
||||||
|
|
||||||
coro = serial_asyncio.create_serial_connection(loop,
|
coro = serial_asyncio.create_serial_connection(loop,
|
||||||
MusicMouseProtocol,
|
MusicMouseProtocol,
|
||||||
cfg["general"]["serial_port"],
|
cfg["general"]["serial_port"],
|
||||||
baudrate=115200)
|
baudrate=115200)
|
||||||
transport, protocol = loop.run_until_complete(coro)
|
transport, protocol = loop.run_until_complete(coro)
|
||||||
controller = Controller(protocol, cfg)
|
controller = Controller(protocol, hass, cfg)
|
||||||
|
loop.create_task(hass.connect())
|
||||||
return controller, loop
|
return controller, loop
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,9 @@ class AudioPlayer:
|
||||||
|
|
||||||
self.on_playlist_end_callback = None
|
self.on_playlist_end_callback = None
|
||||||
|
|
||||||
|
self.volume_min = None
|
||||||
|
self.volume_max = None
|
||||||
|
|
||||||
def create_playlist(self, files):
|
def create_playlist(self, files):
|
||||||
result = vlc.MediaList()
|
result = vlc.MediaList()
|
||||||
for e in files:
|
for e in files:
|
||||||
|
@ -120,11 +123,18 @@ class AudioPlayer:
|
||||||
#print("Callback from VLC", event, args, kwargs)
|
#print("Callback from VLC", event, args, kwargs)
|
||||||
#print(event.meta_type, event.obj, event.type)
|
#print(event.meta_type, event.obj, event.type)
|
||||||
|
|
||||||
|
def set_volume(self, volume):
|
||||||
|
if self.volume_min and volume < self.volume_min:
|
||||||
|
volume = self.volume_min
|
||||||
|
if self.volume_max and volume > self.volume_max:
|
||||||
|
volume = self.volume_max
|
||||||
|
print("volume", volume)
|
||||||
|
self.media_player.audio_set_volume(volume)
|
||||||
|
|
||||||
|
def set_volume_limits(self, vmin, vmax):
|
||||||
|
self.volume_min = vmin
|
||||||
|
self.volume_max = vmax
|
||||||
|
|
||||||
def change_volume(self, amount=1):
|
def change_volume(self, amount=1):
|
||||||
vol = self.media_player.audio_get_volume() + amount
|
vol = self.media_player.audio_get_volume() + amount
|
||||||
print("volume", vol)
|
self.set_volume(vol)
|
||||||
if vol > 100:
|
|
||||||
vol = 100
|
|
||||||
if vol < 0:
|
|
||||||
vol = 0
|
|
||||||
self.media_player.audio_set_volume(vol)
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct MsgRfidTokenRead
|
||||||
struct MsgRotaryEncoder
|
struct MsgRotaryEncoder
|
||||||
{
|
{
|
||||||
int32_t position;
|
int32_t position;
|
||||||
|
int32_t increment;
|
||||||
uint8_t direction;
|
uint8_t direction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -60,11 +60,20 @@ void setupRotaryEncoder()
|
||||||
ESP_ERROR_CHECK(rotary_encoder_set_queue(&info, eventQueueRotaryEncoder));
|
ESP_ERROR_CHECK(rotary_encoder_set_queue(&info, eventQueueRotaryEncoder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t lastRotaryPosition = 0;
|
||||||
|
bool lastRotaryPositionValid = false;
|
||||||
void handleRotaryEncoder()
|
void handleRotaryEncoder()
|
||||||
{
|
{
|
||||||
rotary_encoder_event_t event = {0};
|
rotary_encoder_event_t event = {0};
|
||||||
if (xQueueReceive(eventQueueRotaryEncoder, &event, 0) == pdTRUE)
|
if (xQueueReceive(eventQueueRotaryEncoder, &event, 0) == pdTRUE)
|
||||||
sendMessageToHost(MsgRotaryEncoder{event.state.position, (uint8_t)(event.state.direction)});
|
{
|
||||||
|
int32_t increment = 0;
|
||||||
|
if (lastRotaryPositionValid)
|
||||||
|
increment = lastRotaryPosition - event.state.position;
|
||||||
|
sendMessageToHost(MsgRotaryEncoder{event.state.position, increment, (uint8_t)(event.state.direction)});
|
||||||
|
lastRotaryPositionValid = true;
|
||||||
|
lastRotaryPosition = event.state.position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------- Buttons ----------------------------------------
|
// -------------------------------------------------- Buttons ----------------------------------------
|
||||||
|
@ -190,12 +199,13 @@ void handleTouchInputs()
|
||||||
touch_pad_read(TOUCH_PAD_RIGHT_FOOT, &touchRightFoot);
|
touch_pad_read(TOUCH_PAD_RIGHT_FOOT, &touchRightFoot);
|
||||||
touch_pad_read(TOUCH_PAD_LEFT_EAR, &touchLeftEar);
|
touch_pad_read(TOUCH_PAD_LEFT_EAR, &touchLeftEar);
|
||||||
touch_pad_read(TOUCH_PAD_RIGHT_EAR, &touchRightEar);
|
touch_pad_read(TOUCH_PAD_RIGHT_EAR, &touchRightEar);
|
||||||
|
//Serial.printf("Feet %d %d, Ears %d, %d\n", touchLeftFoot, touchRightFoot, touchLeftEar, touchRightEar);
|
||||||
|
//delay(100);
|
||||||
bool currentState[4];
|
bool currentState[4];
|
||||||
currentState[int(TouchButton::LEFT_FOOT)] = touchLeftFoot < 380;
|
currentState[int(TouchButton::LEFT_FOOT)] = touchLeftFoot < 380;
|
||||||
currentState[int(TouchButton::RIGHT_FOOT)] = touchRightFoot < 380;
|
currentState[int(TouchButton::RIGHT_FOOT)] = touchRightFoot < 380;
|
||||||
currentState[int(TouchButton::LEFT_EAR)] = touchLeftEar < 430;
|
currentState[int(TouchButton::LEFT_EAR)] = touchLeftEar < 430;
|
||||||
currentState[int(TouchButton::RIGHT_EAR)] = touchRightEar < 430;
|
currentState[int(TouchButton::RIGHT_EAR)] = touchRightEar < 400;
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue