app.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package core
  2. import (
  3. "time"
  4. "github.com/BurntSushi/xgb/screensaver"
  5. "github.com/BurntSushi/xgb/xproto"
  6. "github.com/brutella/hc/accessory"
  7. "github.com/brutella/hc/log"
  8. "github.com/brutella/hc/service"
  9. "github.com/bwdezend/occupancyd/internal/telemetry"
  10. "github.com/BurntSushi/xgb"
  11. "github.com/BurntSushi/xgb/dpms"
  12. )
  13. //CheckOccupied checks for x11 idle time
  14. func CheckOccupied(X *xgb.Conn, idleTimerDuration uint32, enableMetrics bool) bool {
  15. screensaver.Init(X)
  16. root := xproto.Setup(X).DefaultScreen(X).Root
  17. info, err := screensaver.QueryInfo(X, xproto.Drawable(root)).Reply()
  18. if err != nil {
  19. log.Info.Println(err)
  20. panic(err)
  21. }
  22. //log.Info.Println(info.MsSinceUserInput)
  23. if enableMetrics == true {
  24. telemetry.IdleTime.Set(float64(info.MsSinceUserInput / 1000))
  25. }
  26. if info.MsSinceUserInput < (idleTimerDuration * 1000) {
  27. return true
  28. }
  29. return false
  30. }
  31. //UpdateOccupiedStatus sets occupied status
  32. func UpdateOccupiedStatus(sensor service.OccupancySensor, idleTimerDuration uint32, sleepInterval int, enableMetrics bool) {
  33. X, err := xgb.NewConn()
  34. if err != nil {
  35. log.Info.Println(err)
  36. panic(err)
  37. }
  38. occupancyState := CheckOccupied(X, idleTimerDuration, enableMetrics)
  39. if occupancyState == true {
  40. sensor.OccupancyDetected.Int.SetValue(1)
  41. } else {
  42. sensor.OccupancyDetected.Int.SetValue(0)
  43. }
  44. for {
  45. occupied := CheckOccupied(X, idleTimerDuration, enableMetrics)
  46. if occupied != occupancyState {
  47. telemetry.OccupancyActivations.Inc()
  48. log.Info.Println("Setting occupancy to", occupied)
  49. occupancyState = occupied
  50. }
  51. if occupied == true {
  52. sensor.OccupancyDetected.Int.SetValue(1)
  53. } else {
  54. sensor.OccupancyDetected.Int.SetValue(0)
  55. }
  56. time.Sleep(time.Second * time.Duration(sleepInterval))
  57. }
  58. }
  59. //UpdateScreenStatus updates HomeKit Lightbulb screen status
  60. func UpdateScreenStatus(screen accessory.Lightbulb, sleepInterval int) error {
  61. X, err := xgb.NewConn()
  62. if err != nil {
  63. return err
  64. }
  65. screenState := CheckScreen(X)
  66. log.Info.Println("UpdateScreenStatus setting screen.Lightbulb.On.SetValue to", screenState)
  67. if screenState == true {
  68. screen.Lightbulb.On.SetValue(true)
  69. } else {
  70. screen.Lightbulb.On.SetValue(false)
  71. }
  72. for {
  73. powered := CheckScreen(X)
  74. if powered != screenState {
  75. log.Info.Println("Setting screen to", powered)
  76. screenState = powered
  77. if powered == true {
  78. screen.Lightbulb.On.SetValue(true)
  79. } else {
  80. screen.Lightbulb.On.SetValue(false)
  81. }
  82. }
  83. time.Sleep(time.Second * time.Duration(sleepInterval))
  84. }
  85. }
  86. //CheckScreen looks up the current state of DPMS
  87. func CheckScreen(X *xgb.Conn) bool {
  88. dpms.Init(X)
  89. info, err := dpms.Info(X).Reply()
  90. if err != nil {
  91. log.Info.Println("ERROR:", err)
  92. }
  93. return info.State
  94. }
  95. //SetScreenPower toggles dpms states
  96. func SetScreenPower(powerState bool) bool {
  97. telemetry.LightbulbActivations.Inc()
  98. X, err := xgb.NewConn()
  99. if err != nil {
  100. log.Info.Println(err)
  101. }
  102. dpms.Init(X)
  103. var state uint16
  104. state = 0
  105. if powerState == false {
  106. state = 3
  107. }
  108. dpms.ForceLevel(X, state)
  109. return true
  110. }