info.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package rgb
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/spf13/cobra"
  7. intrgb "github.com/wobkey/rgb/internal/rgb"
  8. "github.com/wobkey/rgb/internal/via"
  9. )
  10. type infoGetter interface {
  11. GetValue(via.LEDType, uint8) ([]byte, error)
  12. }
  13. type infoColor struct {
  14. Hue uint8 `json:"hue"`
  15. Saturation uint8 `json:"saturation"`
  16. }
  17. type zoneInfo struct {
  18. Zone intrgb.Zone `json:"zone"`
  19. Channel uint8 `json:"channel"`
  20. Enabled bool `json:"enabled"`
  21. Effect string `json:"effect"`
  22. EffectID uint8 `json:"effectId"`
  23. Brightness uint8 `json:"brightness"`
  24. Speed uint8 `json:"speed"`
  25. Color infoColor `json:"color"`
  26. Error string `json:"error,omitempty"`
  27. }
  28. type infoOutput struct {
  29. Enabled bool `json:"enabled"`
  30. Mode string `json:"mode"`
  31. Brightness uint8 `json:"brightness"`
  32. Speed uint8 `json:"speed"`
  33. Zones []zoneInfo `json:"zones"`
  34. }
  35. func readInfo(proto infoGetter, zones []intrgb.Zone) (infoOutput, error) {
  36. out := infoOutput{Zones: make([]zoneInfo, 0, len(zones))}
  37. var queryErrors []error
  38. for _, zone := range zones {
  39. record, err := readZoneInfo(proto, zone)
  40. out.Zones = append(out.Zones, record)
  41. if err != nil {
  42. queryErrors = append(queryErrors, err)
  43. }
  44. }
  45. if len(out.Zones) > 0 {
  46. first := out.Zones[0]
  47. out.Enabled = first.Enabled
  48. out.Mode = first.Effect
  49. out.Brightness = first.Brightness
  50. out.Speed = first.Speed
  51. }
  52. return out, errors.Join(queryErrors...)
  53. }
  54. func readZoneInfo(proto infoGetter, zone intrgb.Zone) (zoneInfo, error) {
  55. record := zoneInfo{Zone: zone, Channel: zone.Channel()}
  56. channel := via.LEDType(zone.Channel())
  57. brightness, err := getInfoValue(proto, channel, uint8(intrgb.Brightness), 1)
  58. if err != nil {
  59. record.Error = err.Error()
  60. return record, err
  61. }
  62. record.Brightness = brightness[0]
  63. effect, err := getInfoValue(proto, channel, uint8(intrgb.EffectID), 1)
  64. if err != nil {
  65. record.Error = err.Error()
  66. return record, err
  67. }
  68. record.EffectID = effect[0]
  69. record.Effect = intrgb.EffectName(zone, record.EffectID)
  70. record.Enabled = lightingEnabled(record.EffectID, record.Brightness)
  71. speed, err := getInfoValue(proto, channel, uint8(intrgb.Speed), 1)
  72. if err != nil {
  73. record.Error = err.Error()
  74. return record, err
  75. }
  76. record.Speed = speed[0]
  77. color, err := getInfoValue(proto, channel, uint8(intrgb.ColorValue), 2)
  78. if err != nil {
  79. record.Error = err.Error()
  80. return record, err
  81. }
  82. record.Color = infoColor{Hue: color[0], Saturation: color[1]}
  83. return record, nil
  84. }
  85. func getInfoValue(proto infoGetter, channel via.LEDType, param uint8, size int) ([]byte, error) {
  86. value, err := proto.GetValue(channel, param)
  87. if err != nil {
  88. return nil, err
  89. }
  90. if len(value) < size {
  91. return nil, fmt.Errorf("short value response: got %d, want %d", len(value), size)
  92. }
  93. return value, nil
  94. }
  95. func NewInfoCmd() *cobra.Command {
  96. return &cobra.Command{
  97. Use: "info",
  98. Short: "Show current RGB state",
  99. RunE: func(cmd *cobra.Command, args []string) error {
  100. zones, err := selectedZones()
  101. if err != nil {
  102. return err
  103. }
  104. proto, err := openRGBProtocol()
  105. if err != nil {
  106. return err
  107. }
  108. defer proto.Close()
  109. out, queryErr := readInfo(proto, zones)
  110. data, err := json.MarshalIndent(out, "", " ")
  111. if err != nil {
  112. return err
  113. }
  114. fmt.Fprintln(cmd.OutOrStdout(), string(data))
  115. return queryErr
  116. },
  117. }
  118. }