Dump and load config, successfully changed bridge IP from ziggs

This commit is contained in:
kayos@tcp.direct 2022-10-29 03:49:28 -07:00
parent a7224a6014
commit bdcdadce52
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
6 changed files with 115 additions and 46 deletions

@ -24,6 +24,8 @@ var (
cpuLastHue = make(map[int]uint16) cpuLastHue = make(map[int]uint16)
) )
type reactor func(bridge *ziggy.Bridge, args []string) error
type ziggsCommand struct { type ziggsCommand struct {
reactor reactor reactor reactor
description string description string
@ -31,8 +33,6 @@ type ziggsCommand struct {
isAlias bool isAlias bool
} }
type reactor func(bridge *ziggy.Bridge, args []string) error
func newZiggsCommand(react reactor, desc string, aliases ...string) *ziggsCommand { func newZiggsCommand(react reactor, desc string, aliases ...string) *ziggsCommand {
ret := &ziggsCommand{ ret := &ziggsCommand{
reactor: react, reactor: react,
@ -255,7 +255,10 @@ func cmdRename(br *ziggy.Bridge, args []string) error {
// cmdDump exports a target object to a JSON file // cmdDump exports a target object to a JSON file
func cmdDump(br *ziggy.Bridge, args []string) error { func cmdDump(br *ziggy.Bridge, args []string) error {
if len(args) < 2 && args[0] != "all" { if len(args) < 2 && args[0] != "all" && args[0] != "conf" && args[0] != "groups" &&
args[0] != "lights" && args[0] != "rules" && args[0] != "schedules" &&
args[0] != "sensors" && args[0] != "scenes" && args[0] != "resourcelinks" &&
args[0] != "config" {
return errors.New("not enough arguments") return errors.New("not enough arguments")
} }
var ( var (
@ -285,6 +288,14 @@ func cmdDump(br *ziggy.Bridge, args []string) error {
case "bridge", "all": case "bridge", "all":
target = br target = br
name = br.Info.Name name = br.Info.Name
case "config":
var conf *huego.Config
conf, err = br.GetConfig()
if err != nil {
return err
}
target = conf
name = br.Info.BridgeID
default: default:
return errors.New("invalid target type") return errors.New("invalid target type")
} }
@ -299,16 +310,27 @@ func cmdDump(br *ziggy.Bridge, args []string) error {
// cmdLoad imports a target JSON object and attempts to apply it to an existing object // cmdLoad imports a target JSON object and attempts to apply it to an existing object
func cmdLoad(br *ziggy.Bridge, args []string) error { func cmdLoad(br *ziggy.Bridge, args []string) error {
if len(args) < 1 { var js []byte
var err error
switch len(args) {
case 0, 1:
return errors.New("not enough arguments") return errors.New("not enough arguments")
case 2:
js, err = os.ReadFile(args[1])
case 3:
js, err = os.ReadFile(args[2])
} }
js, err := os.ReadFile(args[2])
if err != nil { if err != nil {
return err return err
} }
if len(args) < 1 {
return errors.New("not enough arguments")
}
var target interface{}
switch args[0] { switch args[0] {
case "light", "l": case "light", "l":
target, err := br.FindLight(args[1]) target, err = br.FindLight(args[1])
if err != nil { if err != nil {
return err return err
} }
@ -316,13 +338,13 @@ func cmdLoad(br *ziggy.Bridge, args []string) error {
if err := json.Unmarshal(js, &l); err != nil { if err := json.Unmarshal(js, &l); err != nil {
return err return err
} }
if resp, err := br.UpdateLight(target.ID, *l); err != nil { if resp, err := br.UpdateLight(target.(*huego.Light).ID, *l); err != nil {
return err return err
} else { } else {
log.Info().Msgf("%v", resp) log.Info().Msgf("%v", resp)
} }
case "group", "g": case "group", "g":
target, err := br.FindGroup(args[1]) target, err = br.FindGroup(args[1])
if err != nil { if err != nil {
return err return err
} }
@ -330,11 +352,21 @@ func cmdLoad(br *ziggy.Bridge, args []string) error {
if err := json.Unmarshal(js, &g); err != nil { if err := json.Unmarshal(js, &g); err != nil {
return err return err
} }
if resp, err := br.UpdateGroup(target.ID, *g); err != nil { if resp, err := br.UpdateGroup(target.(*huego.Group).ID, *g); err != nil {
return err return err
} else { } else {
log.Info().Msgf("%v", resp) log.Info().Msgf("%v", resp)
} }
case "config", "conf", "cfg":
var conf *huego.Config
if err = json.Unmarshal(js, &conf); err != nil {
return err
}
var resp *huego.Response
if resp, err = br.UpdateConfig(conf); err != nil {
return err
}
log.Info().Msgf("%v", resp)
case "schedule": case "schedule":
return errors.New("not implemented") return errors.New("not implemented")
case "rule": case "rule":

@ -23,6 +23,7 @@ type cmdTarget interface {
Col(color.Color) error Col(color.Color) error
SetState(huego.State) error SetState(huego.State) error
Alert(string) error Alert(string) error
Scene(string) error
} }
func cmdSet(bridge *ziggy.Bridge, args []string) error { func cmdSet(bridge *ziggy.Bridge, args []string) error {
@ -36,7 +37,7 @@ func cmdSet(bridge *ziggy.Bridge, args []string) error {
var ( var (
groupMap map[string]*huego.Group groupMap map[string]*huego.Group
lightMap map[string]*huego.Light lightMap map[string]*ziggy.HueLight
actions []action actions []action
currentState *huego.State currentState *huego.State
argHead = -1 argHead = -1
@ -194,7 +195,27 @@ func cmdSet(bridge *ziggy.Bridge, args []string) error {
return alErr return alErr
}) })
case "cpu", "cpu2": case "cpu", "cpu2":
go cpuInit(args[argHead], bridge, target) go func() {
if err := cpuInit(args[argHead], bridge, target); err != nil {
log.Error().Err(err).Msg("cpu init failed")
}
}()
log.Info().Msg("cpu load lighting started")
return nil
case "scene", "sc":
if len(args) == argHead-1 {
return errors.New("not enough arguments")
}
argHead++
targetScene := args[argHead]
actions = append(actions, func() error {
err := target.Scene(targetScene)
if err != nil {
err = fmt.Errorf("failed to set scene: %w", err)
}
return err
})
default: default:
return fmt.Errorf("unknown argument: " + args[argHead]) return fmt.Errorf("unknown argument: " + args[argHead])
} }
@ -206,7 +227,7 @@ func cmdSet(bridge *ziggy.Bridge, args []string) error {
return errors.New("no target specified") return errors.New("no target specified")
} }
tg, tgok := target.(*huego.Group) tg, tgok := target.(*huego.Group)
tl, tlok := target.(*huego.Light) tl, tlok := target.(*ziggy.HueLight)
switch { switch {
case tgok: case tgok:
currentState = tg.State currentState = tg.State

@ -42,7 +42,7 @@ type Bridge struct {
config *config.KnownBridge config *config.KnownBridge
Info *huego.Config Info *huego.Config
log *zerolog.Logger log *zerolog.Logger
HueLights []*huego.Light HueLights []*HueLight
*huego.Bridge *huego.Bridge
*sync.RWMutex *sync.RWMutex
} }
@ -58,20 +58,25 @@ func (c *Bridge) Log() *zerolog.Logger {
} }
type HueLight struct { type HueLight struct {
l *huego.Light *huego.Light
controller *Bridge controller *Bridge
} }
func (hl *HueLight) Scene(s string) error {
hl.Scene(s)
return nil
}
func (hl *HueLight) Log() *zerolog.Logger { func (hl *HueLight) Log() *zerolog.Logger {
l := log.With(). l := log.With().
Int("caller", hl.l.ID). Int("caller", hl.ID).
Str("name", hl.l.Name). Str("name", hl.Name).
Bool("on", hl.l.IsOn()).Logger() Bool("on", hl.IsOn()).Logger()
return &l return &l
} }
func (hl *HueLight) GetPtr() (*huego.Light, error) { func (hl *HueLight) GetPtr() (*huego.Light, error) {
return hl.controller.GetLight(hl.l.ID) return hl.controller.GetLight(hl.ID)
} }
func getProxiedBridge(cridge *config.KnownBridge) *huego.Bridge { func getProxiedBridge(cridge *config.KnownBridge) *huego.Bridge {
@ -137,12 +142,12 @@ const (
Toggle Toggle
) )
type lCall func(light *huego.Light) (checkFunc, error) type lCall func(light *HueLight) (checkFunc, error)
type checkFunc func(light *huego.Light) bool type checkFunc func(light *HueLight) bool
var lightCallbacks = map[ToggleMode]lCall{ var lightCallbacks = map[ToggleMode]lCall{
ToggleOn: func(light *huego.Light) (checkFunc, error) { ToggleOn: func(light *HueLight) (checkFunc, error) {
return func(light *huego.Light) bool { return func(light *HueLight) bool {
light.State = &huego.State{ light.State = &huego.State{
On: true, On: true,
Bri: 100, Bri: 100,
@ -156,8 +161,8 @@ var lightCallbacks = map[ToggleMode]lCall{
}, },
light.On() light.On()
}, },
ToggleOff: func(light *huego.Light) (checkFunc, error) { ToggleOff: func(light *HueLight) (checkFunc, error) {
return func(light *huego.Light) bool { return func(light *HueLight) bool {
light.State = &huego.State{ light.State = &huego.State{
On: false, On: false,
Bri: 100, Bri: 100,
@ -171,8 +176,8 @@ var lightCallbacks = map[ToggleMode]lCall{
}, },
light.Off() light.Off()
}, },
/* ToggleDim: func(light *huego.Light) (checkFunc, error) { /* ToggleDim: func(light *HueLight) (checkFunc, error) {
return func(light *huego.Light) bool { return func(light *HueLight) bool {
if !light.IsOn() { if !light.IsOn() {
return false return false
} }
@ -180,8 +185,8 @@ var lightCallbacks = map[ToggleMode]lCall{
}, },
light.On() light.On()
},*/ },*/
ToggleRainbow: func(light *huego.Light) (checkFunc, error) { ToggleRainbow: func(light *HueLight) (checkFunc, error) {
return func(light *huego.Light) bool { return func(light *HueLight) bool {
if !light.IsOn() { if !light.IsOn() {
return false return false
} }
@ -191,7 +196,7 @@ var lightCallbacks = map[ToggleMode]lCall{
}, },
} }
func Assert(ctx context.Context, l *huego.Light, mode ToggleMode) error { func Assert(ctx context.Context, l *HueLight, mode ToggleMode) error {
act, ok := lightCallbacks[mode] act, ok := lightCallbacks[mode]
if !ok { if !ok {
panic("not implemented") panic("not implemented")
@ -220,12 +225,12 @@ func Assert(ctx context.Context, l *huego.Light, mode ToggleMode) error {
} }
} }
func toggle(l *huego.Light, mode ToggleMode) error { func toggle(l *HueLight, mode ToggleMode) error {
on := func(l *huego.Light) error { on := func(l *HueLight) error {
log.Trace().Msg("turning light on...") log.Trace().Msg("turning light on...")
return l.On() return l.On()
} }
off := func(l *huego.Light) error { off := func(l *HueLight) error {
log.Trace().Msg("turning light off...") log.Trace().Msg("turning light off...")
return l.Off() return l.Off()
} }
@ -247,7 +252,7 @@ func toggle(l *huego.Light, mode ToggleMode) error {
return err return err
} }
func ToggleLights(Lights []*huego.Light, mode ToggleMode) { func ToggleLights(Lights []*HueLight, mode ToggleMode) {
for _, l := range Lights { for _, l := range Lights {
err := toggle(l, mode) err := toggle(l, mode)
if err != nil { if err != nil {
@ -257,13 +262,20 @@ func ToggleLights(Lights []*huego.Light, mode ToggleMode) {
} }
func (c *Bridge) getLights() error { func (c *Bridge) getLights() error {
var err error var l []*HueLight
var l []huego.Light
l, err = c.GetLights() lit, err := c.GetLights()
if err != nil { if err != nil {
return err return err
} }
for _, lght := range lit {
if lp, err := c.GetLight(lght.ID); err != nil {
log.Error().Err(err).Msg("failed to get light")
continue
} else {
l = append(l, &HueLight{Light: lp, controller: c})
}
}
if l == nil { if l == nil {
return fmt.Errorf("no lights found") return fmt.Errorf("no lights found")
} }
@ -274,16 +286,16 @@ func (c *Bridge) getLights() error {
return err return err
} }
newlight := &HueLight{ newlight := &HueLight{
l: lightPtr, Light: lightPtr,
controller: c, controller: c,
} }
log.Debug().Interface("new light", newlight.l).Msg("+") log.Debug().Interface("new light", newlight.Light).Msg("+")
c.HueLights = append(c.HueLights, newlight.l) c.HueLights = append(c.HueLights, newlight)
} }
return nil return nil
} }
func (c *Bridge) Lights() []*huego.Light { func (c *Bridge) Lights() []*HueLight {
if len(c.HueLights) > 0 { if len(c.HueLights) > 0 {
return c.HueLights return c.HueLights
} }

@ -8,8 +8,8 @@ type Multiplex struct {
bridges []*Bridge bridges []*Bridge
} }
func GetLightMap() map[string]*huego.Light { func GetLightMap() map[string]*HueLight {
var lightMap = make(map[string]*huego.Light) var lightMap = make(map[string]*HueLight)
for _, c := range Lucifer.Bridges { for _, c := range Lucifer.Bridges {
ls, err := c.GetLights() ls, err := c.GetLights()
if err != nil { if err != nil {
@ -26,7 +26,7 @@ func GetLightMap() map[string]*huego.Light {
log.Warn().Msgf("duplicate light name %s on bridge %s - please rename", l.Name, c.ID) log.Warn().Msgf("duplicate light name %s on bridge %s - please rename", l.Name, c.ID)
continue continue
} }
lightMap[l.Name] = light lightMap[l.Name] = &HueLight{Light: light, controller: c}
} }
} }
return lightMap return lightMap

@ -7,7 +7,7 @@ import (
"github.com/amimof/huego" "github.com/amimof/huego"
) )
func (c *Bridge) FindLight(input string) (light *huego.Light, err error) { func (c *Bridge) FindLight(input string) (light *HueLight, err error) {
var lightID int var lightID int
if lightID, err = strconv.Atoi(input); err != nil { if lightID, err = strconv.Atoi(input); err != nil {
targ, ok := GetLightMap()[input] targ, ok := GetLightMap()[input]
@ -16,7 +16,11 @@ func (c *Bridge) FindLight(input string) (light *huego.Light, err error) {
} }
return targ, nil return targ, nil
} }
return c.GetLight(lightID) l, err := c.GetLight(lightID)
if err != nil {
return nil, err
}
return &HueLight{Light: l, controller: c}, nil
} }
func (c *Bridge) FindGroup(input string) (light *huego.Group, err error) { func (c *Bridge) FindGroup(input string) (light *huego.Group, err error) {

@ -33,7 +33,7 @@ func init() {
func TurnAll(Known []*ziggy.Bridge, mode ziggy.ToggleMode) { func TurnAll(Known []*ziggy.Bridge, mode ziggy.ToggleMode) {
for _, bridge := range Known { for _, bridge := range Known {
for _, l := range ziggy.GetLightMap() { for _, l := range ziggy.GetLightMap() {
go func(l *huego.Light) { go func(l *ziggy.HueLight) {
log.Debug(). log.Debug().
Str("caller", bridge.Host). Str("caller", bridge.Host).
Str("type", l.ProductName). Str("type", l.ProductName).