What makes us different from other similar websites? › Forums › Tech › Logitech Litra Glow (Linux Drivers)
Tagged: Linux, Logitech Litra Glow, Ubuntu
- This topic has 8 replies, 1 voice, and was last updated 1 month, 2 weeks ago by
thumbtak.
-
AuthorPosts
-
May 26, 2022 at 6:25 pm #6670
thumbtakModerator
I just got the Logitech Litra Glow, well, I am waiting for it in the mail. While I wait for it, I wanted to get the drivers I found, working on my Linux machine. I got it to work. This is how.$ pip install litra-driver$ sudo echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="046d", ATTR{idProduct}=="c900",\ MODE="0666"' > /etc/udev/rules.d/82-litra-glow.rules$ sudo shutdown -r now$ lcuiIf you get this error message “ModuleNotFoundError: No module named ‘Tkinter” continue on, if not, you are done.
$ sudo apt-get install python3-tk$ lcuiMore information:
https://github.com/derickr/python-litra-driver
https://stackoverflow.com/questions/25905540/importerror-no-module-named-tkinter
May 27, 2022 at 8:03 am #6671
thumbtakModeratorI made an icon that you may use when adding the terminal command to the application menu.
May 28, 2022 at 7:15 pm #6672
thumbtakModeratorI found a bug in the program. The bug is with clicking “X” to close the window instead of “exit”. When you delete a profile, the “X” will not save the deleted profiles. The profile will return when you open the application. To remove them, you must click “exit”, after deleting them.
July 11, 2022 at 12:32 pm #6728
thumbtakModeratorIf you are getting this error message, install the following.

$ sudo apt install gir1.2-appindicator3-0.1July 11, 2022 at 12:37 pm #6729
thumbtakModeratorIf you get a permission denied when doing this command …
$ echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="046d", ATTR{idProduct}=="c900",\ MODE="0666"' > /etc/udev/rules.d/82-litra-glow.rulesRun the following command and give Others, Read & Write access to the 82-litra-glow.rules file located in the /etc/udev/rules.d/ by running the following command …
$ sudo tee /etc/udev/rules.d/82-litra-glow.rules <<< 'SUBSYSTEM=="usb", ATTR{idVendor}=="046d", ATTR{idProduct}=="c900",MODE="0666"'July 11, 2022 at 12:48 pm #6730
thumbtakModeratorIf you are getting this error …
https://i.ibb.co/3zFJ20q/image.png

Run the following command …
$ sudo lcui-
This reply was modified 3 years, 6 months ago by
thumbtak.
September 30, 2022 at 11:45 am #6785
thumbtakModeratorDecember 16, 2024 at 10:07 am #7669
thumbtakModeratorHow to install on later versions of Linux
$ sudo tee /etc/udev/rules.d/82-litra-glow.rules <<< 'SUBSYSTEM=="usb", ATTR{idVendor}=="046d", ATTR{idProduct}=="c900",MODE="0666"'$ sudo tee /etc/udev/rules.d/82-litra-beam.rules <<< 'SUBSYSTEM=="usb", ATTR{idVendor}=="046d", ATTR{idProduct}=="c901",MODE="0666"'$ sudo udevadm control --reload-rules$ sudo udevadm trigger$ sudo reboot$ python3 -m venv litra$ source litra/bin/activate$ pip install litra-driver$ lcuiYou may use this script and make a shortcut on your panel to start the software. It may need modifying, depending on where you place the files. I out the environment in my home directory.
#!/bin/sh # Navigate to the home directory, or the directory where your virtual environment is cd ~/litra || exit # If this fails, exit the script # Activate the virtual environment if [ -f "bin/activate" ]; then . bin/activate # Use '.' (dot) instead of 'source' in sh else echo "Virtual environment not found. Exiting." exit 1 fi # Run open-webui lcui # Notify user the server is up echo "lcui should be opening"The way I set it up in the launcher, on my panel is by copying the sh file and post it in the command section, with sh before the location of the file.
December 4, 2025 at 11:33 am #8344
thumbtakModerator💡 Litra Light Controller GUI Setup Guide for Linux (Xubuntu/Debian)
This guide provides every single step needed to install the
lclicommand-line tool, set up the Python GUI, and create a custom menu entry for controlling your Logitech Litra light.1. Prerequisites and Installing the CLI Tool (
lcli)This application requires Python 3, Tkinter, and the external
lclitool.1.1 Download the Litra CLI Tool
1. Open your web browser and go to the official
lcliGitHub repository Releases page:https://github.com/charles-dyer/lcli/releases2. Download the latest Linux x86_64 release (it will be named something like
lcli_x86_64.tar.gz).3. Open your terminal and navigate to your Downloads directory:
cd ~/Downloads4. Extract the contents (replace
[FILENAME]with the actual file name you downloaded, e.g.,lcli_x86_64.tar.gz):tar -xzf [FILENAME]5. Move the executable to a standard binary location so you know its path. Assuming the extracted executable is named
lcli:sudo mv ./lcli /usr/local/bin/lcliIf this command fails because the file is in a subdirectory, locate the
lcliexecutable inside the extracted folder and move it to/usr/local/bin/.1.2 Identify the Absolute Path
The absolute path for the
lcliexecutable is now:/usr/local/bin/lcli. You will use this path in the Python script in the next step.1.3 Python and Tkinter Check
Ensure you have Python 3 and Tkinter installed. If you are on a Debian/Ubuntu-based system and the GUI doesn’t work, install Tkinter:
sudo apt update sudo apt install python3-tk2. Setup the Application Files
We will create a specific directory to hold the Python script. Open your terminal and run:
mkdir -p ~/.local/share/litra-controller2.A Create the GUI Python Script (
litra_controller.py)This is the main application code. Open your preferred text editor (
mousepad) and save the following content as~/.local/share/litra-controller/litra_controller.py.CRITICAL: The
DEFAULT_CLI_PATHin the code below is set to/usr/local/bin/lcli. Only change it if you moved the executable elsewhere.import tkinter as tk from tkinter import ttk, messagebox import subprocess import webbrowser # --- Configuration Constants --- # ABSOLUTE PATH TO THE EXECUTABLE. DEFAULT_CLI_PATH = '/usr/local/bin/lcli' MIN_BRIGHTNESS = 1 MAX_BRIGHTNESS = 100 MIN_TEMP = 2700 MAX_TEMP = 6500 HIGHLIGHT_COLOR = '#ff66cc' class LitraControllerApp(tk.Tk): def __init__(self): super().__init__() self.title("Litra Light Controller (Python CLI Wrapper)") self.geometry("520x450") self.resizable(False, False) try: ttk.Style().theme_use('clam') except: pass self.cli_path = tk.StringVar(value=DEFAULT_CLI_PATH) self.is_power_on = tk.BooleanVar(value=True) self.generated_command = tk.StringVar(value="Adjust controls or click a button to generate command.") self.create_menu() self.create_widgets() self.update_command(None) def create_menu(self): menubar = tk.Menu(self) self.config(menu=menubar) help_menu = tk.Menu(menubar, tearoff=0) menubar.add_cascade(label="Help", menu=help_menu) help_menu.add_command(label="About", command=self.show_about_dialog) def open_url(self, url): webbrowser.open_new_tab(url) def show_about_dialog(self): about_window = tk.Toplevel(self) about_window.title("About Litra Controller") about_window.resizable(False, False) about_window.transient(self) about_window.grab_set() frame = ttk.Frame(about_window, padding="15") frame.pack(fill="both", expand=True) ttk.Label(frame, text="Litra Light Controller", font=('Arial', 14, 'bold')).pack(pady=(0, 5)) ttk.Label(frame, text="Version 1.0 (Python CLI Wrapper)", font=('Arial', 10)).pack(pady=(0, 10)) description = ( "This GUI allows control of your Logitech Litra light via the " "external Litra CLI (lcli) tool, requiring sudo permissions." ) ttk.Label(frame, text=description, wraplength=350, justify=tk.CENTER).pack(pady=(0, 20)) ttk.Label(frame, text="GUI Development:", font=('Arial', 10, 'bold')).pack() link_text = "thumbtak on taksshack.com" url = "[https://taksshack.com/members/thumbtak/](https://taksshack.com/members/thumbtak/)" link_label = ttk.Label(frame, text=link_text, foreground="blue", cursor="hand2", font=('Arial', 10, 'underline')) link_label.pack(pady=(0, 5)) link_label.bind("<Button-1>", lambda e: self.open_url(url)) ttk.Button(frame, text="Close", command=about_window.destroy, style='Pink.TButton').pack(pady=(15, 0)) about_window.update_idletasks() main_x = self.winfo_x(); main_y = self.winfo_y() main_width = self.winfo_width(); main_height = self.winfo_height() win_width = about_window.winfo_reqwidth(); win_height = about_window.winfo_reqheight() x = main_x + (main_width // 2) - (win_width // 2) y = main_y + (main_height // 2) - (win_height // 2) about_window.geometry(f'+{x}+{y}') self.wait_window(about_window) def create_widgets(self): # Widget creation logic (omitted for brevity, see code for full implementation) main_frame = ttk.Frame(self, padding="15") main_frame.pack(fill='both', expand=True) ttk.Label(main_frame, text="Litra CLI Path (lcli):", font=('Arial', 10, 'bold')).pack(pady=(0, 2), anchor='w') ttk.Entry(main_frame, textvariable=self.cli_path).pack(fill='x', padx=5, pady=(0, 10)) control_frame = ttk.LabelFrame(main_frame, text="Light Controls", padding="10") control_frame.pack(fill='x', pady=10) power_frame = ttk.Frame(control_frame) power_frame.pack(fill='x', pady=5) ttk.Label(power_frame, text="Light Power:", font=('Arial', 11)).pack(side='left') self.power_button = ttk.Button(power_frame, text="", command=self.toggle_power) self.power_button.pack(side='right') ttk.Label(control_frame, text="Brightness:", font=('Arial', 11)).pack(pady=(10, 0), anchor='w') self.brightness_scale = tk.Scale(control_frame, from_=MIN_BRIGHTNESS, to=MAX_BRIGHTNESS, orient=tk.HORIZONTAL, command=self.update_command, length=400, resolution=1, relief=tk.FLAT, bd=0, troughcolor="#E0E7FF", showvalue=True, highlightthickness=0) self.brightness_scale.set(50) self.brightness_scale.pack(fill='x', padx=5) ttk.Label(control_frame, text="Color Temperature (K):", font=('Arial', 11)).pack(pady=(10, 0), anchor='w') self.temp_scale = tk.Scale(control_frame, from_=MIN_TEMP, to=MAX_TEMP, orient=tk.HORIZONTAL, command=self.update_command, length=400, resolution=50, relief=tk.FLAT, bd=0, troughcolor="#E0E7FF", showvalue=True, highlightthickness=0) self.temp_scale.set(4600) self.temp_scale.pack(fill='x', padx=5) ttk.Label(main_frame, text="Generated Command:", font=('Arial', 10, 'bold')).pack(pady=(15, 2), anchor='w') command_output_frame = ttk.Frame(main_frame) command_output_frame.pack(fill='x') command_output_frame.columnconfigure(0, weight=1) self.command_text = tk.Text(command_output_frame, height=2, width=50, state='disabled', bg="#2D3748", fg=HIGHLIGHT_COLOR, font=('Courier', 10), wrap='word', bd=1, relief=tk.SUNKEN) self.command_text.grid(row=0, column=0, sticky="nsew", padx=(0, 5), pady=0) copy_button = ttk.Button(command_output_frame, text="Copy", command=self.copy_command) copy_button.grid(row=0, column=1, sticky="ns", pady=0) self.update_power_button_ui() def update_power_button_ui(self): if self.is_power_on.get(): self.power_button.config(text=" ON ", style='Pink.TButton') else: self.power_button.config(text=" OFF ", style='Red.TButton') s = ttk.Style() s.configure('Pink.TButton', background=HIGHLIGHT_COLOR, foreground='black', font=('Arial', 10, 'bold')) s.map('Pink.TButton', background=[('active', '#e65cb8')]) s.configure('Red.TButton', background='#F56565', foreground='black', font=('Arial', 10, 'bold')) s.map('Red.TButton', background=[('active', '#E53E3E')]) def toggle_power(self): self.is_power_on.set(not self.is_power_on.get()) self.update_power_button_ui() self.update_command(None) def update_command(self, event): cli = self.cli_path.get().strip() brightness = self.brightness_scale.get() temperature = self.temp_scale.get() command_parts = [] sudo_cli = f"sudo {cli}" if self.is_power_on.get(): command_parts.append(f"{sudo_cli} on") command_parts.append(f"{sudo_cli} bright {brightness}") command_parts.append(f"{sudo_cli} temp {temperature}") command_string = " && ".join(command_parts) else: command_string = f"{sudo_cli} off" self.command_text.config(state='normal') self.command_text.delete(1.0, tk.END) self.command_text.insert(tk.END, command_string) self.command_text.config(state='disabled') self.execute_command(auto_exec=True) def copy_command(self): command = self.command_text.get(1.0, tk.END).strip() if command: self.clipboard_clear() self.clipboard_append(command) messagebox.showinfo("Copied", "Command copied to clipboard!") else: messagebox.showwarning("Empty", "No command to copy.") def execute_command(self, auto_exec=False): command = self.command_text.get(1.0, tk.END).strip() if not command: return try: if not auto_exec: messagebox.showinfo("Executing Command", "Running command in shell. You will likely be prompted for your sudo password in the terminal window where you launched this GUI.") result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True) if auto_exec: print(f"Executed: {command}") else: output = result.stdout.strip() if result.stdout else "Command executed successfully with no output." messagebox.showinfo("Execution Success", f"SUCCESS:\n{output}") except subprocess.CalledProcessError as e: error_output = e.stderr.strip() if e.stderr else "Unknown error." messagebox.showerror("Execution Failed", f"Command failed with return code {e.returncode}. You may need to enter your sudo password in the terminal:\n{error_output}") except FileNotFoundError: messagebox.showerror("Execution Failed", f"The executable specified was not found. Check the CLI Path: '{self.cli_path.get()}'") except Exception as e: messagebox.showerror("Execution Failed", f"An unexpected error occurred:\n{e}") if __name__ == "__main__": app = LitraControllerApp() app.mainloop()2.B Create the Runner Script (
run_litra.sh)This shell script launches the Python GUI using a terminal, which is necessary to handle the
sudopassword prompt.1. Create the script file using
mousepad:mkdir -p ~/.local/bin/ mousepad ~/.local/bin/run_litra.sh2. Paste the following content into the file:
#!/bin/bash # Define the absolute path to the Python script using the user's HOME directory SCRIPT_PATH="$HOME/.local/share/litra-controller/litra_controller.py" # Execute the script using the default terminal emulator (e.g., xfce4-terminal). # The --hold option keeps the terminal open to capture the sudo password and see errors. xfce4-terminal --hold --title="Litra Controller Runner" --command="python3 $SCRIPT_PATH"3. Set Permissions: Make the runner script executable:
chmod +x ~/.local/bin/run_litra.sh3. Create the Desktop Launcher (
litra-controller.desktop)This file integrates the application into your desktop environment’s application menu (e.g., the Start Menu).
1. Create the file using
mousepad:mousepad ~/.local/share/applications/litra-controller.desktop2. Paste the following content into the file:
[Desktop Entry] Name=Litra Light Controller Comment=GUI to control Logitech Litra light via lcli Exec=$HOME/.local/bin/run_litra.sh Icon=system-run Terminal=false Type=Application Categories=Utility;3. Save and close
mousepad.4. Final Steps and Usage
1. Refresh Menu: Log out and log back into your desktop session to ensure the application menu refreshes and shows the new entry.
2. Launch: Find “Litra Light Controller” in your application menu and click it. A terminal window will open, and the separate GUI window will launch.
3. Sudo Prompt: The first time you adjust a control (like brightness or color temperature), the terminal window will prompt you for your user password with:
[sudo] password for yourusername:4. Enter Password: Type your user password into the terminal and press Enter.
5. Enjoy: Once authenticated, the application will run all commands successfully until the sudo timeout expires.
-
This reply was modified 3 years, 6 months ago by
-
AuthorPosts
- You must be logged in to reply to this topic.
