diff --git a/internal/cli/commands.go b/internal/cli/commands.go index 75e06c8..b1d8f1d 100644 --- a/internal/cli/commands.go +++ b/internal/cli/commands.go @@ -2,12 +2,15 @@ package cli import ( "context" + "encoding/json" "errors" "fmt" + "os" "strconv" "strings" "time" + "github.com/amimof/huego" "github.com/davecgh/go-spew/spew" "git.tcp.direct/kayos/ziggs/internal/ziggy" @@ -177,7 +180,7 @@ func cmdDelete(br *ziggy.Bridge, args []string) error { return strings.ToLower(input) == "y" } switch args[0] { - case "light": + case "light", "l": t, err := br.FindLight(args[1]) if err != nil { return err @@ -185,7 +188,7 @@ func cmdDelete(br *ziggy.Bridge, args []string) error { if confirm() { return br.DeleteLight(t.ID) } - case "group": + case "group", "g": t, err := br.FindGroup(args[1]) if err != nil { return err @@ -250,6 +253,98 @@ func cmdRename(br *ziggy.Bridge, args []string) error { return target.Rename(args[2]) } +// cmdDump exports a target object to a JSON file +func cmdDump(br *ziggy.Bridge, args []string) error { + if len(args) < 2 && args[0] != "all" { + return errors.New("not enough arguments") + } + var ( + target interface{} + name string + err error + ) + switch args[0] { + case "light", "l": + target, err = br.FindLight(args[1]) + name = target.(*huego.Light).Name + case "group", "g": + target, err = br.FindGroup(args[1]) + name = target.(*huego.Group).Name + case "schedule": + return errors.New("not implemented") + case "rule": + return errors.New("not implemented") + case "sensor": + return errors.New("not implemented") + case "bridge", "all": + target = br + name = br.Info.Name + default: + return errors.New("invalid target type") + } + if err != nil { + return err + } + if js, err := json.Marshal(target); err != nil { + return err + } else { + return os.WriteFile(name, js, 0o666) + } + +} + +// cmdLoad imports a target JSON object and attempts to apply it to an existing object +func cmdLoad(br *ziggy.Bridge, args []string) error { + if len(args) < 1 { + return errors.New("not enough arguments") + } + js, err := os.ReadFile(args[1]) + if err != nil { + return err + } + switch args[0] { + case "light", "l": + target, err := br.FindLight(args[1]) + if err != nil { + return err + } + var l *huego.Light + if err := json.Unmarshal(js, &l); err != nil { + return err + } + if resp, err := br.UpdateLight(target.ID, *l); err != nil { + return err + } else { + log.Info().Msgf("%v", resp) + } + case "group", "g": + target, err := br.FindGroup(args[1]) + if err != nil { + return err + } + var g *huego.Group + if err := json.Unmarshal(js, &g); err != nil { + return err + } + if resp, err := br.UpdateGroup(target.ID, *g); err != nil { + return err + } else { + log.Info().Msgf("%v", resp) + } + case "schedule": + return errors.New("not implemented") + case "rule": + return errors.New("not implemented") + case "sensor": + return errors.New("not implemented") + case "bridge": + return errors.New("not implemented") + default: + return errors.New("invalid target type") + } + return nil +} + func cmdAdopt(br *ziggy.Bridge, args []string) error { resp, err := br.FindLights() if err != nil { diff --git a/internal/cli/completer.go b/internal/cli/completer.go index 67b86e3..d47bb88 100644 --- a/internal/cli/completer.go +++ b/internal/cli/completer.go @@ -80,6 +80,8 @@ func init() { Commands["scan"] = newZiggsCommand(cmdScan, "scan for bridges/lights/sensors", "search", "find") Commands["rename"] = newZiggsCommand(cmdRename, "rename object in bridge", "mv") Commands["adopt"] = newZiggsCommand(cmdAdopt, "adopt new lights to the bridge") + Commands["dump"] = newZiggsCommand(cmdDump, "dump target object JSON to a file") + Commands["load"] = newZiggsCommand(cmdLoad, "load JSON from a file into the bridge") Commands["set"] = newZiggsCommand(cmdSet, "update object properties in bridge", "update") initCompletion() } @@ -97,6 +99,10 @@ func initCompletion() { {Suggest: cli.Suggest{Text: "create"}, inner: Commands["create"]}, {Suggest: cli.Suggest{Text: "delete"}, inner: Commands["delete"]}, {Suggest: cli.Suggest{Text: "scan"}, inner: Commands["scan"]}, + {Suggest: cli.Suggest{Text: "rename"}, inner: Commands["rename"]}, + {Suggest: cli.Suggest{Text: "adopt"}, inner: Commands["adopt"]}, + {Suggest: cli.Suggest{Text: "dump"}, inner: Commands["dump"]}, + {Suggest: cli.Suggest{Text: "load"}, inner: Commands["load"]}, {Suggest: cli.Suggest{Text: "use", Description: "select bridge to perform actions on"}}, {Suggest: cli.Suggest{Text: "clear", Description: "clear screen"}}, {Suggest: cli.Suggest{Text: "exit", Description: "exit ziggs"}}, @@ -125,7 +131,7 @@ func initCompletion() { {Suggest: cli.Suggest{Text: "light", Description: "target light"}}, } for _, sug := range suggestions[1] { - sug.requires = map[int][]string{0: {"delete", "del", "set", "s"}} + sug.requires = map[int][]string{0: {"delete", "del", "set", "s", "rename", "mv", "dump", "load"}} sug.root = false } delCompletion := []*completion{ diff --git a/internal/ziggy/lights.go b/internal/ziggy/lights.go index 63e7a37..2e254d0 100644 --- a/internal/ziggy/lights.go +++ b/internal/ziggy/lights.go @@ -42,7 +42,6 @@ type Bridge struct { config *config.KnownBridge Info *huego.Config log *zerolog.Logger - debuglog *zerolog.Logger HueLights []*huego.Light *huego.Bridge *sync.RWMutex