|
|
package main
import ( "bufio" "context" "encoding/json" "flag" "fmt" "git.aiterp.net/lucifer/new-server/app/config" "git.aiterp.net/lucifer/new-server/internal/color" "git.aiterp.net/lucifer/new-server/models" "log" "os" "sort" "strconv" "strings" "time" )
var flagDriver = flag.String("driver", string(models.DTNanoLeaf), "The bridge driver to use") var flagAddress = flag.String("address", "127.0.0.1", "The bridge's address") var flagToken = flag.String("token", "", "The bridge's access token / api key / login") var flagPair = flag.Bool("pair", false, "Try to pair with the bridge.") var flagSearch = flag.Bool("search", false, "Search for devices first.") var flagSearchTimeout = flag.Duration("search-timeout", time.Second*3, "Timeout for device search.")
func main() { flag.Parse()
// Find drivers
driver, err := config.DriverProvider().Provide(models.DriverKind(*flagDriver)) if err != nil { log.Fatalln("Failed to find driver:", err) }
// Find bridge
bridges, err := driver.SearchBridge(context.Background(), *flagAddress, *flagToken, !*flagPair) if err != nil { log.Fatalln("Failed to search bridge:", err) } if len(bridges) == 0 { log.Fatalln("No bridges found") } bridge := bridges[0] if !*flagPair { bridge.Token = *flagToken } else { log.Println("New token:", bridge.Token) }
ch := config.EventChannel go func() { err := driver.Run(context.Background(), bridge, ch) if err != nil { log.Fatalln("Run bridge stopped:", err) } }() time.Sleep(time.Second)
// List devices
var devices []models.Device if *flagSearch { devices, err = driver.SearchDevices(context.Background(), bridge, *flagSearchTimeout) if err != nil { log.Fatalln("Failed to search devices:", err) } } else { devices, err = driver.ListDevices(context.Background(), bridge) if err != nil { log.Fatalln("Failed to list devices:", err) } }
idMap := make(map[string]int) nextId := len(devices) + 1 for i := range devices { devices[i].ID = i + 1 idMap[devices[i].InternalID] = i + 1 }
go func() { reader := bufio.NewReader(os.Stdin)
_, _ = fmt.Fprintln(os.Stderr, "Format: [id1,id2,...] [on|off] [color] [intensity]") for _, device := range devices { _, _ = fmt.Fprintf(os.Stderr, "Device: %d - %s %+v\n", device.ID, device.InternalID, device.Capabilities) } _, _ = fmt.Fprintln(os.Stderr, "Format: [id1,id2,...] [on|off] [color]")
for { text, _ := reader.ReadString('\n') text = strings.Trim(text, "\t \r\n")
if text == "search" { _, _ = driver.SearchDevices(context.Background(), bridge, time.Second) } if text == "list" || text == "search" || text == "json" { devices, err = driver.ListDevices(context.Background(), bridge) if err != nil { log.Fatalln("Failed to list devices:", err) }
for i, device := range devices { if extId, ok := idMap[device.InternalID]; ok { devices[i].ID = extId } else { idMap[device.InternalID] = nextId devices[i].ID = nextId
nextId += 1 }
if text != "json" { _, _ = fmt.Fprintf(os.Stderr, "Device: %d - %s %+v\n", device.ID, device.InternalID, device.Capabilities) } } } if text == "json" { j, _ := json.MarshalIndent(devices, "", " ") fmt.Println(string(j)) }
tokens := strings.Split(text, " ") if len(tokens) < 4 { continue }
color, err := color.Parse(tokens[2]) if err != nil { _, _ = fmt.Fprintln(os.Stderr, "Invalid color:", err) continue }
intensity, _ := strconv.ParseFloat(tokens[3], 64)
power := strings.ToLower(tokens[1]) == "on"
idsStr := strings.Split(tokens[0], ",") ids := make([]int, 0, len(idsStr)) for _, idStr := range idsStr { if idStr == "*" { ids = append(ids[:0], -1) break }
id, err := strconv.Atoi(idStr) if err != nil { continue }
ids = append(ids, id) }
updatedDevices := devices[:0:0] for _, device := range devices { for _, id := range ids { if id == -1 || id == device.ID { if (color.IsKelvin() && device.HasCapability(models.DCColorKelvin)) || (color.IsHueSat() && device.HasCapability(models.DCColorHS)) { device.State.Color = color } if device.HasCapability(models.DCPower) { device.State.Power = power } if device.HasCapability(models.DCIntensity) { device.State.Intensity = intensity }
updatedDevices = append(updatedDevices, device) } } }
if len(updatedDevices) > 0 { err := driver.Publish(context.Background(), bridge, updatedDevices) if err != nil { log.Fatalln("Publish to bridge failed:", err) return } } } }()
for event := range ch { _, _ = fmt.Fprintf(os.Stderr, "Event %s", event.Name) keys := make([]string, 0, 8) for key := range event.Payload { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { _, _ = fmt.Fprintf(os.Stderr, " %s=%#+v", key, event.Payload[key]) } _, _ = fmt.Fprint(os.Stderr, "\n") } }
|