2
0

kbdLED 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from enum import Enum, StrEnum
  4. # reads and writes RGB and brightness data for led background color of Clevo NL51 Laptops
  5. # ensure to compile drivers before ! read: https://wiki.siningsoft.de/doku.php?id=terra:1500p
  6. # Kernelmodul: tuxedo_keyboard
  7. # 2026-02-02 - devnull - initial
  8. # 2026-02-03 - devnull - added Brightness restore
  9. # 2026-02-04 - devnull - JSON statefile
  10. # 2026-02-11 - devnull - created class
  11. # 2026-02-18 - devnull - added logging
  12. # 2026-02-19 - devnull - added commandline arguments for changing
  13. # 2026-02-21 - devnull - color and brightness switching on commandline
  14. # 2026-02-21 - devnull - enable/disable LED via Commandline
  15. ver="1.4"
  16. import sys
  17. import argparse
  18. import json
  19. import logging
  20. # start with a logger object
  21. log = logging.getLogger(__name__)
  22. class kbdLED_class():
  23. # 2026-02-11 - devnull - added class definition
  24. # 2026-02-19 - devnull - bugfixed write procedure
  25. # - added hard coded colors
  26. class colors(StrEnum):
  27. GREEN = "0 255 0"
  28. WHITE = "255 255 255"
  29. RED = "255 0 0"
  30. BLUE = "0 0 255"
  31. YELLOW = "255 255 0"
  32. PURPLE = "255 0 255"
  33. LIGHTBLUE = "0 0 255"
  34. # d_GREEN = {"R":0,"G": 255,"B": 0}
  35. # d_WHITE = {"R":255,"G": 255,"B": 255}
  36. # d_RED = {"R":255,"G": 0,"B": 0}
  37. # d_BLUE = {"R":0,"G": 0,"B": 255}
  38. # d_YELLOW = {"R":255,"G": 255,"B": 0}
  39. # d_PURPLE = {"R":255,"G": 0,"B": 255}
  40. # d_LIGHTBLUE = {"R":0,"G": 255,"B": 255}
  41. # diese Versionsnummer wird getrennt vom Programmcode geführt, da es sich getrennt entwickeln wird
  42. __version__ = 1.1
  43. config = dict()
  44. # Objekt erzeugen
  45. def __init__(self, cmd,
  46. log,
  47. INcolor=colors.WHITE,
  48. INbrightness=255,
  49. kbd_state_fp='/var/lib/kbdLED.state.json',
  50. sysfs_color_fp='/sys/devices/platform/tuxedo_keyboard/leds/rgb:kbd_backlight/multi_intensity',
  51. sysfs_bri_fp='/sys/devices/platform/tuxedo_keyboard/leds/rgb:kbd_backlight/brightness'):
  52. self.log = log
  53. self.config = {"sysfs" :
  54. {
  55. "color" : sysfs_color_fp ,
  56. "bri" : sysfs_bri_fp
  57. },
  58. "state" : kbd_state_fp}
  59. self.log.debug(str(self.config))
  60. # startup and restore states
  61. if cmd=="start":
  62. self.readStateFile(self.config['state'])
  63. self.log.debug(str(self.config))
  64. self.writeColor()
  65. self.writeBrightness()
  66. # shutdown system and save last states
  67. elif cmd=="stop":
  68. self.readColor()
  69. self.readBrightness()
  70. self.writeStateFile(self.config['state'])
  71. # set the color from commandline
  72. elif cmd=="color":
  73. self.log.debug("INcolor=" + str(INcolor))
  74. self.color2dict2config(INcolor)
  75. self.log.debug("__init__(cmd=color).config['color']=" + str(self.config['color']))
  76. self.writeColor()
  77. # set the brightness from commandline
  78. elif cmd=="brightness":
  79. self.config['Brightness']= int(INbrightness)
  80. self.writeBrightness()
  81. def readStateFile(self,kbd_state_fp):
  82. config = {"color":
  83. {"R": 255,
  84. "G": 255,
  85. "B": 255},
  86. "Brightness": 255
  87. }
  88. try:
  89. with open(kbd_state_fp, 'r') as kbd_state_fh:
  90. self.config = json.load(kbd_state_fh)
  91. except FileNotFoundError:
  92. self.log.error("keine Statusdatei gefunden, nutze Standardwerte")
  93. except PermissionError:
  94. self.log.error("Fehler beim lesen")
  95. def writeStateFile(self,kbd_state_fp):
  96. try:
  97. with open(kbd_state_fp, 'w') as kbd_state_fh:
  98. json.dump(self.config,kbd_state_fh)
  99. except FileNotFoundError:
  100. self.log.error("Verzeichnis oder Datei nicht gefunden")
  101. # color String nach Config Dict
  102. def color2dict2config(self, color_string):
  103. ca=color_string.split(" ")
  104. self.log.debug("color_string=" + color_string)
  105. self.log.debug("after splitting=" + str(ca))
  106. self.config['color'] = {"R": int(ca[0]),
  107. "G": int(ca[1]),
  108. "B": int(ca[2])}
  109. # color Confi Dict nach String
  110. def config2dict2color(self):
  111. return str(self.config['color']['R']) + " " + str(self.config['color']['G']) + " " + str(self.config['color']['B'])
  112. # reads the color Values from sysfs
  113. def readColor(self):
  114. try:
  115. with open(self.config['sysfs']['color']) as fh:
  116. self.color2dict2config(fh.read())
  117. except FileNotFoundError:
  118. self.log.error("fehler beim Öffnen der Sysfs Datei " + self.config['sysfs']['color'])
  119. sys.exit(1)
  120. except PermissionError:
  121. self.log.error("keine Rechte die Datei zu lesen " + self.config['sysfs']['color'])
  122. sys.exit(1)
  123. # writes the color values to sysfs
  124. def writeColor(self):
  125. try:
  126. #with open(self.config['sysfs']['color']) as fh:
  127. # fh.write(self.dict2color())
  128. fh = open(self.config['sysfs']['color'], 'w')
  129. fh.write(self.config2dict2color())
  130. fh.close()
  131. except FileNotFoundError:
  132. self.log.error("fehler beim Schreiben der Sysfs Datei " + self.config['sysfs']['color'])
  133. sys.exit(1)
  134. except PermissionError:
  135. self.log.error("keine Rechte die Datei zu schreiben " + self.config['sysfs']['color'])
  136. sys.exit(1)
  137. # reads Brightness from sysfs
  138. def readBrightness(self):
  139. try:
  140. with open(self.config['sysfs']['bri']) as fh:
  141. self.config['Brightness'] = int(fh.read())
  142. except FileNotFoundError:
  143. self.log.error("fehler beim Öffnen der Sysfs Datei " + self.config['sysfs']['bri'])
  144. sys.exit(1)
  145. except PermissionError:
  146. self.log.error("keine Rechte die Datei zu lesen " + self.config['sysfs']['bri'])
  147. sys.exit(1)
  148. # writes Brightness to sysfs
  149. def writeBrightness(self):
  150. try:
  151. #with open(self.config['sysfs']['bri']) as fh:
  152. # fh.write(self.config['Brightness'])
  153. fh = open(self.config['sysfs']['bri'], 'w')
  154. fh.write(str(self.config['Brightness']))
  155. fh.close()
  156. except FileNotFoundError:
  157. self.log.error("- fehler beim Schreiben der Sysfs Datei " + self.config['sysfs']['bri'])
  158. sys.exit(1)
  159. except PermissionError:
  160. self.log.error("- keine Rechte die Datei zu schreiben " + self.config['sysfs']['bri'])
  161. sys.exit(1)
  162. # Press the green button in the gutter to run the script.
  163. # noinspection aK
  164. if __name__ == '__main__':
  165. #https: // argparse.readthedocs.io
  166. # internal note: um mehrere sich ausschließende Argumente zuzulassen, muss add_mutually_exclusive_groups verwenden
  167. parser = argparse.ArgumentParser(
  168. prog='T1500_KeyboardLED',
  169. description='saves and restore LED Colors',
  170. epilog='GPL')
  171. group_common = parser.add_argument_group("common")
  172. output = group_common.add_mutually_exclusive_group(required=False)
  173. output.add_argument('--verbose', action='store_true', help='extended logging', required=False)
  174. output.add_argument('--debug', action='store_true', help='debug output', required=False)
  175. group_function = parser.add_argument_group("function")
  176. startstop = group_function.add_mutually_exclusive_group()
  177. startstop.add_argument('--on', action='store_true', help='generally turn LED Backlight on')
  178. startstop.add_argument('--off', action='store_true', help='generally turn LED Backlight off')
  179. startstop.add_argument('--start', action='store_true', help='will be used for system starts')
  180. startstop.add_argument('--stop', action='store_true', help='will be used for system shutdowns')
  181. startstop.add_argument('-c', '--color', choices=['white','blue','lightblue','green','red','purple','yellow'], help='keyboard color out of fixed feature set', required=False)
  182. startstop.add_argument('-b', '--brightness', type=int, help='keybpoard brightness between 0..255', required=False)
  183. startstop.add_argument('--version', action='version', version='%(prog)s ' + ver, default='d')
  184. args = parser.parse_args()
  185. if args.verbose:
  186. log.setLevel(logging.INFO)
  187. elif args.debug:
  188. log.setLevel(logging.DEBUG)
  189. else:
  190. log.setLevel(logging.ERROR)
  191. logging.basicConfig(format='%(asctime)s %(message)s')
  192. if args.start:
  193. print("Keyboard: read and set Color and Brightness")
  194. log.debug("System start")
  195. kL = kbdLED_class("start", log)
  196. elif args.stop:
  197. print("Keyboard: read and save Color and Brightness")
  198. log.debug("System stop")
  199. kL = kbdLED_class("stop", log)
  200. elif args.color:
  201. print("Keyboard: set color " + args.color)
  202. log.debug("resolveed Color=" + getattr(kbdLED_class.colors,args.color.upper()))
  203. try:
  204. log.debug("setup keyboard color " + args.color)
  205. kL = kbdLED_class("color", log, INcolor=getattr(kbdLED_class.colors, args.color.upper()))
  206. except AttributeError:
  207. log.error("color does not exists " + args.color)
  208. parser.print_help()
  209. sys.exit((1))
  210. elif args.brightness:
  211. print("Keyboard: set brightness " + str(args.brightness))
  212. log.debug("setup keyboard brightness " + str(args.brightness))
  213. kL = kbdLED_class("brightness",log, INbrightness=args.brightness)
  214. elif args.on:
  215. print("Keyboard: enable Backlight LED")
  216. kL = kbdLED_class("brightness",log, INbrightness=255)
  217. elif args.off:
  218. print("Keyboard: disable Backlight LED")
  219. kL = kbdLED_class("brightness", log, INbrightness=0)
  220. else:
  221. parser.print_help()
  222. sys.exit((10))
  223. sys.exit(0)