Skip to content

Instantly share code, notes, and snippets.

@kaigouthro
Created December 14, 2024 14:36
Show Gist options
  • Save kaigouthro/a7c4ff0d82ee9c0b7170efe3a88a4976 to your computer and use it in GitHub Desktop.
Save kaigouthro/a7c4ff0d82ee9c0b7170efe3a88a4976 to your computer and use it in GitHub Desktop.
Logi lua tool / spec
from dataclasses import dataclass
from typing import List, Union, Optional, Tuple
# Data Classes for Logitech G HUB Lua API
@dataclass
class Event:
name: str
arg: Optional[Union[int, str]] = None
family: Optional[str] = None
@dataclass
class Key:
name: Optional[str] = None
scancode: Optional[int] = None
@dataclass
class MouseButton:
button: int
@dataclass
class MousePosition:
x: int
y: int
@dataclass
class Macro:
name: str
@dataclass
class DeviceProperty:
device: str
property: str
value: Union[int, bool]
@dataclass
class MouseSpeed:
speed: Optional[int] = None
increment: Optional[int] = None
decrement: Optional[int] = None
class LuaScript:
def __init__(self):
self.code = []
self.indent_level = 0
def _add_line(self, line: str):
self.code.append(" " * self.indent_level + line)
def _indent(self):
self.indent_level += 1
def _dedent(self):
self.indent_level -= 1
def start_event_handler(self):
self._add_line("function OnEvent(event, arg, family)")
self._indent()
def end_event_handler(self):
self._dedent()
self._add_line("end")
def add_event_condition(self, event: Event):
condition = f"if event == \"{event.name}\""
if event.arg is not None:
condition += f" and arg == {event.arg}"
if event.family is not None:
condition += f" and family == \"{event.family}\""
self._add_line(condition + " then")
self._indent()
def end_condition(self):
self._dedent()
self._add_line("end")
def get_mkey_state(self, family: Optional[str] = "kb") -> str:
var_name = "currentMKey"
self._add_line(f"local {var_name} = GetMKeyState(\"{family}\")")
return var_name
def set_mkey_state(self, mkey: int, family: Optional[str] = "kb"):
self._add_line(f"SetMKeyState({mkey}, \"{family}\")")
def sleep(self, timeout: int):
self._add_line(f"Sleep({timeout})")
def output_log_message(self, message: str, *args):
formatted_args = ", ".join(str(arg) for arg in args)
if formatted_args:
self._add_line(f"OutputLogMessage(\"{message}\", {formatted_args})")
else:
self._add_line(f"OutputLogMessage(\"{message}\")")
def get_running_time(self) -> str:
var_name = "runningTime"
self._add_line(f"local {var_name} = GetRunningTime()")
return var_name
def get_date(self, format_str: Optional[str] = None, time_table: Optional[dict] = None) -> str:
var_name = "date"
if format_str and time_table:
formatted_time_table = ", ".join([f"{k} = {v}" for k, v in time_table.items()])
self._add_line(f"local {var_name} = GetDate(\"{format_str}\", {{{formatted_time_table}}})")
elif format_str:
self._add_line(f"local {var_name} = GetDate(\"{format_str}\")")
else:
self._add_line(f"local {var_name} = GetDate()")
return var_name
def clear_log(self):
self._add_line("ClearLog()")
def press_key(self, keys: List[Key]):
key_args = ", ".join([f"\"{key.name}\"" if key.name else str(key.scancode) for key in keys])
self._add_line(f"PressKey({key_args})")
def release_key(self, keys: List[Key]):
key_args = ", ".join([f"\"{key.name}\"" if key.name else str(key.scancode) for key in keys])
self._add_line(f"ReleaseKey({key_args})")
def press_and_release_key(self, keys: List[Key]):
key_args = ", ".join([f"\"{key.name}\"" if key.name else str(key.scancode) for key in keys])
self._add_line(f"PressAndReleaseKey({key_args})")
def is_modifier_pressed(self, keyname: str) -> str:
var_name = f"is{keyname.capitalize()}Pressed"
self._add_line(f"local {var_name} = IsModifierPressed(\"{keyname}\")")
return var_name
def is_key_lock_on(self, keyname: str) -> str:
var_name = f"is{keyname.capitalize()}On"
self._add_line(f"local {var_name} = IsKeyLockOn(\"{keyname}\")")
return var_name
def press_mouse_button(self, button: MouseButton):
self._add_line(f"PressMouseButton({button.button})")
def release_mouse_button(self, button: MouseButton):
self._add_line(f"ReleaseMouseButton({button.button})")
def press_and_release_mouse_button(self, button: MouseButton):
self._add_line(f"PressAndReleaseMouseButton({button.button})")
def is_mouse_button_pressed(self, button: MouseButton) -> str:
var_name = f"isMouseButton{button.button}Pressed"
self._add_line(f"local {var_name} = IsMouseButtonPressed({button.button})")
return var_name
def move_mouse_to(self, position: MousePosition):
self._add_line(f"MoveMouseTo({position.x}, {position.y})")
def move_mouse_wheel(self, clicks: int):
self._add_line(f"MoveMouseWheel({clicks})")
def move_mouse_relative(self, x: int, y: int):
self._add_line(f"MoveMouseRelative({x}, {y})")
def move_mouse_to_virtual(self, position: MousePosition):
self._add_line(f"MoveMouseToVirtual({position.x}, {position.y})")
def get_mouse_position(self) -> Tuple[str, str]:
x_var = "x"
y_var = "y"
self._add_line(f"local {x_var}, {y_var} = GetMousePosition()")
return x_var, y_var
def enable_primary_mouse_button_events(self, enable: bool):
self._add_line(f"EnablePrimaryMouseButtonEvents({str(enable).lower()})")
def play_macro(self, macro: Macro):
self._add_line(f"PlayMacro(\"{macro.name}\")")
def press_macro(self, macro: Macro):
self._add_line(f"PressMacro(\"{macro.name}\")")
def release_macro(self, macro: Macro):
self._add_line(f"ReleaseMacro(\"{macro.name}\")")
def abort_macro(self):
self._add_line("AbortMacro()")
def output_debug_message(self, message: str, *args):
formatted_args = ", ".join(str(arg) for arg in args)
if formatted_args:
self._add_line(f"OutputDebugMessage(\"{message}\", {formatted_args})")
else:
self._add_line(f"OutputDebugMessage(\"{message}\")")
def generate(self) -> str:
return "\n".join(self.code)
# Example Usage
script = LuaScript()
script.start_event_handler()
script.add_event_condition(Event(name="PROFILE_ACTIVATED"))
script.output_log_message("Profile activated")
script.end_condition()
script.add_event_condition(Event(name="G_PRESSED", arg=1))
mkey_var = script.get_mkey_state()
script.output_log_message("Current M key state: %d", mkey_var)
script.set_mkey_state(1)
script.press_key([Key(name="a")])
script.sleep(100)
script.release_key([Key(name="a")])
script.press_and_release_key([Key(scancode=30)])
shift_pressed = script.is_modifier_pressed("shift")
script.add_event_condition(Event(name="G_PRESSED", arg=2))
script._add_line(f"if {shift_pressed} then")
script._indent()
script.output_log_message("Shift key is pressed")
script._dedent()
script.end_condition()
numlock_on = script.is_key_lock_on("numlock")
script.add_event_condition(Event(name="G_PRESSED", arg=3))
script._add_line(f"if {numlock_on} then")
script._indent()
script.press_and_release_key([Key(name="numlock")])
script._dedent()
script.end_condition()
script.press_mouse_button(MouseButton(button=1))
script.release_mouse_button(MouseButton(button=1))
script.press_and_release_mouse_button(MouseButton(button=3))
mb3_pressed = script.is_mouse_button_pressed(MouseButton(button=3))
script.add_event_condition(Event(name="G_PRESSED", arg=4))
script._add_line(f"if {mb3_pressed} then")
script._indent()
script.output_log_message("Right mouse button is pressed")
script._dedent()
script.end_condition()
script.move_mouse_to(MousePosition(x=0, y=0))
script.move_mouse_wheel(3)
script.move_mouse_relative(10,-5)
script.move_mouse_to_virtual(MousePosition(x=32767,y=32767))
x,y = script.get_mouse_position()
script.add_event_condition(Event(name="G_PRESSED", arg=5))
script.output_log_message("Mouse position: x=%d, y=%d", x, y)
script.end_condition()
script.enable_primary_mouse_button_events(True)
script.play_macro(Macro(name="my_macro"))
script.press_macro(Macro(name="my_macro"))
script.release_macro(Macro(name="my_macro"))
script.sleep(100)
script.abort_macro()
script.clear_log()
running_time = script.get_running_time()
script.output_log_message("Script has been running for %d ms", running_time)
today = script.get_date("%Y-%m-%d %H:%M:%S")
script.output_log_message("Today's date and time: %s", today)
script.output_debug_message("This is a debug message: %d", 123)
script.end_condition()
script.end_event_handler()
print(script.generate())

Logitech G HUB Lua API Reference (V2023.5)

This document provides a concise reference for the Logitech G HUB Lua API, version 2023.5. It's designed for quick lookups of function specifications and usage examples.

Core Functions

OnEvent

Handles script events. You must implement this function.

Specification:

function OnEvent(event, arg [family])
end

Parameters:

  • event (string): The event identifier.
  • arg (varies): Argument related to the event.
  • family (string, optional): Device family ("kb", "lhc", "mouse").

Events:

Event arg family Description
"PROFILE_ACTIVATED" nil Profile activated. This is the first event seen.
"PROFILE_DEACTIVATED" nil Profile deactivated. This is the last event seen.
"G_PRESSED" 1-18 (G1-G18) G Key pressed.
"G_RELEASED" 1-18 (G1-G18) G Key released.
"M_PRESSED" 1-3 (M1-M3) M Key pressed.
"M_RELEASED" 1-3 (M1-M3) M Key released.
"MOUSE_BUTTON_PRESSED" 2+ "mouse" Mouse button pressed (except left by default, see EnablePrimaryMouseButtonEvents).
"MOUSE_BUTTON_RELEASED" 2+ "mouse" Mouse button released (except left by default, see EnablePrimaryMouseButtonEvents).

Example:

function OnEvent(event, arg, family)
    if event == "PROFILE_ACTIVATED" then
        OutputLogMessage("Profile activated\n")
    elseif event == "G_PRESSED" and arg == 1 then
        OutputLogMessage("G1 key pressed\n")
    end
end

GetMKeyState

Gets the current state of the M keys.

Specification:

mkey = GetMKeyState([family])

Parameters:

  • family (string, optional): Device family ("kb", "lhc"). Default is "kb".

Return Value:

  • mkey (number): 1 (M1), 2 (M2), or 3 (M3).

Example:

local currentMKey = GetMKeyState()
OutputLogMessage("Current M key state: %d\n", currentMKey)

SetMKeyState

Sets the current state of the M keys.

Specification:

SetMKeyState(mkey, [family])

Parameters:

  • mkey (number): 1 (M1), 2 (M2), or 3 (M3).
  • family (string, optional): Device family ("kb", "lhc"). Default is "kb".

Example:

function OnEvent(event, arg)
    if event == "G_PRESSED" and arg == 1 then
        SetMKeyState(1) -- Set M key state to M1
    end
end

Sleep

Pauses the script for a specified duration.

Specification:

Sleep(timeout)

Parameters:

  • timeout (number): Time to sleep in milliseconds.

Example:

Sleep(100)  -- Pause for 100 milliseconds

OutputLogMessage

Sends a formatted message to the script editor's console.

Specification:

OutputLogMessage(...)

Parameters:

  • ... (string): printf-style formatted string and arguments.

Example:

OutputLogMessage("Hello, world! This is a number: %d\n", 42)

GetRunningTime

Returns the script's running time in milliseconds.

Specification:

elapsed = GetRunningTime()

Return Value:

  • elapsed (number): Elapsed time in milliseconds.

Example:

local runningTime = GetRunningTime()
OutputLogMessage("Script has been running for %d ms\n", runningTime)

GetDate

Retrieves the formatted date and time.

Specification:

date = GetDate([format [, time]])

Parameters:

  • format (string, optional): Date format string (strftime style). "*t" for table format.
  • time (table, optional): Time table.

Return Value:

  • date (string or table): Formatted date/time.

Example:

local today = GetDate("%Y-%m-%d %H:%M:%S")
OutputLogMessage("Today's date and time: %s\n", today)

ClearLog

Clears the script editor's output window.

Specification:

ClearLog()

Example:

ClearLog()

Keyboard Functions

PressKey

Simulates a keyboard key press.

Specification:

PressKey(scancode [, scancode ...])
PressKey(keyname [, keyname ...])

Parameters:

  • scancode (number): Numerical scancode of the key.
  • keyname (string): Predefined keyname. (See Appendix A in the documentation for a complete list of scancodes and keynames.)

Example:

PressKey("a")      -- Press the "a" key
PressKey(30)       -- Press the key with scancode 30 ("a")
PressKey("shift", "a") -- Press Shift and "a" together

ReleaseKey

Simulates a keyboard key release.

Specification:

ReleaseKey(scancode [, scancode ...])
ReleaseKey(keyname [, keyname ...])

Parameters:

  • scancode (number): Numerical scancode of the key.
  • keyname (string): Predefined keyname.

Example:

ReleaseKey("a")    -- Release the "a" key
ReleaseKey(30)     -- Release the key with scancode 30

PressAndReleaseKey

Simulates a keyboard key press followed by a release.

Specification:

PressAndReleaseKey(scancode [, scancode ...])
PressAndReleaseKey(keyname [, keyname ...])

Parameters:

  • scancode (number): Numerical scancode of the key.
  • keyname (string): Predefined keyname.

Example:

PressAndReleaseKey("a") -- Press and release "a"

IsModifierPressed

Checks if a modifier key (Alt, Shift, Ctrl) is pressed.

Specification:

boolean = IsModifierPressed(keyname)

Parameters:

  • keyname (string): "lalt", "ralt", "alt", "lshift", "rshift", "shift", "lctrl", "rctrl", "ctrl".

Return Value:

  • boolean (boolean): true if pressed, false otherwise.

Example:

if IsModifierPressed("shift") then
    OutputLogMessage("Shift key is pressed\n")
end

IsKeyLockOn

Checks if a lock key (Scroll Lock, Caps Lock, Num Lock) is enabled.

Specification:

boolean = IsKeyLockOn(keyname)

Parameters:

  • keyname (string): "scrolllock", "capslock", "numlock".

Return Value:

  • boolean (boolean): true if enabled, false otherwise.

Example:

if IsKeyLockOn("numlock") then
    PressAndReleaseKey("numlock") -- Turn off Num Lock
end

Mouse Functions

PressMouseButton

Simulates a mouse button press.

Specification:

PressMouseButton(button)

Parameters:

  • button (number): 1 (Left), 2 (Middle), 3 (Right), 4 (X1), 5 (X2).

Example:

PressMouseButton(1) -- Press the left mouse button

ReleaseMouseButton

Simulates a mouse button release.

Specification:

ReleaseMouseButton(button)

Parameters:

  • button (number): 1 (Left), 2 (Middle), 3 (Right), 4 (X1), 5 (X2).

Example:

ReleaseMouseButton(1) -- Release the left mouse button

PressAndReleaseMouseButton

Simulates a mouse button press followed by a release.

Specification:

PressAndReleaseMouseButton(button)

Parameters:

  • button (number): 1 (Left), 2 (Middle), 3 (Right), 4 (X1), 5 (X2).

Example:

PressAndReleaseMouseButton(1) -- Click the left mouse button

IsMouseButtonPressed

Checks if a mouse button is pressed.

Specification:

boolean = IsMouseButtonPressed(button)

Parameters:

  • button (number): 1 (Left), 2 (Middle), 3 (Right), 4 (X1), 5 (X2).

Return Value:

  • boolean (boolean): true if pressed, false otherwise.

Example:

if IsMouseButtonPressed(3) then
    OutputLogMessage("Right mouse button is pressed\n")
end

MoveMouseTo

Moves the mouse cursor to an absolute screen position.

Specification:

MoveMouseTo(x, y)

Parameters:

  • x (number): Normalized X coordinate (0-65535).
  • y (number): Normalized Y coordinate (0-65535).

Example:

MoveMouseTo(0, 0) -- Move to top-left corner

MoveMouseWheel

Simulates mouse wheel movement.

Specification:

MoveMouseWheel(clicks)

Parameters:

  • clicks (number): Number of clicks (positive for up, negative for down).

Example:

MoveMouseWheel(3)  -- Scroll up 3 clicks
MoveMouseWheel(-1) -- Scroll down 1 click

MoveMouseRelative

Moves the mouse cursor relative to its current position.

Specification:

MoveMouseRelative(x, y)

Parameters:

  • x (number): X-axis movement (positive for right, negative for left).
  • y (number): Y-axis movement (positive for down, negative for up).

Example:

MoveMouseRelative(10, -5) -- Move 10 pixels right and 5 pixels up

MoveMouseToVirtual

Moves the mouse cursor to an absolute position on a multi-monitor setup.

Specification:

MoveMouseToVirtual(x, y)

Parameters:

  • x (number): Normalized X coordinate (0-65535).
  • y (number): Normalized Y coordinate (0-65535).

Example:

MoveMouseToVirtual(32767, 32767) -- Move to the center of the virtual desktop

GetMousePosition

Gets the current normalized mouse cursor position.

Specification:

x, y = GetMousePosition()

Return Values:

  • x (number): Normalized X coordinate (0-65535).
  • y (number): Normalized Y coordinate (0-65535).

Example:

local x, y = GetMousePosition()
OutputLogMessage("Mouse position: x=%d, y=%d\n", x, y)

SetMouseDPITable

Not implemented in G HUB. Sets the DPI table for a gaming mouse.

Specification:

SetMouseDPITable({value1, value2, ...}, [index])

Parameters:

  • {value1, value2, ...} (table): Array of DPI values.
  • index (number, optional): 1-based index to set as current DPI.

SetMouseDPITableIndex

Not implemented in G HUB. Sets the current DPI table index.

Specification:

SetMouseDPITableIndex(index)

Parameters:

  • index (number): 1-based index into the DPI table.

EnablePrimaryMouseButtonEvents

Enables or disables event reporting for the primary (left) mouse button.

Specification:

EnablePrimaryMouseButtonEvents(enable)

Parameters:

  • enable (boolean): true to enable, false to disable.

Example:

EnablePrimaryMouseButtonEvents(true) -- Enable left mouse button events

LCD Functions (G15, G19, etc.)

Note: These functions are not implemented in G HUB.

OutputLCDMessage

Adds a line of text to the LCD.

Specification:

OutputLCDMessage(text [, timeout])

Parameters:

  • text (string): Text to display.
  • timeout (number, optional): Timeout in milliseconds (default 1000).

ClearLCD

Clears the LCD.

Specification:

ClearLCD()

Macro Functions

PlayMacro

Plays an existing macro.

Specification:

PlayMacro(macroname)

Parameters:

  • macroname (string): Name of the macro.

Example:

PlayMacro("my_macro")

PressMacro

Plays a macro by simulating a key press down.

Specification:

PressMacro(macroname)

Parameters:

  • macroname (string): Name of the macro.

Example:

PressMacro("my_macro")

ReleaseMacro

Plays a macro by simulating a key release.

Specification:

ReleaseMacro(macroname)

Parameters:

  • macroname (string): Name of the macro.

Example:

ReleaseMacro("my_macro")

AbortMacro

Aborts a currently playing macro started from a script.

Specification:

AbortMacro()

Example:

PlayMacro("my_macro")
Sleep(100)
AbortMacro()

Device-Specific Functions

SetBacklightColor

Not implemented in G HUB. Sets the backlight color for supported devices.

Specification:

SetBacklightColor(red, green, blue, [family])

Parameters:

  • red (number): Red intensity (0-255).
  • green (number): Green intensity (0-255).
  • blue (number): Blue intensity (0-255).
  • family (string, optional): "kb", "lhc".

SetSteeringWheelProperty

Not implemented in G HUB. Sets properties for steering wheel devices (G29, G920).

Specification:

SetSteeringWheelProperty(device, property, value)

Parameters:

  • device (string): "G29" or "G920".
  • property (string): "operatingRange", "combinedPedals", "defaultCenteringSpring", "defaultCenteringSpringStrength".
  • value (number or boolean): Property value.

G13-Specific Functions

Note: These functions are not implemented in G HUB.

SetMouseSpeed

Sets the analog joystick mouse speed on the G13.

Specification:

SetMouseSpeed(speed)

Parameters:

  • speed (number): Absolute mouse speed (32-255).

GetMouseSpeed

Gets the current analog joystick mouse speed on the G13.

Specification:

speed = GetMouseSpeed()

Return Value:

  • speed (number): Current mouse speed.

IncrementMouseSpeed

Increases the analog joystick mouse speed.

Specification:

IncrementMouseSpeed(increment)

Parameters:

  • increment (number): Increment value.

DecrementMouseSpeed

Decreases the analog joystick mouse speed.

Specification:

DecrementMouseSpeed(decrement)

Parameters:

  • decrement (number): Decrement value.

Debugging

OutputDebugMessage

Sends a message to the Windows debugger.

Specification:

OutputDebugMessage(...)

Parameters:

  • ... (string): printf-style formatted string and arguments.

Example:

OutputDebugMessage("This is a debug message: %d\n", 123)

Standard Lua 5.4 Libraries

The following standard Lua 5.4 libraries are supported. For detailed information, refer to the Lua 5.4 documentation:

Math functions (math.*)

String functions (string.*)

Table functions (table.*)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment