Last active
January 23, 2025 20:50
-
-
Save freman/8d98742de09d476c4d3d9e5d55f9db63 to your computer and use it in GitHub Desktop.
Log into grafana on a samsung tv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// NB our grafana has keycloak in front, probably tweak a little (remove a click or two if you're just logging into grafana) | |
import ( | |
"crypto/tls" | |
"encoding/base64" | |
"encoding/json" | |
"fmt" | |
"log" | |
"strconv" | |
"strings" | |
"time" | |
"github.com/fatih/color" | |
"github.com/gorilla/websocket" | |
) | |
const ( | |
username = "user.name" | |
password = "some password" | |
// not sure why samsung escapes these slashes, but I'll copy them | |
grafanahome = `https:\/\/grafana.example.com` | |
grafanadashboard = `https:\/\/grafnana.example.com\/dashboard` | |
tv = "10.1.1.5" | |
) | |
type chansock struct { | |
*websocket.Conn | |
rCh chan interface{} | |
} | |
type msgwrap struct { | |
m []byte | |
t int | |
} | |
func wrapSock(c *websocket.Conn) *chansock { | |
cs := &chansock{ | |
Conn: c, | |
rCh: make(chan interface{}), | |
} | |
go cs.readPump() | |
return cs | |
} | |
// Can't just use readdeadline because it corrups the socket apparently | |
func (c *chansock) readPump() { | |
c.Conn.SetReadLimit(2048) | |
//c.c.SetpingHandler() | |
for { | |
t, msg, err := c.Conn.ReadMessage() | |
if err != nil { | |
c.rCh <- err | |
return | |
} | |
c.rCh <- msgwrap{m: msg, t: t} | |
} | |
} | |
func (c *chansock) ReadMessage() (messageType int, p []byte, err error) { | |
r := <-c.rCh | |
if err, ok := r.(error); ok && err != nil { | |
return 0, nil, err | |
} | |
msg := r.(msgwrap) | |
return msg.t, msg.m, nil | |
} | |
func (c *chansock) waitFor(event string) { | |
fmt.Println("Waiting for ", event) | |
for { | |
_, msg, err := c.ReadMessage() | |
if err != nil { | |
panic("TV broke: " + err.Error()) | |
} | |
color.HiCyan("TV said: %s", string(msg)) | |
in := struct { | |
Event string `event` | |
}{} | |
if err := json.Unmarshal(msg, &in); err != nil { | |
panic("JSON broke: " + err.Error()) | |
} | |
if strings.EqualFold(in.Event, event) { | |
return | |
} | |
} | |
} | |
func (c *chansock) nbSleep(t time.Duration) { | |
deadline := time.Now().Add(t) | |
for { | |
select { | |
case <-time.After(deadline.Sub(time.Now())): | |
return | |
case r := <-c.rCh: | |
if err, ok := r.(error); ok { | |
panic(err) | |
} | |
msg := r.(msgwrap) | |
color.Cyan("TV said: %s", string(msg.m)) | |
} | |
} | |
} | |
func (c *chansock) send(msg string) { | |
fmt.Println("I said: ", msg) | |
c.WriteMessage(websocket.TextMessage, []byte(msg)) | |
} | |
func ts() string { | |
return strconv.FormatInt(time.Now().UnixNano()/1000/1000, 10) | |
} | |
func main() { | |
websocket.DefaultDialer.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} | |
cs, _, err := websocket.DefaultDialer.Dial("wss://"+tv+":8002/api/v2/channels/samsung.remote.control", nil) | |
if err != nil { | |
log.Fatal("dial:", err) | |
} | |
defer cs.Close() | |
c := wrapSock(cs) | |
c.waitFor("ms.channel.connect") | |
c.send(`{"method":"ms.channel.emit","params":{"event": "ed.apps.launch", "to":"host", "data":{"appId":"org.tizen.browser","action_type":"NATIVE_LAUNCH","metaTag":"` + grafanahome + `"}}}`) | |
c.waitFor("ed.apps.launch") | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":0,"y":0,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.nbSleep(50 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":-1000,"y":-1000,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.nbSleep(50 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":-1000,"y":-1000,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.nbSleep(50 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":550,"y":330,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
// Allow the page to finish loading and moving | |
c.nbSleep(8 * time.Second) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"LeftClick","TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":0,"y":0,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.nbSleep(50 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":0,"y":100,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.nbSleep(50 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":0,"y":140,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.nbSleep(3 * time.Second) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"LeftClick","TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.waitFor("ms.remote.imeStart") | |
c.waitFor("ms.remote.imeUpdate") | |
c.waitFor("ms.remote.touchEnable") | |
c.nbSleep(100 * time.Millisecond) | |
s := base64.StdEncoding.EncodeToString([]byte(username)) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"` + s + `","TypeOfRemote":"SendInputString","DataOfCmd":"base64"}}`) | |
c.nbSleep(800 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Click","DataOfCmd":"KEY_RETURN","Option":"false","TypeOfRemote":"SendRemoteKey"}}`) | |
c.waitFor("ms.remote.imeEnd") | |
c.waitFor("ms.remote.touchEnable") | |
c.nbSleep(300 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":0,"y":0,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.nbSleep(50 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":0,"y":0,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.nbSleep(50 * time.Millisecond) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"Move","Position":{"x":0,"y":170,"Time":"` + ts() + `"},"TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"LeftClick","TypeOfRemote":"ProcessMouseDevice"}}`) | |
c.waitFor("ms.remote.imeStart") | |
c.waitFor("ms.remote.imeUpdate") | |
c.waitFor("ms.remote.touchEnable") | |
c.nbSleep(300 * time.Millisecond) | |
s = base64.StdEncoding.EncodeToString([]byte(password)) | |
c.send(`{"method":"ms.remote.control","params":{"Cmd":"` + s + `","TypeOfRemote":"SendInputString","DataOfCmd":"base64"}}`) | |
c.send(`{"method":"ms.remote.control","params":{"TypeOfRemote":"SendInputEnd"}}`) | |
c.waitFor("ms.remote.imeEnd") | |
c.waitFor("ms.remote.touchEnable") | |
c.nbSleep(1 * time.Second) | |
c.send(`{"method":"ms.channel.emit","params":{"event": "ed.apps.launch", "to":"host", "data":{"appId":"org.tizen.browser","action_type":"NATIVE_LAUNCH","metaTag":"` + grafanadashboard + `"}}}`) | |
} |
Hi!, do you know where I can find documentation on the available methods (ms.channel.emit) and events (ed.apps.launch)?
thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi , any hint on how to use this code?