No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

brightness.py 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/usr/bin/env python
  2. import lux
  3. import ddc
  4. import influx
  5. import window
  6. import time
  7. import sys
  8. import select
  9. filter_fact = 0.90
  10. c_in = 0.6, -30.0, # in_a, in_b
  11. calibration = {
  12. "HPN:HP 27xq:CNK1072BJY": [
  13. 1.0, 10.0, # out_a, out_b
  14. ],
  15. "MSI:MSI G27CQ4:": [
  16. 1.0, 0.0, # out_a, out_b
  17. ],
  18. }
  19. running = True
  20. is_active = True
  21. is_unpaused = True
  22. last_brightness = 0
  23. disps = None
  24. def cal(v, c):
  25. # out = out_b + out_a * in_a * max(0, in_b + in)
  26. return c[1] + c[0] * c_in[0] * max(0, c_in[1] + v)
  27. def filter_lux(old, new):
  28. return max(0.1, (old * filter_fact) + (new * (1.0 - filter_fact)))
  29. def lux_to_disp(name, val):
  30. if name in calibration:
  31. val = cal(int(val), calibration[name])
  32. else:
  33. raise ValueError("no calibration for \"{}\"".format(name))
  34. val = int(val)
  35. return min(max(val, 0), 100)
  36. def main():
  37. global running, is_active, is_unpaused, last_brightness, disps
  38. print("usb init")
  39. usb = lux.usb_init()
  40. print("check usb connection")
  41. lux.check_connection(usb)
  42. print("detect displays")
  43. disps = ddc.ddc_detect()
  44. if len(disps) <= 0:
  45. raise ValueError("no displays found")
  46. print("query displays")
  47. for d in disps:
  48. # select i2c bus if available, id otherwise
  49. if "bus" in d:
  50. d["_id"] = d["bus"]
  51. else:
  52. d["_id"] = d["id"]
  53. # get initial value
  54. d["prev"] = ddc.ddc_get(d["_id"])
  55. print("Display \"{}\" ({}) at {}".format(d["name"], d["_id"], d["prev"]))
  56. brightness = lux.read_brightness(usb)
  57. print("Brightness:", brightness)
  58. last_brightness = brightness
  59. print()
  60. print("{}: Starting main loop".format(time.ctime()))
  61. print()
  62. time_brightness = time.time()
  63. time_displays = time.time() - 8.0
  64. time_window = time.time()
  65. is_active = True
  66. is_unpaused = True
  67. while running:
  68. # read brightness at approx. 1Hz with low-pass filtering
  69. time.sleep(1.0)
  70. brightness = filter_lux(brightness, lux.read_brightness(usb))
  71. if select.select([sys.stdin, ], [], [], 0.0)[0]:
  72. line = sys.stdin.readline()
  73. print("Resetting displays")
  74. for d in disps:
  75. try:
  76. ddc.ddc_set(d["_id"], d["prev"])
  77. except Exception as e:
  78. print(e)
  79. # print brightness changes at most every 5s
  80. if (time.time() - time_brightness) > 5.0:
  81. time_brightness = time.time()
  82. if int(brightness) != last_brightness:
  83. last_brightness = int(brightness)
  84. print("{}: Brightness: {}".format(time.ctime(), last_brightness))
  85. try:
  86. influx.write("brightness,location=pc-back", "lux", brightness)
  87. for d in disps:
  88. name = '_'.join(d["name"].split())
  89. influx.write("brightness,location=" + name, "backlight", d["prev"])
  90. except:
  91. pass
  92. # check for fullscreen windows every 20s
  93. if (time.time() - time_window) > 20.0:
  94. time_window = time.time()
  95. info = window.query()
  96. if info["fullscreen"] and is_active:
  97. print("{}: App \"{}\" is now fullscreen! Pausing.".format(time.ctime(), info["name"]))
  98. if (not info["fullscreen"]) and (not is_active):
  99. print("{}: No longer fullscreen. Continuing.".format(time.ctime()))
  100. # re-apply previous brightness values soon
  101. for d in disps:
  102. d["prev"] = -1
  103. is_active = not info["fullscreen"]
  104. # set displays at most every 10s
  105. if is_active and is_unpaused and ((time.time() - time_displays) > 10.0):
  106. time_displays = time.time()
  107. for d in disps:
  108. val = lux_to_disp(d["name"], brightness)
  109. if val != d["prev"]:
  110. try:
  111. print("{}: Setting \"{}\" to {}".format(time.ctime(), d["name"], val))
  112. ddc.ddc_set(d["_id"], val)
  113. d["prev"] = val
  114. except Exception as e:
  115. print(e)
  116. # set to zero to show display is disconnected
  117. d["prev"] = -1
  118. if __name__ == "__main__":
  119. main()