package main import ( "fmt" "io" "log" "net/http" "strings" "fyne.io/fyne/v2" "github.com/beego/x2j" ) // https://zetcode.com/golang/getpostrequest/ post_req_form.go func Post(where string) *http.Response { resp, err := http.PostForm(where, nil) if err != nil { log.Printf("POST got non 200 code, %v", err) // Catch what error it is, if it's a no access to device try a etherwake return nil } return resp } /*func ListenToRequests(ln *net.UDPConn, data *string) { done := false do_send := true for !done { buffer := make([]byte, 1024) // 1k ln.SetReadDeadline(time.Now().Add(3 * time.Second)) for !done { b, _, err := ln.ReadFromUDP(buffer) if b > 0 { str := string(buffer[0:]) *data += str } if err != nil { if _, ok := err.(net.Error); !ok { log.Print(err) done = true } } if do_send { err = PostFind() if err != nil { log.Printf("POST Find returned %v", err) } do_send = false } } } }*/ /* func PostFind() { file, err := os.ReadFile("finder.txt") if err != nil { log.Print(err) } addr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900") if err != nil { log.Print(err) } conn, err := net.DialUDP("udp", nil, addr) if err != nil { log.Print(err) } defer conn.Close() conn.Write(file) log.Println("Posted Request for devices") } func GetFind(data *[]string) { addr, err := net.ResolveUDPAddr("udp", ":1900") if err != nil { log.Printf("GET Find failed getting port 1900, %v", err) return } fmt.Printf("Listening on %s\r\n", addr.String()) ln, err := net.ListenUDP("udp", addr) if err != nil { log.Printf("GET Find started listener for 1900, %v", err) return } var list []string buffer := make([]byte, 1024) // 1k defer ln.Close() ln.SetReadDeadline(time.Now().Add(3 * time.Second)) for { n, adr, err := ln.ReadFromUDP(buffer) str := string(buffer[0:n]) fmt.Printf("Got '%s' from %s\r\n", str, adr.String()) if err != nil { log.Println(err) break } list = append(list, adr.String()) } *data = list } */ func Get(where string) *http.Response { resp, err := http.Get(where) if err != nil { log.Printf("GET got non 200 code, %v", err) return nil } else { return resp } } // https://developer.roku.com/docs/developer-program/debugging/external-control-api.md#keypress-key-values codes func KeyPress(ip, command string) string { return fmt.Sprintf("http://%s:8060/keypress/%s", ip, command) } // https://developer.roku.com/docs/developer-program/debugging/external-control-api.md#general-ecp-commands func Query(ip, what string) string { return fmt.Sprintf("http://%s:8060/query/%s", ip, what) } func PerformKey(ip, command string) bool { r := Post(KeyPress(ip, command)) if r == nil { return false } defer r.Body.Close() return true } func GetQuery(ip, command string) []byte { var resp *http.Response = Get(Query(ip, command)) if resp == nil { return nil } var body []byte var err error body, err = io.ReadAll(resp.Body) if err != nil { log.Printf("Reading from body got error, %v", err) } defer resp.Body.Close() return body } func GetCurrentPlay(ip string) *MediaPlayer { var resp []byte = GetQuery(ip, "media-player") var mp MediaPlayer var err error = x2j.Unmarshal(resp, &mp) if err != nil { log.Printf("Error occurred processing XML, %v", err) } return &mp } func ObtainDeviceInfo(ip string) *DeviceInfo { var resp []byte = GetQuery(ip, "device-info") var di DeviceInfo var err error = x2j.Unmarshal(resp, &di) if err != nil { log.Printf("Error occurred processing XML, %v", err) } return &di } // Returns a map of device-infos func GetDeviceInfo(ip string) *DeviceInfo { var di *DeviceInfo = ObtainDeviceInfo(ip) /*keys := glom.GetPossible(dev) for _, key := range keys { log.Printf("%s = %v", key, dev[key]) }*/ return di } func GetDevices(wake_on_lan map[string]string, w fyne.Window) ([]string, map[string]string) { var str []string resp := strings.Split(PostFind(w), "\n") //fmt.Printf("Processing %d lines\n", len(resp)) ip := "" for _, line := range resp { if strings.Contains(line, "LOCATION") { st := strings.ReplaceAll(line, "LOCATION: http://", "") st = strings.ReplaceAll(st, ":8060/", "") st = strings.ReplaceAll(st, "\r", "") //fmt.Printf("IP='%s'", st) str = append(str, st) ip = st } else if strings.Contains(line, "WAKEUP") { st := strings.ReplaceAll(line, "WAKEUP: MAC=", "") st = strings.ReplaceAll(st, ";Timeout=10", "") st = strings.ReplaceAll(st, "\r", "") //fmt.Printf("IP='%s' MAC='%s'", ip, st) wake_on_lan[ip] = st } } return str, wake_on_lan } func DebugInfo(ip string) string { // Query the current playing thing, and get the tv channels var mp *MediaPlayer = GetCurrentPlay(ip) var name string var id string /*r1 := GetQuery(ip, "tv-channels") chan_name, _ := glom.Glom(r1, "tv-channels.channel.name") chan_phy_id, _ := glom.Glom(r1, "tv-channels.channel.physical-channel") chan_number, _ := glom.Glom(r1, "tv-channels.channel.number")*/ if mp.Plugin.Name == "" && mp.Plugin.Id == 0 { name = "TV" id = "Off" } else { name = mp.Plugin.Name id = fmt.Sprintf("%d", mp.Plugin.Id) } // Debug print fmt.Printf("Name: %v (%v)\r\n", name, id) //fmt.Printf("Channel: %v (%v / %v)\r\n", chan_name, chan_phy_id, chan_number) return fmt.Sprintf("%v (%v)", name, id) }