From 9ee063a9d64f2e67c6764389cdf560ac324c55db Mon Sep 17 00:00:00 2001 From: Richard Nespithal Date: Sun, 19 Jan 2025 22:13:48 +0100 Subject: [PATCH 01/25] WIP: Multi light support Closes #4 --- actions/ElgatoKeyLight/Core.py | 90 +++++++++++++++++++++++++++++----- backend/backend.py | 38 +++++++++++--- locales/en_US.json | 5 +- 3 files changed, 112 insertions(+), 21 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 3e9f548..d121234 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -8,6 +8,7 @@ gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") +from ipaddress import ip_address import requests from gi.repository import Gtk, Adw @@ -19,6 +20,7 @@ def __init__(self, *args, **kwargs): self.lm = self.plugin_base.locale_manager self.plugin_base.backend.on_light_state_changed.subscribe(self.update_icon) + self.plugin_base.backend.on_device_added.subscribe(self.update_device_list) self.supported_lights = { "ElgatoKeyLight": { @@ -89,20 +91,42 @@ def current_temperature(self, value): self.plugin_base.backend.on_temperature_changed.emit() threading.Thread(target=self.update_light, daemon=True, name="update_light").start() + def on_ready(self) -> None: + self.load_default_config() self.update_icon() + + def update_device_list(self): + if not hasattr(self, "registered_devices"): + return + + print(self.registered_devices) + self.registered_devices.splice(0, self.registered_devices.get_n_items()) + for device in self.plugin_base.backend.get_devices(): + self.registered_devices.append(str(device)) + + def get_config_rows(self) -> list: - self.ip_entry = Adw.EntryRow(title=self.plugin_base.locale_manager.get("actions.ip_entry.title"), input_purpose=Gtk.InputPurpose.FREE_FORM) - self.ip_entry.connect("notify::text", self.on_ip_address_changed) + self.add_new_ip_entry = Adw.EntryRow(title=self.plugin_base.locale_manager.get("actions.add_ip_entry.title"), input_purpose=Gtk.InputPurpose.FREE_FORM, show_apply_button=True) + self.add_new_ip_entry.connect("apply", self.on_ip_address_added) + + # List of existing devices + self.registered_devices = Gtk.StringList() + for device in self.plugin_base.backend.get_devices(): + self.registered_devices.append(str(device)) + + self.device_list = Adw.ComboRow(title=self.plugin_base.locale_manager.get("actions.device_list.title"), model=self.registered_devices) + self.device_list.connect("notify::selected", self.set_ip_address) self.connection_banner = Adw.Banner() self.connection_banner.set_revealed(True) self.banner_is_visible = True + self.load_default_config() - return [self.ip_entry, self.connection_banner] + return [self.add_new_ip_entry, self.device_list, self.connection_banner] def set_banner_connection_info(self) -> None: if not self.banner_is_visible: @@ -138,18 +162,57 @@ def toggle_light(self): self.update_light() def load_default_config(self): - settings = self.plugin_base.get_settings() - ip_address = settings.get("ip_address") + # Fallback for old global settings + global_settings = self.plugin_base.get_settings() + migrate_global_address_to_local_address = global_settings.get("ip_address") - if ip_address: - self.ip_entry.set_text(ip_address) + settings = self.get_settings() - def on_ip_address_changed(self, entry: Adw.EntryRow, text): - settings = self.plugin_base.get_settings() - settings["ip_address"] = entry.get_text() - self.plugin_base.set_settings(settings) + if migrate_global_address_to_local_address: + settings["ip_address"] = migrate_global_address_to_local_address + del global_settings["ip_address"] + self.plugin_base.set_settings(global_settings) + print("Migrating global settings") + self.set_settings(settings) + + saved_ip_address = settings.get("ip_address") + + if saved_ip_address: + print("Saved ip address in config ", saved_ip_address) + + self.plugin_base.backend.register_new_device(saved_ip_address, saved_ip_address) + self.preselect_device_by_ip() + self.ip_address = saved_ip_address + + def preselect_device_by_ip(self): + base_devices = self.plugin_base.backend.get_devices() + for index, key in enumerate(base_devices): + if base_devices[key].ip_address == ip_address: + self.device_list.set_selected(index) + break + + def on_ip_address_added(self, entry: Adw.EntryRow): + new_ip_address = entry.get_text() + + self.plugin_base.backend.register_new_device(new_ip_address, new_ip_address) + self.device_list.set_selected(self.registered_devices.get_n_items() - 1) + self.set_ip_address(self.device_list) + + + def set_ip_address(self, entry: Adw.EntryRow, *args): + settings = self.get_settings() + + ip_by_index = list(self.plugin_base.backend.get_devices().values())[entry.get_selected()].ip_address + + print("Save new selected ip address ", ip_by_index) + settings["ip_address"] = ip_by_index + + self.ip_address = ip_by_index + + self.set_settings(settings) threading.Thread(target=self.update_light, daemon=True, name="update_light").start() + def update_icon(self): settings = self.plugin_base.get_settings() if settings.get("light_active") == 1: @@ -170,7 +233,8 @@ def get_light_data(self): def update_light(self): - settings = self.plugin_base.get_settings() + settings = self.get_settings() + global_settings = self.plugin_base.get_settings() ip_address = settings.get("ip_address") url = f"http://{ip_address}:9123/elgato/lights" @@ -178,7 +242,7 @@ def update_light(self): "numberOfLights": 1, "lights": [ { - "on": settings.get("light_active"), + "on": global_settings.get("light_active"), "brightness": self.current_brightness, "temperature": self.current_temperature } diff --git a/backend/backend.py b/backend/backend.py index 980c45e..2c1a80a 100644 --- a/backend/backend.py +++ b/backend/backend.py @@ -1,11 +1,5 @@ from streamcontroller_plugin_tools import BackendBase -import gi - -gi.require_version("Gtk", "4.0") -gi.require_version("Adw", "1") - - class Event: def __init__(self): self.listeners = [] @@ -21,11 +15,43 @@ def emit(self, *args): listener(*args) +class Device: + def __init__(self, ip_address: str, name: str): + self.ip_address = ip_address + self.name = name + + class Backend(BackendBase): def __init__(self): super().__init__() self.on_brightness_changed = Event() self.on_temperature_changed = Event() self.on_light_state_changed = Event() + self.on_device_added = Event() + + self.devices : dict[str, Device] = {} + + + def register_new_device(self, device_ip: str, device_name: str): + print("Registering new device: ", device_ip) + + if device_ip in self.devices: + return + + self.devices[device_ip] = Device(device_ip, device_name) + self.on_device_added.emit() + + + def remove_device(self, device_ip: str): + del self.devices[device_ip] + self.on_device_removed.emit(device_ip) + + + def get_devices(self) -> dict[str, Device]: + return self.devices + + + def is_device_in_list(self, device_ip: str) -> bool: + return device_ip in self.devices backend = Backend() diff --git a/locales/en_US.json b/locales/en_US.json index 55af2a2..e3d6082 100644 --- a/locales/en_US.json +++ b/locales/en_US.json @@ -1,6 +1,6 @@ { "actions.live_update.title": "Live Update", - "actions.ip_entry.title": "IP Address", + "actions.add_ip_entry.title": "Add new IP Address", "actions.step_size.title": "Step Size", "actions.dial_selection.title": "Dial Selection", "actions.brightness_entry.title": "Brightness", @@ -13,5 +13,6 @@ "actions.current_temperature.title": "Temperature", "actions.toggle_selection.title": "On press", "actions.toggle_selection.light_on_off": "Toggle Light", - "actions.toggle_selection.brightness_temperature": "Change Brightness/Temperature" + "actions.toggle_selection.brightness_temperature": "Change Brightness/Temperature", + "actions.device_list.title": "Existing devices" } From c5635f93d9d51d0dd687b9839136d896ab59f725 Mon Sep 17 00:00:00 2001 From: Richard Nespithal Date: Sat, 1 Feb 2025 16:35:31 +0100 Subject: [PATCH 02/25] Add button for adding lights --- actions/ElgatoKeyLight/Core.py | 95 +++++++++++-------- actions/ElgatoKeyLight/Dial.py | 93 +++++++++--------- .../ElgatoKeyLight/IncreaseDecreaseButton.py | 20 ++-- actions/ElgatoKeyLight/SetButton.py | 26 +++-- actions/ElgatoKeyLight/ToggleButton.py | 1 + 5 files changed, 135 insertions(+), 100 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index d121234..0c8ac78 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -1,4 +1,7 @@ # Import StreamController modules +from gi.repository import Gtk, Adw +import requests +from ipaddress import ip_address from src.backend.PluginManager.ActionBase import ActionBase import os @@ -8,10 +11,6 @@ gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from ipaddress import ip_address - -import requests -from gi.repository import Gtk, Adw class Core(ActionBase): @@ -19,8 +18,10 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.lm = self.plugin_base.locale_manager - self.plugin_base.backend.on_light_state_changed.subscribe(self.update_icon) - self.plugin_base.backend.on_device_added.subscribe(self.update_device_list) + self.plugin_base.backend.on_light_state_changed.subscribe( + self.update_icon) + self.plugin_base.backend.on_device_added.subscribe( + self.update_device_list) self.supported_lights = { "ElgatoKeyLight": { @@ -66,13 +67,15 @@ def current_brightness(self): def current_brightness(self, value): settings = self.plugin_base.get_settings() - _current_brightness = max(self.supported_lights["ElgatoKeyLight"]["min_brightness"], min(value, self.supported_lights["ElgatoKeyLight"]["max_brightness"])) + _current_brightness = max(self.supported_lights["ElgatoKeyLight"]["min_brightness"], min( + value, self.supported_lights["ElgatoKeyLight"]["max_brightness"])) settings["brightness"] = int(_current_brightness) self.plugin_base.set_settings(settings) self.plugin_base.backend.on_brightness_changed.emit() - threading.Thread(target=self.update_light, daemon=True, name="update_light").start() + threading.Thread(target=self.update_light, daemon=True, + name="update_light").start() @property def current_temperature(self): @@ -83,40 +86,47 @@ def current_temperature(self): def current_temperature(self, value): settings = self.plugin_base.get_settings() - _current_temperature = max(self.supported_lights["ElgatoKeyLight"]["min_temperature"], min(value, self.supported_lights["ElgatoKeyLight"]["max_temperature"])) + _current_temperature = max(self.supported_lights["ElgatoKeyLight"]["min_temperature"], min( + value, self.supported_lights["ElgatoKeyLight"]["max_temperature"])) settings["temperature"] = int(_current_temperature) self.plugin_base.set_settings(settings) self.plugin_base.backend.on_temperature_changed.emit() - threading.Thread(target=self.update_light, daemon=True, name="update_light").start() - + threading.Thread(target=self.update_light, daemon=True, + name="update_light").start() def on_ready(self) -> None: self.load_default_config() self.update_icon() - def update_device_list(self): if not hasattr(self, "registered_devices"): return print(self.registered_devices) - self.registered_devices.splice(0, self.registered_devices.get_n_items()) + self.registered_devices.splice( + 0, self.registered_devices.get_n_items()) for device in self.plugin_base.backend.get_devices(): self.registered_devices.append(str(device)) - def get_config_rows(self) -> list: - self.add_new_ip_entry = Adw.EntryRow(title=self.plugin_base.locale_manager.get("actions.add_ip_entry.title"), input_purpose=Gtk.InputPurpose.FREE_FORM, show_apply_button=True) - self.add_new_ip_entry.connect("apply", self.on_ip_address_added) + self.add_new_ip_entry = Adw.EntryRow(title=self.plugin_base.locale_manager.get( + "actions.add_ip_entry.title"), input_purpose=Gtk.InputPurpose.FREE_FORM) + self.add_light_button = Adw.ButtonRow( + title=self.plugin_base.locale_manager.get("actions.add_light_button.title")) + + # Disable button until we have a working connection + self.add_light_button + + self.add_light_button.connect("activated", self.on_ip_address_added) - # List of existing devices self.registered_devices = Gtk.StringList() for device in self.plugin_base.backend.get_devices(): self.registered_devices.append(str(device)) - self.device_list = Adw.ComboRow(title=self.plugin_base.locale_manager.get("actions.device_list.title"), model=self.registered_devices) + self.device_list = Adw.ComboRow(title=self.plugin_base.locale_manager.get( + "actions.device_list.title"), model=self.registered_devices) self.device_list.connect("notify::selected", self.set_ip_address) self.connection_banner = Adw.Banner() @@ -126,18 +136,21 @@ def get_config_rows(self) -> list: self.load_default_config() - return [self.add_new_ip_entry, self.device_list, self.connection_banner] + return [self.add_new_ip_entry, self.add_light_button, self.device_list, self.connection_banner] def set_banner_connection_info(self) -> None: if not self.banner_is_visible: return if self.running_requests > 0: - self.connection_banner.set_title(self.plugin_base.locale_manager.get("actions.connection_banner.loading")) + self.connection_banner.set_title( + self.plugin_base.locale_manager.get("actions.connection_banner.loading")) elif self.is_connected: - self.connection_banner.set_title(self.plugin_base.locale_manager.get("actions.connection_banner.connected")) + self.connection_banner.set_title( + self.plugin_base.locale_manager.get("actions.connection_banner.connected")) else: - self.connection_banner.set_title(self.plugin_base.locale_manager.get("actions.connection_banner.not_connected")) + self.connection_banner.set_title(self.plugin_base.locale_manager.get( + "actions.connection_banner.not_connected")) def modify_brightness(self, amount: int): settings = self.plugin_base.get_settings() @@ -164,7 +177,8 @@ def toggle_light(self): def load_default_config(self): # Fallback for old global settings global_settings = self.plugin_base.get_settings() - migrate_global_address_to_local_address = global_settings.get("ip_address") + migrate_global_address_to_local_address = global_settings.get( + "ip_address") settings = self.get_settings() @@ -180,7 +194,8 @@ def load_default_config(self): if saved_ip_address: print("Saved ip address in config ", saved_ip_address) - self.plugin_base.backend.register_new_device(saved_ip_address, saved_ip_address) + self.plugin_base.backend.register_new_device( + saved_ip_address, saved_ip_address) self.preselect_device_by_ip() self.ip_address = saved_ip_address @@ -191,38 +206,41 @@ def preselect_device_by_ip(self): self.device_list.set_selected(index) break - def on_ip_address_added(self, entry: Adw.EntryRow): - new_ip_address = entry.get_text() + def on_ip_address_added(self, entry): + new_ip_address = self.add_new_ip_entry.get_text() - self.plugin_base.backend.register_new_device(new_ip_address, new_ip_address) - self.device_list.set_selected(self.registered_devices.get_n_items() - 1) + self.plugin_base.backend.register_new_device( + new_ip_address, new_ip_address) + self.device_list.set_selected( + self.registered_devices.get_n_items() - 1) self.set_ip_address(self.device_list) - def set_ip_address(self, entry: Adw.EntryRow, *args): settings = self.get_settings() - ip_by_index = list(self.plugin_base.backend.get_devices().values())[entry.get_selected()].ip_address + ip_by_index = list(self.plugin_base.backend.get_devices().values())[ + entry.get_selected()].ip_address - print("Save new selected ip address ", ip_by_index) settings["ip_address"] = ip_by_index self.ip_address = ip_by_index self.set_settings(settings) - threading.Thread(target=self.update_light, daemon=True, name="update_light").start() - + threading.Thread(target=self.update_light, daemon=True, + name="update_light").start() def update_icon(self): settings = self.plugin_base.get_settings() if settings.get("light_active") == 1: - icon_path = os.path.join(self.plugin_base.PATH, "assets", "ring_light_on.png") + icon_path = os.path.join( + self.plugin_base.PATH, "assets", "ring_light_on.png") else: - icon_path = os.path.join(self.plugin_base.PATH, "assets", "ring_light_off.png") + icon_path = os.path.join( + self.plugin_base.PATH, "assets", "ring_light_off.png") self.set_media(media_path=icon_path, size=0.75) - # TODO: Fetch data from light (singleton) + def get_light_data(self): url = "" try: @@ -231,7 +249,6 @@ def get_light_data(self): except: return "Failed to get lights" - def update_light(self): settings = self.get_settings() global_settings = self.plugin_base.get_settings() @@ -239,8 +256,8 @@ def update_light(self): url = f"http://{ip_address}:9123/elgato/lights" data = { - "numberOfLights": 1, - "lights": [ + "numberOfLights": 1, + "lights": [ { "on": global_settings.get("light_active"), "brightness": self.current_brightness, diff --git a/actions/ElgatoKeyLight/Dial.py b/actions/ElgatoKeyLight/Dial.py index bfc83ae..17f3c9f 100644 --- a/actions/ElgatoKeyLight/Dial.py +++ b/actions/ElgatoKeyLight/Dial.py @@ -1,4 +1,5 @@ # Import StreamController modules +from gi.repository import Gtk, Adw from src.backend.DeckManagement.InputIdentifier import Input, InputEvent from enum import Enum @@ -8,16 +9,18 @@ import gi gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from gi.repository import Gtk, Adw + class DialProperty(Enum): Brightness = 0 Temperature = 1 + class ToggleProperty(Enum): ToggleLightOnOff = 0 ChangeBrightnessTemperature = 1 + class Dial(Core): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -26,22 +29,24 @@ def __init__(self, *args, **kwargs): self.current_dial_selection = 0 self.current_toggle_selection = 0 - def on_ready(self) -> None: self.load_local_saved_config() self.update_icon() self.update_labels() - self.plugin_base.backend.on_brightness_changed.subscribe(self.update_labels) - self.plugin_base.backend.on_temperature_changed.subscribe(self.update_labels) - + self.plugin_base.backend.on_brightness_changed.subscribe( + self.update_labels) + self.plugin_base.backend.on_temperature_changed.subscribe( + self.update_labels) def get_config_rows(self) -> list: parent_entries = super().get_config_rows() self.toggle_property_selection = Gtk.StringList() - self.toggle_property_selection.append(self.plugin_base.locale_manager.get("actions.toggle_selection.light_on_off")) - self.toggle_property_selection.append(self.plugin_base.locale_manager.get("actions.toggle_selection.brightness_temperature")) + self.toggle_property_selection.append( + self.plugin_base.locale_manager.get("actions.toggle_selection.light_on_off")) + self.toggle_property_selection.append(self.plugin_base.locale_manager.get( + "actions.toggle_selection.brightness_temperature")) self.property_selection = Gtk.StringList() @@ -49,44 +54,47 @@ def get_config_rows(self) -> list: self.property_selection.append(property.name) self.step_size = Adw.SpinRow.new_with_range(1, 10, 1) - self.step_size.set_title(self.plugin_base.locale_manager.get("actions.step_size.title")) + self.step_size.set_title( + self.plugin_base.locale_manager.get("actions.step_size.title")) self.step_size.set_value(self.selected_step_size) - self.dial_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get("actions.dial_selection.title"), model=self.property_selection) + self.dial_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get( + "actions.dial_selection.title"), model=self.property_selection) self.dial_selection.set_selected(self.current_dial_selection) - self.toggle_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get("actions.toggle_selection.title"), model=self.toggle_property_selection) + self.toggle_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get( + "actions.toggle_selection.title"), model=self.toggle_property_selection) self.toggle_selection.set_selected(self.current_toggle_selection) self.step_size.connect("notify::text", self.on_step_size_changed) - self.dial_selection.connect("notify::selected", self.on_dial_selection_changed) - self.toggle_selection.connect("notify::selected", self.on_toggle_selection_changed) + self.dial_selection.connect( + "notify::selected", self.on_dial_selection_changed) + self.toggle_selection.connect( + "notify::selected", self.on_toggle_selection_changed) return parent_entries + [self.dial_selection, self.toggle_selection, self.step_size] - def on_step_size_changed(self, spinner: Adw.SpinRow, *args): self.selected_step_size = int(self.step_size.get_value()) self.save_settings() - def on_dial_selection_changed(self, spinner: Adw.ComboRow, *args): self.current_dial_selection = int(self.dial_selection.get_selected()) self.save_settings() - def on_toggle_selection_changed(self, spinner: Adw.ComboRow, *args): - self.current_toggle_selection = int(self.toggle_selection.get_selected()) + self.current_toggle_selection = int( + self.toggle_selection.get_selected()) self.save_settings() - def load_local_saved_config(self): local_settings = self.get_settings() self.selected_step_size = local_settings.get("step_size") or 1 - self.current_dial_selection = local_settings.get("current_dial_selection") or 0 - self.current_toggle_selection = local_settings.get("current_toggle_selection") or 0 - + self.current_dial_selection = local_settings.get( + "current_dial_selection") or 0 + self.current_toggle_selection = local_settings.get( + "current_toggle_selection") or 0 def save_settings(self): local_settings = self.get_settings() @@ -96,26 +104,24 @@ def save_settings(self): local_settings["current_toggle_selection"] = self.current_toggle_selection self.set_settings(local_settings) - def event_callback(self, event: InputEvent, data: dict) -> None: - if event == Input.Key.Events.DOWN or event == Input.Dial.Events.DOWN: - self.on_key_down() - return - - new_value = 0 - if str(event) == str(Input.Dial.Events.TURN_CW): - new_value = +self.selected_step_size - if str(event) == str(Input.Dial.Events.TURN_CCW): - new_value = -self.selected_step_size - - is_brightness = self.current_dial_selection == DialProperty.Brightness.value - if is_brightness: - self.modify_brightness(new_value) - else: - self.modify_temperature(new_value) - - self.update_labels() + if event == Input.Key.Events.DOWN or event == Input.Dial.Events.DOWN: + self.on_key_down() + return + + new_value = 0 + if str(event) == str(Input.Dial.Events.TURN_CW): + new_value = +self.selected_step_size + if str(event) == str(Input.Dial.Events.TURN_CCW): + new_value = -self.selected_step_size + + is_brightness = self.current_dial_selection == DialProperty.Brightness.value + if is_brightness: + self.modify_brightness(new_value) + else: + self.modify_temperature(new_value) + self.update_labels() def toggle_brightness_temperature(self): if self.current_dial_selection == DialProperty.Brightness.value: @@ -125,16 +131,17 @@ def toggle_brightness_temperature(self): self.save_settings() - def update_labels(self): if self.current_dial_selection == DialProperty.Brightness.value: - self.set_top_label(text=self.plugin_base.locale_manager.get("actions.current_brightness.title")) - self.set_bottom_label(text=self.plugin_base.locale_manager.get("actions.current_brightness.value") % self.current_brightness) + self.set_top_label(text=self.plugin_base.locale_manager.get( + "actions.current_brightness.title")) + self.set_bottom_label(text=self.plugin_base.locale_manager.get( + "actions.current_brightness.value") % self.current_brightness) else: - self.set_top_label(text=self.plugin_base.locale_manager.get("actions.current_temperature.title")) + self.set_top_label(text=self.plugin_base.locale_manager.get( + "actions.current_temperature.title")) self.set_bottom_label(text=str(self.current_temperature)) - def on_key_down(self) -> None: if self.current_toggle_selection == ToggleProperty.ToggleLightOnOff.value: self.toggle_light() diff --git a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py index 05ef1f0..9b8abf8 100644 --- a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py +++ b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py @@ -1,4 +1,5 @@ # Import StreamController modules +from gi.repository import Gtk, Adw from src.backend.DeckManagement.InputIdentifier import Input, InputEvent from enum import Enum @@ -8,12 +9,13 @@ import gi gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from gi.repository import Gtk, Adw + class AvailableProperty(Enum): Brightness = 0 Temperature = 1 + class IncreaseDecreaseButton(Core): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -21,7 +23,6 @@ def __init__(self, *args, **kwargs): self.selected_step_size = 1 self.current_dial_selection = 0 - def on_ready(self) -> None: self.load_local_saved_config() self.update_icon() @@ -35,23 +36,24 @@ def get_config_rows(self) -> list: self.property_selection.append(property.name) self.step_size = Adw.SpinRow.new_with_range(-10, 10, 1) - self.step_size.set_title(self.plugin_base.locale_manager.get("actions.step_size.title")) + self.step_size.set_title( + self.plugin_base.locale_manager.get("actions.step_size.title")) self.step_size.set_value(self.selected_step_size) - self.dial_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get("actions.dial_selection.title"), model=self.property_selection) + self.dial_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get( + "actions.dial_selection.title"), model=self.property_selection) self.dial_selection.set_selected(self.current_dial_selection) self.step_size.connect("notify::text", self.on_step_size_changed) - self.dial_selection.connect("notify::selected", self.on_dial_selection_changed) + self.dial_selection.connect( + "notify::selected", self.on_dial_selection_changed) return parent_entries + [self.dial_selection, self.step_size] - def on_step_size_changed(self, spinner: Adw.SpinRow, *args): self.selected_step_size = int(self.step_size.get_value()) self.save_settings() - def on_dial_selection_changed(self, spinner: Adw.ComboRow, *args): self.current_dial_selection = int(self.dial_selection.get_selected()) self.save_settings() @@ -60,8 +62,8 @@ def load_local_saved_config(self): local_settings = self.get_settings() self.selected_step_size = local_settings.get("step_size") or 1 - self.current_dial_selection = local_settings.get("current_dial_selection") or 0 - + self.current_dial_selection = local_settings.get( + "current_dial_selection") or 0 def save_settings(self): local_settings = self.get_settings() diff --git a/actions/ElgatoKeyLight/SetButton.py b/actions/ElgatoKeyLight/SetButton.py index 7b98fd9..747f737 100644 --- a/actions/ElgatoKeyLight/SetButton.py +++ b/actions/ElgatoKeyLight/SetButton.py @@ -1,10 +1,10 @@ +from gi.repository import Adw from .Core import Core # Import gtk modules - used for the config rows import gi gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from gi.repository import Adw class SetButton(Core): @@ -14,8 +14,10 @@ def __init__(self, *args, **kwargs): def on_ready(self) -> None: local_settings = self.get_settings() - self._custom_brightness = local_settings.get("custom_brightness") or self.supported_lights["ElgatoKeyLight"]["min_brightness"] - self._custom_temperature = local_settings.get("custom_temperature") or self.supported_lights["ElgatoKeyLight"]["min_temperature"] + self._custom_brightness = local_settings.get( + "custom_brightness") or self.supported_lights["ElgatoKeyLight"]["min_brightness"] + self._custom_temperature = local_settings.get( + "custom_temperature") or self.supported_lights["ElgatoKeyLight"]["min_temperature"] self._live_update = local_settings.get("live_update") or False self.update_icon() @@ -61,16 +63,22 @@ def get_config_rows(self) -> list: self.live_update.set_active(self.live_update_active) self.live_update.connect("notify::active", self.on_live_update_changed) - self.brightness_entry = Adw.SpinRow.new_with_range(self.supported_lights["ElgatoKeyLight"]["min_brightness"], self.supported_lights["ElgatoKeyLight"]["max_brightness"], 1) - self.brightness_entry.set_title(self.plugin_base.locale_manager.get("actions.brightness_entry.title")) + self.brightness_entry = Adw.SpinRow.new_with_range( + self.supported_lights["ElgatoKeyLight"]["min_brightness"], self.supported_lights["ElgatoKeyLight"]["max_brightness"], 1) + self.brightness_entry.set_title( + self.plugin_base.locale_manager.get("actions.brightness_entry.title")) self.brightness_entry.set_value(self.custom_brightness) - self.temperature_entry = Adw.SpinRow.new_with_range(self.supported_lights["ElgatoKeyLight"]["min_temperature"], self.supported_lights["ElgatoKeyLight"]["max_temperature"], 1) - self.temperature_entry.set_title(self.plugin_base.locale_manager.get("actions.brightness_entry.title")) + self.temperature_entry = Adw.SpinRow.new_with_range( + self.supported_lights["ElgatoKeyLight"]["min_temperature"], self.supported_lights["ElgatoKeyLight"]["max_temperature"], 1) + self.temperature_entry.set_title( + self.plugin_base.locale_manager.get("actions.brightness_entry.title")) self.temperature_entry.set_value(self.custom_temperature) - self.brightness_entry.connect("notify::value", self.on_brightness_changed) - self.temperature_entry.connect("notify::value", self.on_temperature_changed) + self.brightness_entry.connect( + "notify::value", self.on_brightness_changed) + self.temperature_entry.connect( + "notify::value", self.on_temperature_changed) return parent_entries + [self.live_update, self.brightness_entry, self.temperature_entry] def on_live_update_changed(self, switch: Adw.SwitchRow, *args): diff --git a/actions/ElgatoKeyLight/ToggleButton.py b/actions/ElgatoKeyLight/ToggleButton.py index dbbfb29..a14e71d 100644 --- a/actions/ElgatoKeyLight/ToggleButton.py +++ b/actions/ElgatoKeyLight/ToggleButton.py @@ -1,5 +1,6 @@ from .Core import Core + class ToggleButton(Core): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) From df3e66a07aa14ba8b37ddd7c561d387f91f18dcc Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Mon, 5 May 2025 18:32:34 -0600 Subject: [PATCH 03/25] feat (locales): Add missing title for Add IP to List button --- locales/en_US.json | 1 + 1 file changed, 1 insertion(+) diff --git a/locales/en_US.json b/locales/en_US.json index e3d6082..e433d2c 100644 --- a/locales/en_US.json +++ b/locales/en_US.json @@ -1,6 +1,7 @@ { "actions.live_update.title": "Live Update", "actions.add_ip_entry.title": "Add new IP Address", + "actions.add_light_button.title": "Add new IP Address", "actions.step_size.title": "Step Size", "actions.dial_selection.title": "Dial Selection", "actions.brightness_entry.title": "Brightness", From 75f709ec055f8e172f6db03c5b86f610ec43f758 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Mon, 5 May 2025 18:36:31 -0600 Subject: [PATCH 04/25] feat (core): Add get_light_data implementation --- actions/ElgatoKeyLight/Core.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 0c8ac78..7b70927 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -8,6 +8,7 @@ import gi import threading import time +import json gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") @@ -61,6 +62,7 @@ def is_connected(self, value): @property def current_brightness(self): settings = self.plugin_base.get_settings() + return settings.get("brightness") or self.supported_lights["ElgatoKeyLight"]["min_brightness"] @current_brightness.setter @@ -242,10 +244,11 @@ def update_icon(self): # TODO: Fetch data from light (singleton) def get_light_data(self): - url = "" + ip_address = settings.get("ip_address") + url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.get(url) - return r.text + return json.loads(r.text()[0]) except: return "Failed to get lights" From 6082cb292646a2c5dd3db1b3f6988f9fcc454768 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Mon, 5 May 2025 21:10:38 -0600 Subject: [PATCH 05/25] fix (core): Fixed json parsin on get_light_data method --- actions/ElgatoKeyLight/Core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 7b70927..a0c55cc 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -248,7 +248,7 @@ def get_light_data(self): url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.get(url) - return json.loads(r.text()[0]) + return json.loads(r.text["lights"][0]) except: return "Failed to get lights" From 1994e85b973cbf92e149fe1d0d4ae4579d80c50e Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Mon, 5 May 2025 21:27:13 -0600 Subject: [PATCH 06/25] feature (Core): Refactor update_light to use current settings from Elgato API --- actions/ElgatoKeyLight/Core.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index a0c55cc..1ff2bed 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -252,9 +252,9 @@ def get_light_data(self): except: return "Failed to get lights" - def update_light(self): - settings = self.get_settings() - global_settings = self.plugin_base.get_settings() + def update_light(self,_is_light_active,_brightness,_temperature): + current_settings = self.get_light_data() + ip_address = settings.get("ip_address") url = f"http://{ip_address}:9123/elgato/lights" @@ -262,9 +262,9 @@ def update_light(self): "numberOfLights": 1, "lights": [ { - "on": global_settings.get("light_active"), - "brightness": self.current_brightness, - "temperature": self.current_temperature + "on": _is_light_active or current_settings["on"] + "brightness": _brightness or current_settings:["brightness"], + "temperature": _temperature or current_settings:["temperature"] } ] } From 08c6120297ff1a9cdd7242604f6f3fda18af612d Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Tue, 6 May 2025 09:53:03 -0600 Subject: [PATCH 07/25] fix (Core): Fix update_lighs and get_light_data implementations --- actions/ElgatoKeyLight/Core.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 1ff2bed..203ced0 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -248,7 +248,7 @@ def get_light_data(self): url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.get(url) - return json.loads(r.text["lights"][0]) + return json.loads(r.text)["lights"][0] except: return "Failed to get lights" @@ -262,9 +262,9 @@ def update_light(self,_is_light_active,_brightness,_temperature): "numberOfLights": 1, "lights": [ { - "on": _is_light_active or current_settings["on"] - "brightness": _brightness or current_settings:["brightness"], - "temperature": _temperature or current_settings:["temperature"] + "on": _is_light_active or current_settings["on"], + "brightness": _brightness or current_settings["brightness"], + "temperature": _temperature or current_settings["temperature"] } ] } From fac9f263c964eb69d3060574797362e6b266c13a Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Tue, 6 May 2025 10:56:23 -0600 Subject: [PATCH 08/25] feat (core): Add brightness and toggle control --- actions/ElgatoKeyLight/Core.py | 36 ++++++++++++++-------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 203ced0..308aafb 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -61,22 +61,17 @@ def is_connected(self, value): @property def current_brightness(self): - settings = self.plugin_base.get_settings() - - return settings.get("brightness") or self.supported_lights["ElgatoKeyLight"]["min_brightness"] + return self.get_light_data()["brightness"] or self.supported_lights["ElgatoKeyLight"]["min_brightness"] @current_brightness.setter def current_brightness(self, value): - settings = self.plugin_base.get_settings() - _current_brightness = max(self.supported_lights["ElgatoKeyLight"]["min_brightness"], min( value, self.supported_lights["ElgatoKeyLight"]["max_brightness"])) - settings["brightness"] = int(_current_brightness) - - self.plugin_base.set_settings(settings) self.plugin_base.backend.on_brightness_changed.emit() - threading.Thread(target=self.update_light, daemon=True, + threading.Thread(target=self.update_light, + args=(None,int(_current_brightness),None,), + daemon=True, name="update_light").start() @property @@ -155,8 +150,7 @@ def set_banner_connection_info(self) -> None: "actions.connection_banner.not_connected")) def modify_brightness(self, amount: int): - settings = self.plugin_base.get_settings() - new_brightness = int(settings.get("brightness") or 0) + amount + new_brightness = int(self.get_light_data()["brightness"] or 0) + amount self.current_brightness = new_brightness def modify_temperature(self, amount: int): @@ -165,16 +159,13 @@ def modify_temperature(self, amount: int): self.current_temperature = new_temperature def toggle_light(self): - settings = self.plugin_base.get_settings() + + status = self.get_light_data()["on"] - if settings.get("light_active") == 0: - settings["light_active"] = 1 - else: - settings["light_active"] = 0 + status = 1 - status - self.plugin_base.set_settings(settings) self.plugin_base.backend.on_light_state_changed.emit() - self.update_light() + self.update_light(status,None,None) def load_default_config(self): # Fallback for old global settings @@ -244,7 +235,7 @@ def update_icon(self): # TODO: Fetch data from light (singleton) def get_light_data(self): - ip_address = settings.get("ip_address") + ip_address = self.get_settings().get("ip_address") url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.get(url) @@ -255,14 +246,17 @@ def get_light_data(self): def update_light(self,_is_light_active,_brightness,_temperature): current_settings = self.get_light_data() - ip_address = settings.get("ip_address") + ip_address = self.get_settings().get("ip_address") url = f"http://{ip_address}:9123/elgato/lights" + if _is_light_active is None: + _is_light_active = current_settings["on"] + data = { "numberOfLights": 1, "lights": [ { - "on": _is_light_active or current_settings["on"], + "on": _is_light_active, "brightness": _brightness or current_settings["brightness"], "temperature": _temperature or current_settings["temperature"] } From a2ae8425d4a316a661df23dfb7d78aa3f2c2f297 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Tue, 6 May 2025 12:24:31 -0600 Subject: [PATCH 09/25] feat (Core): Refactor temperature control with Dial --- actions/ElgatoKeyLight/Core.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 308aafb..ca8c446 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -76,21 +76,17 @@ def current_brightness(self, value): @property def current_temperature(self): - settings = self.plugin_base.get_settings() - return settings.get("temperature") or self.supported_lights["ElgatoKeyLight"]["min_temperature"] + return self.get_light_data()["temperature"] or self.supported_lights["ElgatoKeyLight"]["min_temperature"] @current_temperature.setter def current_temperature(self, value): - settings = self.plugin_base.get_settings() - _current_temperature = max(self.supported_lights["ElgatoKeyLight"]["min_temperature"], min( value, self.supported_lights["ElgatoKeyLight"]["max_temperature"])) - settings["temperature"] = int(_current_temperature) - - self.plugin_base.set_settings(settings) self.plugin_base.backend.on_temperature_changed.emit() - threading.Thread(target=self.update_light, daemon=True, + threading.Thread(target=self.update_light, + args=(None,None,int(_current_temperature),), + daemon=True, name="update_light").start() def on_ready(self) -> None: @@ -154,8 +150,7 @@ def modify_brightness(self, amount: int): self.current_brightness = new_brightness def modify_temperature(self, amount: int): - settings = self.plugin_base.get_settings() - new_temperature = int(settings.get("temperature") or 0) + amount + new_temperature = int(self.get_light_data()["temperature"] or 0) + amount self.current_temperature = new_temperature def toggle_light(self): From 4da63e34924a2cb33375b98afea94d9488f681e1 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Tue, 6 May 2025 13:07:26 -0600 Subject: [PATCH 10/25] feat (Core): Add current_status property and refactor update_light On update_light implementation, changed the requirement to request the elgato api to fetch the current values, to use the class properties --- actions/ElgatoKeyLight/Core.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index ca8c446..a85c26e 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -1,6 +1,5 @@ # Import StreamController modules from gi.repository import Gtk, Adw -import requests from ipaddress import ip_address from src.backend.PluginManager.ActionBase import ActionBase @@ -9,6 +8,7 @@ import threading import time import json +import requests gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") @@ -59,6 +59,18 @@ def is_connected(self, value): self._is_connected = value self.set_banner_connection_info() + @property + def current_status(self): + return self.get_light_data()["on"] or 0 + + @current_status.setter + def current_status(self, value): + self.plugin_base.backend.on_light_state_changed.emit() + threading.Thread(target=self.update_light, + args=(int(value),None,None,), + daemon=True, + name="update_light").start() + @property def current_brightness(self): return self.get_light_data()["brightness"] or self.supported_lights["ElgatoKeyLight"]["min_brightness"] @@ -154,13 +166,9 @@ def modify_temperature(self, amount: int): self.current_temperature = new_temperature def toggle_light(self): - status = self.get_light_data()["on"] - status = 1 - status - - self.plugin_base.backend.on_light_state_changed.emit() - self.update_light(status,None,None) + self.current_status = status def load_default_config(self): # Fallback for old global settings @@ -239,21 +247,20 @@ def get_light_data(self): return "Failed to get lights" def update_light(self,_is_light_active,_brightness,_temperature): - current_settings = self.get_light_data() ip_address = self.get_settings().get("ip_address") url = f"http://{ip_address}:9123/elgato/lights" if _is_light_active is None: - _is_light_active = current_settings["on"] + _is_light_active = self.current_status data = { "numberOfLights": 1, "lights": [ { "on": _is_light_active, - "brightness": _brightness or current_settings["brightness"], - "temperature": _temperature or current_settings["temperature"] + "brightness": _brightness or self.current_brightness, + "temperature": _temperature or self.current_temperature } ] } From 25823185c56e7d92865aacce5144bae71b515b1a Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 11:09:51 -0600 Subject: [PATCH 11/25] Refactor (network-imprv): Change properties setup and request - New implementation of a json-object for local cache to avoid requesting to elgato API every operation - Add set_property method to apply changes into json-object and request - Change request implementation, TODO async lockeable request --- actions/ElgatoKeyLight/Core.py | 75 +++++++++++++++++++++++++++++++++- actions/ElgatoKeyLight/Dial.py | 10 ++--- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index a85c26e..fb95e12 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -34,12 +34,85 @@ def __init__(self, *args, **kwargs): } } + self.json_data = { + "numberOfLights": 1, + "lights": [ + { + "on": 0, + "brightness": 1, + "temperature": 143 + } + ] + } + + self._get_from_api() + self.banner_is_visible = False self._is_connected = False self._connection_error = "" self._last_request_number = 0 self._running_requests = 0 + + self._lock = threading.Lock() + self._send_timer = None + self._async_time = 0.15 #150 Ms + def set_property(self, key, value): + #with self._lock: + + match key: + case "brightness": + self.plugin_base.backend.on_brightness_changed.emit() + self.json_data["lights"][0][key] = int(self.json_data["lights"][0][key] or 0) + value + + case "temperature": + self.plugin_base.backend.on_temperature_changed.emit() + self.json_data["lights"][0][key] = int(self.json_data["lights"][0][key] or 0) + value + + case "on": + self.json_data["lights"][0][key] = 1 - int(self.json_data["lights"][0][key]) + case _: + print("No actions passed") + + self._async_send() + + def _async_send(self): + #if self._send_timer: + # print("We killing the process") + # self._send_timer.cancel() + + #self._send_timer = threading.Timer(self._async_time,self._send_to_api) + #self._send_timer.start() + threading.Thread(target=self._send_to_api, + daemon=True, + name="_send_to_api").start() + + + + def _send_to_api(self): + #with self._lock: + payload = self.json_data.copy() + + ip_address = self.get_settings().get("ip_address") + url = f"http://{ip_address}:9123/elgato/lights" + try: + r = requests.put(url, json=payload, timeout=10) + except: + print(f"[Error]: Couldnt Sent update, request_body={payload}") + + def _get_from_api(self): + ip_address = self.get_settings().get("ip_address") + url = f"http://{ip_address}:9123/elgato/lights" + try: + r = requests.get(url,timeout=10) + self.json_data = r.json() + print(f"[LOG]: Information retrieved, request_body={self.json_data}") + except: + print(f"[Error]: Couldnt Sent update, request_body={self.json_data}") + #with self._lock: + + + @property def running_requests(self): @@ -73,7 +146,7 @@ def current_status(self, value): @property def current_brightness(self): - return self.get_light_data()["brightness"] or self.supported_lights["ElgatoKeyLight"]["min_brightness"] + return self.json_data["lights"][0]["brightness"] @current_brightness.setter def current_brightness(self, value): diff --git a/actions/ElgatoKeyLight/Dial.py b/actions/ElgatoKeyLight/Dial.py index 17f3c9f..b8a81b6 100644 --- a/actions/ElgatoKeyLight/Dial.py +++ b/actions/ElgatoKeyLight/Dial.py @@ -41,7 +41,7 @@ def on_ready(self) -> None: def get_config_rows(self) -> list: parent_entries = super().get_config_rows() - + self.toggle_property_selection = Gtk.StringList() self.toggle_property_selection.append( self.plugin_base.locale_manager.get("actions.toggle_selection.light_on_off")) @@ -117,11 +117,9 @@ def event_callback(self, event: InputEvent, data: dict) -> None: is_brightness = self.current_dial_selection == DialProperty.Brightness.value if is_brightness: - self.modify_brightness(new_value) + self.set_property("brightness",new_value) else: - self.modify_temperature(new_value) - - self.update_labels() + self.set_property("temperature",new_value) def toggle_brightness_temperature(self): if self.current_dial_selection == DialProperty.Brightness.value: @@ -144,6 +142,6 @@ def update_labels(self): def on_key_down(self) -> None: if self.current_toggle_selection == ToggleProperty.ToggleLightOnOff.value: - self.toggle_light() + self.set_property("on",None) else: self.toggle_brightness_temperature() From 6d2b2e26689d08adb086eef74a3b5ae1d1a4ce87 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 11:50:56 -0600 Subject: [PATCH 12/25] Refactor (network-imprv): Remove unused locking mechanism and methods --- actions/ElgatoKeyLight/Core.py | 58 +++------------------------------- 1 file changed, 5 insertions(+), 53 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index fb95e12..86806d2 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -54,43 +54,29 @@ def __init__(self, *args, **kwargs): self._last_request_number = 0 self._running_requests = 0 - self._lock = threading.Lock() - self._send_timer = None - self._async_time = 0.15 #150 Ms def set_property(self, key, value): - #with self._lock: - match key: case "brightness": self.plugin_base.backend.on_brightness_changed.emit() - self.json_data["lights"][0][key] = int(self.json_data["lights"][0][key] or 0) + value + self.json_data["lights"][0][key] = max(1, min(self.current_brightness + value, 100)) case "temperature": self.plugin_base.backend.on_temperature_changed.emit() - self.json_data["lights"][0][key] = int(self.json_data["lights"][0][key] or 0) + value + self.json_data["lights"][0][key] = max(143, min(self.current_temperature + value, 344)) case "on": - self.json_data["lights"][0][key] = 1 - int(self.json_data["lights"][0][key]) + self.json_data["lights"][0][key] = 1 - self.current_status case _: print("No actions passed") self._async_send() def _async_send(self): - #if self._send_timer: - # print("We killing the process") - # self._send_timer.cancel() - - #self._send_timer = threading.Timer(self._async_time,self._send_to_api) - #self._send_timer.start() threading.Thread(target=self._send_to_api, daemon=True, name="_send_to_api").start() - - def _send_to_api(self): - #with self._lock: payload = self.json_data.copy() ip_address = self.get_settings().get("ip_address") @@ -109,10 +95,6 @@ def _get_from_api(self): print(f"[LOG]: Information retrieved, request_body={self.json_data}") except: print(f"[Error]: Couldnt Sent update, request_body={self.json_data}") - #with self._lock: - - - @property def running_requests(self): @@ -134,45 +116,15 @@ def is_connected(self, value): @property def current_status(self): - return self.get_light_data()["on"] or 0 - - @current_status.setter - def current_status(self, value): - self.plugin_base.backend.on_light_state_changed.emit() - threading.Thread(target=self.update_light, - args=(int(value),None,None,), - daemon=True, - name="update_light").start() + return self.json_data["lights"][0]["on"] @property def current_brightness(self): return self.json_data["lights"][0]["brightness"] - @current_brightness.setter - def current_brightness(self, value): - _current_brightness = max(self.supported_lights["ElgatoKeyLight"]["min_brightness"], min( - value, self.supported_lights["ElgatoKeyLight"]["max_brightness"])) - - self.plugin_base.backend.on_brightness_changed.emit() - threading.Thread(target=self.update_light, - args=(None,int(_current_brightness),None,), - daemon=True, - name="update_light").start() - @property def current_temperature(self): - return self.get_light_data()["temperature"] or self.supported_lights["ElgatoKeyLight"]["min_temperature"] - - @current_temperature.setter - def current_temperature(self, value): - _current_temperature = max(self.supported_lights["ElgatoKeyLight"]["min_temperature"], min( - value, self.supported_lights["ElgatoKeyLight"]["max_temperature"])) - - self.plugin_base.backend.on_temperature_changed.emit() - threading.Thread(target=self.update_light, - args=(None,None,int(_current_temperature),), - daemon=True, - name="update_light").start() + return self.json_data["lights"][0]["temperature"] def on_ready(self) -> None: self.load_default_config() From 8704ef12ff6be3280b4597d247cc670055b84125 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 12:12:27 -0600 Subject: [PATCH 13/25] Refactor (Display): Add K Temperature property for display --- actions/ElgatoKeyLight/Core.py | 9 +++++++++ actions/ElgatoKeyLight/Dial.py | 3 ++- locales/en_US.json | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 86806d2..8f80c0d 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -31,6 +31,8 @@ def __init__(self, *args, **kwargs): "max_brightness": 100, "min_temperature": 143, "max_temperature": 344, + "min_k_temperature": 2900, + "max_k_temperature": 7000, } } @@ -126,6 +128,13 @@ def current_brightness(self): def current_temperature(self): return self.json_data["lights"][0]["temperature"] + @property + def current_k_temperature(self): + real_min, real_max = self.supported_lights["ElgatoKeyLight"]["min_temperature"],self.supported_lights["ElgatoKeyLight"]["max_temperature"] + shown_min, shown_max = self.supported_lights["ElgatoKeyLight"]["min_k_temperature"],self.supported_lights["ElgatoKeyLight"]["max_k_temperature"] + real_value = self.current_temperature + return ((real_value - real_min) / (real_max - real_min)) * (shown_max - shown_min) + shown_min + def on_ready(self) -> None: self.load_default_config() self.update_icon() diff --git a/actions/ElgatoKeyLight/Dial.py b/actions/ElgatoKeyLight/Dial.py index b8a81b6..d1f4cae 100644 --- a/actions/ElgatoKeyLight/Dial.py +++ b/actions/ElgatoKeyLight/Dial.py @@ -138,7 +138,8 @@ def update_labels(self): else: self.set_top_label(text=self.plugin_base.locale_manager.get( "actions.current_temperature.title")) - self.set_bottom_label(text=str(self.current_temperature)) + self.set_bottom_label(text=self.plugin_base.locale_manager.get( + "actions.current_temperature.value") % int(self.current_k_temperature)) def on_key_down(self) -> None: if self.current_toggle_selection == ToggleProperty.ToggleLightOnOff.value: diff --git a/locales/en_US.json b/locales/en_US.json index e433d2c..de7444b 100644 --- a/locales/en_US.json +++ b/locales/en_US.json @@ -12,6 +12,7 @@ "actions.current_brightness.title": "Brightness", "actions.current_brightness.value": "%s %%", "actions.current_temperature.title": "Temperature", + "actions.current_temperature.value": "%s K", "actions.toggle_selection.title": "On press", "actions.toggle_selection.light_on_off": "Toggle Light", "actions.toggle_selection.brightness_temperature": "Change Brightness/Temperature", From 401d8831ebb5a494ffe0bd6e2f6569a447ddbd68 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 12:42:24 -0600 Subject: [PATCH 14/25] Refactor (network-imprv): Change method on Toggle action --- actions/ElgatoKeyLight/ToggleButton.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/ElgatoKeyLight/ToggleButton.py b/actions/ElgatoKeyLight/ToggleButton.py index a14e71d..9bf89af 100644 --- a/actions/ElgatoKeyLight/ToggleButton.py +++ b/actions/ElgatoKeyLight/ToggleButton.py @@ -6,4 +6,4 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def on_key_down(self) -> None: - self.toggle_light() + self.set_property("on",None) From 0e8d078647292f54cb24861661c5795c9bdc98aa Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 18:21:10 -0600 Subject: [PATCH 15/25] fix (core): Fix overlap issues with configurations and IPs --- actions/ElgatoKeyLight/Core.py | 66 ++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 8f80c0d..8e2e5dc 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -15,6 +15,9 @@ class Core(ActionBase): + + data = {} + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.lm = self.plugin_base.locale_manager @@ -47,8 +50,6 @@ def __init__(self, *args, **kwargs): ] } - self._get_from_api() - self.banner_is_visible = False self._is_connected = False @@ -60,14 +61,15 @@ def set_property(self, key, value): match key: case "brightness": self.plugin_base.backend.on_brightness_changed.emit() - self.json_data["lights"][0][key] = max(1, min(self.current_brightness + value, 100)) + #self.json_data["lights"][0][key] = max(1, min(self.current_brightness + value, 100)) + Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = max(1, min(Core.data[self.get_settings().get("ip_address")]["lights"][0][key] + value, 100)) case "temperature": self.plugin_base.backend.on_temperature_changed.emit() - self.json_data["lights"][0][key] = max(143, min(self.current_temperature + value, 344)) - + #self.json_data["lights"][0][key] = max(143, min(self.current_temperature + value, 344)) + Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = max(143, min(Core.data[self.get_settings().get("ip_address")]["lights"][0][key] + value, 344)) case "on": - self.json_data["lights"][0][key] = 1 - self.current_status + Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = 1 - Core.data[self.get_settings().get("ip_address")]["lights"][0][key] case _: print("No actions passed") @@ -79,24 +81,33 @@ def _async_send(self): name="_send_to_api").start() def _send_to_api(self): - payload = self.json_data.copy() - ip_address = self.get_settings().get("ip_address") + payload = Core.data[ip_address].copy() url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.put(url, json=payload, timeout=10) except: print(f"[Error]: Couldnt Sent update, request_body={payload}") - def _get_from_api(self): - ip_address = self.get_settings().get("ip_address") - url = f"http://{ip_address}:9123/elgato/lights" + def _get_from_api(self,ip): + url = f"http://{ip}:9123/elgato/lights" try: r = requests.get(url,timeout=10) - self.json_data = r.json() - print(f"[LOG]: Information retrieved, request_body={self.json_data}") + return r.json() except: - print(f"[Error]: Couldnt Sent update, request_body={self.json_data}") + print("[Error]: Couldnt Sent update") + return None + + def _add_data_dictonary(self, ip): + if ip in Core.data: + return 0 + data_from_api = self._get_from_api(ip) + Core.data[ip] = data_from_api + + def _get_data_dictonary(self, ip): + if ip not in Core.data: + return {} + return data[ip] @property def running_requests(self): @@ -118,15 +129,28 @@ def is_connected(self, value): @property def current_status(self): - return self.json_data["lights"][0]["on"] + ip = self.get_settings().get("ip_address") + if ip not in Core.data: + self._add_data_dictonary(ip) + cur_status = Core.data[ip]["lights"][0]["on"] + return cur_status or 0 @property def current_brightness(self): - return self.json_data["lights"][0]["brightness"] + ip = self.get_settings().get("ip_address") + if ip not in Core.data: + self._add_data_dictonary(ip) + + cur_status = Core.data[ip]["lights"][0]["brightness"] + return cur_status or 1 @property def current_temperature(self): - return self.json_data["lights"][0]["temperature"] + ip = self.get_settings().get("ip_address") + if ip not in Core.data: + self._add_data_dictonary(ip) + cur_status = Core.data[ip]["lights"][0]["temperature"] + return cur_status or 143 @property def current_k_temperature(self): @@ -220,6 +244,7 @@ def load_default_config(self): self.set_settings(settings) saved_ip_address = settings.get("ip_address") + if saved_ip_address: print("Saved ip address in config ", saved_ip_address) @@ -256,8 +281,11 @@ def set_ip_address(self, entry: Adw.EntryRow, *args): self.ip_address = ip_by_index self.set_settings(settings) - threading.Thread(target=self.update_light, daemon=True, - name="update_light").start() + + self._add_data_dictonary(ip_by_index) + + #threading.Thread(target=self.update_light, daemon=True, + # name="update_light").start() def update_icon(self): settings = self.plugin_base.get_settings() From 43513c6a2e6b039e3d30167ac981a8c15b698dc8 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 19:09:33 -0600 Subject: [PATCH 16/25] fix (Dial): Change screen text to update after light update --- actions/ElgatoKeyLight/Dial.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/actions/ElgatoKeyLight/Dial.py b/actions/ElgatoKeyLight/Dial.py index d1f4cae..28a22fe 100644 --- a/actions/ElgatoKeyLight/Dial.py +++ b/actions/ElgatoKeyLight/Dial.py @@ -120,6 +120,8 @@ def event_callback(self, event: InputEvent, data: dict) -> None: self.set_property("brightness",new_value) else: self.set_property("temperature",new_value) + + self.update_labels() def toggle_brightness_temperature(self): if self.current_dial_selection == DialProperty.Brightness.value: From a1047902cb2029513cd6c60c71ca3dab7f5d61f4 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 19:33:09 -0600 Subject: [PATCH 17/25] fix (IDButton): Change to set_property implementation for changes --- actions/ElgatoKeyLight/IncreaseDecreaseButton.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py index 9b8abf8..878f454 100644 --- a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py +++ b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py @@ -77,6 +77,6 @@ def on_key_down(self) -> None: new_value = +self.selected_step_size is_brightness = self.current_dial_selection == AvailableProperty.Brightness.value if is_brightness: - self.modify_brightness(new_value) + self.set_property("brightness",new_value) else: - self.modify_temperature(new_value) + self.set_property("temperature",new_value) From d67ecd472dd5ebf5beda31d7414018cc1b21fd9d Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 19:44:13 -0600 Subject: [PATCH 18/25] Refactor (core): Change set_properties to only work with specific values --- actions/ElgatoKeyLight/Core.py | 4 ++-- actions/ElgatoKeyLight/Dial.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 8e2e5dc..9107ea9 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -62,12 +62,12 @@ def set_property(self, key, value): case "brightness": self.plugin_base.backend.on_brightness_changed.emit() #self.json_data["lights"][0][key] = max(1, min(self.current_brightness + value, 100)) - Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = max(1, min(Core.data[self.get_settings().get("ip_address")]["lights"][0][key] + value, 100)) + Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = value case "temperature": self.plugin_base.backend.on_temperature_changed.emit() #self.json_data["lights"][0][key] = max(143, min(self.current_temperature + value, 344)) - Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = max(143, min(Core.data[self.get_settings().get("ip_address")]["lights"][0][key] + value, 344)) + Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = value case "on": Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = 1 - Core.data[self.get_settings().get("ip_address")]["lights"][0][key] case _: diff --git a/actions/ElgatoKeyLight/Dial.py b/actions/ElgatoKeyLight/Dial.py index 28a22fe..1ed5ca1 100644 --- a/actions/ElgatoKeyLight/Dial.py +++ b/actions/ElgatoKeyLight/Dial.py @@ -117,9 +117,9 @@ def event_callback(self, event: InputEvent, data: dict) -> None: is_brightness = self.current_dial_selection == DialProperty.Brightness.value if is_brightness: - self.set_property("brightness",new_value) + self.set_property("brightness",max(1, min(self.current_brightness + new_value, 100))) else: - self.set_property("temperature",new_value) + self.set_property("temperature",max(143, min(self.current_temperature + new_value, 344))) self.update_labels() From 76a6871accb39beafad6b0462e5fc592f95ba0ba Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 19:47:32 -0600 Subject: [PATCH 19/25] feat (SetButton): Implement set_property method to use API and local based changes --- actions/ElgatoKeyLight/SetButton.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/actions/ElgatoKeyLight/SetButton.py b/actions/ElgatoKeyLight/SetButton.py index 747f737..f762c84 100644 --- a/actions/ElgatoKeyLight/SetButton.py +++ b/actions/ElgatoKeyLight/SetButton.py @@ -102,11 +102,9 @@ def on_key_down(self) -> None: self.push_light_properties() def push_light_properties(self): - settings = self.plugin_base.get_settings() + self.set_property("brightness",self.custom_brightness) + self.set_property("temperature",self.custom_temperature) - self.current_brightness = self.custom_brightness - self.current_temperature = self.custom_temperature - - if settings.get("light_active") == 0: - self.toggle_light() + if self.current_status == 0: + self.set_property("on",None) return From fbc70b592e8d9b10a73ce932e871d96b457289cf Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 7 May 2025 20:08:12 -0600 Subject: [PATCH 20/25] fix (Core): Update icons on property update --- actions/ElgatoKeyLight/Core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 9107ea9..b7a3de0 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -86,6 +86,7 @@ def _send_to_api(self): url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.put(url, json=payload, timeout=10) + self.update_icon() except: print(f"[Error]: Couldnt Sent update, request_body={payload}") @@ -288,8 +289,7 @@ def set_ip_address(self, entry: Adw.EntryRow, *args): # name="update_light").start() def update_icon(self): - settings = self.plugin_base.get_settings() - if settings.get("light_active") == 1: + if self.current_status == 1: icon_path = os.path.join( self.plugin_base.PATH, "assets", "ring_light_on.png") else: From 60be3dad8abf8922e4237d99806aaa94be194c0b Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Thu, 8 May 2025 10:35:47 -0600 Subject: [PATCH 21/25] fix (docs): Change the REPO url inside Plugin definition --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 6e165c2..5dac037 100644 --- a/main.py +++ b/main.py @@ -62,7 +62,7 @@ def __init__(self): # Register plugin self.register( plugin_name = "Elgato Key Light", - github_repo = "https://github.com/StreamController/PluginTemplate", + github_repo = "https://github.com/cozybuild/StreamControllerElgatoKeyLight/", plugin_version = "0.3.0", app_version = "1.1.1-alpha" ) From 60fc3b1631938d2438dfc71dc4684f4bcf6d9d3f Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Fri, 9 May 2025 13:45:08 -0600 Subject: [PATCH 22/25] fix (icon-update): Change method call to event call on update --- actions/ElgatoKeyLight/Core.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index b7a3de0..87e6d4e 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -86,7 +86,9 @@ def _send_to_api(self): url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.put(url, json=payload, timeout=10) - self.update_icon() + #self.update_icon() + self.plugin_base.backend.on_light_state_changed.emit() + except: print(f"[Error]: Couldnt Sent update, request_body={payload}") @@ -297,6 +299,7 @@ def update_icon(self): self.plugin_base.PATH, "assets", "ring_light_off.png") self.set_media(media_path=icon_path, size=0.75) + # TODO: Fetch data from light (singleton) def get_light_data(self): From 21904ec3b9cb90e4b45b6cf08769b9bf97c233d2 Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Mon, 12 May 2025 14:56:08 -0600 Subject: [PATCH 23/25] fix (display): Change the formula for Temperature in K --- actions/ElgatoKeyLight/Core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 87e6d4e..446c45e 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -158,7 +158,7 @@ def current_temperature(self): @property def current_k_temperature(self): real_min, real_max = self.supported_lights["ElgatoKeyLight"]["min_temperature"],self.supported_lights["ElgatoKeyLight"]["max_temperature"] - shown_min, shown_max = self.supported_lights["ElgatoKeyLight"]["min_k_temperature"],self.supported_lights["ElgatoKeyLight"]["max_k_temperature"] + shown_min, shown_max = self.supported_lights["ElgatoKeyLight"]["max_k_temperature"],self.supported_lights["ElgatoKeyLight"]["min_k_temperature"] real_value = self.current_temperature return ((real_value - real_min) / (real_max - real_min)) * (shown_max - shown_min) + shown_min From 857841f92cf33747c45ce6bbd4bd63d2a7fb920b Mon Sep 17 00:00:00 2001 From: DavidVallaLope Date: Wed, 14 May 2025 23:12:01 -0600 Subject: [PATCH 24/25] fix (ui): Devices dropdown picks current config --- actions/ElgatoKeyLight/Core.py | 12 ++++++------ actions/ElgatoKeyLight/IncreaseDecreaseButton.py | 4 ++-- actions/ElgatoKeyLight/ToggleButton.py | 7 +++++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 446c45e..1d6e5bf 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -104,8 +104,8 @@ def _get_from_api(self,ip): def _add_data_dictonary(self, ip): if ip in Core.data: return 0 - data_from_api = self._get_from_api(ip) - Core.data[ip] = data_from_api + Core.data[ip] = self._get_from_api(ip) + return None def _get_data_dictonary(self, ip): if ip not in Core.data: @@ -141,7 +141,7 @@ def current_status(self): @property def current_brightness(self): ip = self.get_settings().get("ip_address") - if ip not in Core.data: + if ip not in Core.data : self._add_data_dictonary(ip) cur_status = Core.data[ip]["lights"][0]["brightness"] @@ -254,13 +254,13 @@ def load_default_config(self): self.plugin_base.backend.register_new_device( saved_ip_address, saved_ip_address) - self.preselect_device_by_ip() + self.preselect_device_by_ip(saved_ip_address) self.ip_address = saved_ip_address - def preselect_device_by_ip(self): + def preselect_device_by_ip(self,ip): base_devices = self.plugin_base.backend.get_devices() for index, key in enumerate(base_devices): - if base_devices[key].ip_address == ip_address: + if base_devices[key].ip_address == ip: self.device_list.set_selected(index) break diff --git a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py index 878f454..d911aac 100644 --- a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py +++ b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py @@ -77,6 +77,6 @@ def on_key_down(self) -> None: new_value = +self.selected_step_size is_brightness = self.current_dial_selection == AvailableProperty.Brightness.value if is_brightness: - self.set_property("brightness",new_value) + self.set_property("brightness",max(1, min(self.current_brightness + new_value, 100))) else: - self.set_property("temperature",new_value) + self.set_property("temperature",max(143, min(self.current_temperature + new_value, 344))) diff --git a/actions/ElgatoKeyLight/ToggleButton.py b/actions/ElgatoKeyLight/ToggleButton.py index 9bf89af..6fa4d6c 100644 --- a/actions/ElgatoKeyLight/ToggleButton.py +++ b/actions/ElgatoKeyLight/ToggleButton.py @@ -7,3 +7,10 @@ def __init__(self, *args, **kwargs): def on_key_down(self) -> None: self.set_property("on",None) + + def on_ready(self): + self.update_icon() + + def get_config_rows(self) -> list: + parent_entries = super().get_config_rows() + return parent_entries From 4494d75bab570a3b88a598f37954036ba9ba31f8 Mon Sep 17 00:00:00 2001 From: Caesar Date: Sun, 19 Oct 2025 19:53:46 +0200 Subject: [PATCH 25/25] fix: diverse issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Core.py: 1. Line 113 - Fixed typo: Changed return data[ip] → return Core.data[ip] 2. Lines 134-167 - Added null-safety to all property getters: - current_status, current_brightness, current_temperature - Now check for None IP addresses and failed API calls - Return safe defaults instead of crashing 3. Lines 60-87 - Added null-safety to set_property(): - Validates IP address exists before accessing data - Handles missing data gracefully 4. Lines 94-113 - Added null-safety to _send_to_api(): - Checks for None IP address - Validates data exists before sending - Improved error messages 5. Lines 291-298 - Fixed preselect_device_by_ip() crash: - Added if not hasattr(self, 'device_list'): return check 6. Lines 221-227 - Removed obsolete modify_brightness() and modify_temperature() methods that tried to use non-existent setters 7. Line 254 - Fixed toggle_light(): - Changed to use self.set_property("on", None) 8. Lines 294-299 - Added IP address validation in on_ip_address_added(): - Uses imported ipaddress.ip_address() for validation 9. Lines 42-51 - Removed unused self.json_data instance variable SetButton.py: 10. Lines 94, 99 - Fixed live update to use set_property(): - Changed self.current_brightness = ... → self.set_property("brightness", ...) - Changed self.current_temperature = ... → self.set_property("temperature", ...) --- actions/ElgatoKeyLight/Core.py | 202 +++++++++++------- actions/ElgatoKeyLight/Dial.py | 99 ++++++--- .../ElgatoKeyLight/IncreaseDecreaseButton.py | 28 ++- actions/ElgatoKeyLight/SetButton.py | 51 +++-- actions/ElgatoKeyLight/ToggleButton.py | 2 +- backend/backend.py | 8 +- main.py | 52 +++-- 7 files changed, 271 insertions(+), 171 deletions(-) diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 1d6e5bf..ca799b6 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -22,10 +22,8 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.lm = self.plugin_base.locale_manager - self.plugin_base.backend.on_light_state_changed.subscribe( - self.update_icon) - self.plugin_base.backend.on_device_added.subscribe( - self.update_device_list) + self.plugin_base.backend.on_light_state_changed.subscribe(self.update_icon) + self.plugin_base.backend.on_device_added.subscribe(self.update_device_list) self.supported_lights = { "ElgatoKeyLight": { @@ -39,63 +37,76 @@ def __init__(self, *args, **kwargs): } } - self.json_data = { - "numberOfLights": 1, - "lights": [ - { - "on": 0, - "brightness": 1, - "temperature": 143 - } - ] - } - self.banner_is_visible = False self._is_connected = False self._connection_error = "" self._last_request_number = 0 self._running_requests = 0 - + def set_property(self, key, value): + ip_address = self.get_settings().get("ip_address") + + if not ip_address: + print("[Error]: No IP address configured") + return + + if ip_address not in Core.data: + self._add_data_dictonary(ip_address) + + if ip_address not in Core.data or Core.data[ip_address] is None: + print(f"[Error]: Failed to get data for {ip_address}") + return + match key: case "brightness": self.plugin_base.backend.on_brightness_changed.emit() - #self.json_data["lights"][0][key] = max(1, min(self.current_brightness + value, 100)) - Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = value + Core.data[ip_address]["lights"][0][key] = value case "temperature": self.plugin_base.backend.on_temperature_changed.emit() - #self.json_data["lights"][0][key] = max(143, min(self.current_temperature + value, 344)) - Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = value + Core.data[ip_address]["lights"][0][key] = value case "on": - Core.data[self.get_settings().get("ip_address")]["lights"][0][key] = 1 - Core.data[self.get_settings().get("ip_address")]["lights"][0][key] + Core.data[ip_address]["lights"][0][key] = ( + 1 - Core.data[ip_address]["lights"][0][key] + ) case _: print("No actions passed") self._async_send() - + def _async_send(self): - threading.Thread(target=self._send_to_api, - daemon=True, - name="_send_to_api").start() + threading.Thread( + target=self._send_to_api, daemon=True, name="_send_to_api" + ).start() def _send_to_api(self): ip_address = self.get_settings().get("ip_address") + + if not ip_address: + print("[Error]: No IP address configured") + return + + if ip_address not in Core.data or Core.data[ip_address] is None: + print(f"[Error]: No data available for {ip_address}") + return + payload = Core.data[ip_address].copy() url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.put(url, json=payload, timeout=10) - #self.update_icon() + # self.update_icon() self.plugin_base.backend.on_light_state_changed.emit() - except: - print(f"[Error]: Couldnt Sent update, request_body={payload}") + except Exception as e: + print( + f"[Error]: Couldn't send update to {ip_address}, request_body={payload}, error={e}" + ) - def _get_from_api(self,ip): + def _get_from_api(self, ip): url = f"http://{ip}:9123/elgato/lights" try: - r = requests.get(url,timeout=10) + r = requests.get(url, timeout=10) return r.json() except: print("[Error]: Couldnt Sent update") @@ -106,11 +117,11 @@ def _add_data_dictonary(self, ip): return 0 Core.data[ip] = self._get_from_api(ip) return None - + def _get_data_dictonary(self, ip): if ip not in Core.data: return {} - return data[ip] + return Core.data[ip] @property def running_requests(self): @@ -133,34 +144,53 @@ def is_connected(self, value): @property def current_status(self): ip = self.get_settings().get("ip_address") + if not ip: + return 0 if ip not in Core.data: self._add_data_dictonary(ip) + if ip not in Core.data or Core.data[ip] is None: + return 0 cur_status = Core.data[ip]["lights"][0]["on"] return cur_status or 0 @property def current_brightness(self): ip = self.get_settings().get("ip_address") - if ip not in Core.data : + if not ip: + return 1 + if ip not in Core.data: self._add_data_dictonary(ip) - + if ip not in Core.data or Core.data[ip] is None: + return 1 cur_status = Core.data[ip]["lights"][0]["brightness"] return cur_status or 1 @property def current_temperature(self): ip = self.get_settings().get("ip_address") + if not ip: + return 143 if ip not in Core.data: self._add_data_dictonary(ip) + if ip not in Core.data or Core.data[ip] is None: + return 143 cur_status = Core.data[ip]["lights"][0]["temperature"] return cur_status or 143 @property def current_k_temperature(self): - real_min, real_max = self.supported_lights["ElgatoKeyLight"]["min_temperature"],self.supported_lights["ElgatoKeyLight"]["max_temperature"] - shown_min, shown_max = self.supported_lights["ElgatoKeyLight"]["max_k_temperature"],self.supported_lights["ElgatoKeyLight"]["min_k_temperature"] + real_min, real_max = ( + self.supported_lights["ElgatoKeyLight"]["min_temperature"], + self.supported_lights["ElgatoKeyLight"]["max_temperature"], + ) + shown_min, shown_max = ( + self.supported_lights["ElgatoKeyLight"]["max_k_temperature"], + self.supported_lights["ElgatoKeyLight"]["min_k_temperature"], + ) real_value = self.current_temperature - return ((real_value - real_min) / (real_max - real_min)) * (shown_max - shown_min) + shown_min + return ((real_value - real_min) / (real_max - real_min)) * ( + shown_max - shown_min + ) + shown_min def on_ready(self) -> None: self.load_default_config() @@ -171,16 +201,18 @@ def update_device_list(self): return print(self.registered_devices) - self.registered_devices.splice( - 0, self.registered_devices.get_n_items()) + self.registered_devices.splice(0, self.registered_devices.get_n_items()) for device in self.plugin_base.backend.get_devices(): self.registered_devices.append(str(device)) def get_config_rows(self) -> list: - self.add_new_ip_entry = Adw.EntryRow(title=self.plugin_base.locale_manager.get( - "actions.add_ip_entry.title"), input_purpose=Gtk.InputPurpose.FREE_FORM) + self.add_new_ip_entry = Adw.EntryRow( + title=self.plugin_base.locale_manager.get("actions.add_ip_entry.title"), + input_purpose=Gtk.InputPurpose.FREE_FORM, + ) self.add_light_button = Adw.ButtonRow( - title=self.plugin_base.locale_manager.get("actions.add_light_button.title")) + title=self.plugin_base.locale_manager.get("actions.add_light_button.title") + ) # Disable button until we have a working connection self.add_light_button @@ -191,8 +223,10 @@ def get_config_rows(self) -> list: for device in self.plugin_base.backend.get_devices(): self.registered_devices.append(str(device)) - self.device_list = Adw.ComboRow(title=self.plugin_base.locale_manager.get( - "actions.device_list.title"), model=self.registered_devices) + self.device_list = Adw.ComboRow( + title=self.plugin_base.locale_manager.get("actions.device_list.title"), + model=self.registered_devices, + ) self.device_list.connect("notify::selected", self.set_ip_address) self.connection_banner = Adw.Banner() @@ -202,7 +236,12 @@ def get_config_rows(self) -> list: self.load_default_config() - return [self.add_new_ip_entry, self.add_light_button, self.device_list, self.connection_banner] + return [ + self.add_new_ip_entry, + self.add_light_button, + self.device_list, + self.connection_banner, + ] def set_banner_connection_info(self) -> None: if not self.banner_is_visible: @@ -210,32 +249,28 @@ def set_banner_connection_info(self) -> None: if self.running_requests > 0: self.connection_banner.set_title( - self.plugin_base.locale_manager.get("actions.connection_banner.loading")) + self.plugin_base.locale_manager.get("actions.connection_banner.loading") + ) elif self.is_connected: self.connection_banner.set_title( - self.plugin_base.locale_manager.get("actions.connection_banner.connected")) + self.plugin_base.locale_manager.get( + "actions.connection_banner.connected" + ) + ) else: - self.connection_banner.set_title(self.plugin_base.locale_manager.get( - "actions.connection_banner.not_connected")) - - def modify_brightness(self, amount: int): - new_brightness = int(self.get_light_data()["brightness"] or 0) + amount - self.current_brightness = new_brightness - - def modify_temperature(self, amount: int): - new_temperature = int(self.get_light_data()["temperature"] or 0) + amount - self.current_temperature = new_temperature + self.connection_banner.set_title( + self.plugin_base.locale_manager.get( + "actions.connection_banner.not_connected" + ) + ) def toggle_light(self): - status = self.get_light_data()["on"] - status = 1 - status - self.current_status = status + self.set_property("on", None) def load_default_config(self): # Fallback for old global settings global_settings = self.plugin_base.get_settings() - migrate_global_address_to_local_address = global_settings.get( - "ip_address") + migrate_global_address_to_local_address = global_settings.get("ip_address") settings = self.get_settings() @@ -247,17 +282,19 @@ def load_default_config(self): self.set_settings(settings) saved_ip_address = settings.get("ip_address") - if saved_ip_address: print("Saved ip address in config ", saved_ip_address) self.plugin_base.backend.register_new_device( - saved_ip_address, saved_ip_address) + saved_ip_address, saved_ip_address + ) self.preselect_device_by_ip(saved_ip_address) self.ip_address = saved_ip_address - def preselect_device_by_ip(self,ip): + def preselect_device_by_ip(self, ip): + if not hasattr(self, "device_list"): + return base_devices = self.plugin_base.backend.get_devices() for index, key in enumerate(base_devices): if base_devices[key].ip_address == ip: @@ -267,17 +304,23 @@ def preselect_device_by_ip(self,ip): def on_ip_address_added(self, entry): new_ip_address = self.add_new_ip_entry.get_text() - self.plugin_base.backend.register_new_device( - new_ip_address, new_ip_address) - self.device_list.set_selected( - self.registered_devices.get_n_items() - 1) + # Validate IP address + try: + ip_address(new_ip_address) + except ValueError: + print(f"[Error]: Invalid IP address: {new_ip_address}") + return + + self.plugin_base.backend.register_new_device(new_ip_address, new_ip_address) + self.device_list.set_selected(self.registered_devices.get_n_items() - 1) self.set_ip_address(self.device_list) def set_ip_address(self, entry: Adw.EntryRow, *args): settings = self.get_settings() ip_by_index = list(self.plugin_base.backend.get_devices().values())[ - entry.get_selected()].ip_address + entry.get_selected() + ].ip_address settings["ip_address"] = ip_by_index @@ -287,19 +330,20 @@ def set_ip_address(self, entry: Adw.EntryRow, *args): self._add_data_dictonary(ip_by_index) - #threading.Thread(target=self.update_light, daemon=True, + # threading.Thread(target=self.update_light, daemon=True, # name="update_light").start() def update_icon(self): if self.current_status == 1: icon_path = os.path.join( - self.plugin_base.PATH, "assets", "ring_light_on.png") + self.plugin_base.PATH, "assets", "ring_light_on.png" + ) else: icon_path = os.path.join( - self.plugin_base.PATH, "assets", "ring_light_off.png") + self.plugin_base.PATH, "assets", "ring_light_off.png" + ) self.set_media(media_path=icon_path, size=0.75) - # TODO: Fetch data from light (singleton) def get_light_data(self): @@ -307,11 +351,11 @@ def get_light_data(self): url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.get(url) - return json.loads(r.text)["lights"][0] + return json.loads(r.text)["lights"][0] except: return "Failed to get lights" - def update_light(self,_is_light_active,_brightness,_temperature): + def update_light(self, _is_light_active, _brightness, _temperature): ip_address = self.get_settings().get("ip_address") url = f"http://{ip_address}:9123/elgato/lights" @@ -323,11 +367,11 @@ def update_light(self,_is_light_active,_brightness,_temperature): "numberOfLights": 1, "lights": [ { - "on": _is_light_active, + "on": _is_light_active, "brightness": _brightness or self.current_brightness, - "temperature": _temperature or self.current_temperature + "temperature": _temperature or self.current_temperature, } - ] + ], } request_number = self._last_request_number + 1 diff --git a/actions/ElgatoKeyLight/Dial.py b/actions/ElgatoKeyLight/Dial.py index 1ed5ca1..e5e58d8 100644 --- a/actions/ElgatoKeyLight/Dial.py +++ b/actions/ElgatoKeyLight/Dial.py @@ -7,6 +7,7 @@ # Import gtk modules - used for the config rows import gi + gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") @@ -34,19 +35,21 @@ def on_ready(self) -> None: self.update_icon() self.update_labels() - self.plugin_base.backend.on_brightness_changed.subscribe( - self.update_labels) - self.plugin_base.backend.on_temperature_changed.subscribe( - self.update_labels) + self.plugin_base.backend.on_brightness_changed.subscribe(self.update_labels) + self.plugin_base.backend.on_temperature_changed.subscribe(self.update_labels) def get_config_rows(self) -> list: parent_entries = super().get_config_rows() - + self.toggle_property_selection = Gtk.StringList() self.toggle_property_selection.append( - self.plugin_base.locale_manager.get("actions.toggle_selection.light_on_off")) - self.toggle_property_selection.append(self.plugin_base.locale_manager.get( - "actions.toggle_selection.brightness_temperature")) + self.plugin_base.locale_manager.get("actions.toggle_selection.light_on_off") + ) + self.toggle_property_selection.append( + self.plugin_base.locale_manager.get( + "actions.toggle_selection.brightness_temperature" + ) + ) self.property_selection = Gtk.StringList() @@ -55,24 +58,33 @@ def get_config_rows(self) -> list: self.step_size = Adw.SpinRow.new_with_range(1, 10, 1) self.step_size.set_title( - self.plugin_base.locale_manager.get("actions.step_size.title")) + self.plugin_base.locale_manager.get("actions.step_size.title") + ) self.step_size.set_value(self.selected_step_size) - self.dial_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get( - "actions.dial_selection.title"), model=self.property_selection) + self.dial_selection = Adw.ComboRow( + title=self.plugin_base.locale_manager.get("actions.dial_selection.title"), + model=self.property_selection, + ) self.dial_selection.set_selected(self.current_dial_selection) - self.toggle_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get( - "actions.toggle_selection.title"), model=self.toggle_property_selection) + self.toggle_selection = Adw.ComboRow( + title=self.plugin_base.locale_manager.get("actions.toggle_selection.title"), + model=self.toggle_property_selection, + ) self.toggle_selection.set_selected(self.current_toggle_selection) self.step_size.connect("notify::text", self.on_step_size_changed) - self.dial_selection.connect( - "notify::selected", self.on_dial_selection_changed) + self.dial_selection.connect("notify::selected", self.on_dial_selection_changed) self.toggle_selection.connect( - "notify::selected", self.on_toggle_selection_changed) + "notify::selected", self.on_toggle_selection_changed + ) - return parent_entries + [self.dial_selection, self.toggle_selection, self.step_size] + return parent_entries + [ + self.dial_selection, + self.toggle_selection, + self.step_size, + ] def on_step_size_changed(self, spinner: Adw.SpinRow, *args): self.selected_step_size = int(self.step_size.get_value()) @@ -83,18 +95,17 @@ def on_dial_selection_changed(self, spinner: Adw.ComboRow, *args): self.save_settings() def on_toggle_selection_changed(self, spinner: Adw.ComboRow, *args): - self.current_toggle_selection = int( - self.toggle_selection.get_selected()) + self.current_toggle_selection = int(self.toggle_selection.get_selected()) self.save_settings() def load_local_saved_config(self): local_settings = self.get_settings() self.selected_step_size = local_settings.get("step_size") or 1 - self.current_dial_selection = local_settings.get( - "current_dial_selection") or 0 - self.current_toggle_selection = local_settings.get( - "current_toggle_selection") or 0 + self.current_dial_selection = local_settings.get("current_dial_selection") or 0 + self.current_toggle_selection = ( + local_settings.get("current_toggle_selection") or 0 + ) def save_settings(self): local_settings = self.get_settings() @@ -117,10 +128,14 @@ def event_callback(self, event: InputEvent, data: dict) -> None: is_brightness = self.current_dial_selection == DialProperty.Brightness.value if is_brightness: - self.set_property("brightness",max(1, min(self.current_brightness + new_value, 100))) + self.set_property( + "brightness", max(1, min(self.current_brightness + new_value, 100)) + ) else: - self.set_property("temperature",max(143, min(self.current_temperature + new_value, 344))) - + self.set_property( + "temperature", max(143, min(self.current_temperature + new_value, 344)) + ) + self.update_labels() def toggle_brightness_temperature(self): @@ -133,18 +148,32 @@ def toggle_brightness_temperature(self): def update_labels(self): if self.current_dial_selection == DialProperty.Brightness.value: - self.set_top_label(text=self.plugin_base.locale_manager.get( - "actions.current_brightness.title")) - self.set_bottom_label(text=self.plugin_base.locale_manager.get( - "actions.current_brightness.value") % self.current_brightness) + self.set_top_label( + text=self.plugin_base.locale_manager.get( + "actions.current_brightness.title" + ) + ) + self.set_bottom_label( + text=self.plugin_base.locale_manager.get( + "actions.current_brightness.value" + ) + % self.current_brightness + ) else: - self.set_top_label(text=self.plugin_base.locale_manager.get( - "actions.current_temperature.title")) - self.set_bottom_label(text=self.plugin_base.locale_manager.get( - "actions.current_temperature.value") % int(self.current_k_temperature)) + self.set_top_label( + text=self.plugin_base.locale_manager.get( + "actions.current_temperature.title" + ) + ) + self.set_bottom_label( + text=self.plugin_base.locale_manager.get( + "actions.current_temperature.value" + ) + % int(self.current_k_temperature) + ) def on_key_down(self) -> None: if self.current_toggle_selection == ToggleProperty.ToggleLightOnOff.value: - self.set_property("on",None) + self.set_property("on", None) else: self.toggle_brightness_temperature() diff --git a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py index d911aac..a7d0949 100644 --- a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py +++ b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py @@ -7,6 +7,7 @@ # Import gtk modules - used for the config rows import gi + gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") @@ -37,16 +38,18 @@ def get_config_rows(self) -> list: self.step_size = Adw.SpinRow.new_with_range(-10, 10, 1) self.step_size.set_title( - self.plugin_base.locale_manager.get("actions.step_size.title")) + self.plugin_base.locale_manager.get("actions.step_size.title") + ) self.step_size.set_value(self.selected_step_size) - self.dial_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get( - "actions.dial_selection.title"), model=self.property_selection) + self.dial_selection = Adw.ComboRow( + title=self.plugin_base.locale_manager.get("actions.dial_selection.title"), + model=self.property_selection, + ) self.dial_selection.set_selected(self.current_dial_selection) self.step_size.connect("notify::text", self.on_step_size_changed) - self.dial_selection.connect( - "notify::selected", self.on_dial_selection_changed) + self.dial_selection.connect("notify::selected", self.on_dial_selection_changed) return parent_entries + [self.dial_selection, self.step_size] @@ -62,8 +65,7 @@ def load_local_saved_config(self): local_settings = self.get_settings() self.selected_step_size = local_settings.get("step_size") or 1 - self.current_dial_selection = local_settings.get( - "current_dial_selection") or 0 + self.current_dial_selection = local_settings.get("current_dial_selection") or 0 def save_settings(self): local_settings = self.get_settings() @@ -75,8 +77,14 @@ def save_settings(self): def on_key_down(self) -> None: new_value = 0 new_value = +self.selected_step_size - is_brightness = self.current_dial_selection == AvailableProperty.Brightness.value + is_brightness = ( + self.current_dial_selection == AvailableProperty.Brightness.value + ) if is_brightness: - self.set_property("brightness",max(1, min(self.current_brightness + new_value, 100))) + self.set_property( + "brightness", max(1, min(self.current_brightness + new_value, 100)) + ) else: - self.set_property("temperature",max(143, min(self.current_temperature + new_value, 344))) + self.set_property( + "temperature", max(143, min(self.current_temperature + new_value, 344)) + ) diff --git a/actions/ElgatoKeyLight/SetButton.py b/actions/ElgatoKeyLight/SetButton.py index f762c84..c3601c9 100644 --- a/actions/ElgatoKeyLight/SetButton.py +++ b/actions/ElgatoKeyLight/SetButton.py @@ -3,6 +3,7 @@ # Import gtk modules - used for the config rows import gi + gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") @@ -14,10 +15,14 @@ def __init__(self, *args, **kwargs): def on_ready(self) -> None: local_settings = self.get_settings() - self._custom_brightness = local_settings.get( - "custom_brightness") or self.supported_lights["ElgatoKeyLight"]["min_brightness"] - self._custom_temperature = local_settings.get( - "custom_temperature") or self.supported_lights["ElgatoKeyLight"]["min_temperature"] + self._custom_brightness = ( + local_settings.get("custom_brightness") + or self.supported_lights["ElgatoKeyLight"]["min_brightness"] + ) + self._custom_temperature = ( + local_settings.get("custom_temperature") + or self.supported_lights["ElgatoKeyLight"]["min_temperature"] + ) self._live_update = local_settings.get("live_update") or False self.update_icon() @@ -64,22 +69,32 @@ def get_config_rows(self) -> list: self.live_update.connect("notify::active", self.on_live_update_changed) self.brightness_entry = Adw.SpinRow.new_with_range( - self.supported_lights["ElgatoKeyLight"]["min_brightness"], self.supported_lights["ElgatoKeyLight"]["max_brightness"], 1) + self.supported_lights["ElgatoKeyLight"]["min_brightness"], + self.supported_lights["ElgatoKeyLight"]["max_brightness"], + 1, + ) self.brightness_entry.set_title( - self.plugin_base.locale_manager.get("actions.brightness_entry.title")) + self.plugin_base.locale_manager.get("actions.brightness_entry.title") + ) self.brightness_entry.set_value(self.custom_brightness) self.temperature_entry = Adw.SpinRow.new_with_range( - self.supported_lights["ElgatoKeyLight"]["min_temperature"], self.supported_lights["ElgatoKeyLight"]["max_temperature"], 1) + self.supported_lights["ElgatoKeyLight"]["min_temperature"], + self.supported_lights["ElgatoKeyLight"]["max_temperature"], + 1, + ) self.temperature_entry.set_title( - self.plugin_base.locale_manager.get("actions.brightness_entry.title")) + self.plugin_base.locale_manager.get("actions.brightness_entry.title") + ) self.temperature_entry.set_value(self.custom_temperature) - self.brightness_entry.connect( - "notify::value", self.on_brightness_changed) - self.temperature_entry.connect( - "notify::value", self.on_temperature_changed) - return parent_entries + [self.live_update, self.brightness_entry, self.temperature_entry] + self.brightness_entry.connect("notify::value", self.on_brightness_changed) + self.temperature_entry.connect("notify::value", self.on_temperature_changed) + return parent_entries + [ + self.live_update, + self.brightness_entry, + self.temperature_entry, + ] def on_live_update_changed(self, switch: Adw.SwitchRow, *args): self.live_update_active = switch.get_active() @@ -91,20 +106,20 @@ def on_brightness_changed(self, spinner: Adw.SpinRow, *args): self.custom_brightness = spinner.get_value() if self.live_update_active: - self.current_brightness = self.custom_brightness + self.set_property("brightness", self.custom_brightness) def on_temperature_changed(self, spinner: Adw.SpinRow, *args): self.custom_temperature = spinner.get_value() if self.live_update_active: - self.current_temperature = self.custom_temperature + self.set_property("temperature", self.custom_temperature) def on_key_down(self) -> None: self.push_light_properties() def push_light_properties(self): - self.set_property("brightness",self.custom_brightness) - self.set_property("temperature",self.custom_temperature) + self.set_property("brightness", self.custom_brightness) + self.set_property("temperature", self.custom_temperature) if self.current_status == 0: - self.set_property("on",None) + self.set_property("on", None) return diff --git a/actions/ElgatoKeyLight/ToggleButton.py b/actions/ElgatoKeyLight/ToggleButton.py index 6fa4d6c..9baed62 100644 --- a/actions/ElgatoKeyLight/ToggleButton.py +++ b/actions/ElgatoKeyLight/ToggleButton.py @@ -6,7 +6,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def on_key_down(self) -> None: - self.set_property("on",None) + self.set_property("on", None) def on_ready(self): self.update_icon() diff --git a/backend/backend.py b/backend/backend.py index 2c1a80a..4e8729a 100644 --- a/backend/backend.py +++ b/backend/backend.py @@ -1,5 +1,6 @@ from streamcontroller_plugin_tools import BackendBase + class Event: def __init__(self): self.listeners = [] @@ -29,8 +30,7 @@ def __init__(self): self.on_light_state_changed = Event() self.on_device_added = Event() - self.devices : dict[str, Device] = {} - + self.devices: dict[str, Device] = {} def register_new_device(self, device_ip: str, device_name: str): print("Registering new device: ", device_ip) @@ -41,17 +41,15 @@ def register_new_device(self, device_ip: str, device_name: str): self.devices[device_ip] = Device(device_ip, device_name) self.on_device_added.emit() - def remove_device(self, device_ip: str): del self.devices[device_ip] self.on_device_removed.emit(device_ip) - def get_devices(self) -> dict[str, Device]: return self.devices - def is_device_in_list(self, device_ip: str) -> bool: return device_ip in self.devices + backend = Backend() diff --git a/main.py b/main.py index 5dac037..55fd3a7 100644 --- a/main.py +++ b/main.py @@ -12,6 +12,7 @@ import os + class PluginTemplate(PluginBase): def __init__(self): super().__init__() @@ -22,35 +23,41 @@ def __init__(self): ## Register actions self.set_light_action_holder = ActionHolder( - plugin_base = self, - action_base = SetButton, - action_id = "com_memclash_elgatokeylight::SetButton", # Change this to your own plugin id - action_name = "Set Light Properties", + plugin_base=self, + action_base=SetButton, + action_id="com_memclash_elgatokeylight::SetButton", # Change this to your own plugin id + action_name="Set Light Properties", action_support={Input.Key: ActionInputSupport.SUPPORTED}, ) self.increase_decrease_light_action_holder = ActionHolder( - plugin_base = self, - action_base = IncreaseDecreaseButton, - action_id = "com_memclash_elgatokeylight::IncreaseDecreaseButton", # Change this to your own plugin id - action_name = "Increase/Decrease Light Properties", + plugin_base=self, + action_base=IncreaseDecreaseButton, + action_id="com_memclash_elgatokeylight::IncreaseDecreaseButton", # Change this to your own plugin id + action_name="Increase/Decrease Light Properties", action_support={Input.Key: ActionInputSupport.SUPPORTED}, ) self.toggle_light_action_holder = ActionHolder( - plugin_base = self, - action_base = ToggleButton, - action_id = "com_memclash_elgatokeylight::ToggleButton", # Change this to your own plugin id - action_name = "Toggle Light", - action_support={Input.Key: ActionInputSupport.SUPPORTED, Input.Dial: ActionInputSupport.SUPPORTED}, + plugin_base=self, + action_base=ToggleButton, + action_id="com_memclash_elgatokeylight::ToggleButton", # Change this to your own plugin id + action_name="Toggle Light", + action_support={ + Input.Key: ActionInputSupport.SUPPORTED, + Input.Dial: ActionInputSupport.SUPPORTED, + }, ) self.dial_action_holder = ActionHolder( - plugin_base = self, - action_base = Dial, - action_id = "com_memclash_elgatokeylight::Dial", # Change this to your own plugin id - action_name = "Dial Brightness Temperature", - action_support={Input.Dial: ActionInputSupport.SUPPORTED, Input.Key: ActionInputSupport.UNSUPPORTED}, + plugin_base=self, + action_base=Dial, + action_id="com_memclash_elgatokeylight::Dial", # Change this to your own plugin id + action_name="Dial Brightness Temperature", + action_support={ + Input.Dial: ActionInputSupport.SUPPORTED, + Input.Key: ActionInputSupport.UNSUPPORTED, + }, ) self.add_action_holder(self.set_light_action_holder) @@ -58,11 +65,10 @@ def __init__(self): self.add_action_holder(self.toggle_light_action_holder) self.add_action_holder(self.dial_action_holder) - # Register plugin self.register( - plugin_name = "Elgato Key Light", - github_repo = "https://github.com/cozybuild/StreamControllerElgatoKeyLight/", - plugin_version = "0.3.0", - app_version = "1.1.1-alpha" + plugin_name="Elgato Key Light", + github_repo="https://github.com/cozybuild/StreamControllerElgatoKeyLight/", + plugin_version="0.3.0", + app_version="1.1.1-alpha", )