From 3436d6c91f787b76c8ae92ba0beee74eb1e5055e Mon Sep 17 00:00:00 2001 From: Markus Pesch Date: Sun, 16 Jun 2019 20:11:10 +0200 Subject: [PATCH] fix(pkg/rgb-led): complete rgb-led pkg --- cmd/rgbled/add.go | 16 ++- cmd/rgbled/off.go | 41 +++++++ cmd/rgbled/on.go | 50 ++++++++ pkg/cli/cli.go | 2 +- pkg/config/flucky.go | 58 +++++++++ pkg/config/{option.go => options.go} | 0 pkg/led/led.go | 71 ----------- pkg/rgbled/interfaces.go | 12 ++ pkg/rgbled/led.go | 169 +++++++++++++++++++++++++++ pkg/rgbled/rgbled.go | 129 ++++++++++++++++++++ pkg/types/led.go | 82 +++++++++---- 11 files changed, 527 insertions(+), 103 deletions(-) create mode 100644 cmd/rgbled/off.go create mode 100644 cmd/rgbled/on.go rename pkg/config/{option.go => options.go} (100%) delete mode 100644 pkg/led/led.go create mode 100644 pkg/rgbled/interfaces.go create mode 100644 pkg/rgbled/led.go create mode 100644 pkg/rgbled/rgbled.go diff --git a/cmd/rgbled/add.go b/cmd/rgbled/add.go index 1f3ae09..43f5418 100644 --- a/cmd/rgbled/add.go +++ b/cmd/rgbled/add.go @@ -10,7 +10,7 @@ import ( ) var enabled bool -var location, wireID, wirePath string +var location string var addRgbLedCmd = &cobra.Command{ Use: "add", @@ -27,7 +27,7 @@ flucky rgb-led add my-led GPIO13 GPIO17 GPIO26`), } // determine gpio port - gpioRed, err := types.StringToGPIO(args[1]) + gpioBlue, err := types.StringToGPIO(args[1]) if err != nil { log.Fatalln(err) } @@ -37,7 +37,7 @@ flucky rgb-led add my-led GPIO13 GPIO17 GPIO26`), log.Fatalln(err) } - gpioBlue, err := types.StringToGPIO(args[3]) + gpioRed, err := types.StringToGPIO(args[3]) if err != nil { log.Fatalln(err) } @@ -47,10 +47,10 @@ flucky rgb-led add my-led GPIO13 GPIO17 GPIO26`), RGBLEDName: args[0], RGBLEDLocation: location, RGBLEDEnabled: enabled, - RGBLEDColorToGPIO: map[types.RGBColor]*types.GPIO{ - types.RGBLEDBlue: &gpioBlue, - types.RGBLEDGreen: &gpioGreen, - types.RGBLEDRed: &gpioRed, + BaseColorsToGPIO: map[types.BaseColor]*types.GPIO{ + types.BaseColorBlue: &gpioBlue, + types.BaseColorGreen: &gpioGreen, + types.BaseColorRed: &gpioRed, }, } @@ -73,6 +73,4 @@ func init() { addRgbLedCmd.Flags().BoolVarP(&enabled, "enabled", "e", true, "Enable Sensor") addRgbLedCmd.Flags().StringVarP(&location, "location", "l", "", "Sensor location") - addRgbLedCmd.Flags().StringVarP(&wireID, "wire-id", "i", "", "Wire-ID") - addRgbLedCmd.Flags().StringVarP(&wirePath, "wire-path", "w", "/sys/bus/w1/devices", "Wire device path") } diff --git a/cmd/rgbled/off.go b/cmd/rgbled/off.go new file mode 100644 index 0000000..f35db1b --- /dev/null +++ b/cmd/rgbled/off.go @@ -0,0 +1,41 @@ +package rgbled + +import ( + "log" + + "github.com/go-flucky/flucky/pkg/config" + "github.com/go-flucky/flucky/pkg/rgbled" + "github.com/spf13/cobra" +) + +var offRgbLedCmd = &cobra.Command{ + Use: "off", + Short: "Turn a RGB-LED color off", + Example: `flucky rgb-led off + flucky rgb-led off my-led`, + Run: func(cmd *cobra.Command, args []string) { + + // read configuration + cnf, err := config.Read(configFile) + if err != nil { + log.Fatalln(err) + } + + rgbLEDs := make([]rgbled.RGBLED, 0) + if len(args) != 0 { + rgbLEDs = cnf.GetRGBLEDsByName(args) + } else { + rgbLEDs = cnf.GetRGBLEDs(config.ENABLED) + } + + err = rgbled.Off(rgbLEDs) + if err != nil { + log.Fatalln(err) + } + + }, +} + +func init() { + rgbLedCmd.AddCommand(offRgbLedCmd) +} diff --git a/cmd/rgbled/on.go b/cmd/rgbled/on.go new file mode 100644 index 0000000..34b5b22 --- /dev/null +++ b/cmd/rgbled/on.go @@ -0,0 +1,50 @@ +package rgbled + +import ( + "log" + + "github.com/go-flucky/flucky/pkg/config" + "github.com/go-flucky/flucky/pkg/rgbled" + "github.com/go-flucky/flucky/pkg/types" + "github.com/spf13/cobra" +) + +var onRgbLedCmd = &cobra.Command{ + Use: "on", + Short: "Turn a RGB-LED color on", + Example: `flucky rgb-led on +flucky rgb-led on my-led blue +flucky rgb-led on my-led my-sweet-led white +flucky rgb-led on 1c5b9424-f6e9-4a37-be5c-77e531e94aab red`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + + // read configuration + cnf, err := config.Read(configFile) + if err != nil { + log.Fatalln(err) + } + + rgbLEDs := make([]rgbled.RGBLED, 0) + if len(args) > 1 { + rgbLEDs = cnf.GetRGBLEDsByName(args[0 : len(args)-1]) + } else { + rgbLEDs = cnf.GetRGBLEDs(config.ENABLED) + } + + color, err := types.StrintToLEDColor(args[len(args)-1]) + if err != nil { + log.Fatalln(err) + } + + err = rgbled.CustomColor(rgbLEDs, color) + if err != nil { + log.Fatalln(err) + } + + }, +} + +func init() { + rgbLedCmd.AddCommand(onRgbLedCmd) +} diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index e1ead6e..d83dd26 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -77,7 +77,7 @@ func PrintRGBLEDs(cnf *config.Configuration, w io.Writer) { fmt.Fprintln(tw, "name\tlocation\tblue\tgreen\tred\tenabled") for _, rgbled := range cnf.RGBLEDs { - fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%v\n", rgbled.RGBLEDName, rgbled.RGBLEDLocation, *rgbled.RGBLEDColorToGPIO[types.RGBLEDBlue], *rgbled.RGBLEDColorToGPIO[types.RGBLEDGreen], *rgbled.RGBLEDColorToGPIO[types.RGBLEDRed], rgbled.RGBLEDEnabled) + fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%v\n", rgbled.RGBLEDName, rgbled.RGBLEDLocation, *rgbled.BaseColorsToGPIO[types.BaseColorBlue], *rgbled.BaseColorsToGPIO[types.BaseColorGreen], *rgbled.BaseColorsToGPIO[types.BaseColorRed], rgbled.RGBLEDEnabled) } tw.Flush() diff --git a/pkg/config/flucky.go b/pkg/config/flucky.go index 85aa4a5..267d7f3 100644 --- a/pkg/config/flucky.go +++ b/pkg/config/flucky.go @@ -5,6 +5,7 @@ import ( "time" + "github.com/go-flucky/flucky/pkg/rgbled" "github.com/go-flucky/flucky/pkg/sensor" "github.com/go-flucky/flucky/pkg/types" @@ -308,6 +309,51 @@ func (c *Configuration) GetHumiditySensorsByName(names []string) []sensor.Humidi return c.convertHumiditySensors(humiditySensors) } +func (c *Configuration) GetRGBLEDs(option Option) []rgbled.RGBLED { + rgbLEDs := c.RGBLEDs + + switch option { + case ENABLED: + for i, rgbLED := range c.RGBLEDs { + if !rgbLED.RGBLEDEnabled { + rgbLEDs = append(rgbLEDs[:i], rgbLEDs[i+1:]...) + } + } + return c.convertRGBLEDs(rgbLEDs) + case DISABLED: + for i, rgbLED := range c.RGBLEDs { + if rgbLED.RGBLEDEnabled { + rgbLEDs = append(rgbLEDs[:i], rgbLEDs[i+1:]...) + } + } + return c.convertRGBLEDs(rgbLEDs) + default: + return c.convertRGBLEDs(rgbLEDs) + } +} + +func (c *Configuration) GetRGBLEDsByName(names []string) []rgbled.RGBLED { + configRGBLEDs := make(map[string]*types.RGBLED, 0) + + for _, name := range names { + for _, led := range c.RGBLEDs { + switch name { + case led.RGBLEDID: + configRGBLEDs[led.RGBLEDID] = led + case led.RGBLEDName: + configRGBLEDs[led.RGBLEDID] = led + } + } + } + + rgbLEDs := make([]*types.RGBLED, 0) + for _, rgbLED := range configRGBLEDs { + rgbLEDs = append(rgbLEDs, rgbLED) + } + + return c.convertRGBLEDs(rgbLEDs) +} + // GetTemperatureSensors returns a list of temperature sensors func (c *Configuration) GetTemperatureSensors(option Option) []sensor.TemperatureSensor { temperatureSensors := c.getTemperatureSensors() @@ -457,6 +503,18 @@ func (c *Configuration) convertHumiditySensors(sensors []*types.Sensor) []sensor return humiditySensors } +func (c *Configuration) convertRGBLEDs(rgbLEDs []*types.RGBLED) []rgbled.RGBLED { + leds := make([]rgbled.RGBLED, 0) + + for _, rgbLED := range rgbLEDs { + leds = append(leds, &rgbled.LED{ + RGBLED: rgbLED, + }) + } + + return leds +} + func (c *Configuration) convertTemperatureSensors(sensors []*types.Sensor) []sensor.TemperatureSensor { temperatureSensors := make([]sensor.TemperatureSensor, 0) diff --git a/pkg/config/option.go b/pkg/config/options.go similarity index 100% rename from pkg/config/option.go rename to pkg/config/options.go diff --git a/pkg/led/led.go b/pkg/led/led.go deleted file mode 100644 index c489181..0000000 --- a/pkg/led/led.go +++ /dev/null @@ -1,71 +0,0 @@ -package led - -import ( - "fmt" - - "github.com/go-flucky/flucky/pkg/types" - "github.com/stianeikeland/go-rpio" -) - -type LED interface { - On() error - Off() error - Toggel() error -} - -type RGBLED struct { - *types.LED -} - -func (l *RGBLED) On() error { - if err := rpio.Open(); err != nil { - return fmt.Errorf("Can not open rpio: %v", err) - } - defer rpio.Close() - - gpio, err := types.GPIOToInt(*l.GPIONumber) - if err != nil { - return fmt.Errorf("Can not determine %v into integer: %v", l.GPIONumber, err) - } - - pin := rpio.Pin(gpio) - pin.High() - - return nil -} - -func (l *RGBLED) Off() error { - - if err := rpio.Open(); err != nil { - return fmt.Errorf("Can not open rpio: %v", err) - } - defer rpio.Close() - - gpio, err := types.GPIOToInt(*l.GPIONumber) - if err != nil { - return fmt.Errorf("Can not determine %v into integer: %v", l.GPIONumber, err) - } - - pin := rpio.Pin(gpio) - pin.Low() - - return nil -} - -func (l *RGBLED) Toggel() error { - - if err := rpio.Open(); err != nil { - return fmt.Errorf("Can not open rpio: %v", err) - } - defer rpio.Close() - - gpio, err := types.GPIOToInt(*l.GPIONumber) - if err != nil { - return fmt.Errorf("Can not determine %v into integer: %v", l.GPIONumber, err) - } - - pin := rpio.Pin(gpio) - pin.Toggle() - - return nil -} diff --git a/pkg/rgbled/interfaces.go b/pkg/rgbled/interfaces.go new file mode 100644 index 0000000..b5eb08f --- /dev/null +++ b/pkg/rgbled/interfaces.go @@ -0,0 +1,12 @@ +package rgbled + +type RGBLED interface { + Blue(on bool) error + Green(on bool) error + Off() error + Purple(on bool) error + Red(on bool) error + Turquoise(on bool) error + White(on bool) error + Yellow(on bool) error +} diff --git a/pkg/rgbled/led.go b/pkg/rgbled/led.go new file mode 100644 index 0000000..3967c9f --- /dev/null +++ b/pkg/rgbled/led.go @@ -0,0 +1,169 @@ +package rgbled + +import ( + "fmt" + + "github.com/go-flucky/flucky/pkg/types" + "github.com/stianeikeland/go-rpio" +) + +type LED struct { + *types.RGBLED +} + +func (l *LED) Blue(on bool) error { + gpios := []*types.GPIO{ + l.BaseColorsToGPIO[types.BaseColorBlue], + } + + if err := l.Off(); err != nil { + return err + } + + if err := l.operate(gpios, on); err != nil { + return fmt.Errorf("Can not operate with GPIOs: %v", err) + } + + return nil +} + +func (l *LED) Green(on bool) error { + + gpios := []*types.GPIO{ + l.BaseColorsToGPIO[types.BaseColorGreen], + } + + if err := l.Off(); err != nil { + return err + } + + if err := l.operate(gpios, on); err != nil { + return fmt.Errorf("Can not operate with GPIOs: %v", err) + } + + return nil + +} + +func (l *LED) Off() error { + + gpios := []*types.GPIO{ + l.BaseColorsToGPIO[types.BaseColorBlue], + l.BaseColorsToGPIO[types.BaseColorGreen], + l.BaseColorsToGPIO[types.BaseColorRed], + } + + if err := l.operate(gpios, false); err != nil { + return fmt.Errorf("Can not turn GPIOs off: %v", err) + } + + return nil +} + +func (l *LED) Purple(on bool) error { + gpios := []*types.GPIO{ + l.BaseColorsToGPIO[types.BaseColorBlue], + l.BaseColorsToGPIO[types.BaseColorRed], + } + + if err := l.Off(); err != nil { + return err + } + + if err := l.operate(gpios, on); err != nil { + return fmt.Errorf("Can not operate with GPIOs: %v", err) + } + + return nil +} + +func (l *LED) Red(on bool) error { + gpios := []*types.GPIO{ + l.BaseColorsToGPIO[types.BaseColorRed], + } + + if err := l.Off(); err != nil { + return err + } + + if err := l.operate(gpios, on); err != nil { + return fmt.Errorf("Can not operate with GPIOs: %v", err) + } + + return nil +} + +func (l *LED) Turquoise(on bool) error { + gpios := []*types.GPIO{ + l.BaseColorsToGPIO[types.BaseColorBlue], + l.BaseColorsToGPIO[types.BaseColorGreen], + } + + if err := l.Off(); err != nil { + return err + } + + if err := l.operate(gpios, on); err != nil { + return fmt.Errorf("Can not operate with GPIOs: %v", err) + } + + return nil +} + +func (l *LED) White(on bool) error { + gpios := []*types.GPIO{ + l.BaseColorsToGPIO[types.BaseColorBlue], + l.BaseColorsToGPIO[types.BaseColorGreen], + l.BaseColorsToGPIO[types.BaseColorRed], + } + + if err := l.Off(); err != nil { + return err + } + + if err := l.operate(gpios, on); err != nil { + return fmt.Errorf("Can not operate with GPIOs: %v", err) + } + + return nil +} + +func (l *LED) Yellow(on bool) error { + gpios := []*types.GPIO{ + l.BaseColorsToGPIO[types.BaseColorGreen], + l.BaseColorsToGPIO[types.BaseColorRed], + } + + if err := l.Off(); err != nil { + return err + } + + if err := l.operate(gpios, on); err != nil { + return fmt.Errorf("Can not operate with GPIOs: %v", err) + } + + return nil +} + +func (l *LED) operate(gpios []*types.GPIO, on bool) error { + if err := rpio.Open(); err != nil { + return fmt.Errorf("Cam not open rpio connection: %v", err) + } + defer rpio.Close() + + for _, gpio := range gpios { + gpioInt, err := types.GPIOToInt(*gpio) + if err != nil { + return fmt.Errorf("Can not determine %v into integer: %v", gpio, err) + } + + pin := rpio.Pin(gpioInt) + + if on { + pin.High() + } else { + pin.Low() + } + } + return nil +} diff --git a/pkg/rgbled/rgbled.go b/pkg/rgbled/rgbled.go new file mode 100644 index 0000000..c1af8d6 --- /dev/null +++ b/pkg/rgbled/rgbled.go @@ -0,0 +1,129 @@ +package rgbled + +import ( + "sync" + + "github.com/go-flucky/flucky/pkg/internal/collect" + "github.com/go-flucky/flucky/pkg/internal/prittyprint" + "github.com/go-flucky/flucky/pkg/types" +) + +func Blue(rgbLEDs []RGBLED) error { + color := types.LEDColorBlue + if err := operate(rgbLEDs, true, color); err != nil { + return err + } + return nil +} + +func CustomColor(rgbLEDs []RGBLED, color types.LEDColor) error { + if err := operate(rgbLEDs, true, color); err != nil { + return err + } + return nil +} + +func Green(rgbLEDs []RGBLED) error { + color := types.LEDColorGreen + if err := operate(rgbLEDs, true, color); err != nil { + return err + } + return nil +} + +func Off(rgbLEDs []RGBLED) error { + color := types.LEDColorNone + if err := operate(rgbLEDs, false, color); err != nil { + return err + } + return nil +} + +func Purple(rgbLEDs []RGBLED) error { + color := types.LEDColorPurple + if err := operate(rgbLEDs, true, color); err != nil { + return err + } + return nil +} + +func Red(rgbLEDs []RGBLED) error { + color := types.LEDColorRed + if err := operate(rgbLEDs, true, color); err != nil { + return err + } + return nil +} + +func Turquoise(rgbLEDs []RGBLED) error { + color := types.LEDColorTurquoise + if err := operate(rgbLEDs, true, color); err != nil { + return err + } + return nil +} + +func White(rgbLEDs []RGBLED) error { + color := types.LEDColorWhite + if err := operate(rgbLEDs, true, color); err != nil { + return err + } + return nil +} + +func Yellow(rgbLEDs []RGBLED) error { + color := types.LEDColorYellow + if err := operate(rgbLEDs, true, color); err != nil { + return err + } + return nil +} + +func operate(rgbLEDs []RGBLED, on bool, color types.LEDColor) error { + + errorChannel := make(chan error, len(rgbLEDs)) + + wg := new(sync.WaitGroup) + wg.Add(len(rgbLEDs)) + + for _, rgbLED := range rgbLEDs { + go func(rgbLED RGBLED, color types.LEDColor, on bool, errorChannel chan<- error, wg *sync.WaitGroup) { + defer wg.Done() + + var err error + + switch color { + case types.LEDColorBlue: + err = rgbLED.Blue(on) + case types.LEDColorGreen: + err = rgbLED.Green(on) + case types.LEDColorPurple: + err = rgbLED.Purple(on) + case types.LEDColorNone: + err = rgbLED.Off() + case types.LEDColorRed: + err = rgbLED.Red(on) + case types.LEDColorTurquoise: + err = rgbLED.Turquoise(on) + case types.LEDColorWhite: + err = rgbLED.White(on) + case types.LEDColorYellow: + err = rgbLED.Yellow(on) + default: + err = rgbLED.Off() + } + + if err != nil { + errorChannel <- err + } + }(rgbLED, color, on, errorChannel, wg) + } + + wg.Wait() + + errors := collect.Errors(errorChannel) + if len(errors) > 0 { + return prittyprint.FormatErrors(errors) + } + return nil +} diff --git a/pkg/types/led.go b/pkg/types/led.go index daf5708..0268018 100644 --- a/pkg/types/led.go +++ b/pkg/types/led.go @@ -1,6 +1,9 @@ package types -import "time" +import ( + "fmt" + "time" +) type LED struct { LEDID string `json:"led_id"` @@ -14,39 +17,74 @@ type LED struct { } type RGBLED struct { - RGBLEDID string `json:"rgbled_id"` - RGBLEDName string `json:"rgbled_name"` - RGBLEDLocation string `json:"rgbled_location"` - RGBLEDColorToGPIO map[RGBColor]*GPIO `json:"color_to_gpio"` - RGBLEDEnabled bool `json:"rgbled_enabled"` - DeviceID string `json:"device_id"` - CreationDate time.Time `json:"creation_date"` + RGBLEDID string `json:"rgbled_id"` + RGBLEDName string `json:"rgbled_name"` + RGBLEDLocation string `json:"rgbled_location"` + BaseColorsToGPIO map[BaseColor]*GPIO `json:"color_to_gpio"` + ActionMapping map[LEDOption]LEDColor `json:"action_mapping"` + RGBLEDEnabled bool `json:"rgbled_enabled"` + DeviceID string `json:"device_id"` + CreationDate time.Time `json:"creation_date"` } -type RGBColor string +type BaseColor string const ( - RGBLEDBlue RGBColor = "blue" - RGBLEDRed = "red" - RGBLEDGreen = "green" + BaseColorBlue BaseColor = "blue" + BaseColorRed BaseColor = "red" + BaseColorGreen BaseColor = "green" ) type LEDColor string const ( - LEDBlue LEDColor = "blue" - LEDRed = "red" - LEDGreen = "green" - LEDPurple = "purple" - LEDTurquoiseGravel = "turquoise gravel" - LEDYellow = "yellow" - LEDWhite = "white" + LEDColorBlue LEDColor = "blue" + LEDColorGreen LEDColor = "green" + LEDColorNone LEDColor = "none" + LEDColorPurple LEDColor = "purple" + LEDColorRed LEDColor = "red" + LEDColorTurquoise LEDColor = "turquoise" + LEDColorYellow LEDColor = "yellow" + LEDColorWhite LEDColor = "white" ) +func StrintToLEDColor(color string) (LEDColor, error) { + switch color { + case "blue": + return LEDColorBlue, nil + case "red": + return LEDColorRed, nil + case "green": + return LEDColorGreen, nil + case "none": + return LEDColorNone, nil + case "purple": + return LEDColorPurple, nil + case "turquoise": + return LEDColorTurquoise, nil + case "yellow": + return LEDColorYellow, nil + case "white": + return LEDColorWhite, nil + default: + return LEDColorNone, fmt.Errorf("Can not convert color to const") + } +} + type LEDOption string const ( - LEDError LEDOption = "error" - LEDWarn = "warn" - LEDOk = "ok" + LEDError LEDOption = "error" + LEDWarn = "warn" + LEDOk = "ok" + LEDSync = "sync" + LEDLogfile = "logfile" ) + +var DefaultActionMapping = map[LEDOption]LEDColor{ + LEDError: LEDColorRed, + LEDWarn: LEDColorYellow, + LEDOk: LEDColorGreen, + LEDSync: LEDColorTurquoise, + LEDLogfile: LEDColorBlue, +}