v0.1
This commit is contained in:
311
edledsync.py
Executable file
311
edledsync.py
Executable file
@@ -0,0 +1,311 @@
|
||||
#!/bin/python3
|
||||
from openrgb import OpenRGBClient
|
||||
from openrgb.utils import DeviceType, RGBColor
|
||||
from watchdog.observers import Observer
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
import json
|
||||
import xmltodict
|
||||
from os.path import basename
|
||||
from enum import IntFlag
|
||||
from pathlib import Path
|
||||
from functools import wraps
|
||||
|
||||
|
||||
def after(runAfter):
|
||||
def inner(fun):
|
||||
@wraps(fun)
|
||||
def wrapper(*args, **kwds):
|
||||
res = fun(*args, **kwds)
|
||||
runAfter()
|
||||
return res
|
||||
|
||||
return wrapper
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
qwertyToAzerty = {
|
||||
"A": "Q",
|
||||
"Z": "W",
|
||||
"E": "E",
|
||||
"R": "R",
|
||||
"T": "T",
|
||||
"Y": "Y",
|
||||
"U": "U",
|
||||
"I": "I",
|
||||
"O": "O",
|
||||
"P": "P",
|
||||
"Q": "A",
|
||||
"S": "S",
|
||||
"D": "D",
|
||||
"F": "F",
|
||||
"G": "G",
|
||||
"H": "H",
|
||||
"J": "J",
|
||||
"K": "K",
|
||||
"L": "L",
|
||||
"M": ";",
|
||||
"W": "Z",
|
||||
"X": "X",
|
||||
"C": "C",
|
||||
"V": "V",
|
||||
"B": "B",
|
||||
"N": "N",
|
||||
",": ";",
|
||||
";": "M",
|
||||
":": "M",
|
||||
}
|
||||
COLORS = {
|
||||
"ELITE_ORANGE": RGBColor(255, 106, 0),
|
||||
"BLUE": RGBColor(0, 255, 255),
|
||||
"DEFAULT": RGBColor(0, 255, 255),
|
||||
"MOVEMENT": RGBColor(0, 255, 255),
|
||||
"ATTACK": RGBColor(255, 0, 0),
|
||||
"MENU": RGBColor(255, 255, 255),
|
||||
"UTIL": RGBColor(0, 255, 0),
|
||||
"INVENTORY": RGBColor(255, 255, 0),
|
||||
"OFF": RGBColor(0, 0, 0),
|
||||
}
|
||||
|
||||
ED_SAVE_PATH = Path(
|
||||
"/home/ar2000/.steam/steam/steamapps/compatdata/359320/pfx/drive_c/users/steamuser/Saved Games/Frontier Developments/Elite Dangerous/Status.json"
|
||||
)
|
||||
ED_BINDINGS_CUSTOM_PATH = Path(
|
||||
"/home/ar2000/.steam/steam/steamapps/compatdata/359320/pfx/drive_c/users/steamuser/AppData/Local/Frontier Developments/Elite Dangerous/Options/Bindings/"
|
||||
)
|
||||
ED_BINDINGS_TEMPLATE_PATH = Path(
|
||||
"/home/ar2000/.steam/steam/steamapps/common/Elite Dangerous/Products/elite-dangerous-odyssey-64/ControlSchemes/"
|
||||
)
|
||||
file = None
|
||||
|
||||
ON_FOOT_KEYS = {
|
||||
"HumanoidForwardButton": COLORS["MOVEMENT"],
|
||||
"HumanoidBackwardButton": COLORS["MOVEMENT"],
|
||||
"HumanoidStrafeLeftButton": COLORS["MOVEMENT"],
|
||||
"HumanoidStrafeRightButton": COLORS["MOVEMENT"],
|
||||
"HumanoidRotateLeftButton": COLORS["MOVEMENT"],
|
||||
"HumanoidRotateRightButton": COLORS["MOVEMENT"],
|
||||
"HumanoidPitchUpButton": COLORS["MOVEMENT"],
|
||||
"HumanoidPitchDownButton": COLORS["MOVEMENT"],
|
||||
"HumanoidSprintButton": COLORS["MOVEMENT"],
|
||||
"HumanoidWalkButton": COLORS["MOVEMENT"],
|
||||
"HumanoidCrouchButton": COLORS["MOVEMENT"],
|
||||
"HumanoidJumpButton": COLORS["MOVEMENT"],
|
||||
"HumanoidPrimaryInteractButton": COLORS["MENU"],
|
||||
"HumanoidSecondaryInteractButton": COLORS["MENU"],
|
||||
"HumanoidItemWheelButton": COLORS["MENU"],
|
||||
"HumanoidEmoteWheelButton": COLORS["MENU"],
|
||||
"HumanoidItemWheelButton_XAxis": COLORS["MENU"],
|
||||
"HumanoidItemWheelButton_XLeft": COLORS["MENU"],
|
||||
"HumanoidItemWheelButton_XRight": COLORS["MENU"],
|
||||
"HumanoidItemWheelButton_YAxis": COLORS["MENU"],
|
||||
"HumanoidItemWheelButton_YUp": COLORS["MENU"],
|
||||
"HumanoidItemWheelButton_YDown": COLORS["MENU"],
|
||||
"HumanoidPrimaryFireButton": COLORS["ATTACK"],
|
||||
"HumanoidZoomButton": COLORS["DEFAULT"],
|
||||
"HumanoidThrowGrenadeButton": COLORS["ATTACK"],
|
||||
"HumanoidMeleeButton": COLORS["ATTACK"],
|
||||
"HumanoidReloadButton": COLORS["UTIL"],
|
||||
"HumanoidSelectPrimaryWeaponButton": COLORS["INVENTORY"],
|
||||
"HumanoidSelectSecondaryWeaponButton": COLORS["INVENTORY"],
|
||||
"HumanoidSelectUtilityWeaponButton": COLORS["INVENTORY"],
|
||||
"HumanoidSelectNextWeaponButton": COLORS["INVENTORY"],
|
||||
"HumanoidSelectPreviousWeaponButton": COLORS["INVENTORY"],
|
||||
"HumanoidHideWeaponButton": COLORS["UTIL"],
|
||||
"HumanoidSelectNextGrenadeTypeButton": COLORS["INVENTORY"],
|
||||
"HumanoidSelectPreviousGrenadeTypeButton": COLORS["INVENTORY"],
|
||||
"HumanoidToggleFlashlightButton": COLORS["UTIL"],
|
||||
"HumanoidToggleNightVisionButton": COLORS["UTIL"],
|
||||
"HumanoidToggleShieldsButton": COLORS["UTIL"],
|
||||
"HumanoidToggleToolModeButton": COLORS["UTIL"],
|
||||
"HumanoidToggleMissionHelpPanelButton": COLORS["MENU"],
|
||||
"HumanoidOpenAccessPanelButton": COLORS["MENU"],
|
||||
"HumanoidConflictContextualUIButton": COLORS["MENU"],
|
||||
"PhotoCameraToggle_Humanoid": COLORS["MENU"],
|
||||
"GalaxyMapOpen_Humanoid": COLORS["MENU"],
|
||||
"SystemMapOpen_Humanoid": COLORS["MENU"],
|
||||
"FocusCommsPanel_Humanoid": COLORS["MENU"],
|
||||
"QuickCommsPanel_Humanoid": COLORS["MENU"],
|
||||
}
|
||||
|
||||
KEYS_TR = {
|
||||
f"{a}{b}": f"{a} {b}"
|
||||
for a in ["Up", "Down", "Left", "Right"]
|
||||
for b in ["Arrow", "Alt", "Shift", "Control"]
|
||||
}
|
||||
configured_on_foot_keys, keybindgs = {}, {}
|
||||
|
||||
|
||||
class StatusFlag(IntFlag):
|
||||
DOCKED = 1 << 0
|
||||
LANDED = 1 << 1
|
||||
LANDING_GEAR_DOWN = 1 << 2
|
||||
SHIELDS_UP = 1 << 3
|
||||
SUPERCRUISE = 1 << 4
|
||||
FLIGHTASSIST_OFF = 1 << 5
|
||||
HARDPOINTS_DEPLOYED = 1 << 6
|
||||
IN_WING = 1 << 7
|
||||
LIGHTS_ON = 1 << 8
|
||||
CARGO_SCOOP_DEPLOYED = 1 << 9
|
||||
SILENT_RUNNING = 1 << 10
|
||||
SCOOPING_FUEL = 1 << 11
|
||||
SRV_HANDBRAKE = 1 << 12
|
||||
SRV_USING_TURRET_VIEW = 1 << 13
|
||||
SRV_TURRET_RETRACTED = 1 << 14
|
||||
SRV_DRIVEASSIST = 1 << 15
|
||||
FSD_MASSLOCKED = 1 << 16
|
||||
FSD_CHARGING = 1 << 17
|
||||
FSD_COOLDOWN = 1 << 18
|
||||
LOW_FUEL = 1 << 19
|
||||
OVER_HEATING = 1 << 20
|
||||
HAS_LAT_LONG = 1 << 21
|
||||
IS_IN_DANGER = 1 << 22
|
||||
BEING_INTERDICTED = 1 << 23
|
||||
IN_MAINSHIP = 1 << 24
|
||||
IN_FIGHTER = 1 << 25
|
||||
IN_SRV = 1 << 26
|
||||
HUD_IN_ANALYSIS_MODE = 1 << 27
|
||||
NIGHT_VISION = 1 << 28
|
||||
ALTITUDE_FROM_AVERAGE_RADIUS = 1 << 29
|
||||
FSDJUMP = 1 << 30
|
||||
SRV_HIGHBEAM = 1 << 31
|
||||
|
||||
|
||||
class StatusFlag2(IntFlag):
|
||||
ON_FOOT = 1 << 0
|
||||
IN_TAXI = 1 << 1
|
||||
IN_MULTICREW = 1 << 2
|
||||
ON_FOOT_IN_STATION = 1 << 3
|
||||
ON_FOOT_ON_PLANET = 1 << 4
|
||||
AIM_DOWN_SIGHT = 1 << 5
|
||||
LOW_OXYGEN = 1 << 6
|
||||
LOW_HEALTH = 1 << 7
|
||||
COLD = 1 << 8
|
||||
HOT = 1 << 9
|
||||
VERY_COLD = 1 << 10
|
||||
VERY_HOT = 1 << 11
|
||||
GLIDE_MODE = 1 << 12
|
||||
ON_FOOT_INHANGAR = 1 << 13
|
||||
ON_FOOT_SOCIAL_SPACE = 1 << 14
|
||||
ON_FOOT_EXTERIOR = 1 << 15
|
||||
BREATHABLE_ATMOSPHERE = 1 << 16
|
||||
TELEPRESENCE_MULTICREW = 1 << 17
|
||||
PHYSICAL_MULTICREW = 1 << 18
|
||||
FSD_HYPERDRIVE_CHARGING = 1 << 19
|
||||
|
||||
|
||||
def setKeysColor(device, keys: list | str, color: RGBColor | list):
|
||||
if type(keys) == list:
|
||||
assert len(color) == len(keys)
|
||||
for i, key in enumerate(keys):
|
||||
for led in device.leds:
|
||||
try:
|
||||
if qwertyToAzerty[led.name.lstrip("Key: ")] == key:
|
||||
led.set_color(color if type(color) == RGBColor else color[i])
|
||||
continue
|
||||
except KeyError:
|
||||
if led.name.lstrip("Key: ") == key:
|
||||
led.set_color(color if type(color) == RGBColor else color[i])
|
||||
continue
|
||||
|
||||
|
||||
def keepAlive():
|
||||
keyboard.update()
|
||||
|
||||
|
||||
def parseKeybinds():
|
||||
with open(Path(ED_BINDINGS_CUSTOM_PATH, "Custom.4.0.binds"), "r") as f:
|
||||
readKeybinds = xmltodict.parse(f.read())
|
||||
keybindgs = readKeybinds["Root"]
|
||||
|
||||
# extract keys for on foot keys
|
||||
for k in ON_FOOT_KEYS:
|
||||
if not k in keybindgs:
|
||||
continue
|
||||
keybind = keybindgs[k]
|
||||
if "Primary" in keybind:
|
||||
if keybind["Primary"]["@Device"] == "Keyboard":
|
||||
key = keybind["Primary"]["@Key"].lstrip("Key_")
|
||||
if key in KEYS_TR:
|
||||
key = KEYS_TR[key]
|
||||
configured_on_foot_keys[k] = key
|
||||
print(f"{k} : {key}")
|
||||
if "Secondary" in keybind:
|
||||
if keybind["Secondary"]["@Device"] == "Keyboard":
|
||||
key = keybind["Secondary"]["@Key"].lstrip("Key_")
|
||||
if key in KEYS_TR:
|
||||
key = KEYS_TR[key]
|
||||
if k in configured_on_foot_keys:
|
||||
print(f'Key "{k}" already found. Ignoring')
|
||||
configured_on_foot_keys[k] = key
|
||||
print(f"{k} : {key}")
|
||||
|
||||
|
||||
class StatusHandler(FileSystemEventHandler):
|
||||
lastOnFoot = False
|
||||
|
||||
@after(keepAlive)
|
||||
def on_modified(self, event):
|
||||
try:
|
||||
with open(ED_SAVE_PATH, "r") as f:
|
||||
print("EDIT")
|
||||
statusData = json.load(f)
|
||||
except:
|
||||
return
|
||||
print(statusData)
|
||||
if "Flags2" not in statusData:
|
||||
return # game not running
|
||||
print(StatusFlag(statusData["Flags"]))
|
||||
print(StatusFlag2(statusData["Flags2"]))
|
||||
if self.isOnFoot(statusData) and self.lastOnFoot == False:
|
||||
keyboard.set_color(RGBColor(0, 0, 0))
|
||||
setKeysColor(
|
||||
keyboard,
|
||||
[v for k, v in configured_on_foot_keys.items()],
|
||||
[c for k, c in ON_FOOT_KEYS.items() if k in configured_on_foot_keys],
|
||||
)
|
||||
elif self.isOnFoot(statusData) == False and self.lastOnFoot == True:
|
||||
keyboard.set_color(COLORS["ELITE_ORANGE"])
|
||||
|
||||
self.lastOnFoot = self.isOnFoot(statusData)
|
||||
return super().on_modified(event)
|
||||
|
||||
def isOnFoot(self, statusData):
|
||||
return StatusFlag2.ON_FOOT in StatusFlag2(statusData["Flags2"])
|
||||
|
||||
|
||||
class KeybindHandler(FileSystemEventHandler):
|
||||
|
||||
def on_modified(self, event):
|
||||
parseKeybinds()
|
||||
return super().on_modified(event)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
print("Parsing keybinds")
|
||||
parseKeybinds()
|
||||
|
||||
openrgbClient = OpenRGBClient(name=basename(__file__))
|
||||
keyboard = openrgbClient.get_devices_by_type(DeviceType.KEYBOARD)[0]
|
||||
keyboard.set_mode("direct")
|
||||
keyboard.set_color(COLORS["ELITE_ORANGE"])
|
||||
|
||||
observer = Observer()
|
||||
statusHandler = StatusHandler()
|
||||
keybindHandler = KeybindHandler()
|
||||
observer.schedule(statusHandler, path=ED_SAVE_PATH, recursive=False)
|
||||
observer.schedule(
|
||||
keybindHandler,
|
||||
path=Path(ED_BINDINGS_CUSTOM_PATH, "Custom.4.0.binds"),
|
||||
recursive=False,
|
||||
)
|
||||
observer.start()
|
||||
|
||||
try:
|
||||
# main loop
|
||||
while observer.is_alive():
|
||||
observer.join(1)
|
||||
finally:
|
||||
observer.stop()
|
||||
observer.join()
|
Reference in New Issue
Block a user