diff options
-rw-r--r-- | 50-docking-station.rules | 4 | ||||
-rw-r--r-- | Makefile | 17 | ||||
-rw-r--r-- | dock-action.py | 93 | ||||
-rw-r--r-- | dock-action.sh | 8 |
4 files changed, 108 insertions, 14 deletions
diff --git a/50-docking-station.rules b/50-docking-station.rules index 18c70f5..06021dd 100644 --- a/50-docking-station.rules +++ b/50-docking-station.rules @@ -1,2 +1,2 @@ -ACTION=="add", SUBSYSTEM=="net", ATTRS{addr_assign_type}=="0", ATTRS{addr_len}=="6", ATTRS{address}=="ac:91:a1:fe:97:bf" RUN+="/home/eddy/projects/arch-dock/dock-action.sh connected" -ACTION=="remove", SUBSYSTEM=="net", ENV{ID_NET_NAME_MAC}=="enxac91a1fe97bf" RUN+="/home/eddy/projects/arch-dock/dock-action.sh disconnected" +ACTION=="add", SUBSYSTEM=="net", ATTRS{addr_assign_type}=="0", ATTRS{addr_len}=="6", ATTRS{address}=="ac:91:a1:fe:97:bf" RUN+="/usr/local/bin/dock-action.py connected work-desk" +ACTION=="remove", SUBSYSTEM=="net", ENV{ID_NET_NAME_MAC}=="enxac91a1fe97bf" RUN+="/usr/local/bin/dock-action.py disconnected work-desk" @@ -1,14 +1,23 @@ UDEV_RULE_DIR := /etc/udev/rules.d RULES_FILE := 50-docking-station.rules -$(UDEV_RULE_DIR)/$(RULES_FILE): $(RULES_FILE) - @echo "Installing udev rules (requires root access)" - sudo install --owner=root --group=root --mode=644 -t $(UDEV_RULE_DIR) $(RULES_FILE) +SCRIPT_DIR := /usr/local/bin +SCRIPT := dock-action.py -install: $(UDEV_RULE_DIR)/$(RULES_FILE) +install: $(UDEV_RULE_DIR)/$(RULES_FILE) $(SCRIPT_DIR)/$(SCRIPT) uninstall: @echo "Removing udev rules (requires root access)" sudo rm "$(UDEV_RULE_DIR)/$(RULES_FILE)" + @echo "Removing script (requires root access)" + sudo rm "$(SCRIPT_DIR)/$(SCRIPT)" + +$(UDEV_RULE_DIR)/$(RULES_FILE): $(RULES_FILE) + @echo "Installing udev rules (requires root access)" + sudo install --owner=root --group=root --mode=644 -t $(UDEV_RULE_DIR) $(RULES_FILE) + +$(SCRIPT_DIR)/$(SCRIPT): $(SCRIPT) + @echo "Installing script (requires root access)" + sudo install --owner=root --group=root --mode=755 -t $(SCRIPT_DIR) $(SCRIPT) .PHONY: install uninstall diff --git a/dock-action.py b/dock-action.py new file mode 100644 index 0000000..454cab8 --- /dev/null +++ b/dock-action.py @@ -0,0 +1,93 @@ +#!/usr/bin/python + +import logging +import argparse +import os +from subprocess import run + +DRY_RUN = False +WLAN_ADAPTER = "wlp1s0" +DEVICES = { + "work-desk" : { + "displays" : { + "DisplayPort-2" : "auto", + "eDP" : "off" + }, + "mac_address" : "ac:91:a1:fe:97:bf" + } +} + +def get_adapter_name(mac_address: str) -> str: + import json + interfaces = json.loads(run(["ip", "-j", "link"], capture_output=True).stdout) + matches = [i for i in interfaces if i["address"].lower() == mac_address] + if len(matches) > 0: + return matches[0]["ifname"] + else: + return None + +def do(command: list[str]) -> None: + if DRY_RUN: + logging.info(f"Run command: {command}") + else: + result = run(command, capture_output=True) + if result.returncode != 0: + logging.error(f"Command returned {result.returncode}: {' '.join(command)}") + logging.error(result.stdout) + logging.error(result.stderr) + +def connected(device_name: str) -> None: + logging.info(f"Connected notification for {device_name}") + + if device_name not in DEVICES: + logging.info(f"Unregistered device {device_name}, ignoring") + return + device = DEVICES[device_name] + + eth_adapter = get_adapter_name(device["mac_address"]) + if eth_adapter is None: + logging.error("No network adapter found, exiting") + return + + logging.debug("Disabling wireless adapter") + do(["ip", "link", "set", WLAN_ADAPTER, "down"]) + + logging.debug("Enabling ethernet adapter") + do(["ip", "link", "set", eth_adapter, "up"]) + + logging.debug("Configuring monitors") + xrandr_args = ["xrandr"] + for display, mode in device["displays"].items(): + xrandr_args.append("--output") + xrandr_args.append(display) + xrandr_args.append(f"--{mode}") + do(xrandr_args) + +def disconnected(device_name: str) -> None: + logging.info(f"Disconnected notification for {device_name}") + + logging.debug("Enabling wireless adapter") + do(["ip", "link", "set", WLAN_ADAPTER, "up"]) + + logging.debug("Configuring monitors") + do(["xrandr", "--auto"]) + +def main() -> None: + #logging.basicConfig(filename="/home/eddy/dock.log", encoding="utf-8", level=logging.DEBUG) + os.environ["DISPLAY"] = ":0" + os.environ["XAUTHORITY"] = "/home/eddy/.Xauthority" + + parser = argparse.ArgumentParser() + parser.add_argument("action") + parser.add_argument("device") + args = parser.parse_args() + + if args.action == "connected": + connected(args.device) + elif args.action == "disconnected": + disconnected(args.device) + + logging.info("Done") + +if __name__ == "__main__": + main() diff --git a/dock-action.sh b/dock-action.sh deleted file mode 100644 index 3b93398..0000000 --- a/dock-action.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/bash - -if [ "$1" = "connected" ]; then - echo "Dock connected" >> /home/eddy/dock.log -elif [ "$1" = "disconnected" ]; then - echo "Dock disconnected" >> /home/eddy/dock.log -fi - |