This commit is contained in:
kayos@tcp.direct 2022-07-08 17:09:49 -07:00
parent e0c7f1dbf4
commit 2705ff6140
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
7 changed files with 92 additions and 74 deletions

3
common/ui.go Normal file
View File

@ -0,0 +1,3 @@
package common
var ZiggsPointer = func(to []rune) []rune { return []rune(``) }

View File

@ -97,9 +97,9 @@ func setDefaults() {
"use_date_filename": true,
}
Opt["bridges"] = map[string]interface{}{
"hostname": "192.168.6.100",
"hostname": "192.168.69.100",
"username": "",
"proxy": "socks5://127.0.0.1:8060",
"proxy": "",
}
Opt["http"] = map[string]interface{}{

View File

@ -11,8 +11,9 @@ import (
tui "github.com/manifoldco/promptui"
"github.com/rs/zerolog"
"git.tcp.direct/kayos/ziggs/common"
"git.tcp.direct/kayos/ziggs/config"
"git.tcp.direct/kayos/ziggs/lights"
"git.tcp.direct/kayos/ziggs/ziggy"
)
var log *zerolog.Logger
@ -45,10 +46,8 @@ func InteractiveAuth() string {
// Interpret is where we will actuall define our commands
func executor(cmd string) {
cmd = strings.TrimSpace(cmd)
var args []string
args = strings.Split(cmd, " ")
switch args[0] {
case "quit", "exit":
os.Exit(0)
@ -57,7 +56,7 @@ func executor(cmd string) {
println("use: use <bridge>")
return
}
if br, ok := lights.Lucifer.Bridges[args[1]]; !ok {
if br, ok := ziggy.Lucifer.Bridges[args[1]]; !ok {
println("invalid bridge: " + args[1])
} else {
selectedBridge = args[1]
@ -83,12 +82,20 @@ func executor(cmd string) {
default:
bcmd, ok := bridgeCMD[args[0]]
if !ok {
println()
return
}
br, ok := lights.Lucifer.Bridges[selectedBridge]
br, ok := ziggy.Lucifer.Bridges[selectedBridge]
if selectedBridge == "" || !ok {
for _, br := range lights.Lucifer.Bridges {
prompt := tui.Select{
Label: "Send to all known bridges?",
Items: []string{"yes", "no"},
Pointer: common.ZiggsPointer,
}
_, ch, _ := prompt.Run()
if ch != "yes" {
return
}
for _, br := range ziggy.Lucifer.Bridges {
go bcmd(br, args[1:])
}
} else {
@ -98,7 +105,6 @@ func executor(cmd string) {
}
}
}
}
func getHelp(target string) {
@ -129,7 +135,7 @@ func getHelp(target string) {
*/
}
func cmdScan(br *lights.Bridge, args []string) error {
func cmdScan(br *ziggy.Bridge, args []string) error {
r, err := br.FindLights()
if err != nil {
return err
@ -171,7 +177,7 @@ func StartCLI() {
log = config.GetLogger()
var hist []string
processBridges(lights.Lucifer.Bridges)
processBridges(ziggy.Lucifer.Bridges)
/* comphead := 0
compmu := &sync.Mutex{}

View File

@ -9,7 +9,7 @@ import (
cli "git.tcp.direct/Mirrors/go-prompt"
"github.com/amimof/huego"
"git.tcp.direct/kayos/ziggs/lights"
"git.tcp.direct/kayos/ziggs/ziggy"
)
var errInvalidFormat = errors.New("invalid format")
@ -49,7 +49,7 @@ func ParseHexColorFast(s string) (c color.RGBA, err error) {
return
}
func cmdLights(br *lights.Bridge, args []string) error {
func cmdLights(br *ziggy.Bridge, args []string) error {
if len(br.HueLights) == 0 {
return errors.New("no lights found")
}
@ -61,7 +61,7 @@ func cmdLights(br *lights.Bridge, args []string) error {
return nil
}
func cmdSet(bridge *lights.Bridge, args []string) error {
func cmdSet(bridge *ziggy.Bridge, args []string) error {
if len(args) < 3 {
return errors.New("not enough arguments")
}
@ -80,7 +80,8 @@ func cmdSet(bridge *lights.Bridge, args []string) error {
var groupmap map[string]huego.Group
var action func() error
type action func() error
var actions []action
var currentState *huego.State
var argHead = -1
@ -107,11 +108,11 @@ func cmdSet(bridge *lights.Bridge, args []string) error {
}
target = &g
case "on":
action = target.On
actions = append(actions, target.On)
case "off":
action = target.Off
actions = append(actions, target.Off)
case "brightness--", "dim":
action = func() error {
actions = append(actions, func() error {
if currentState == nil {
return fmt.Errorf("no state found")
}
@ -120,9 +121,9 @@ func cmdSet(bridge *lights.Bridge, args []string) error {
err = fmt.Errorf("couldn't lower brightness: %w", err)
}
return err
}
})
case "brightness++", "brighten":
action = func() error {
actions = append(actions, func() error {
if currentState == nil {
return fmt.Errorf("no state found")
}
@ -131,7 +132,7 @@ func cmdSet(bridge *lights.Bridge, args []string) error {
err = fmt.Errorf("couldn't raise brightness: %w", err)
}
return err
}
})
case "brightness":
if len(args) == argHead-1 {
return errors.New("no brightness specified")
@ -141,13 +142,13 @@ func cmdSet(bridge *lights.Bridge, args []string) error {
if numErr != nil {
return fmt.Errorf("given brightness is not a number: %w", numErr)
}
action = func() error {
actions = append(actions, func() error {
err := target.Bri(uint8(newBrightness))
if err != nil {
err = fmt.Errorf("failed to set brightness: %w", err)
}
return err
}
})
case "color":
if len(args) == argHead-1 {
return errors.New("not enough arguments")
@ -157,26 +158,26 @@ func cmdSet(bridge *lights.Bridge, args []string) error {
if err != nil {
return err
}
action = func() error {
actions = append(actions, func() error {
colErr := target.Col(newcolor)
if colErr != nil {
colErr = fmt.Errorf("failed to set color: %w", colErr)
}
return colErr
}
})
case "alert":
action = func() error {
actions = append(actions, func() error {
alErr := target.Alert("select")
if alErr != nil {
alErr = fmt.Errorf("failed to turn on alert: %w", alErr)
}
return alErr
}
})
default:
return fmt.Errorf("unknown argument: " + args[argHead])
}
}
if action == nil {
if actions == nil {
return errors.New("no action specified")
}
if target == nil {
@ -191,21 +192,24 @@ func cmdSet(bridge *lights.Bridge, args []string) error {
currentState = tl.State
}
log.Trace().Msgf("current state: %v", currentState)
err := action()
if err != nil {
return err
for d, act := range actions {
log.Trace().Msgf("running action %d", d)
err := act()
if err != nil {
return err
}
switch {
case tgok:
currentState = tg.State
case tlok:
currentState = tl.State
}
log.Trace().Msgf("new state: %v", currentState)
}
switch {
case tgok:
currentState = tg.State
case tlok:
currentState = tl.State
}
log.Trace().Msgf("new state: %v", currentState)
return nil
}
func getGroupMap(br *lights.Bridge) (map[string]huego.Group, error) {
func getGroupMap(br *ziggy.Bridge) (map[string]huego.Group, error) {
var groupmap = make(map[string]huego.Group)
gs, err := br.Bridge.GetGroups()
if err != nil {
@ -217,7 +221,7 @@ func getGroupMap(br *lights.Bridge) (map[string]huego.Group, error) {
return groupmap, nil
}
func cmdGroups(br *lights.Bridge, args []string) error {
func cmdGroups(br *ziggy.Bridge, args []string) error {
groupmap, err := getGroupMap(br)
if err != nil {
return err
@ -232,7 +236,7 @@ func cmdGroups(br *lights.Bridge, args []string) error {
return nil
}
type reactor func(bridge *lights.Bridge, args []string) error
type reactor func(bridge *ziggy.Bridge, args []string) error
var bridgeCMD = map[string]reactor{
"scan": cmdScan,
@ -247,7 +251,7 @@ type completeMapper map[cli.Suggest][]cli.Suggest
var suggestions completeMapper = make(map[cli.Suggest][]cli.Suggest)
func processBridges(brs map[string]*lights.Bridge) {
func processBridges(brs map[string]*ziggy.Bridge) {
for brd, c := range brs {
suggestions[cli.Suggest{Text: "use"}] = append(
suggestions[cli.Suggest{Text: "use"}],

25
main.go
View File

@ -10,9 +10,10 @@ import (
"github.com/manifoldco/promptui"
"github.com/rs/zerolog"
"git.tcp.direct/kayos/ziggs/common"
"git.tcp.direct/kayos/ziggs/config"
"git.tcp.direct/kayos/ziggs/interactive"
"git.tcp.direct/kayos/ziggs/lights"
"git.tcp.direct/kayos/ziggs/ziggy"
)
var (
@ -28,23 +29,23 @@ func init() {
}
}
func TurnAll(Known []*lights.Bridge, mode lights.ToggleMode) {
func TurnAll(Known []*ziggy.Bridge, mode ziggy.ToggleMode) {
for _, bridge := range Known {
for _, l := range bridge.HueLights {
go func(l *lights.HueLight) {
go func(l *ziggy.HueLight) {
l.Log().Debug().
Str("caller", bridge.Host).
Str("type", l.ProductName).
Bool("on", l.IsOn()).Msg(l.ModelID)
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
lights.Assert(ctx, l, mode)
ziggy.Assert(ctx, l, mode)
defer cancel()
}(l)
}
}
}
func FindLights(ctx context.Context, c *lights.Bridge) error {
func FindLights(ctx context.Context, c *ziggy.Bridge) error {
log.Trace().Msg("looking for lights...")
resp, err := c.FindLights()
if err != nil {
@ -71,7 +72,7 @@ func FindLights(ctx context.Context, c *lights.Bridge) error {
}
}
func getNewSensors(known *lights.Bridge) {
func getNewSensors(known *ziggy.Bridge) {
go known.FindSensors()
Sensors, err := known.GetNewSensors()
if err != nil {
@ -98,7 +99,7 @@ func selSensor(Sensors []*huego.Sensor) huego.Sensor {
CursorPos: 0,
HideHelp: false,
HideSelected: false,
Pointer: func(to []rune) []rune { return []rune(``) },
Pointer: common.ZiggsPointer,
}
i, s, e := p.Run()
if e != nil {
@ -109,9 +110,9 @@ func selSensor(Sensors []*huego.Sensor) huego.Sensor {
}
func main() {
var Known []*lights.Bridge
var Known []*ziggy.Bridge
var err error
Known, err = lights.Setup()
Known, err = ziggy.Setup()
if err != nil {
log.Fatal().Err(err).Msg("failed to get bridges")
@ -123,13 +124,13 @@ func main() {
case "on":
log.Debug().Msg("turning all " + arg)
TurnAll(Known, lights.ToggleOn)
TurnAll(Known, ziggy.ToggleOn)
case "off":
log.Debug().Msg("turning all " + arg)
TurnAll(Known, lights.ToggleOff)
TurnAll(Known, ziggy.ToggleOff)
case "rainbow":
log.Debug().Msg("turning all " + arg)
TurnAll(Known, lights.ToggleRainbow)
TurnAll(Known, ziggy.ToggleRainbow)
case "scan":
log.Debug().Msg("executing " + arg)
if len(os.Args) < 2 {

View File

@ -1,4 +1,4 @@
package lights
package ziggy
import (
"context"
@ -21,6 +21,7 @@ import (
"golang.org/x/net/proxy"
"inet.af/netaddr"
"git.tcp.direct/kayos/ziggs/common"
"git.tcp.direct/kayos/ziggs/config"
)
@ -281,9 +282,7 @@ func promptForUser(cnt *Bridge) bool {
Items: []string{"Create new user", "Provide existing username"},
CursorPos: 0,
IsVimMode: false,
Pointer: func(x []rune) []rune {
return []rune("")
},
Pointer: common.ZiggsPointer,
}
choice, _, _ := confirmPrompt.Run()
switch choice {
@ -307,9 +306,7 @@ func promptForUser(cnt *Bridge) bool {
},
Mask: 'x',
HideEntered: false,
Pointer: func(x []rune) []rune {
return []rune("")
},
Pointer: common.ZiggsPointer,
}
var err error
var input string
@ -409,15 +406,13 @@ func scanChoicePrompt(interfaces []net.Interface) net.Interface {
Items: interfaces,
CursorPos: 0,
IsVimMode: false,
Pointer: func(x []rune) []rune {
return []rune("")
},
Pointer: common.ZiggsPointer,
}
choice, _, _ := confirmPrompt.Run()
return interfaces[choice]
}
func checkAddrs(addrs []net.Addr, working *int32, resChan chan interface{}) {
func checkAddrs(ctx context.Context, addrs []net.Addr, working *int32, resChan chan interface{}) {
var init = &sync.Once{}
log.Trace().Msg("checking addresses")
for _, a := range addrs {
@ -425,11 +420,18 @@ func checkAddrs(addrs []net.Addr, working *int32, resChan chan interface{}) {
ips := network.IterateNetRange(netaddr.MustParseIPPrefix(a.String()))
for ipa := range ips {
init.Do(func() { resChan <- &huego.Bridge{} })
ctxLoop:
for {
if atomic.LoadInt32(working) > 50 {
time.Sleep(time.Second)
select {
case <-ctx.Done():
return
default:
if atomic.LoadInt32(working) > 25 {
time.Sleep(100 * time.Millisecond)
continue
}
break ctxLoop
}
break
}
log.Trace().Msgf("checking %s", ipa.String())
atomic.AddInt32(working, 1)
@ -461,8 +463,9 @@ func scanForBridges() ([]*huego.Bridge, error) {
}
var working int32
resChan := make(chan interface{}, 55)
ctx, cancel := context.WithCancel(context.Background())
log.Trace().Interface("addresses", addrs).Msg("checkAddrs()")
go checkAddrs(addrs, &working, resChan)
go checkAddrs(ctx, addrs, &working, resChan)
<-resChan // wait for sync.Once to throw us a nil
resultLoop:
@ -473,9 +476,12 @@ resultLoop:
if ok && bridge != nil {
log.Info().Msgf("found %T: %v", bridge, bridge)
hueIPs = append(hueIPs, bridge)
cancel()
atomic.StoreInt32(&working, 0)
}
default:
if atomic.LoadInt32(&working) <= 0 {
cancel()
break resultLoop
}
}
@ -495,9 +501,7 @@ func promptForDiscovery() error {
Items: []string{"Yes", "No"},
CursorPos: 0,
IsVimMode: false,
Pointer: func(x []rune) []rune {
return []rune("")
},
Pointer: common.ZiggsPointer,
}
choice, _, _ := confirmPrompt.Run()
if choice != 0 {

View File

@ -1,4 +1,4 @@
package lights
package ziggy
// Multiplex is all of the lights (all of the lights).
// I'll see myself out.