Skip to content

Commit

Permalink
feat: add brighness feature (#51)
Browse files Browse the repository at this point in the history
* direct command `brightness` (Aliases: `b`, `br`, `bright`)
* flag `-b|--brightness min|max|1-99` for `on`
* skip G602 check due to false positive
  • Loading branch information
xx4h authored Oct 14, 2024
1 parent 2644f93 commit 212b247
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 11 deletions.
74 changes: 74 additions & 0 deletions cmd/brightness.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2024 Fabian `xx4h` Sylvester
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"slices"

"github.com/rs/zerolog/log"
"github.com/spf13/cobra"

"github.com/xx4h/hctl/pkg"
o "github.com/xx4h/hctl/pkg/output"
"github.com/xx4h/hctl/pkg/util"
)

var (
brightnessRange = util.MakeRangeString(1, 99)
)

func newBrightnessCmd(h *pkg.Hctl) *cobra.Command {
cmd := &cobra.Command{
Use: "brightness [min|max|1-99]",
Short: "Change brightness",
Aliases: []string{"b", "br", "bright"},
Args: cobra.MatchAll(cobra.ExactArgs(2)),
ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return compListStates(toComplete, args, []string{"turn_on", "turn_off"}, []string{"brightness"}, "", h)
} else if len(args) == 1 {
brightnessRange = append([]string{"min", "max"}, brightnessRange...)
return brightnessRange, cobra.ShellCompDirectiveNoFileComp
}
return nil, cobra.ShellCompDirectiveDefault
},
PersistentPreRunE: func(_ *cobra.Command, args []string) error {
if err := validateBrightness(args[1]); err != nil {
return err
}
return nil
},
Run: func(_ *cobra.Command, args []string) {
c := h.GetRest()
obj, state, sub, err := c.TurnLightOnBrightness(args[0], args[1])
if err != nil {
o.PrintError(err)
} else {
o.PrintSuccessAction(obj, state)
}
log.Debug().Caller().Msgf("Result: %s(%s) to %s", obj, sub, state)
},
}

return cmd
}

func validateBrightness(brightness string) error {
if !slices.Contains(brightnessRange, brightness) && brightness != "min" && brightness != "max" {
return fmt.Errorf("brightness needs to be 1-99, or min/max")
}
return nil
}
26 changes: 24 additions & 2 deletions cmd/on.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import (
)

func newOnCmd(h *pkg.Hctl) *cobra.Command {
var brightness string

cmd := &cobra.Command{
Use: "on",
Use: "on [-b|--brightness min|max|1-99]",
Short: "Switch or turn on a light or switch",
Args: cobra.MatchAll(cobra.ExactArgs(1)),
ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
Expand All @@ -34,9 +35,21 @@ func newOnCmd(h *pkg.Hctl) *cobra.Command {
}
return compListStates(toComplete, args, []string{"turn_on"}, nil, "off", h)
},
PersistentPreRunE: func(_ *cobra.Command, _ []string) error {
if err := validateBrightness(brightness); err != nil {
return err
}
return nil
},
Run: func(_ *cobra.Command, args []string) {
c := h.GetRest()
obj, state, sub, err := c.TurnOn(args[0])
var obj, state, sub string
var err error
if brightness != "" {
obj, state, sub, err = c.TurnLightOnBrightness(args[0], brightness)
} else {
obj, state, sub, err = c.TurnOn(args[0])
}
if err != nil {
o.PrintError(err)
} else {
Expand All @@ -46,5 +59,14 @@ func newOnCmd(h *pkg.Hctl) *cobra.Command {
},
}

cmd.PersistentFlags().StringVarP(&brightness, "brightness", "b", "", "Set brightness")
err := cmd.RegisterFlagCompletionFunc("brightness", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
brightnessRange = append([]string{"min", "max"}, brightnessRange...)
return brightnessRange, cobra.ShellCompDirectiveNoFileComp
})
if err != nil {
log.Error().Msgf("Could not register flag completion func for brightness: %+v", err)
}

return cmd
}
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func newRootCmd(h *pkg.Hctl, out io.Writer, _ []string) *cobra.Command {
}

cmd.AddCommand(
newBrightnessCmd(h),
newCompletionCmd(),
newConfigCmd(h, out),
newInitCmd(h),
Expand Down
7 changes: 5 additions & 2 deletions pkg/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,14 @@ func (h *Hass) findEntity(name string, domain string, service string) (string, s
}

func (h *Hass) entityArgHandler(args []string, service string) (string, string, error) {
domain, name := splitDomainAndName(args[0])
if len(args) == 1 {
domain, name := splitDomainAndName(args[0])
return h.findEntity(name, domain, service)
} else if len(args) == 2 {
return args[0], args[1], nil
if domain == "" {
return args[0], args[1], nil // #nosec G602
}
return h.findEntity(name, domain, service)
}
return "", "", fmt.Errorf("entityArgHandler has to many entries in args: %d", len(args))
}
Expand Down
31 changes: 24 additions & 7 deletions pkg/rest/turn.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,19 @@

package rest

import "fmt"
import (
"fmt"
)

func (h *Hass) turn(state string, sub string, obj string) error {
func (h *Hass) turn(state, domain, device, brightness string) error {
// if err := h.checkEntity(sub, fmt.Sprintf("turn_%s", state), obj); err != nil {
// return err
// }

payload := map[string]any{"entity_id": fmt.Sprintf("%s.%s", sub, obj)}
res, err := h.api("POST", fmt.Sprintf("/services/%s/turn_%s", sub, state), payload)
payload := map[string]any{"entity_id": fmt.Sprintf("%s.%s", domain, device)}
if brightness != "" {
payload["brightness"] = brightness
}
res, err := h.api("POST", fmt.Sprintf("/services/%s/turn_%s", domain, state), payload)
if err != nil {
return err
}
Expand All @@ -39,15 +43,28 @@ func (h *Hass) TurnOff(args ...string) (string, string, string, error) {
if err != nil {
return "", "", "", err
}
return obj, "off", sub, h.turn("off", sub, obj)
return obj, "off", sub, h.turn("off", sub, obj, "")
}

func (h *Hass) TurnOn(args ...string) (string, string, string, error) {
sub, obj, err := h.entityArgHandler(args, "turn_on")
if err != nil {
return "", "", "", err
}
return obj, "on", sub, h.turn("on", sub, obj)
return obj, "on", sub, h.turn("on", sub, obj, "")
}

func (h *Hass) TurnLightOnBrightness(device, brightness string) (string, string, string, error) {
domain, device, err := h.entityArgHandler([]string{device}, "turn_on")
if brightness == "min" {
brightness = "1"
} else if brightness == "max" {
brightness = "99"
}
if err != nil {
return "", "", "", err
}
return device, "on", domain, h.turn("on", domain, device, brightness)
}

func (h *Hass) TurnLightOff(obj string) (string, string, string, error) {
Expand Down

0 comments on commit 212b247

Please sign in to comment.