Skip to content

Commit

Permalink
Update color utils
Browse files Browse the repository at this point in the history
  • Loading branch information
apoclyps committed Oct 4, 2020
1 parent 85cb3e6 commit e2cbf5f
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 71 deletions.
25 changes: 21 additions & 4 deletions cmd/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,30 @@ var deviceCmd = &cobra.Command{
}

// device will validate the IP address for a single device (if provided) otherwise
// defaults to using all devices available on the local network.
// defaults to using all devices available on the local network.
// The color is set for one or more device's using either an exact match for
// a hex value or the name of a color preset.
func device(ip string, hex string, name string, args []string) error {
color, err := lights.GetColor(hex, name)
if err != nil {
return err
var color lights.Color

if hex != "" {
cv, err := lights.NewValue(hex)
if err != nil {
return err
}
color, err = cv.GetColorByHex()
if err != nil {
return err
}
} else if name != "" {
cv, err := lights.NewValue(hex)
if err != nil {
return err
}
color, err = cv.GetColorByName()
if err != nil {
return err
}
}

if ip != "" && !magichome.IsPrivateIpv4(ip) {
Expand Down
27 changes: 19 additions & 8 deletions cmd/scene.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var sceneCmd = &cobra.Command{
},
}

func createColorArray(c lights.Color, iterations int) []lights.Color {
func createColors(c lights.Color, iterations int) ([]lights.Color, error) {
var arr []lights.Color

var r uint8 = c.R
Expand All @@ -40,30 +40,41 @@ func createColorArray(c lights.Color, iterations int) []lights.Color {
if c.B == 255 {
b = c.B - 200
}
var w uint8 = c.W

modifiedColor := lights.Color{R: r, G: g, B: b, W: c.W}
modifiedColor, err := lights.NewColor(r, g, b, w)
if err != nil {
return nil, err
}
for i := 0; i < iterations; i++ {
arr = append(arr, c)
arr = append(arr, modifiedColor)
}
arr = append(arr, c)

return arr
return arr, nil
}

func scene(ip string, colorName string, args []string) error {
c, err := lights.GetColorByName(colorName)
func scene(ip string, name string, args []string) error {
cv, err := lights.NewValue(name)
if err != nil {
return err
}
c, err := cv.GetColorByName()
if err != nil {
return err
}

colorArray := createColorArray(c, 3)
colors, err := createColors(c, 3)
if err != nil {
return err
}

if ip != "" && !magichome.IsPrivateIpv4(ip) {
fmt.Printf("Error while validating ip: %s", ip)
return fmt.Errorf("error while validating ip: %s", ip)
} else if ip != "" {
for _, color := range colorArray {
for _, color := range colors {
d, err := magichome.NewDevice(net.ParseIP(ip), "", "", "")
if err != nil {
fmt.Println(err)
Expand All @@ -85,7 +96,7 @@ func scene(ip string, colorName string, args []string) error {
var iterations uint8 = 3
var delay time.Duration = 250 * time.Millisecond

s := magichome.NewScene(devices, colorArray, iterations, delay)
s := magichome.NewScene(devices, colors, iterations, delay)
if err := s.Play(); err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions examples/scene/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ func main() {
Timeout: 3,
})

var colorArray = []lights.Color{
var colors = []lights.Color{
lights.Blue(),
lights.Red(),
lights.Blue(),
}
var iterations uint8 = 3
var delay time.Duration = 250 * time.Millisecond

s := magichome.NewScene(devices, colorArray, iterations, delay)
s := magichome.NewScene(devices, colors, iterations, delay)
if err := s.Play(); err != nil {
fmt.Printf("Error %+v", err)
os.Exit(1)
Expand Down
54 changes: 54 additions & 0 deletions pkg/lights/color.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package lights

type InvalidColorError struct {
color string
msg string
}

func (err *InvalidColorError) Error() string {
return err.msg
}

type InvalidColorValue struct {
value uint8
msg string
}

func (err *InvalidColorValue) Error() string {
return err.msg
}

// Color represents a RGBW color
type Color struct {
R uint8
G uint8
B uint8
W uint8
}

// NewColor initializes a new Color using valid RGBW values (between 0 - 255).
func NewColor(r uint8, g uint8, b uint8, w uint8) (Color, error) {
var color Color

if r > 255 {
return color, &InvalidColorValue{r, "Red value is not within range. e.g. Value must be between 0 - 255"}
}
if g > 255 {
return color, &InvalidColorValue{r, "Green value is not within range. e.g. Value must be between 0 - 255"}
}
if b > 255 {
return color, &InvalidColorValue{r, "Blue value is not within range. e.g. Value must be between 0 - 255"}
}
if w > 255 {
return color, &InvalidColorValue{r, "White value is not within range. e.g. Value must be between 0 - 255"}
}

color = Color{
R: r,
G: g,
B: b,
W: w,
}

return color, nil
}
8 changes: 0 additions & 8 deletions pkg/lights/presets.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
package lights

// Color represents a RGBW color
type Color struct {
R uint8
G uint8
B uint8
W uint8
}

// A White light
func White() Color {
return Color{R: 255, G: 255, B: 255, W: 0}
Expand Down
82 changes: 33 additions & 49 deletions pkg/lights/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"gopkg.in/go-playground/colors.v1"
)

type invalidColorError struct {
color string
type InvalidHexValue struct {
value string
msg string
}

func (ir *invalidColorError) Error() string {
return ir.msg
func (err *InvalidHexValue) Error() string {
return err.msg
}

func reverseMap(m map[string]string) map[string]string {
Expand All @@ -29,72 +29,56 @@ func validHexPrefix(hex string) bool {
return hex[0] == '#'
}

func HexToColor(hex string) Color {
func HexToColor(hex string) (Color, error) {
var color Color

if !validHexPrefix(hex) {
hex = "#" + hex
} else {
return color, &InvalidHexValue{hex, "Hex Value is invalid"}
}

hexColor, _ := colors.ParseHEX(hex)
rgba := hexColor.ToRGBA()
return Color{R: rgba.R, G: rgba.G, B: rgba.B, W: uint8(rgba.A * 100)}

color, err := NewColor(
rgba.R,
rgba.G,
rgba.B,
uint8(rgba.A*100),
)
if err != nil {
return color, &InvalidHexValue{hex, "Hex Value is invalid"}
}

return color, nil
}

func lookupColorByName(color string) (*Color, *invalidColorError) {
func lookupColorByName(color string) (*Color, *InvalidColorError) {
content, err := ioutil.ReadFile("colors.min.json")

if err != nil {
fmt.Printf("Error while reading a file %v", err)
}
var hexMap map[string]string
_ = json.Unmarshal(content, &hexMap)
var hexes map[string]string
_ = json.Unmarshal(content, &hexes)

colorMap := reverseMap(hexMap)
hex, ok := colorMap[string(color)]
names := reverseMap(hexes)
hex, ok := names[string(color)]
if !ok {
return nil, &invalidColorError{color, "Color is invalid"}
return nil, &InvalidColorError{color, "Color is invalid"}
}
h, err := HexToColor(hex)
if err != nil {
return nil, &InvalidColorError{color, "Color is invalid"}
}
h := HexToColor(hex)
return &h, nil
}

func lookupPrimaryColor(color string) (*Color, *invalidColorError) {
func lookupPrimaryColor(color string) (*Color, *InvalidColorError) {
c, ok := ColorPresets[color]
if !ok {
return nil, &invalidColorError{color, "Color is invalid"}
return nil, &InvalidColorError{color, "Color is invalid"}
}
return &c, nil
}

func GetColorByName(name string) (Color, error) {
if name != "" {
cn, _ := lookupColorByName(name)
if cn != nil {
return *cn, nil
}

cl, err := lookupPrimaryColor(name)
if err != nil {
fmt.Println(err)
return White(), err
}
return *cl, nil
}
return White(), nil
}

func GetColor(hex string, name string) (color Color, err error) {
if hex != "" {
color = HexToColor(hex)
return color, nil
}

if color, err = GetColorByName(name); err != nil {
return color, err
}

if color != (Color{}) {
return color, nil
}

return White(), nil
}
49 changes: 49 additions & 0 deletions pkg/lights/value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package lights

// Value represents the string value used to present a color.
type Value struct {
value string
}

// NewValue initialize a string or hex representation of a Color
func NewValue(value string) (Value, error) {
return Value{value: value}, nil
}

// GetColorByHex attempt's to find a matching Color using the value as a hex value.
func (c *Value) GetColorByHex() (Color, error) {
var color Color

if c.value != "" {
color, err := HexToColor(c.value)
if err == nil {
return color, nil
}
}

return color, &InvalidColorError{c.value, "Value is invalid"}
}

// GetColorByName attempt's to find a matching Color using the value as a color preset.
func (c *Value) GetColorByName() (Color, error) {
var color Color

if c.value == "" {
return color, &InvalidColorError{c.value, "Value is invalid"}
}

cn, _ := lookupColorByName(c.value)
if cn != nil {
return *cn, nil
}

cl, err := lookupPrimaryColor(c.value)
if err != nil {
return *cl, &InvalidColorError{c.value, "Value is invalid"}
}
if cl != nil {
return *cl, nil
}

return color, &InvalidColorError{c.value, "Value is invalid"}
}

0 comments on commit e2cbf5f

Please sign in to comment.