diff --git a/bravia/avContent.go b/bravia/avContent.go new file mode 100644 index 0000000..52fc525 --- /dev/null +++ b/bravia/avContent.go @@ -0,0 +1,14 @@ +package bravia + +type setPlayContentOptions struct { + URI string `json:"uri"` +} + +type AVContent struct { + *Client +} + +func (c *AVContent) SetPlayContent(uri string) error { + options := &setPlayContentOptions{URI: uri} + return c.rpc("avContent", "setPowerStatus", "1.0", options, nil) +} diff --git a/bravia/bravia.go b/bravia/bravia.go new file mode 100644 index 0000000..587ff51 --- /dev/null +++ b/bravia/bravia.go @@ -0,0 +1,82 @@ +package bravia + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "os" +) + +type Client struct { + client *http.Client + ip string + psk string + id int + + System *System + AVContent *AVContent +} + +func NewClient(ip, psk string) *Client { + c := &Client{ + client: http.DefaultClient, + ip: ip, + psk: psk, + } + c.System = &System{Client: c} + c.AVContent = &AVContent{Client: c} + return c +} + +func (c *Client) nextID() int { + c.id++ + return c.id +} + +type rpcRequest struct { + Method string `json:"method"` + ID int `json:"id"` + Params []any `json:"params"` + Version string `json:"version"` +} + +func (c *Client) rpc(service, method, version string, params, result any) error { + + rpcBody := &rpcRequest{ + Method: method, + ID: c.nextID(), + Params: []any{params}, + Version: version, + } + + body := &bytes.Buffer{} + err := json.NewEncoder(body).Encode(rpcBody) + if err != nil { + return err + } + + req, err := http.NewRequest("POST", fmt.Sprintf("http://%s/sony/%s", c.ip, service), body) + if err != nil { + return err + } + + req.Header.Add("X-Auth-PSK", c.psk) + + resp, err := c.client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode > 299 { + return fmt.Errorf("request failed with %s", resp.Status) + } + + if result == nil { + io.Copy(os.Stdout, resp.Body) + return nil + } + return json.NewDecoder(req.Body).Decode(result) +} diff --git a/bravia/system.go b/bravia/system.go new file mode 100644 index 0000000..8fd97f8 --- /dev/null +++ b/bravia/system.go @@ -0,0 +1,15 @@ +package bravia + +type System struct { + *Client +} + +type setPowerStatusOptions struct { + Status bool `json:"status"` +} + +// https://pro-bravia.sony.net/develop/integrate/rest-api/spec/service/system/v1_0/setPowerStatus/index.html +func (c *System) SetPowerStatus(status bool) error { + options := &setPowerStatusOptions{Status: status} + return c.rpc("system", "setPowerStatus", "1.0", options, nil) +} diff --git a/go.mod b/go.mod index df36427..4ac7b66 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.19 require ( github.com/abibby/fileserver v0.0.0-20221208191705-087686654550 + github.com/davecgh/go-spew v1.1.1 github.com/gorilla/websocket v1.5.0 github.com/joho/godotenv v1.5.1 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index e407aa1..d3bc8dd 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/abibby/fileserver v0.0.0-20221208191705-087686654550 h1:UsWK0321m+VxaYzoRMbpCXO4RBgM8lwkX9V1tTojN1w= github.com/abibby/fileserver v0.0.0-20221208191705-087686654550/go.mod h1:xHBGw2P5B6OigP/ehSFN0L0SVNJSuGnllCrkfZBEX4s= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= diff --git a/ui/src/bravia/avContent.ts b/ui/src/bravia/avContent.ts index 9dfe33e..b6a7f61 100644 --- a/ui/src/bravia/avContent.ts +++ b/ui/src/bravia/avContent.ts @@ -8,19 +8,16 @@ export interface Source { source: string } -export const getSourceList = braviaAPIFactory<[options:GetSourceListOptions], Source[]>( - 'avContent', - 'getSourceList', - '1.0', -) +export const getSourceList = braviaAPIFactory< + [options: GetSourceListOptions], + Source[] +>('avContent', 'getSourceList', '1.0') export interface SetPlayContentOptions { uri: string } - -export const setPlayContent = braviaAPIFactory<[options:SetPlayContentOptions], void>( - 'avContent', - 'setPlayContent', - '1.0', -) +export const setPlayContent = braviaAPIFactory< + [options: SetPlayContentOptions], + void +>('avContent', 'setPlayContent', '1.0')