167 lines
3.6 KiB
Go
167 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/amimof/huego"
|
|
"github.com/rs/zerolog"
|
|
"golang.org/x/net/proxy"
|
|
|
|
"git.tcp.direct/kayos/ziggs/config"
|
|
)
|
|
|
|
var (
|
|
log *zerolog.Logger
|
|
)
|
|
|
|
var Known = make(map[string]*Controller)
|
|
var AllLights []*Light
|
|
|
|
// Controller is just another word for a bridge, a light controller.
|
|
type Controller struct {
|
|
config *config.KnownBridge
|
|
info *huego.Config
|
|
lights []*Light
|
|
*huego.Bridge
|
|
log zerolog.Logger
|
|
}
|
|
|
|
type Light struct {
|
|
*huego.Light
|
|
log zerolog.Logger
|
|
controller *Controller
|
|
}
|
|
|
|
func getProxiedBridge(cridge *config.KnownBridge) *huego.Bridge {
|
|
cridge.Proxy = strings.TrimPrefix(cridge.Proxy, "socks5://")
|
|
newTransport := http.DefaultTransport.(*http.Transport).Clone()
|
|
proxyDialer, _ := proxy.SOCKS5("tcp", cridge.Proxy, nil, proxy.Direct)
|
|
newTransport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
return proxyDialer.Dial(network, addr)
|
|
}
|
|
newClient := http.DefaultClient
|
|
newClient.Transport = newTransport
|
|
return huego.NewCustom(cridge.Hostname, cridge.Username, newClient)
|
|
}
|
|
|
|
func newController(cridge *config.KnownBridge) (*Controller, error) {
|
|
c := &Controller{
|
|
config: cridge,
|
|
}
|
|
if c.config.Proxy == "" {
|
|
c.Bridge = huego.New(c.config.Hostname, c.config.Username)
|
|
} else {
|
|
c.Bridge = getProxiedBridge(cridge)
|
|
}
|
|
|
|
var err error
|
|
c.info, err = c.GetConfig()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.log = log.With().Str("caller", c.info.BridgeID).Str("mac", c.info.Mac).Logger()
|
|
return c, nil
|
|
}
|
|
|
|
func GetControllers(bridges []config.KnownBridge) {
|
|
for _, lightConfig := range bridges {
|
|
log.Debug().Str("caller", lightConfig.Hostname).Str("proxy", lightConfig.Proxy).Msg("attempting connection")
|
|
c, err := newController(&lightConfig)
|
|
if err != nil {
|
|
log.Error().Str("caller", lightConfig.Hostname).Err(err).Msg("unsuccessful connection")
|
|
continue
|
|
}
|
|
c.log.Info().Msg("successful connection")
|
|
Known[c.info.BridgeID] = c
|
|
}
|
|
}
|
|
|
|
type ToggleMode uint8
|
|
|
|
const (
|
|
ToggleOn ToggleMode = iota
|
|
ToggleOff
|
|
Toggle
|
|
)
|
|
|
|
func toggle(l *Light, mode ToggleMode) error {
|
|
on := func(l *Light) error {
|
|
l.log.Trace().Msg("turning light on...")
|
|
return l.On()
|
|
}
|
|
off := func(l *Light) error {
|
|
l.log.Trace().Msg("turning light off...")
|
|
return l.Off()
|
|
}
|
|
var err error
|
|
switch mode {
|
|
case ToggleOn:
|
|
err = on(l)
|
|
case ToggleOff:
|
|
err = off(l)
|
|
case Toggle:
|
|
if !l.IsOn() {
|
|
err = off(l)
|
|
break
|
|
}
|
|
err = on(l)
|
|
default:
|
|
//
|
|
}
|
|
return err
|
|
}
|
|
|
|
func ToggleLights(Lights []*Light, mode ToggleMode) {
|
|
for _, l := range Lights {
|
|
err := toggle(l, mode)
|
|
if err != nil {
|
|
l.log.Error().Err(err).Bool("On", l.IsOn()).Msg("failed to toggle light")
|
|
}
|
|
}
|
|
}
|
|
|
|
func Setup() {
|
|
log.Debug().Int("count", len(config.KnownBridges)).Msg("trying bridges...")
|
|
GetControllers(config.KnownBridges)
|
|
if len(Known) == 0 {
|
|
log.Fatal().Msg("failed to connect to any bridges")
|
|
}
|
|
|
|
for _, bridge := range Known {
|
|
l, err := bridge.GetLights()
|
|
if err != nil || len(l) < 1 {
|
|
log.Fatal().Err(err).Msg("failed to discover lights")
|
|
}
|
|
bridge.log.Info().Msgf("Found %d lights", len(l))
|
|
for _, light := range l {
|
|
newlight := &Light{
|
|
Light: &light,
|
|
log: bridge.log.With().
|
|
Int("caller", light.ID).
|
|
Str("name", light.Name).Logger(),
|
|
controller: bridge,
|
|
}
|
|
bridge.lights = append(bridge.lights, newlight)
|
|
AllLights = append(AllLights, newlight)
|
|
}
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
config.Init()
|
|
log = config.StartLogger()
|
|
}
|
|
|
|
func main() {
|
|
Setup()
|
|
for name, bridge := range Known {
|
|
bridge.log.Debug().Str("caller", name).Interface("details", bridge).Msg("+")
|
|
for _, l := range bridge.lights {
|
|
l.log.Debug().Str("caller", bridge.ID).Msg("+")
|
|
}
|
|
}
|
|
}
|