devices.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #!/usr/bin/env python3
  2. import subprocess
  3. IGNORED_DEVICES = {
  4. "lo",
  5. "docker0",
  6. }
  7. IGNORED_PREFIXES = (
  8. "br-",
  9. "veth",
  10. "virbr",
  11. "tun",
  12. "tap",
  13. )
  14. IGNORED_TYPES = {
  15. "loopback",
  16. "bridge",
  17. }
  18. def devices() -> list:
  19. result = subprocess.run(
  20. [
  21. "nmcli",
  22. "-t",
  23. "-f",
  24. "DEVICE,TYPE,STATE,CONNECTION",
  25. "device",
  26. "status",
  27. ],
  28. text=True,
  29. capture_output=True,
  30. check=True,
  31. )
  32. devices = []
  33. for line in result.stdout.strip().splitlines():
  34. device, dev_type, state, connection = line.split(":", 3)
  35. # filter ignored device names
  36. if device in IGNORED_DEVICES:
  37. continue
  38. # filter virtual interface prefixes
  39. if any(device.startswith(prefix) for prefix in IGNORED_PREFIXES):
  40. continue
  41. # filter unwanted interface types
  42. if dev_type in IGNORED_TYPES:
  43. continue
  44. devices.append({
  45. "device": device,
  46. "type": dev_type,
  47. "state": state,
  48. "connection": None if connection == "--" else connection,
  49. })
  50. return devices
  51. def yuck() -> str:
  52. ret = r"""(box :orientation "v" :spacing 8"""
  53. for device in devices():
  54. safe_name = device["device"].replace('"', r'\"')
  55. signal_icon = "settings_input_antenna" if device["type"] == "wifi" else "lan"
  56. if device["state"] == "connected":
  57. ret += rf"""
  58. (box :orientation "h" :space-evenly false :spacing 16 :class "device-item"
  59. (label :class "device-icon" :text "{signal_icon}")
  60. (box :orientation "v" :space-evenly false :spacing 2
  61. (label :class "device-name" :text "{safe_name}" :xalign 0)
  62. (label :class "device-subtext" :text "Active" :xalign 0)
  63. )
  64. (box :hexpand true)
  65. (checkbox
  66. :checked true
  67. :onchecked "~/.config/eww/widgets/network/scripts/device_up.sh '{safe_name}'"
  68. :onunchecked "~/.config/eww/widgets/network/scripts/device_down.sh '{safe_name}'"
  69. )
  70. )
  71. """
  72. else:
  73. ret += rf"""
  74. (box :orientation "h" :space-evenly false :spacing 16 :class "device-item"
  75. (label :class "device-icon" :text "{signal_icon}")
  76. (box :orientation "v" :space-evenly true :spacing 2
  77. (label :class "device-name" :text "{safe_name}" :xalign 0)
  78. )
  79. (box :hexpand true)
  80. (checkbox
  81. :checked false
  82. :onchecked "~/.config/eww/widgets/network/scripts/device_up.sh '{safe_name}'"
  83. :onunchecked "~/.config/eww/widgets/network/scripts/device_down.sh '{safe_name}'"
  84. )
  85. )
  86. """
  87. return ret + ")"
  88. print(yuck())