rgb.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. intdevice "netdome.biz/paul/impact-80/internal/device"
  6. intrgb "netdome.biz/paul/impact-80/internal/rgb"
  7. "netdome.biz/paul/impact-80/internal/via"
  8. )
  9. type zoneProtocol interface {
  10. SetValue(via.LEDType, uint8, uint8) error
  11. SetColor(via.LEDType, uint8, uint8) error
  12. }
  13. type rgbProtocol interface {
  14. zoneProtocol
  15. GetValue(via.LEDType, uint8) ([]byte, error)
  16. Close() error
  17. }
  18. var openRGBProtocol = func() (rgbProtocol, error) {
  19. return OpenDevice()
  20. }
  21. func forEachSelectedZone(zones []intrgb.Zone, fn func(intrgb.Zone, via.LEDType) error) error {
  22. channels := zoneChannels(zones)
  23. for i, zone := range zones {
  24. if err := fn(zone, channels[i]); err != nil {
  25. return err
  26. }
  27. }
  28. return nil
  29. }
  30. func setValueOnZones(proto zoneProtocol, zones []intrgb.Zone, param, value uint8) error {
  31. return forEachSelectedZone(zones, func(_ intrgb.Zone, channel via.LEDType) error {
  32. return proto.SetValue(channel, param, value)
  33. })
  34. }
  35. func setBrightnessOnZones(proto zoneProtocol, zones []intrgb.Zone, value uint8) error {
  36. return setValueOnZones(proto, zones, uint8(intrgb.Brightness), value)
  37. }
  38. func setSpeedOnZones(proto zoneProtocol, zones []intrgb.Zone, value uint8) error {
  39. return setValueOnZones(proto, zones, uint8(intrgb.Speed), value)
  40. }
  41. func setColorOnZones(proto zoneProtocol, zones []intrgb.Zone, hue, saturation uint8) error {
  42. return forEachSelectedZone(zones, func(_ intrgb.Zone, channel via.LEDType) error {
  43. return proto.SetColor(channel, hue, saturation)
  44. })
  45. }
  46. func disableLightingOnZones(proto zoneProtocol, zones []intrgb.Zone) error {
  47. return forEachSelectedZone(zones, func(_ intrgb.Zone, channel via.LEDType) error {
  48. if err := proto.SetValue(channel, uint8(intrgb.EffectID), 0); err != nil {
  49. return err
  50. }
  51. return proto.SetValue(channel, uint8(intrgb.Brightness), 0)
  52. })
  53. }
  54. func enableLightingOnZones(proto zoneProtocol, zones []intrgb.Zone) error {
  55. return forEachSelectedZone(zones, func(zone intrgb.Zone, channel via.LEDType) error {
  56. if err := proto.SetValue(channel, uint8(intrgb.EffectID), intrgb.DefaultEffect(zone)); err != nil {
  57. return err
  58. }
  59. return proto.SetValue(channel, uint8(intrgb.Brightness), 160)
  60. })
  61. }
  62. func setModeOnZones(proto zoneProtocol, zones []intrgb.Zone, value uint8) error {
  63. return setValueOnZones(proto, zones, uint8(intrgb.EffectID), value)
  64. }
  65. // OpenDevice discovers the connected QMK keyboards and opens the one selected
  66. // by --device. Without --device it only proceeds when exactly one keyboard is
  67. // connected, so a command can never hit an unintended keyboard.
  68. func OpenDevice() (*via.Protocol, error) {
  69. if _, err := selectedZones(); err != nil {
  70. return nil, err
  71. }
  72. devices, err := intdevice.DiscoverAll()
  73. if err != nil {
  74. return nil, fmt.Errorf("discover: %w", err)
  75. }
  76. dev, err := selectDevice(devices, targetDevice)
  77. if err != nil {
  78. return nil, err
  79. }
  80. proto, err := via.New(dev)
  81. if err != nil {
  82. return nil, fmt.Errorf("open protocol: %w", err)
  83. }
  84. return proto, nil
  85. }
  86. func lightingEnabled(mode, brightness uint8) bool {
  87. return mode != 0 && brightness > 0
  88. }
  89. func ParseUint8(s string) (uint8, error) {
  90. v, err := strconv.ParseUint(s, 10, 8)
  91. if err != nil {
  92. return 0, fmt.Errorf("invalid value: %w", err)
  93. }
  94. return uint8(v), nil
  95. }