cert renew
This commit is contained in:
+1
-1
@@ -1,2 +1,2 @@
|
||||
service*
|
||||
cert
|
||||
renew.local.env
|
||||
Vendored
+1
-1
@@ -12,7 +12,7 @@
|
||||
"program": "${workspaceFolder}/main.go",
|
||||
"env": {
|
||||
"HTTP_STATIC": "${workspaceFolder}/static/dist",
|
||||
"VIDEO_OUT_DEVICE": "/dev/video4",
|
||||
//"VIDEO_OUT_DEVICE": "/dev/video4",
|
||||
"AUDIO_OUT_DEVICE": "plughw:0,1,0",
|
||||
"INPUT_DEVICE": "/dev/input/event5",
|
||||
"JINGLE_PATH": "${workspaceFolder}/audio",
|
||||
|
||||
@@ -3,6 +3,7 @@ build:
|
||||
|
||||
build-static:
|
||||
npm --prefix static ci && npm --prefix static run build
|
||||
cp -r audio static/dist/audio
|
||||
|
||||
build-armhf:
|
||||
GOARCH=arm \
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
HTTPREQ_ENDPOINT=<your httpreq endpoint>
|
||||
ACME_KID=<your acme kid>
|
||||
ACME_HMAC=<your acme hmac>
|
||||
ACME_DOMAINS=<your domain>
|
||||
ACME_EMAIL=<your email>
|
||||
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Renew certificate
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
EnvironmentFile=/etc/ring/renew.env
|
||||
ExecStart=/usr/local/bin/renew.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
set +x
|
||||
|
||||
lego --path "/etc/ldap/cert" --email "${ACME_EMAIL}" --server "https://acme.zerossl.com/v2/DV90" --accept-tos --eab \
|
||||
--kid "${ACME_KID}" \
|
||||
--hmac "${ACME_HMAC}" \
|
||||
--key-type "rsa4096" \
|
||||
--dns "httpreq" \
|
||||
--domains "${ACME_DOMAINS}" \
|
||||
--pem \
|
||||
renew \
|
||||
--renew-hook="systemctl restart ring"
|
||||
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Renew certificate
|
||||
|
||||
[Timer]
|
||||
Persistent=true
|
||||
OnCalendar=*-*-* 3:35
|
||||
RandomizedDelaySec=1h
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@@ -5,12 +5,11 @@ go 1.20
|
||||
require (
|
||||
github.com/alexflint/go-arg v1.4.3
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/hashicorp/mdns v1.0.5
|
||||
github.com/holoplot/go-evdev v0.0.0-20230626094006-70c9462cc0f2
|
||||
github.com/ianr0bkny/go-sonos v0.0.0-20171025003233-056585059953
|
||||
github.com/pion/rtcp v1.2.10
|
||||
github.com/pion/webrtc/v3 v3.2.10
|
||||
github.com/szatmary/sonos v0.0.0-20191204204454-000c9219ff0e
|
||||
github.com/tinyzimmer/go-glib v0.0.25
|
||||
github.com/tinyzimmer/go-gst v0.2.33
|
||||
go.uber.org/zap v1.24.0
|
||||
@@ -28,7 +27,6 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.14.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.10.3 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
|
||||
@@ -68,8 +68,6 @@ github.com/hashicorp/mdns v1.0.5/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/
|
||||
github.com/holoplot/go-evdev v0.0.0-20230626094006-70c9462cc0f2 h1:bxudnRpvfq2PMYEYN7VGj03+MXG4EobVUmONigCx1yA=
|
||||
github.com/holoplot/go-evdev v0.0.0-20230626094006-70c9462cc0f2/go.mod h1:iHAf8OIncO2gcQ8XOjS7CMJ2aPbX2Bs0wl5pZyanEqk=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianr0bkny/go-sonos v0.0.0-20171025003233-056585059953 h1:n9vfPPfv66b56toxNZk/w7VPSZ5eK/NxVrtRs1uptzo=
|
||||
github.com/ianr0bkny/go-sonos v0.0.0-20171025003233-056585059953/go.mod h1:uvzy1yuMP2e76h67o5rpaXPDPq4e/cUGU4RYkm9a0Js=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
@@ -168,8 +166,6 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/szatmary/sonos v0.0.0-20191204204454-000c9219ff0e h1:beo21nzzdqCVGe6EdG3Lo3UbU7meQN4JjAAeyZccH94=
|
||||
github.com/szatmary/sonos v0.0.0-20191204204454-000c9219ff0e/go.mod h1:F5m1XEgf251EShYE9r+2Rl45NPLGovXttfuAjBb93bY=
|
||||
github.com/tinyzimmer/go-glib v0.0.25 h1:2GpumtkxA0wpXhCXP6D3ksb5pGMfo9WbhgLvEw8njK4=
|
||||
github.com/tinyzimmer/go-glib v0.0.25/go.mod h1:ltV0gO6xNFzZhsIRbFXv8RTq9NGoNT2dmAER4YmZfaM=
|
||||
github.com/tinyzimmer/go-gst v0.2.33 h1:wdwUYoN7dkWGUTrZIgB9Mp5LMRr/Sld5PVGRsE7/O9s=
|
||||
|
||||
@@ -27,10 +27,10 @@ type ConfigLogging struct {
|
||||
}
|
||||
|
||||
type ConfigRing struct {
|
||||
Device string `arg:"--input-device,env:INPUT_DEVICE" default:"/dev/input/by-path/platform-gpio-keys-user-event"`
|
||||
Device *string `arg:"--input-device,env:INPUT_DEVICE"`
|
||||
Key string `arg:"--ring-key" default:"KEY_F1"`
|
||||
JingleName string `arg:"--jingle-name,env:JINGLE_NAME" default:"ding-dong.wav"`
|
||||
JinglePath *string `arg:"--jingle-path,env:JINGLE_PATH"`
|
||||
JingleBaseUri *string `arg:"--jingle-base-uri,env:JINGLE_BASE_URI"`
|
||||
JinglePath string `arg:"--jingle-path,env:JINGLE_PATH" default:"audio/ding-dong.wav"`
|
||||
SonosTarget string `arg:"--sonos-target,env:SONOS_TARGET" default:"-"`
|
||||
SonosVolume int `arg:"--sonos-volume,env:SONOS_VOLUME" default:"50"`
|
||||
}
|
||||
@@ -52,6 +52,7 @@ type ConfigVideoOutputStream struct {
|
||||
Codec string `arg:"--video-out-codec,env:VIDEO_OUT_CODEC" default:"vp8"`
|
||||
Height uint `arg:"--video-out-height,env:VIDEO_OUT_HEIGHT" default:"480"`
|
||||
Width uint `arg:"--video-out-width,env:VIDEO_OUT_WIDTH" default:"640"`
|
||||
USE_QUEUE bool `arg:"--video-out-queue,env:VIDEO_OUT_QUEUE" default:"false"`
|
||||
}
|
||||
|
||||
type ConfigAudioOutputStream struct {
|
||||
@@ -60,6 +61,7 @@ type ConfigAudioOutputStream struct {
|
||||
Device *string `arg:"--audio-out-device,env:AUDIO_OUT_DEVICE"`
|
||||
Codec string `arg:"--audio-out-codec,env:AUDIO_OUT_CODEC" default:"opus"`
|
||||
Channels uint `arg:"--audio-out-channels,env:AUDIO_OUT_CHANNELS" default:"1"`
|
||||
USE_QUEUE bool `arg:"--audio-out-queue,env:AUDIO_OUT_QUEUE" default:"false"`
|
||||
}
|
||||
|
||||
type ConfigAudioInputStream struct {
|
||||
|
||||
+15
-5
@@ -32,13 +32,23 @@ func NewRingHandler(lg *zap.Logger, cfg *common.ConfigRing) (*RingHandler, error
|
||||
}
|
||||
|
||||
func (h *RingHandler) Watch(ctx context.Context) error {
|
||||
if h.cfg.Device == nil {
|
||||
h.lg.Warn("nothing to watch for key press")
|
||||
return nil
|
||||
}
|
||||
|
||||
if h.cfg.JingleBaseUri == nil {
|
||||
h.lg.Warn("missing jingle base uri, nothing to play")
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, p := range h.playHandlers {
|
||||
if err := p.Watch(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d, err := evdev.Open(h.cfg.Device)
|
||||
d, err := evdev.Open(*h.cfg.Device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -48,9 +58,9 @@ func (h *RingHandler) Watch(ctx context.Context) error {
|
||||
|
||||
key := evdev.KEYFromString[h.cfg.Key]
|
||||
|
||||
bu := url.URL{
|
||||
Scheme: "http",
|
||||
Host: "192.168.60.141:9099",
|
||||
bu, err := url.Parse(*h.cfg.JingleBaseUri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
@@ -62,7 +72,7 @@ func (h *RingHandler) Watch(ctx context.Context) error {
|
||||
for {
|
||||
e, err := d.ReadOne()
|
||||
if err == nil && e.Code == key && e.Value == 0 {
|
||||
tu := bu.JoinPath(h.cfg.JingleName)
|
||||
tu := bu.JoinPath(h.cfg.JinglePath)
|
||||
for _, p := range h.playHandlers {
|
||||
if err := p.Play(tu); err != nil {
|
||||
h.lg.Error("failed to play", zap.Error(err))
|
||||
|
||||
@@ -43,6 +43,7 @@ type sonosInfo struct {
|
||||
type sonosAudioClip struct {
|
||||
Name string `json:"name"`
|
||||
AppId string `json:"appId"`
|
||||
ClipType string `json:"clipType,omitempty"`
|
||||
StreamUrl string `json:"streamUrl"`
|
||||
Volume int `json:"volume"`
|
||||
}
|
||||
@@ -108,6 +109,7 @@ func (p *SonosPlayer) Play(uri *url.URL, volume int) error {
|
||||
sab := sonosAudioClip{
|
||||
Name: "Pull Bell",
|
||||
AppId: "com.acme.app",
|
||||
ClipType: "CHIME",
|
||||
StreamUrl: uri.String(),
|
||||
Volume: volume,
|
||||
}
|
||||
@@ -181,6 +183,7 @@ func (h *SonosHandler) Watch(ctx context.Context) error {
|
||||
|
||||
func (h *SonosHandler) Play(uri *url.URL) error {
|
||||
for _, p := range h.players {
|
||||
h.lg.Info("playing clip", zap.String("target", p.address.String()), zap.String("clip", uri.String()))
|
||||
if err := p.Play(uri, h.cfg.SonosVolume); err != nil {
|
||||
h.lg.Error("failed to play", zap.String("address", p.address.String()), zap.Error(err))
|
||||
}
|
||||
|
||||
@@ -71,6 +71,15 @@ func CreateVideoPipelineSink(s StreamElement) (*gst.Pipeline, <-chan media.Sampl
|
||||
}
|
||||
elems = append(elems, conv)
|
||||
|
||||
if s.Queue {
|
||||
// add a queue
|
||||
queue, err := gst.NewElement("queue")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
elems = append(elems, queue)
|
||||
}
|
||||
|
||||
// Create the enc
|
||||
enc, err := gst.NewElement("vp8enc")
|
||||
if err != nil {
|
||||
@@ -140,6 +149,15 @@ func CreateAudioPipelineSink(s StreamElement) (*gst.Pipeline, <-chan media.Sampl
|
||||
}
|
||||
elems = append(elems, conv)
|
||||
|
||||
if s.Queue {
|
||||
// add a queue
|
||||
queue, err := gst.NewElement("queue")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
elems = append(elems, queue)
|
||||
}
|
||||
|
||||
// Create the enc
|
||||
enc, err := gst.NewElement("opusenc")
|
||||
if err != nil {
|
||||
|
||||
@@ -30,6 +30,7 @@ type StreamElement struct {
|
||||
Kind string
|
||||
Properties map[string]interface{}
|
||||
Caps *StreamElementCaps
|
||||
Queue bool
|
||||
}
|
||||
|
||||
func (se StreamElement) ToGstCaps() *gst.Caps {
|
||||
|
||||
+31
-7
@@ -2,6 +2,8 @@ package webrtc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -121,6 +123,7 @@ func (wh *WebrtcHandler) handleAudioSamples(ctx context.Context, cfg *common.Con
|
||||
Channels: cfg.Channels,
|
||||
Rate: 48000,
|
||||
},
|
||||
Queue: cfg.USE_QUEUE,
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -164,6 +167,7 @@ func (wh *WebrtcHandler) handleVideoSamples(ctx context.Context, cfg *common.Con
|
||||
Width: cfg.Width,
|
||||
Height: cfg.Height,
|
||||
},
|
||||
Queue: cfg.USE_QUEUE,
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -195,7 +199,7 @@ func (wh *WebrtcHandler) handleVideoSamples(ctx context.Context, cfg *common.Con
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wh *WebrtcHandler) createPeerHandle(ctx context.Context, sh *server.SignalingHandle) error {
|
||||
func (wh *WebrtcHandler) createPeerHandle(rctx context.Context, sh *server.SignalingHandle) error {
|
||||
wh.mu.Lock()
|
||||
defer wh.mu.Unlock()
|
||||
|
||||
@@ -210,6 +214,9 @@ func (wh *WebrtcHandler) createPeerHandle(ctx context.Context, sh *server.Signal
|
||||
return err
|
||||
}
|
||||
|
||||
// create a context for this handle
|
||||
hctx, hcancel := context.WithCancel(rctx)
|
||||
|
||||
// Set a handler for when a new remote track starts, this handler creates a gstreamer pipeline
|
||||
// for the given codec
|
||||
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
||||
@@ -227,9 +234,13 @@ func (wh *WebrtcHandler) createPeerHandle(ctx context.Context, sh *server.Signal
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if err := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); err != nil {
|
||||
if errors.Is(err, io.ErrClosedPipe) {
|
||||
return
|
||||
}
|
||||
|
||||
wh.lg.Error("failed to send PLI", zap.Error(err))
|
||||
}
|
||||
case <-ctx.Done():
|
||||
case <-hctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -240,18 +251,24 @@ func (wh *WebrtcHandler) createPeerHandle(ctx context.Context, sh *server.Signal
|
||||
})
|
||||
if err != nil {
|
||||
wh.lg.Error("failed to create src pipeline", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
pipeline.Start()
|
||||
buf := make([]byte, 1400)
|
||||
for {
|
||||
i, _, readErr := track.Read(buf)
|
||||
n, _, readErr := track.Read(buf)
|
||||
if readErr != nil {
|
||||
wh.lg.Error("read failed", zap.Error(err))
|
||||
if errors.Is(readErr, io.EOF) {
|
||||
return
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
pipeline.Push(buf[:i])
|
||||
wh.lg.Error("read failed", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
if n > 0 {
|
||||
err := pipeline.Push(buf[:n])
|
||||
if err != nil {
|
||||
wh.lg.Error("push failed", zap.Error(err))
|
||||
}
|
||||
@@ -266,10 +283,17 @@ func (wh *WebrtcHandler) createPeerHandle(ctx context.Context, sh *server.Signal
|
||||
|
||||
if connectionState == webrtc.ICEConnectionStateDisconnected {
|
||||
peerConnection.Close()
|
||||
hcancel()
|
||||
|
||||
// remove this handle
|
||||
wh.mu.Lock()
|
||||
|
||||
delete(wh.peerHandles, sh.Id)
|
||||
|
||||
if len(wh.peerHandles) == 0 {
|
||||
wh.stopPipelines()
|
||||
}
|
||||
|
||||
wh.mu.Unlock()
|
||||
}
|
||||
})
|
||||
@@ -354,7 +378,7 @@ func (wh *WebrtcHandler) createPeerHandle(ctx context.Context, sh *server.Signal
|
||||
if err != nil {
|
||||
wh.lg.Error("failed to handle offer", zap.Error(err))
|
||||
}
|
||||
case <-ctx.Done():
|
||||
case <-hctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,12 +39,6 @@ func (s staticDiskSource) Open(p string) (common.StaticSourceFile, error) {
|
||||
}
|
||||
|
||||
func SetupHandler(e *gin.Engine, cfg *common.Config) {
|
||||
if cfg.Ring.JinglePath != nil {
|
||||
e.GET(cfg.Ring.JingleName, func(c *gin.Context) {
|
||||
c.File(path.Join(*cfg.Ring.JinglePath, cfg.Ring.JingleName))
|
||||
})
|
||||
}
|
||||
|
||||
if cfg.Http.StaticPath != nil {
|
||||
handler := common.NewStaticHandler(staticDiskSource{*cfg.Http.StaticPath}, "index.html")
|
||||
e.NoRoute(func(c *gin.Context) {
|
||||
|
||||
@@ -42,12 +42,6 @@ func (s staticSource) Open(p string) (common.StaticSourceFile, error) {
|
||||
}
|
||||
|
||||
func SetupHandler(e *gin.Engine, cfg *common.Config) {
|
||||
if cfg.Ring.JinglePath != nil {
|
||||
e.GET(cfg.Ring.JingleName, func(c *gin.Context) {
|
||||
c.File(path.Join(*cfg.Ring.JinglePath, cfg.Ring.JingleName))
|
||||
})
|
||||
}
|
||||
|
||||
handler := common.NewStaticHandler(staticSource{"dist"}, "index.html")
|
||||
e.NoRoute(func(c *gin.Context) {
|
||||
encoding := c.Request.Header.Get("Accept-Encoding")
|
||||
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
go-sonos
|
||||
========
|
||||
|
||||
Copyright (c) 2012, Ian T. Richards <ianr@panix.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-942
@@ -1,942 +0,0 @@
|
||||
//
|
||||
// go-sonos
|
||||
// ========
|
||||
//
|
||||
// Copyright (c) 2012, Ian T. Richards <ianr@panix.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
//
|
||||
// A client implementation of the SSDP protocol.
|
||||
//
|
||||
// mgr := ssdp.MakeManager()
|
||||
// mgr.Discover("eth0", "13104", false)
|
||||
// qry := ssdp.ServiceQueryTerms{
|
||||
// ssdp.ServiceKey("schemas-upnp-org-MusicServices"): -1,
|
||||
// }
|
||||
// result := mgr.QueryServices(qry)
|
||||
// if device_list, has := result["schemas-upnp-org-MusicServices"]; has {
|
||||
// for _, device := range device_list {
|
||||
// ...
|
||||
// }
|
||||
// }
|
||||
// mgr.Close()
|
||||
//
|
||||
package ssdp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/textproto"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ssdpHNAPRegex *regexp.Regexp
|
||||
var ssdpOtherDeviceRegex *regexp.Regexp
|
||||
var ssdpOtherDeviceUUIDRegex *regexp.Regexp
|
||||
var ssdpOtherServiceRegex *regexp.Regexp
|
||||
var ssdpOtherServiceUUIDRegex *regexp.Regexp
|
||||
var ssdpResponseStartLineRegexp *regexp.Regexp
|
||||
var ssdpServerStringRegexp *regexp.Regexp
|
||||
var ssdpRootDeviceUUIDRegex *regexp.Regexp
|
||||
var ssdpUPnPBareUUIDRegex *regexp.Regexp
|
||||
var ssdpUPnPDeviceRegex *regexp.Regexp
|
||||
var ssdpUPnPDeviceUUIDRegex *regexp.Regexp
|
||||
var ssdpUPnPServiceRegex *regexp.Regexp
|
||||
var ssdpUPnPServiceUUIDRegex *regexp.Regexp
|
||||
var ssdpUPnPUIDRegex *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
ssdpHNAPRegex = regexp.MustCompile("^hnap:(.+)$")
|
||||
ssdpOtherDeviceRegex = regexp.MustCompile("^urn:([^:]+):device:([^:]+)(:(.+))?$")
|
||||
ssdpOtherDeviceUUIDRegex = regexp.MustCompile("^uuid:([^:]+)::urn:([^:]+):device:([^:]+)(:(.+))?$")
|
||||
ssdpOtherServiceRegex = regexp.MustCompile("^urn:([^:]+):service:([^:]+)(:(.+))?$")
|
||||
ssdpOtherServiceUUIDRegex = regexp.MustCompile("^uuid:([^:]+)::urn:([^:]+):service:([^:]+)(:(.+))?$")
|
||||
ssdpResponseStartLineRegexp = regexp.MustCompile("^HTTP/([0-9\\.]+)$")
|
||||
ssdpServerStringRegexp = regexp.MustCompile("^([^ /,]+)(/([^ ,]+))?,?\\s+[Uu][Pp][Nn][Pp](/([^ ,]+))?,?\\s+([^/]+)(/(.+))?$")
|
||||
ssdpRootDeviceUUIDRegex = regexp.MustCompile("^uuid:([^:]+)::upnp:rootdevice$")
|
||||
ssdpUPnPBareUUIDRegex = regexp.MustCompile("^uuid:([^:]+)$")
|
||||
ssdpUPnPDeviceRegex = regexp.MustCompile("^urn:schemas-upnp-org:device:([^:]+)(:(.+))?$")
|
||||
ssdpUPnPDeviceUUIDRegex = regexp.MustCompile("uuid:([^:]+)::urn:schemas-upnp-org:device:([^:]+)(:(.+))?$")
|
||||
ssdpUPnPServiceRegex = regexp.MustCompile("^urn:schemas-upnp-org:service:([^:]+)(:(.+))?$")
|
||||
ssdpUPnPServiceUUIDRegex = regexp.MustCompile("uuid:([^:]+)::urn:schemas-upnp-org:service:([^:]+)(:(.+))?$")
|
||||
ssdpUPnPUIDRegex = regexp.MustCompile("^uuid:(.+)$")
|
||||
}
|
||||
|
||||
const (
|
||||
ssdpBroadcastGroup = "239.255.255.250:1900"
|
||||
ssdpBroadcastVersion = "udp"
|
||||
)
|
||||
|
||||
// Type protection for a device URI
|
||||
type Location string
|
||||
|
||||
// Type protection for a SSDP service key
|
||||
type ServiceKey string
|
||||
|
||||
// Type protection for a Universally Unique ID
|
||||
type UUID string
|
||||
|
||||
type ssdpServerDescription struct {
|
||||
os string
|
||||
os_version string
|
||||
upnp_version string
|
||||
product string
|
||||
productVersion string
|
||||
}
|
||||
|
||||
type ssdpResourceBase struct {
|
||||
ssdpServerDescription
|
||||
location Location
|
||||
uuid UUID
|
||||
}
|
||||
|
||||
// An abstraction of an SSDP service
|
||||
type Service interface {
|
||||
// The version of the service
|
||||
Version() int64
|
||||
}
|
||||
|
||||
type ssdpService struct {
|
||||
ssdpResourceBase
|
||||
name string
|
||||
version int64
|
||||
uri string
|
||||
}
|
||||
|
||||
func (this *ssdpService) Version() int64 {
|
||||
return this.version
|
||||
}
|
||||
|
||||
type ssdpServiceSet map[ServiceKey]Service
|
||||
|
||||
// An abstraction of an SSDP leaf device
|
||||
type Device interface {
|
||||
// The product name (e.g. "Sonos")
|
||||
Product() string
|
||||
// The product version (e.g. "28.1-83040 (BR100)")
|
||||
ProductVersion() string
|
||||
// The device name (e.h. "ZonePlayer")
|
||||
Name() string
|
||||
// A URI that can be queried for device capabilities
|
||||
Location() Location
|
||||
// The device's Universally Unique ID
|
||||
UUID() UUID
|
||||
// Search for a service in the device's capabilities; same
|
||||
// return semantics as querying a map
|
||||
Service(key ServiceKey) (service Service, has bool)
|
||||
// Return a list of services implemented by this device
|
||||
Services() []ServiceKey
|
||||
}
|
||||
|
||||
type ssdpDevice struct {
|
||||
ssdpResourceBase
|
||||
name string
|
||||
version int64
|
||||
uri string
|
||||
services ssdpServiceSet
|
||||
}
|
||||
|
||||
func (this *ssdpDevice) Product() string {
|
||||
return this.product
|
||||
}
|
||||
|
||||
func (this *ssdpDevice) ProductVersion() string {
|
||||
return this.productVersion
|
||||
}
|
||||
|
||||
func (this *ssdpDevice) Name() string {
|
||||
return this.name
|
||||
}
|
||||
|
||||
func (this *ssdpDevice) Location() Location {
|
||||
return this.location
|
||||
}
|
||||
|
||||
func (this *ssdpDevice) UUID() UUID {
|
||||
return this.uuid
|
||||
}
|
||||
|
||||
func (this *ssdpDevice) Service(key ServiceKey) (service Service, has bool) {
|
||||
service, has = this.services[key]
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDevice) Services() []ServiceKey {
|
||||
i := 0
|
||||
keys := make([]ServiceKey, len(this.services))
|
||||
for key, _ := range this.services {
|
||||
keys[i] = key
|
||||
i += 1
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// Indexes leaf devices by UUID
|
||||
type DeviceMap map[UUID]Device
|
||||
|
||||
type ssdpRootDevice struct {
|
||||
ssdpResourceBase
|
||||
Devices DeviceMap
|
||||
}
|
||||
|
||||
type ssdpRootDeviceMap map[Location]*ssdpRootDevice
|
||||
|
||||
// Discovered devices sorted by supported service
|
||||
type ServiceMap map[ServiceKey]DeviceMap
|
||||
|
||||
type ssdpResourceType int
|
||||
|
||||
const (
|
||||
ssdpTypessdpRootDevice ssdpResourceType = iota
|
||||
ssdpTypeService
|
||||
ssdpTypeDevice
|
||||
ssdpTypeHNAP
|
||||
ssdpTypeUUID
|
||||
ssdpTypeUnknown
|
||||
)
|
||||
|
||||
type ssdpResource struct {
|
||||
ssdpServerDescription
|
||||
ssdptype ssdpResourceType
|
||||
uuid UUID
|
||||
name string
|
||||
version int64
|
||||
uri string
|
||||
location Location
|
||||
children []*ssdpResource
|
||||
}
|
||||
|
||||
type ssdpMessageType int
|
||||
|
||||
const (
|
||||
ssdpSearch ssdpMessageType = iota
|
||||
ssdpNotify
|
||||
ssdpResponse
|
||||
ssdpInvalid
|
||||
)
|
||||
|
||||
type ssdpRawMessage struct {
|
||||
msgtype ssdpMessageType
|
||||
httpver string
|
||||
header map[string]string
|
||||
}
|
||||
|
||||
type ssdpNotifyMessage struct {
|
||||
_01_nls string
|
||||
cache_control string
|
||||
host string
|
||||
location Location
|
||||
nts string
|
||||
nt string
|
||||
opt string
|
||||
server string
|
||||
usn string
|
||||
x_rincon_bootseq string
|
||||
x_rincon_household string
|
||||
x_user_agent string
|
||||
}
|
||||
|
||||
type ssdpNotifyQueue chan *ssdpNotifyMessage
|
||||
|
||||
type ssdpResponseMessage struct {
|
||||
ssdpServerDescription
|
||||
_01_nls string
|
||||
al string
|
||||
cache_control string
|
||||
date string
|
||||
ext string
|
||||
location Location
|
||||
opt string
|
||||
st string
|
||||
usn string
|
||||
x_rincon_bootseq string
|
||||
x_rincon_household string
|
||||
x_rincon_variant string
|
||||
x_rincon_wifimode string
|
||||
x_user_agent string
|
||||
content_length string
|
||||
bootid_upnp_org string
|
||||
configid_upnp_org string
|
||||
household_smartspeaker_audio string
|
||||
x_av_server_info string
|
||||
}
|
||||
|
||||
type ssdpResponseQueue chan *ssdpResponseMessage
|
||||
|
||||
type ssdpConnection struct {
|
||||
conn *net.UDPConn
|
||||
addr *net.UDPAddr
|
||||
}
|
||||
|
||||
// A map of service key to minimum required version
|
||||
type ServiceQueryTerms map[ServiceKey]int64
|
||||
|
||||
// Encapsulates SSDP discovery, handles updates, and stores results
|
||||
type Manager interface {
|
||||
// Initiates SSDP discovery, where ifiname names a network device
|
||||
// to query, port gives a free port on that network device to listen
|
||||
// for responses, and the subscribe flag (currrently unimplemented)
|
||||
// determines whether to listen to asynchronous updates after the
|
||||
// initial query is complete.
|
||||
Discover(ifiname, port string, subscribe bool) error
|
||||
// After discovery is complete searches for devices implementing
|
||||
// the services specified in query.
|
||||
QueryServices(query ServiceQueryTerms) ServiceMap
|
||||
// Return the list of devices that were found during discovery
|
||||
Devices() DeviceMap
|
||||
// Shuts down asynchronous subscriptions to device state
|
||||
Close() error
|
||||
}
|
||||
|
||||
type ssdpDefaultManager struct {
|
||||
responseQueue ssdpResponseQueue
|
||||
notifyQueue ssdpNotifyQueue
|
||||
unicast ssdpConnection
|
||||
multicast ssdpConnection
|
||||
rootDeviceMap ssdpRootDeviceMap
|
||||
deviceMap DeviceMap
|
||||
serviceMap ServiceMap
|
||||
readyChan chan int
|
||||
closeChan chan int
|
||||
}
|
||||
|
||||
// Returns an empty manager ready for SSDP discovery
|
||||
func MakeManager() Manager {
|
||||
mgr := &ssdpDefaultManager{}
|
||||
mgr.responseQueue = make(ssdpResponseQueue)
|
||||
mgr.notifyQueue = make(ssdpNotifyQueue)
|
||||
mgr.unicast = ssdpConnection{}
|
||||
mgr.multicast = ssdpConnection{}
|
||||
mgr.rootDeviceMap = make(ssdpRootDeviceMap)
|
||||
mgr.deviceMap = make(DeviceMap)
|
||||
mgr.serviceMap = make(ServiceMap)
|
||||
mgr.readyChan = make(chan int)
|
||||
mgr.closeChan = make(chan int)
|
||||
return mgr
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) Discover(ifiname, port string, subscribe bool) (err error) {
|
||||
this.ssdpDiscoverImpl(ifiname, port, subscribe)
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) QueryServices(query ServiceQueryTerms) (results ServiceMap) {
|
||||
results = make(ServiceMap)
|
||||
for name, minver := range query {
|
||||
results[name] = make(DeviceMap)
|
||||
if dlist, has := this.serviceMap[name]; has {
|
||||
for uuid, _ := range dlist {
|
||||
de := this.deviceMap[uuid]
|
||||
if svc, has := de.Service(name); has {
|
||||
if minver <= svc.Version() {
|
||||
results[name][de.UUID()] = de
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) Devices() DeviceMap {
|
||||
return this.deviceMap
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) Close() (err error) {
|
||||
if nil != this.unicast.conn {
|
||||
this.unicast.conn.Close()
|
||||
<-this.closeChan
|
||||
}
|
||||
if nil != this.multicast.conn {
|
||||
this.multicast.conn.Close()
|
||||
<-this.closeChan
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ssdpNewDevice(res *ssdpResource) (de *ssdpDevice) {
|
||||
de = new(ssdpDevice)
|
||||
de.ssdpServerDescription = res.ssdpServerDescription
|
||||
de.uuid = res.uuid
|
||||
de.location = res.location
|
||||
de.name = res.name
|
||||
de.version = res.version
|
||||
de.uri = res.uri
|
||||
de.services = make(ssdpServiceSet)
|
||||
return
|
||||
}
|
||||
|
||||
func ssdpNewssdpRootDevice(res *ssdpResource) (rd *ssdpRootDevice) {
|
||||
rd = new(ssdpRootDevice)
|
||||
rd.ssdpServerDescription = res.ssdpServerDescription
|
||||
rd.uuid = res.uuid
|
||||
rd.location = res.location
|
||||
rd.Devices = make(DeviceMap)
|
||||
return
|
||||
}
|
||||
|
||||
func (rd *ssdpRootDevice) ssdpRequireEmbeddedDevice(de *ssdpDevice) {
|
||||
if _, has := rd.Devices[de.UUID()]; !has {
|
||||
rd.Devices[de.UUID()] = de
|
||||
}
|
||||
}
|
||||
|
||||
func ssdpNewRawMessage() *ssdpRawMessage {
|
||||
return &ssdpRawMessage{ssdpInvalid, "1.1", make(map[string]string)}
|
||||
}
|
||||
|
||||
func ssdpNewResource(uuid UUID) (res *ssdpResource) {
|
||||
res = new(ssdpResource)
|
||||
res.ssdptype = ssdpTypeUnknown
|
||||
res.uuid = uuid
|
||||
return
|
||||
}
|
||||
|
||||
func ssdpNewService(res *ssdpResource) (sv *ssdpService) {
|
||||
sv = new(ssdpService)
|
||||
sv.ssdpServerDescription = res.ssdpServerDescription
|
||||
sv.uuid = res.uuid
|
||||
sv.location = res.location
|
||||
sv.name = res.name
|
||||
sv.version = res.version
|
||||
sv.uri = res.uri
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpParseStartLineFields(raw *ssdpRawMessage, fields []string) {
|
||||
if "M-SEARCH" == fields[0] {
|
||||
raw.msgtype = ssdpSearch
|
||||
} else if "NOTIFY" == fields[0] {
|
||||
raw.msgtype = ssdpNotify
|
||||
} else if m := ssdpResponseStartLineRegexp.FindStringSubmatch(fields[0]); 0 < len(m) {
|
||||
raw.msgtype = ssdpResponse
|
||||
raw.httpver = m[1]
|
||||
} else {
|
||||
panic(fmt.Sprintf("Invalid start line `%s'", fields[0]))
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpParseStartLine(raw *ssdpRawMessage, line []byte) {
|
||||
fields := strings.Fields(string(line))
|
||||
if 3 != len(fields) {
|
||||
panic("Invalid start line")
|
||||
} else {
|
||||
this.ssdpParseStartLineFields(raw, fields)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpParseHeaderLine(raw *ssdpRawMessage, line []byte) {
|
||||
i := strings.Index(string(line), ":")
|
||||
if -1 == i {
|
||||
panic("Invalid header")
|
||||
}
|
||||
field := textproto.CanonicalMIMEHeaderKey(strings.TrimSpace(string(line[0:i])))
|
||||
value := strings.TrimSpace(string(line[i+1:]))
|
||||
if _, has := raw.header[field]; has {
|
||||
panic("Header field redefined")
|
||||
} else {
|
||||
raw.header[field] = value
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpParseInputLine(raw *ssdpRawMessage, line []byte, lineno int) {
|
||||
if 1 < lineno {
|
||||
this.ssdpParseHeaderLine(raw, line)
|
||||
} else {
|
||||
this.ssdpParseStartLine(raw, line)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpParseInput(msg []byte) (raw *ssdpRawMessage) {
|
||||
raw = ssdpNewRawMessage()
|
||||
bin := bufio.NewReader(bytes.NewReader(msg))
|
||||
var line []byte
|
||||
lineno := 0
|
||||
for {
|
||||
if fragment, is_prefix, err := bin.ReadLine(); nil == err {
|
||||
line = append(line, fragment...)
|
||||
if !is_prefix {
|
||||
lineno += 1
|
||||
if 1 < lineno && 0 == len(line) {
|
||||
break
|
||||
}
|
||||
this.ssdpParseInputLine(raw, line, lineno)
|
||||
line = nil
|
||||
}
|
||||
} else if io.EOF == err {
|
||||
panic("Premature end of header")
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpHandleNotify(raw *ssdpRawMessage) *ssdpNotifyMessage {
|
||||
msg := new(ssdpNotifyMessage) /*asynchronous reply from multicast*/
|
||||
for key, value := range raw.header {
|
||||
switch key {
|
||||
case "Location":
|
||||
msg.location = Location(value)
|
||||
case "Server":
|
||||
msg.server = value
|
||||
case "Host":
|
||||
msg.host = value
|
||||
case "Usn":
|
||||
msg.usn = value
|
||||
case "Cache-Control":
|
||||
msg.cache_control = value
|
||||
case "X-User-Agent":
|
||||
msg.x_user_agent = value
|
||||
case "X-Rincon-Bootseq":
|
||||
msg.x_rincon_bootseq = value
|
||||
case "X-Rincon-Household":
|
||||
msg.x_rincon_household = value
|
||||
case "Nts":
|
||||
msg.nts = value
|
||||
case "Nt":
|
||||
msg.nt = value
|
||||
case "Opt":
|
||||
msg.opt = value
|
||||
case "01-Nls":
|
||||
msg._01_nls = value
|
||||
default:
|
||||
log.Printf("No support for field `%s' (value `%s')", key, value)
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpHandleResponse(raw *ssdpRawMessage) *ssdpResponseMessage {
|
||||
msg := new(ssdpResponseMessage) /*synchronous reply from unicast*/
|
||||
for key, value := range raw.header {
|
||||
switch key {
|
||||
case "Location":
|
||||
msg.location = Location(value)
|
||||
case "St":
|
||||
msg.st = value
|
||||
case "Server":
|
||||
m := ssdpServerStringRegexp.FindStringSubmatch(value)
|
||||
if 0 < len(m) {
|
||||
msg.os = m[1]
|
||||
msg.os_version = m[3]
|
||||
msg.upnp_version = m[5]
|
||||
msg.product = m[6]
|
||||
msg.productVersion = m[8]
|
||||
} else {
|
||||
log.Printf("Invalid server description `%s'", value)
|
||||
}
|
||||
case "Opt":
|
||||
msg.opt = value
|
||||
case "Usn":
|
||||
msg.usn = value
|
||||
case "Ext":
|
||||
msg.ext = value
|
||||
case "Date":
|
||||
msg.date = value
|
||||
case "Cache-Control":
|
||||
msg.cache_control = value
|
||||
case "X-User-Agent":
|
||||
msg.x_user_agent = value
|
||||
case "X-Rincon-Bootseq":
|
||||
msg.x_rincon_bootseq = value
|
||||
case "X-Rincon-Household":
|
||||
msg.x_rincon_household = value
|
||||
case "X-Rincon-Variant":
|
||||
msg.x_rincon_variant = value
|
||||
case "X-Rincon-Wifimode":
|
||||
msg.x_rincon_wifimode = value
|
||||
case "Al":
|
||||
msg.al = value
|
||||
case "01-Nls":
|
||||
msg._01_nls = value
|
||||
case "Content-Length":
|
||||
msg.content_length = value
|
||||
case "Bootid.upnp.org":
|
||||
msg.bootid_upnp_org = value
|
||||
case "Configid.upnp.org":
|
||||
msg.configid_upnp_org = value
|
||||
case "Household.smartspeaker.audio":
|
||||
msg.household_smartspeaker_audio = value
|
||||
case "X-Av-Server-Info":
|
||||
msg.x_av_server_info = value
|
||||
default:
|
||||
log.Printf("No support for field `%s' (value `%s')", key, value)
|
||||
log.Printf("%v", raw)
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpHandleMessage(raw *ssdpRawMessage) {
|
||||
switch raw.msgtype {
|
||||
case ssdpSearch: /*ignore*/
|
||||
case ssdpResponse:
|
||||
this.responseQueue <- this.ssdpHandleResponse(raw)
|
||||
case ssdpNotify:
|
||||
this.notifyQueue <- this.ssdpHandleNotify(raw)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpDiscoverLoop(conn net.Conn) {
|
||||
this.readyChan <- 1
|
||||
msg := make([]byte, 65536) /*max size of a single UDP packet*/
|
||||
defer func() {
|
||||
recover()
|
||||
this.closeChan <- 1
|
||||
}()
|
||||
for {
|
||||
if n, err := conn.Read(msg); nil != err {
|
||||
panic(err)
|
||||
} else if raw := this.ssdpParseInput(msg[:n]); nil != raw {
|
||||
this.ssdpHandleMessage(raw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpUnicastDiscoverImpl(ifi *net.Interface, port string) (err error) {
|
||||
addrs, err := ifi.Addrs()
|
||||
if nil != err {
|
||||
return
|
||||
} else if 0 == len(addrs) {
|
||||
err = errors.New(fmt.Sprintf("No addresses found for interface %s", ifi.Name))
|
||||
return
|
||||
}
|
||||
var lip net.IP
|
||||
for _, addr := range addrs {
|
||||
if nil != addr.(*net.IPNet).IP.DefaultMask() {
|
||||
lip = addr.(*net.IPNet).IP
|
||||
break;
|
||||
}
|
||||
}
|
||||
laddr, err := net.ResolveUDPAddr(ssdpBroadcastVersion, net.JoinHostPort(lip.String(), port))
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
uc, err := net.ListenUDP(ssdpBroadcastVersion, laddr)
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
this.unicast.addr = laddr
|
||||
this.unicast.conn = uc
|
||||
go this.ssdpDiscoverLoop(uc)
|
||||
<-this.readyChan
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpMulticastDiscoverImpl(ifi *net.Interface, subscribe bool) (err error) {
|
||||
maddr, err := net.ResolveUDPAddr(ssdpBroadcastVersion, ssdpBroadcastGroup)
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
this.multicast.addr = maddr
|
||||
var mc *net.UDPConn
|
||||
if subscribe {
|
||||
mc, err = net.ListenMulticastUDP(ssdpBroadcastVersion, ifi, maddr)
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
this.multicast.conn = mc
|
||||
go this.ssdpDiscoverLoop(mc)
|
||||
<-this.readyChan
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpQueryMessage(timeout int) (msg *bytes.Buffer) {
|
||||
msg = new(bytes.Buffer)
|
||||
msg.WriteString("M-SEARCH * HTTP/1.1\r\n")
|
||||
msg.WriteString("HosT: 239.255.255.250:1900\r\n")
|
||||
msg.WriteString("MAN: \"ssdp:discover\"\r\n")
|
||||
msg.WriteString(fmt.Sprintf("MX: %d\r\n", timeout))
|
||||
msg.WriteString("ST: ssdp:all\r\n")
|
||||
msg.WriteString("USER-AGENT: unix/5.1 UPnP/1.1 crash/1.0\r\n")
|
||||
msg.WriteString("\r\n")
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpRequiressdpRootDevice(res *ssdpResource) (rd *ssdpRootDevice) {
|
||||
var has bool
|
||||
if rd, has = this.rootDeviceMap[res.location]; !has {
|
||||
rd = ssdpNewssdpRootDevice(res)
|
||||
this.rootDeviceMap[rd.location] = rd
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpRequireDevice(res *ssdpResource) (de *ssdpDevice) {
|
||||
if raw, has := this.deviceMap[res.uuid]; !has {
|
||||
de = ssdpNewDevice(res)
|
||||
this.deviceMap[res.uuid] = de
|
||||
} else {
|
||||
de = raw.(*ssdpDevice)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpNotifyssdpRootDevice(res *ssdpResource) {
|
||||
this.ssdpRequiressdpRootDevice(res)
|
||||
this.ssdpRequireDevice(res)
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpNotifyDevice(res *ssdpResource) {
|
||||
rd := this.ssdpRequiressdpRootDevice(res)
|
||||
de := this.ssdpRequireDevice(res)
|
||||
rd.ssdpRequireEmbeddedDevice(de)
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpGetServiceKey(sv *ssdpService) (key ServiceKey) {
|
||||
uri := sv.uri
|
||||
if 0 >= len(uri) {
|
||||
uri = "schemas-upnp-org"
|
||||
}
|
||||
key = ServiceKey(fmt.Sprintf("%s-%s", uri, sv.name))
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpRequireService(de *ssdpDevice, sv *ssdpService) {
|
||||
key := this.ssdpGetServiceKey(sv)
|
||||
if _, has := de.services[key]; !has {
|
||||
de.services[key] = sv
|
||||
if _, has := this.serviceMap[key]; !has {
|
||||
this.serviceMap[key] = make(DeviceMap)
|
||||
}
|
||||
this.serviceMap[key][de.UUID()] = de
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpNotifyService(res *ssdpResource) {
|
||||
de := this.ssdpRequireDevice(res)
|
||||
sv := ssdpNewService(res)
|
||||
this.ssdpRequireService(de, sv)
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpNotifyResource(res *ssdpResource) {
|
||||
switch res.ssdptype {
|
||||
case ssdpTypessdpRootDevice:
|
||||
this.ssdpNotifyssdpRootDevice(res)
|
||||
case ssdpTypeDevice:
|
||||
this.ssdpNotifyDevice(res)
|
||||
case ssdpTypeService:
|
||||
this.ssdpNotifyService(res)
|
||||
case ssdpTypeHNAP:
|
||||
/*TODO*/
|
||||
case ssdpTypeUUID:
|
||||
/*TODO ... not sure what to do*/
|
||||
default:
|
||||
log.Fatalf("Unhandled ssdptype %d", res.ssdptype)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludessdpRootDevice(ssdpsm *ssdpResponseMessage) {
|
||||
if n := ssdpRootDeviceUUIDRegex.FindStringSubmatch(ssdpsm.usn); 0 < len(n) {
|
||||
uuid := UUID(n[1])
|
||||
res := ssdpNewResource(uuid)
|
||||
res.ssdpServerDescription = ssdpsm.ssdpServerDescription
|
||||
res.uuid = uuid
|
||||
res.location = ssdpsm.location
|
||||
res.ssdptype = ssdpTypessdpRootDevice
|
||||
this.ssdpNotifyResource(res)
|
||||
} else {
|
||||
log.Printf("Invalid Unique Service Name for upnp:rootdevice: `%s'", ssdpsm.usn)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludeService(ssdpsm *ssdpResponseMessage) {
|
||||
if n := ssdpUPnPServiceUUIDRegex.FindStringSubmatch(ssdpsm.usn); 0 < len(n) {
|
||||
uuid := UUID(n[1])
|
||||
res := ssdpNewResource(uuid)
|
||||
res.ssdpServerDescription = ssdpsm.ssdpServerDescription
|
||||
res.location = ssdpsm.location
|
||||
res.ssdptype = ssdpTypeService
|
||||
res.name = n[2]
|
||||
var err error
|
||||
if res.version, err = strconv.ParseInt(n[4], 10, 4); nil != err {
|
||||
log.Printf("Error in parsing service version `%s'", n[4])
|
||||
}
|
||||
this.ssdpNotifyResource(res)
|
||||
} else {
|
||||
log.Printf("Invalid Unique Service Name for UPnP service: `%s'", ssdpsm.usn)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludeDevice(ssdpsm *ssdpResponseMessage) {
|
||||
if n := ssdpUPnPDeviceUUIDRegex.FindStringSubmatch(ssdpsm.usn); 0 < len(n) {
|
||||
uuid := UUID(n[1])
|
||||
res := ssdpNewResource(uuid)
|
||||
res.ssdpServerDescription = ssdpsm.ssdpServerDescription
|
||||
res.location = ssdpsm.location
|
||||
res.ssdptype = ssdpTypeDevice
|
||||
res.name = n[2]
|
||||
var err error
|
||||
if res.version, err = strconv.ParseInt(n[4], 10, 4); nil != err {
|
||||
log.Printf("Error in parsing device version `%s'", n[4])
|
||||
}
|
||||
this.ssdpNotifyResource(res)
|
||||
} else {
|
||||
log.Printf("Invalid Unique Service Name for UPnP device: `%s'", ssdpsm.usn)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludeUUID(ssdpsm *ssdpResponseMessage) {
|
||||
if n := ssdpUPnPBareUUIDRegex.FindStringSubmatch(ssdpsm.usn); 0 < len(n) {
|
||||
uuid := UUID(n[1])
|
||||
res := ssdpNewResource(uuid)
|
||||
res.ssdpServerDescription = ssdpsm.ssdpServerDescription
|
||||
res.location = ssdpsm.location
|
||||
res.ssdptype = ssdpTypeUUID
|
||||
this.ssdpNotifyResource(res)
|
||||
} else {
|
||||
log.Printf("Invalid Unique Service Name: `%s'", ssdpsm.usn)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludeHNAP(ssdpsm *ssdpResponseMessage, name string) {
|
||||
if n := ssdpUPnPBareUUIDRegex.FindStringSubmatch(ssdpsm.usn); 0 < len(n) {
|
||||
uuid := UUID(n[1])
|
||||
res := ssdpNewResource(uuid)
|
||||
res.ssdpServerDescription = ssdpsm.ssdpServerDescription
|
||||
res.location = ssdpsm.location
|
||||
res.ssdptype = ssdpTypeHNAP
|
||||
res.name = name
|
||||
this.ssdpNotifyResource(res)
|
||||
} else {
|
||||
log.Printf("Invalid Unique Service Name for HNAP: `%s'", ssdpsm.usn)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludeOtherService(ssdpsm *ssdpResponseMessage) {
|
||||
if n := ssdpOtherServiceUUIDRegex.FindStringSubmatch(ssdpsm.usn); 0 < len(n) {
|
||||
uuid := UUID(n[1])
|
||||
res := ssdpNewResource(uuid)
|
||||
res.ssdpServerDescription = ssdpsm.ssdpServerDescription
|
||||
res.location = ssdpsm.location
|
||||
res.ssdptype = ssdpTypeService
|
||||
res.uri = n[2]
|
||||
res.name = n[3]
|
||||
var err error
|
||||
if res.version, err = strconv.ParseInt(n[5], 10, 4); nil != err {
|
||||
log.Printf("Error in parsing service version `%s'", n[4])
|
||||
}
|
||||
this.ssdpNotifyResource(res)
|
||||
} else {
|
||||
log.Printf("Invalid Unique Service Name for third-party service: `%s'", ssdpsm.usn)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludeOtherDevice(ssdpsm *ssdpResponseMessage) {
|
||||
if n := ssdpOtherDeviceUUIDRegex.FindStringSubmatch(ssdpsm.usn); 0 < len(n) {
|
||||
uuid := UUID(n[1])
|
||||
res := ssdpNewResource(uuid)
|
||||
res.ssdpServerDescription = ssdpsm.ssdpServerDescription
|
||||
res.location = ssdpsm.location
|
||||
res.ssdptype = ssdpTypeDevice
|
||||
res.uri = n[2]
|
||||
res.name = n[3]
|
||||
var err error
|
||||
if res.version, err = strconv.ParseInt(n[5], 10, 4); nil != err {
|
||||
log.Printf("Error in parsing device version `%s'", n[4])
|
||||
}
|
||||
this.ssdpNotifyResource(res)
|
||||
} else {
|
||||
log.Printf("Invalid Unique Service Name for third-party device: `%s'", ssdpsm.usn)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludeResponse(msg *ssdpResponseMessage) {
|
||||
if "upnp:rootdevice" == msg.st {
|
||||
this.ssdpIncludessdpRootDevice(msg)
|
||||
} else if m := ssdpUPnPServiceRegex.FindStringSubmatch(msg.st); 0 < len(m) {
|
||||
this.ssdpIncludeService(msg)
|
||||
} else if m := ssdpUPnPDeviceRegex.FindStringSubmatch(msg.st); 0 < len(m) {
|
||||
this.ssdpIncludeDevice(msg)
|
||||
} else if m := ssdpUPnPUIDRegex.FindStringSubmatch(msg.st); 0 < len(m) {
|
||||
this.ssdpIncludeUUID(msg)
|
||||
} else if m := ssdpHNAPRegex.FindStringSubmatch(msg.st); 0 < len(m) {
|
||||
this.ssdpIncludeHNAP(msg, m[1])
|
||||
} else if m := ssdpOtherServiceRegex.FindStringSubmatch(msg.st); 0 < len(m) {
|
||||
this.ssdpIncludeOtherService(msg)
|
||||
} else if m := ssdpOtherDeviceRegex.FindStringSubmatch(msg.st); 0 < len(m) {
|
||||
this.ssdpIncludeOtherDevice(msg)
|
||||
} else {
|
||||
log.Printf("Unsupported search term [ST] `%s'", msg.st)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpIncludeNotification(msg *ssdpNotifyMessage) {
|
||||
/*TODO*/
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpSendQuery(timeout int) (err error) {
|
||||
msg := this.ssdpQueryMessage(timeout)
|
||||
if _, err = this.unicast.conn.WriteTo(msg.Bytes(), this.multicast.addr); nil != err {
|
||||
return
|
||||
} else {
|
||||
timeout := time.NewTimer(time.Duration(timeout) * time.Second)
|
||||
done := false
|
||||
for !done {
|
||||
select {
|
||||
case m := <-this.responseQueue:
|
||||
this.ssdpIncludeResponse(m)
|
||||
case raw := <-this.notifyQueue:
|
||||
this.ssdpIncludeNotification(raw)
|
||||
case <-timeout.C:
|
||||
done = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpQueryLoop() (err error) {
|
||||
for i := 0; i < 2; i++ {
|
||||
if err = this.ssdpSendQuery(3 /*timeout seconds*/); nil != err {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ssdpDefaultManager) ssdpDiscoverImpl(ifiname, port string, subscribe bool) {
|
||||
ifi, err := net.InterfaceByName(ifiname)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
} else if err = this.ssdpUnicastDiscoverImpl(ifi, port); nil != err {
|
||||
panic(err)
|
||||
} else if err = this.ssdpMulticastDiscoverImpl(ifi, subscribe); nil != err {
|
||||
panic(err)
|
||||
} else if err = this.ssdpQueryLoop(); nil != err {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
-1379
File diff suppressed because it is too large
Load Diff
-593
@@ -1,593 +0,0 @@
|
||||
package alarmclock
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:AlarmClock:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/AlarmClock/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/AlarmClock/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
SetFormat *SetFormatArgs `xml:"u:SetFormat,omitempty"`
|
||||
GetFormat *GetFormatArgs `xml:"u:GetFormat,omitempty"`
|
||||
SetTimeZone *SetTimeZoneArgs `xml:"u:SetTimeZone,omitempty"`
|
||||
GetTimeZone *GetTimeZoneArgs `xml:"u:GetTimeZone,omitempty"`
|
||||
GetTimeZoneAndRule *GetTimeZoneAndRuleArgs `xml:"u:GetTimeZoneAndRule,omitempty"`
|
||||
GetTimeZoneRule *GetTimeZoneRuleArgs `xml:"u:GetTimeZoneRule,omitempty"`
|
||||
SetTimeServer *SetTimeServerArgs `xml:"u:SetTimeServer,omitempty"`
|
||||
GetTimeServer *GetTimeServerArgs `xml:"u:GetTimeServer,omitempty"`
|
||||
SetTimeNow *SetTimeNowArgs `xml:"u:SetTimeNow,omitempty"`
|
||||
GetHouseholdTimeAtStamp *GetHouseholdTimeAtStampArgs `xml:"u:GetHouseholdTimeAtStamp,omitempty"`
|
||||
GetTimeNow *GetTimeNowArgs `xml:"u:GetTimeNow,omitempty"`
|
||||
CreateAlarm *CreateAlarmArgs `xml:"u:CreateAlarm,omitempty"`
|
||||
UpdateAlarm *UpdateAlarmArgs `xml:"u:UpdateAlarm,omitempty"`
|
||||
DestroyAlarm *DestroyAlarmArgs `xml:"u:DestroyAlarm,omitempty"`
|
||||
ListAlarms *ListAlarmsArgs `xml:"u:ListAlarms,omitempty"`
|
||||
SetDailyIndexRefreshTime *SetDailyIndexRefreshTimeArgs `xml:"u:SetDailyIndexRefreshTime,omitempty"`
|
||||
GetDailyIndexRefreshTime *GetDailyIndexRefreshTimeArgs `xml:"u:GetDailyIndexRefreshTime,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
SetFormat *SetFormatResponse `xml:"SetFormatResponse,omitempty"`
|
||||
GetFormat *GetFormatResponse `xml:"GetFormatResponse,omitempty"`
|
||||
SetTimeZone *SetTimeZoneResponse `xml:"SetTimeZoneResponse,omitempty"`
|
||||
GetTimeZone *GetTimeZoneResponse `xml:"GetTimeZoneResponse,omitempty"`
|
||||
GetTimeZoneAndRule *GetTimeZoneAndRuleResponse `xml:"GetTimeZoneAndRuleResponse,omitempty"`
|
||||
GetTimeZoneRule *GetTimeZoneRuleResponse `xml:"GetTimeZoneRuleResponse,omitempty"`
|
||||
SetTimeServer *SetTimeServerResponse `xml:"SetTimeServerResponse,omitempty"`
|
||||
GetTimeServer *GetTimeServerResponse `xml:"GetTimeServerResponse,omitempty"`
|
||||
SetTimeNow *SetTimeNowResponse `xml:"SetTimeNowResponse,omitempty"`
|
||||
GetHouseholdTimeAtStamp *GetHouseholdTimeAtStampResponse `xml:"GetHouseholdTimeAtStampResponse,omitempty"`
|
||||
GetTimeNow *GetTimeNowResponse `xml:"GetTimeNowResponse,omitempty"`
|
||||
CreateAlarm *CreateAlarmResponse `xml:"CreateAlarmResponse,omitempty"`
|
||||
UpdateAlarm *UpdateAlarmResponse `xml:"UpdateAlarmResponse,omitempty"`
|
||||
DestroyAlarm *DestroyAlarmResponse `xml:"DestroyAlarmResponse,omitempty"`
|
||||
ListAlarms *ListAlarmsResponse `xml:"ListAlarmsResponse,omitempty"`
|
||||
SetDailyIndexRefreshTime *SetDailyIndexRefreshTimeResponse `xml:"SetDailyIndexRefreshTimeResponse,omitempty"`
|
||||
GetDailyIndexRefreshTime *GetDailyIndexRefreshTimeResponse `xml:"GetDailyIndexRefreshTimeResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type SetFormatArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
DesiredTimeFormat string `xml:"DesiredTimeFormat"`
|
||||
DesiredDateFormat string `xml:"DesiredDateFormat"`
|
||||
}
|
||||
type SetFormatResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetFormat(httpClient *http.Client, args *SetFormatArgs) (*SetFormatResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetFormat`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetFormat: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetFormat == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.SetFormat()`)
|
||||
}
|
||||
|
||||
return r.Body.SetFormat, nil
|
||||
}
|
||||
|
||||
type GetFormatArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetFormatResponse struct {
|
||||
CurrentTimeFormat string `xml:"CurrentTimeFormat"`
|
||||
CurrentDateFormat string `xml:"CurrentDateFormat"`
|
||||
}
|
||||
|
||||
func (s *Service) GetFormat(httpClient *http.Client, args *GetFormatArgs) (*GetFormatResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetFormat`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetFormat: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetFormat == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.GetFormat()`)
|
||||
}
|
||||
|
||||
return r.Body.GetFormat, nil
|
||||
}
|
||||
|
||||
type SetTimeZoneArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Index int32 `xml:"Index"`
|
||||
AutoAdjustDst bool `xml:"AutoAdjustDst"`
|
||||
}
|
||||
type SetTimeZoneResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetTimeZone(httpClient *http.Client, args *SetTimeZoneArgs) (*SetTimeZoneResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetTimeZone`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetTimeZone: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetTimeZone == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.SetTimeZone()`)
|
||||
}
|
||||
|
||||
return r.Body.SetTimeZone, nil
|
||||
}
|
||||
|
||||
type GetTimeZoneArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetTimeZoneResponse struct {
|
||||
Index int32 `xml:"Index"`
|
||||
AutoAdjustDst bool `xml:"AutoAdjustDst"`
|
||||
}
|
||||
|
||||
func (s *Service) GetTimeZone(httpClient *http.Client, args *GetTimeZoneArgs) (*GetTimeZoneResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetTimeZone`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetTimeZone: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetTimeZone == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeZone()`)
|
||||
}
|
||||
|
||||
return r.Body.GetTimeZone, nil
|
||||
}
|
||||
|
||||
type GetTimeZoneAndRuleArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetTimeZoneAndRuleResponse struct {
|
||||
Index int32 `xml:"Index"`
|
||||
AutoAdjustDst bool `xml:"AutoAdjustDst"`
|
||||
CurrentTimeZone string `xml:"CurrentTimeZone"`
|
||||
}
|
||||
|
||||
func (s *Service) GetTimeZoneAndRule(httpClient *http.Client, args *GetTimeZoneAndRuleArgs) (*GetTimeZoneAndRuleResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetTimeZoneAndRule`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetTimeZoneAndRule: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetTimeZoneAndRule == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeZoneAndRule()`)
|
||||
}
|
||||
|
||||
return r.Body.GetTimeZoneAndRule, nil
|
||||
}
|
||||
|
||||
type GetTimeZoneRuleArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Index int32 `xml:"Index"`
|
||||
}
|
||||
type GetTimeZoneRuleResponse struct {
|
||||
TimeZone string `xml:"TimeZone"`
|
||||
}
|
||||
|
||||
func (s *Service) GetTimeZoneRule(httpClient *http.Client, args *GetTimeZoneRuleArgs) (*GetTimeZoneRuleResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetTimeZoneRule`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetTimeZoneRule: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetTimeZoneRule == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeZoneRule()`)
|
||||
}
|
||||
|
||||
return r.Body.GetTimeZoneRule, nil
|
||||
}
|
||||
|
||||
type SetTimeServerArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
DesiredTimeServer string `xml:"DesiredTimeServer"`
|
||||
}
|
||||
type SetTimeServerResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetTimeServer(httpClient *http.Client, args *SetTimeServerArgs) (*SetTimeServerResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetTimeServer`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetTimeServer: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetTimeServer == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.SetTimeServer()`)
|
||||
}
|
||||
|
||||
return r.Body.SetTimeServer, nil
|
||||
}
|
||||
|
||||
type GetTimeServerArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetTimeServerResponse struct {
|
||||
CurrentTimeServer string `xml:"CurrentTimeServer"`
|
||||
}
|
||||
|
||||
func (s *Service) GetTimeServer(httpClient *http.Client, args *GetTimeServerArgs) (*GetTimeServerResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetTimeServer`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetTimeServer: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetTimeServer == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeServer()`)
|
||||
}
|
||||
|
||||
return r.Body.GetTimeServer, nil
|
||||
}
|
||||
|
||||
type SetTimeNowArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
DesiredTime string `xml:"DesiredTime"`
|
||||
TimeZoneForDesiredTime string `xml:"TimeZoneForDesiredTime"`
|
||||
}
|
||||
type SetTimeNowResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetTimeNow(httpClient *http.Client, args *SetTimeNowArgs) (*SetTimeNowResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetTimeNow`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetTimeNow: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetTimeNow == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.SetTimeNow()`)
|
||||
}
|
||||
|
||||
return r.Body.SetTimeNow, nil
|
||||
}
|
||||
|
||||
type GetHouseholdTimeAtStampArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
TimeStamp string `xml:"TimeStamp"`
|
||||
}
|
||||
type GetHouseholdTimeAtStampResponse struct {
|
||||
HouseholdUTCTime string `xml:"HouseholdUTCTime"`
|
||||
}
|
||||
|
||||
func (s *Service) GetHouseholdTimeAtStamp(httpClient *http.Client, args *GetHouseholdTimeAtStampArgs) (*GetHouseholdTimeAtStampResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetHouseholdTimeAtStamp`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetHouseholdTimeAtStamp: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetHouseholdTimeAtStamp == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.GetHouseholdTimeAtStamp()`)
|
||||
}
|
||||
|
||||
return r.Body.GetHouseholdTimeAtStamp, nil
|
||||
}
|
||||
|
||||
type GetTimeNowArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetTimeNowResponse struct {
|
||||
CurrentUTCTime string `xml:"CurrentUTCTime"`
|
||||
CurrentLocalTime string `xml:"CurrentLocalTime"`
|
||||
CurrentTimeZone string `xml:"CurrentTimeZone"`
|
||||
CurrentTimeGeneration uint32 `xml:"CurrentTimeGeneration"`
|
||||
}
|
||||
|
||||
func (s *Service) GetTimeNow(httpClient *http.Client, args *GetTimeNowArgs) (*GetTimeNowResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetTimeNow`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetTimeNow: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetTimeNow == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeNow()`)
|
||||
}
|
||||
|
||||
return r.Body.GetTimeNow, nil
|
||||
}
|
||||
|
||||
type CreateAlarmArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
StartLocalTime string `xml:"StartLocalTime"`
|
||||
Duration string `xml:"Duration"`
|
||||
// Allowed Value: ONCE
|
||||
// Allowed Value: WEEKDAYS
|
||||
// Allowed Value: WEEKENDS
|
||||
// Allowed Value: DAILY
|
||||
Recurrence string `xml:"Recurrence"`
|
||||
Enabled bool `xml:"Enabled"`
|
||||
RoomUUID string `xml:"RoomUUID"`
|
||||
ProgramURI string `xml:"ProgramURI"`
|
||||
ProgramMetaData string `xml:"ProgramMetaData"`
|
||||
// Allowed Value: NORMAL
|
||||
// Allowed Value: REPEAT_ALL
|
||||
// Allowed Value: SHUFFLE_NOREPEAT
|
||||
// Allowed Value: SHUFFLE
|
||||
PlayMode string `xml:"PlayMode"`
|
||||
Volume uint16 `xml:"Volume"`
|
||||
IncludeLinkedZones bool `xml:"IncludeLinkedZones"`
|
||||
}
|
||||
type CreateAlarmResponse struct {
|
||||
AssignedID uint32 `xml:"AssignedID"`
|
||||
}
|
||||
|
||||
func (s *Service) CreateAlarm(httpClient *http.Client, args *CreateAlarmArgs) (*CreateAlarmResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`CreateAlarm`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{CreateAlarm: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.CreateAlarm == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.CreateAlarm()`)
|
||||
}
|
||||
|
||||
return r.Body.CreateAlarm, nil
|
||||
}
|
||||
|
||||
type UpdateAlarmArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ID uint32 `xml:"ID"`
|
||||
StartLocalTime string `xml:"StartLocalTime"`
|
||||
Duration string `xml:"Duration"`
|
||||
// Allowed Value: ONCE
|
||||
// Allowed Value: WEEKDAYS
|
||||
// Allowed Value: WEEKENDS
|
||||
// Allowed Value: DAILY
|
||||
Recurrence string `xml:"Recurrence"`
|
||||
Enabled bool `xml:"Enabled"`
|
||||
RoomUUID string `xml:"RoomUUID"`
|
||||
ProgramURI string `xml:"ProgramURI"`
|
||||
ProgramMetaData string `xml:"ProgramMetaData"`
|
||||
// Allowed Value: NORMAL
|
||||
// Allowed Value: REPEAT_ALL
|
||||
// Allowed Value: SHUFFLE_NOREPEAT
|
||||
// Allowed Value: SHUFFLE
|
||||
PlayMode string `xml:"PlayMode"`
|
||||
Volume uint16 `xml:"Volume"`
|
||||
IncludeLinkedZones bool `xml:"IncludeLinkedZones"`
|
||||
}
|
||||
type UpdateAlarmResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) UpdateAlarm(httpClient *http.Client, args *UpdateAlarmArgs) (*UpdateAlarmResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`UpdateAlarm`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{UpdateAlarm: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.UpdateAlarm == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.UpdateAlarm()`)
|
||||
}
|
||||
|
||||
return r.Body.UpdateAlarm, nil
|
||||
}
|
||||
|
||||
type DestroyAlarmArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ID uint32 `xml:"ID"`
|
||||
}
|
||||
type DestroyAlarmResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) DestroyAlarm(httpClient *http.Client, args *DestroyAlarmArgs) (*DestroyAlarmResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`DestroyAlarm`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{DestroyAlarm: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.DestroyAlarm == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.DestroyAlarm()`)
|
||||
}
|
||||
|
||||
return r.Body.DestroyAlarm, nil
|
||||
}
|
||||
|
||||
type ListAlarmsArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type ListAlarmsResponse struct {
|
||||
CurrentAlarmList string `xml:"CurrentAlarmList"`
|
||||
CurrentAlarmListVersion string `xml:"CurrentAlarmListVersion"`
|
||||
}
|
||||
|
||||
func (s *Service) ListAlarms(httpClient *http.Client, args *ListAlarmsArgs) (*ListAlarmsResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ListAlarms`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ListAlarms: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ListAlarms == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.ListAlarms()`)
|
||||
}
|
||||
|
||||
return r.Body.ListAlarms, nil
|
||||
}
|
||||
|
||||
type SetDailyIndexRefreshTimeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
DesiredDailyIndexRefreshTime string `xml:"DesiredDailyIndexRefreshTime"`
|
||||
}
|
||||
type SetDailyIndexRefreshTimeResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetDailyIndexRefreshTime(httpClient *http.Client, args *SetDailyIndexRefreshTimeArgs) (*SetDailyIndexRefreshTimeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetDailyIndexRefreshTime`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetDailyIndexRefreshTime: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetDailyIndexRefreshTime == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.SetDailyIndexRefreshTime()`)
|
||||
}
|
||||
|
||||
return r.Body.SetDailyIndexRefreshTime, nil
|
||||
}
|
||||
|
||||
type GetDailyIndexRefreshTimeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetDailyIndexRefreshTimeResponse struct {
|
||||
CurrentDailyIndexRefreshTime string `xml:"CurrentDailyIndexRefreshTime"`
|
||||
}
|
||||
|
||||
func (s *Service) GetDailyIndexRefreshTime(httpClient *http.Client, args *GetDailyIndexRefreshTimeArgs) (*GetDailyIndexRefreshTimeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetDailyIndexRefreshTime`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetDailyIndexRefreshTime: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetDailyIndexRefreshTime == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling alarmclock.GetDailyIndexRefreshTime()`)
|
||||
}
|
||||
|
||||
return r.Body.GetDailyIndexRefreshTime, nil
|
||||
}
|
||||
-174
@@ -1,174 +0,0 @@
|
||||
package connectionmanager
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:ConnectionManager:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/MediaServer/ConnectionManager/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/MediaServer/ConnectionManager/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
GetProtocolInfo *GetProtocolInfoArgs `xml:"u:GetProtocolInfo,omitempty"`
|
||||
GetCurrentConnectionIDs *GetCurrentConnectionIDsArgs `xml:"u:GetCurrentConnectionIDs,omitempty"`
|
||||
GetCurrentConnectionInfo *GetCurrentConnectionInfoArgs `xml:"u:GetCurrentConnectionInfo,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
GetProtocolInfo *GetProtocolInfoResponse `xml:"GetProtocolInfoResponse,omitempty"`
|
||||
GetCurrentConnectionIDs *GetCurrentConnectionIDsResponse `xml:"GetCurrentConnectionIDsResponse,omitempty"`
|
||||
GetCurrentConnectionInfo *GetCurrentConnectionInfoResponse `xml:"GetCurrentConnectionInfoResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type GetProtocolInfoArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetProtocolInfoResponse struct {
|
||||
Source string `xml:"Source"`
|
||||
Sink string `xml:"Sink"`
|
||||
}
|
||||
|
||||
func (s *Service) GetProtocolInfo(httpClient *http.Client, args *GetProtocolInfoArgs) (*GetProtocolInfoResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetProtocolInfo`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetProtocolInfo: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetProtocolInfo == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling connectionmanager.GetProtocolInfo()`)
|
||||
}
|
||||
|
||||
return r.Body.GetProtocolInfo, nil
|
||||
}
|
||||
|
||||
type GetCurrentConnectionIDsArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetCurrentConnectionIDsResponse struct {
|
||||
ConnectionIDs string `xml:"ConnectionIDs"`
|
||||
}
|
||||
|
||||
func (s *Service) GetCurrentConnectionIDs(httpClient *http.Client, args *GetCurrentConnectionIDsArgs) (*GetCurrentConnectionIDsResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetCurrentConnectionIDs`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetCurrentConnectionIDs: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetCurrentConnectionIDs == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling connectionmanager.GetCurrentConnectionIDs()`)
|
||||
}
|
||||
|
||||
return r.Body.GetCurrentConnectionIDs, nil
|
||||
}
|
||||
|
||||
type GetCurrentConnectionInfoArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ConnectionID int32 `xml:"ConnectionID"`
|
||||
}
|
||||
type GetCurrentConnectionInfoResponse struct {
|
||||
RcsID int32 `xml:"RcsID"`
|
||||
AVTransportID int32 `xml:"AVTransportID"`
|
||||
ProtocolInfo string `xml:"ProtocolInfo"`
|
||||
PeerConnectionManager string `xml:"PeerConnectionManager"`
|
||||
PeerConnectionID int32 `xml:"PeerConnectionID"`
|
||||
Direction string `xml:"Direction"`
|
||||
Status string `xml:"Status"`
|
||||
}
|
||||
|
||||
func (s *Service) GetCurrentConnectionInfo(httpClient *http.Client, args *GetCurrentConnectionInfoArgs) (*GetCurrentConnectionInfoResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetCurrentConnectionInfo`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetCurrentConnectionInfo: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetCurrentConnectionInfo == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling connectionmanager.GetCurrentConnectionInfo()`)
|
||||
}
|
||||
|
||||
return r.Body.GetCurrentConnectionInfo, nil
|
||||
}
|
||||
-539
@@ -1,539 +0,0 @@
|
||||
package contentdirectory
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:ContentDirectory:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/MediaServer/ContentDirectory/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/MediaServer/ContentDirectory/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
GetSearchCapabilities *GetSearchCapabilitiesArgs `xml:"u:GetSearchCapabilities,omitempty"`
|
||||
GetSortCapabilities *GetSortCapabilitiesArgs `xml:"u:GetSortCapabilities,omitempty"`
|
||||
GetSystemUpdateID *GetSystemUpdateIDArgs `xml:"u:GetSystemUpdateID,omitempty"`
|
||||
GetAlbumArtistDisplayOption *GetAlbumArtistDisplayOptionArgs `xml:"u:GetAlbumArtistDisplayOption,omitempty"`
|
||||
GetLastIndexChange *GetLastIndexChangeArgs `xml:"u:GetLastIndexChange,omitempty"`
|
||||
Browse *BrowseArgs `xml:"u:Browse,omitempty"`
|
||||
FindPrefix *FindPrefixArgs `xml:"u:FindPrefix,omitempty"`
|
||||
GetAllPrefixLocations *GetAllPrefixLocationsArgs `xml:"u:GetAllPrefixLocations,omitempty"`
|
||||
CreateObject *CreateObjectArgs `xml:"u:CreateObject,omitempty"`
|
||||
UpdateObject *UpdateObjectArgs `xml:"u:UpdateObject,omitempty"`
|
||||
DestroyObject *DestroyObjectArgs `xml:"u:DestroyObject,omitempty"`
|
||||
RefreshShareIndex *RefreshShareIndexArgs `xml:"u:RefreshShareIndex,omitempty"`
|
||||
RequestResort *RequestResortArgs `xml:"u:RequestResort,omitempty"`
|
||||
GetShareIndexInProgress *GetShareIndexInProgressArgs `xml:"u:GetShareIndexInProgress,omitempty"`
|
||||
GetBrowseable *GetBrowseableArgs `xml:"u:GetBrowseable,omitempty"`
|
||||
SetBrowseable *SetBrowseableArgs `xml:"u:SetBrowseable,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
GetSearchCapabilities *GetSearchCapabilitiesResponse `xml:"GetSearchCapabilitiesResponse,omitempty"`
|
||||
GetSortCapabilities *GetSortCapabilitiesResponse `xml:"GetSortCapabilitiesResponse,omitempty"`
|
||||
GetSystemUpdateID *GetSystemUpdateIDResponse `xml:"GetSystemUpdateIDResponse,omitempty"`
|
||||
GetAlbumArtistDisplayOption *GetAlbumArtistDisplayOptionResponse `xml:"GetAlbumArtistDisplayOptionResponse,omitempty"`
|
||||
GetLastIndexChange *GetLastIndexChangeResponse `xml:"GetLastIndexChangeResponse,omitempty"`
|
||||
Browse *BrowseResponse `xml:"BrowseResponse,omitempty"`
|
||||
FindPrefix *FindPrefixResponse `xml:"FindPrefixResponse,omitempty"`
|
||||
GetAllPrefixLocations *GetAllPrefixLocationsResponse `xml:"GetAllPrefixLocationsResponse,omitempty"`
|
||||
CreateObject *CreateObjectResponse `xml:"CreateObjectResponse,omitempty"`
|
||||
UpdateObject *UpdateObjectResponse `xml:"UpdateObjectResponse,omitempty"`
|
||||
DestroyObject *DestroyObjectResponse `xml:"DestroyObjectResponse,omitempty"`
|
||||
RefreshShareIndex *RefreshShareIndexResponse `xml:"RefreshShareIndexResponse,omitempty"`
|
||||
RequestResort *RequestResortResponse `xml:"RequestResortResponse,omitempty"`
|
||||
GetShareIndexInProgress *GetShareIndexInProgressResponse `xml:"GetShareIndexInProgressResponse,omitempty"`
|
||||
GetBrowseable *GetBrowseableResponse `xml:"GetBrowseableResponse,omitempty"`
|
||||
SetBrowseable *SetBrowseableResponse `xml:"SetBrowseableResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type GetSearchCapabilitiesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetSearchCapabilitiesResponse struct {
|
||||
SearchCaps string `xml:"SearchCaps"`
|
||||
}
|
||||
|
||||
func (s *Service) GetSearchCapabilities(httpClient *http.Client, args *GetSearchCapabilitiesArgs) (*GetSearchCapabilitiesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetSearchCapabilities`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetSearchCapabilities: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetSearchCapabilities == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetSearchCapabilities()`)
|
||||
}
|
||||
|
||||
return r.Body.GetSearchCapabilities, nil
|
||||
}
|
||||
|
||||
type GetSortCapabilitiesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetSortCapabilitiesResponse struct {
|
||||
SortCaps string `xml:"SortCaps"`
|
||||
}
|
||||
|
||||
func (s *Service) GetSortCapabilities(httpClient *http.Client, args *GetSortCapabilitiesArgs) (*GetSortCapabilitiesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetSortCapabilities`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetSortCapabilities: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetSortCapabilities == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetSortCapabilities()`)
|
||||
}
|
||||
|
||||
return r.Body.GetSortCapabilities, nil
|
||||
}
|
||||
|
||||
type GetSystemUpdateIDArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetSystemUpdateIDResponse struct {
|
||||
Id uint32 `xml:"Id"`
|
||||
}
|
||||
|
||||
func (s *Service) GetSystemUpdateID(httpClient *http.Client, args *GetSystemUpdateIDArgs) (*GetSystemUpdateIDResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetSystemUpdateID`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetSystemUpdateID: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetSystemUpdateID == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetSystemUpdateID()`)
|
||||
}
|
||||
|
||||
return r.Body.GetSystemUpdateID, nil
|
||||
}
|
||||
|
||||
type GetAlbumArtistDisplayOptionArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetAlbumArtistDisplayOptionResponse struct {
|
||||
AlbumArtistDisplayOption string `xml:"AlbumArtistDisplayOption"`
|
||||
}
|
||||
|
||||
func (s *Service) GetAlbumArtistDisplayOption(httpClient *http.Client, args *GetAlbumArtistDisplayOptionArgs) (*GetAlbumArtistDisplayOptionResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetAlbumArtistDisplayOption`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetAlbumArtistDisplayOption: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetAlbumArtistDisplayOption == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetAlbumArtistDisplayOption()`)
|
||||
}
|
||||
|
||||
return r.Body.GetAlbumArtistDisplayOption, nil
|
||||
}
|
||||
|
||||
type GetLastIndexChangeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetLastIndexChangeResponse struct {
|
||||
LastIndexChange string `xml:"LastIndexChange"`
|
||||
}
|
||||
|
||||
func (s *Service) GetLastIndexChange(httpClient *http.Client, args *GetLastIndexChangeArgs) (*GetLastIndexChangeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetLastIndexChange`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetLastIndexChange: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetLastIndexChange == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetLastIndexChange()`)
|
||||
}
|
||||
|
||||
return r.Body.GetLastIndexChange, nil
|
||||
}
|
||||
|
||||
type BrowseArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ObjectID string `xml:"ObjectID"`
|
||||
// Allowed Value: BrowseMetadata
|
||||
// Allowed Value: BrowseDirectChildren
|
||||
BrowseFlag string `xml:"BrowseFlag"`
|
||||
Filter string `xml:"Filter"`
|
||||
StartingIndex uint32 `xml:"StartingIndex"`
|
||||
RequestedCount uint32 `xml:"RequestedCount"`
|
||||
SortCriteria string `xml:"SortCriteria"`
|
||||
}
|
||||
type BrowseResponse struct {
|
||||
Result string `xml:"Result"`
|
||||
NumberReturned uint32 `xml:"NumberReturned"`
|
||||
TotalMatches uint32 `xml:"TotalMatches"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) Browse(httpClient *http.Client, args *BrowseArgs) (*BrowseResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Browse`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Browse: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Browse == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.Browse()`)
|
||||
}
|
||||
|
||||
return r.Body.Browse, nil
|
||||
}
|
||||
|
||||
type FindPrefixArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ObjectID string `xml:"ObjectID"`
|
||||
Prefix string `xml:"Prefix"`
|
||||
}
|
||||
type FindPrefixResponse struct {
|
||||
StartingIndex uint32 `xml:"StartingIndex"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) FindPrefix(httpClient *http.Client, args *FindPrefixArgs) (*FindPrefixResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`FindPrefix`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{FindPrefix: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.FindPrefix == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.FindPrefix()`)
|
||||
}
|
||||
|
||||
return r.Body.FindPrefix, nil
|
||||
}
|
||||
|
||||
type GetAllPrefixLocationsArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ObjectID string `xml:"ObjectID"`
|
||||
}
|
||||
type GetAllPrefixLocationsResponse struct {
|
||||
TotalPrefixes uint32 `xml:"TotalPrefixes"`
|
||||
PrefixAndIndexCSV string `xml:"PrefixAndIndexCSV"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) GetAllPrefixLocations(httpClient *http.Client, args *GetAllPrefixLocationsArgs) (*GetAllPrefixLocationsResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetAllPrefixLocations`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetAllPrefixLocations: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetAllPrefixLocations == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetAllPrefixLocations()`)
|
||||
}
|
||||
|
||||
return r.Body.GetAllPrefixLocations, nil
|
||||
}
|
||||
|
||||
type CreateObjectArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ContainerID string `xml:"ContainerID"`
|
||||
Elements string `xml:"Elements"`
|
||||
}
|
||||
type CreateObjectResponse struct {
|
||||
ObjectID string `xml:"ObjectID"`
|
||||
Result string `xml:"Result"`
|
||||
}
|
||||
|
||||
func (s *Service) CreateObject(httpClient *http.Client, args *CreateObjectArgs) (*CreateObjectResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`CreateObject`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{CreateObject: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.CreateObject == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.CreateObject()`)
|
||||
}
|
||||
|
||||
return r.Body.CreateObject, nil
|
||||
}
|
||||
|
||||
type UpdateObjectArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ObjectID string `xml:"ObjectID"`
|
||||
CurrentTagValue string `xml:"CurrentTagValue"`
|
||||
NewTagValue string `xml:"NewTagValue"`
|
||||
}
|
||||
type UpdateObjectResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) UpdateObject(httpClient *http.Client, args *UpdateObjectArgs) (*UpdateObjectResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`UpdateObject`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{UpdateObject: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.UpdateObject == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.UpdateObject()`)
|
||||
}
|
||||
|
||||
return r.Body.UpdateObject, nil
|
||||
}
|
||||
|
||||
type DestroyObjectArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ObjectID string `xml:"ObjectID"`
|
||||
}
|
||||
type DestroyObjectResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) DestroyObject(httpClient *http.Client, args *DestroyObjectArgs) (*DestroyObjectResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`DestroyObject`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{DestroyObject: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.DestroyObject == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.DestroyObject()`)
|
||||
}
|
||||
|
||||
return r.Body.DestroyObject, nil
|
||||
}
|
||||
|
||||
type RefreshShareIndexArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AlbumArtistDisplayOption string `xml:"AlbumArtistDisplayOption"`
|
||||
}
|
||||
type RefreshShareIndexResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RefreshShareIndex(httpClient *http.Client, args *RefreshShareIndexArgs) (*RefreshShareIndexResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RefreshShareIndex`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RefreshShareIndex: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RefreshShareIndex == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.RefreshShareIndex()`)
|
||||
}
|
||||
|
||||
return r.Body.RefreshShareIndex, nil
|
||||
}
|
||||
|
||||
type RequestResortArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
SortOrder string `xml:"SortOrder"`
|
||||
}
|
||||
type RequestResortResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RequestResort(httpClient *http.Client, args *RequestResortArgs) (*RequestResortResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RequestResort`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RequestResort: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RequestResort == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.RequestResort()`)
|
||||
}
|
||||
|
||||
return r.Body.RequestResort, nil
|
||||
}
|
||||
|
||||
type GetShareIndexInProgressArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetShareIndexInProgressResponse struct {
|
||||
IsIndexing bool `xml:"IsIndexing"`
|
||||
}
|
||||
|
||||
func (s *Service) GetShareIndexInProgress(httpClient *http.Client, args *GetShareIndexInProgressArgs) (*GetShareIndexInProgressResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetShareIndexInProgress`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetShareIndexInProgress: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetShareIndexInProgress == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetShareIndexInProgress()`)
|
||||
}
|
||||
|
||||
return r.Body.GetShareIndexInProgress, nil
|
||||
}
|
||||
|
||||
type GetBrowseableArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetBrowseableResponse struct {
|
||||
IsBrowseable bool `xml:"IsBrowseable"`
|
||||
}
|
||||
|
||||
func (s *Service) GetBrowseable(httpClient *http.Client, args *GetBrowseableArgs) (*GetBrowseableResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetBrowseable`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetBrowseable: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetBrowseable == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetBrowseable()`)
|
||||
}
|
||||
|
||||
return r.Body.GetBrowseable, nil
|
||||
}
|
||||
|
||||
type SetBrowseableArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Browseable bool `xml:"Browseable"`
|
||||
}
|
||||
type SetBrowseableResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetBrowseable(httpClient *http.Client, args *SetBrowseableArgs) (*SetBrowseableResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetBrowseable`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetBrowseable: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetBrowseable == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling contentdirectory.SetBrowseable()`)
|
||||
}
|
||||
|
||||
return r.Body.SetBrowseable, nil
|
||||
}
|
||||
-789
@@ -1,789 +0,0 @@
|
||||
package deviceproperties
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:DeviceProperties:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/DeviceProperties/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/DeviceProperties/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
SetLEDState *SetLEDStateArgs `xml:"u:SetLEDState,omitempty"`
|
||||
GetLEDState *GetLEDStateArgs `xml:"u:GetLEDState,omitempty"`
|
||||
AddBondedZones *AddBondedZonesArgs `xml:"u:AddBondedZones,omitempty"`
|
||||
RemoveBondedZones *RemoveBondedZonesArgs `xml:"u:RemoveBondedZones,omitempty"`
|
||||
CreateStereoPair *CreateStereoPairArgs `xml:"u:CreateStereoPair,omitempty"`
|
||||
SeparateStereoPair *SeparateStereoPairArgs `xml:"u:SeparateStereoPair,omitempty"`
|
||||
SetZoneAttributes *SetZoneAttributesArgs `xml:"u:SetZoneAttributes,omitempty"`
|
||||
GetZoneAttributes *GetZoneAttributesArgs `xml:"u:GetZoneAttributes,omitempty"`
|
||||
GetHouseholdID *GetHouseholdIDArgs `xml:"u:GetHouseholdID,omitempty"`
|
||||
GetZoneInfo *GetZoneInfoArgs `xml:"u:GetZoneInfo,omitempty"`
|
||||
SetAutoplayLinkedZones *SetAutoplayLinkedZonesArgs `xml:"u:SetAutoplayLinkedZones,omitempty"`
|
||||
GetAutoplayLinkedZones *GetAutoplayLinkedZonesArgs `xml:"u:GetAutoplayLinkedZones,omitempty"`
|
||||
SetAutoplayRoomUUID *SetAutoplayRoomUUIDArgs `xml:"u:SetAutoplayRoomUUID,omitempty"`
|
||||
GetAutoplayRoomUUID *GetAutoplayRoomUUIDArgs `xml:"u:GetAutoplayRoomUUID,omitempty"`
|
||||
SetAutoplayVolume *SetAutoplayVolumeArgs `xml:"u:SetAutoplayVolume,omitempty"`
|
||||
GetAutoplayVolume *GetAutoplayVolumeArgs `xml:"u:GetAutoplayVolume,omitempty"`
|
||||
SetUseAutoplayVolume *SetUseAutoplayVolumeArgs `xml:"u:SetUseAutoplayVolume,omitempty"`
|
||||
GetUseAutoplayVolume *GetUseAutoplayVolumeArgs `xml:"u:GetUseAutoplayVolume,omitempty"`
|
||||
AddHTSatellite *AddHTSatelliteArgs `xml:"u:AddHTSatellite,omitempty"`
|
||||
RemoveHTSatellite *RemoveHTSatelliteArgs `xml:"u:RemoveHTSatellite,omitempty"`
|
||||
EnterConfigMode *EnterConfigModeArgs `xml:"u:EnterConfigMode,omitempty"`
|
||||
ExitConfigMode *ExitConfigModeArgs `xml:"u:ExitConfigMode,omitempty"`
|
||||
GetButtonState *GetButtonStateArgs `xml:"u:GetButtonState,omitempty"`
|
||||
SetButtonLockState *SetButtonLockStateArgs `xml:"u:SetButtonLockState,omitempty"`
|
||||
GetButtonLockState *GetButtonLockStateArgs `xml:"u:GetButtonLockState,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
SetLEDState *SetLEDStateResponse `xml:"SetLEDStateResponse,omitempty"`
|
||||
GetLEDState *GetLEDStateResponse `xml:"GetLEDStateResponse,omitempty"`
|
||||
AddBondedZones *AddBondedZonesResponse `xml:"AddBondedZonesResponse,omitempty"`
|
||||
RemoveBondedZones *RemoveBondedZonesResponse `xml:"RemoveBondedZonesResponse,omitempty"`
|
||||
CreateStereoPair *CreateStereoPairResponse `xml:"CreateStereoPairResponse,omitempty"`
|
||||
SeparateStereoPair *SeparateStereoPairResponse `xml:"SeparateStereoPairResponse,omitempty"`
|
||||
SetZoneAttributes *SetZoneAttributesResponse `xml:"SetZoneAttributesResponse,omitempty"`
|
||||
GetZoneAttributes *GetZoneAttributesResponse `xml:"GetZoneAttributesResponse,omitempty"`
|
||||
GetHouseholdID *GetHouseholdIDResponse `xml:"GetHouseholdIDResponse,omitempty"`
|
||||
GetZoneInfo *GetZoneInfoResponse `xml:"GetZoneInfoResponse,omitempty"`
|
||||
SetAutoplayLinkedZones *SetAutoplayLinkedZonesResponse `xml:"SetAutoplayLinkedZonesResponse,omitempty"`
|
||||
GetAutoplayLinkedZones *GetAutoplayLinkedZonesResponse `xml:"GetAutoplayLinkedZonesResponse,omitempty"`
|
||||
SetAutoplayRoomUUID *SetAutoplayRoomUUIDResponse `xml:"SetAutoplayRoomUUIDResponse,omitempty"`
|
||||
GetAutoplayRoomUUID *GetAutoplayRoomUUIDResponse `xml:"GetAutoplayRoomUUIDResponse,omitempty"`
|
||||
SetAutoplayVolume *SetAutoplayVolumeResponse `xml:"SetAutoplayVolumeResponse,omitempty"`
|
||||
GetAutoplayVolume *GetAutoplayVolumeResponse `xml:"GetAutoplayVolumeResponse,omitempty"`
|
||||
SetUseAutoplayVolume *SetUseAutoplayVolumeResponse `xml:"SetUseAutoplayVolumeResponse,omitempty"`
|
||||
GetUseAutoplayVolume *GetUseAutoplayVolumeResponse `xml:"GetUseAutoplayVolumeResponse,omitempty"`
|
||||
AddHTSatellite *AddHTSatelliteResponse `xml:"AddHTSatelliteResponse,omitempty"`
|
||||
RemoveHTSatellite *RemoveHTSatelliteResponse `xml:"RemoveHTSatelliteResponse,omitempty"`
|
||||
EnterConfigMode *EnterConfigModeResponse `xml:"EnterConfigModeResponse,omitempty"`
|
||||
ExitConfigMode *ExitConfigModeResponse `xml:"ExitConfigModeResponse,omitempty"`
|
||||
GetButtonState *GetButtonStateResponse `xml:"GetButtonStateResponse,omitempty"`
|
||||
SetButtonLockState *SetButtonLockStateResponse `xml:"SetButtonLockStateResponse,omitempty"`
|
||||
GetButtonLockState *GetButtonLockStateResponse `xml:"GetButtonLockStateResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type SetLEDStateArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
// Allowed Value: On
|
||||
// Allowed Value: Off
|
||||
DesiredLEDState string `xml:"DesiredLEDState"`
|
||||
}
|
||||
type SetLEDStateResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetLEDState(httpClient *http.Client, args *SetLEDStateArgs) (*SetLEDStateResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetLEDState`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetLEDState: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetLEDState == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetLEDState()`)
|
||||
}
|
||||
|
||||
return r.Body.SetLEDState, nil
|
||||
}
|
||||
|
||||
type GetLEDStateArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetLEDStateResponse struct {
|
||||
CurrentLEDState string `xml:"CurrentLEDState"`
|
||||
}
|
||||
|
||||
func (s *Service) GetLEDState(httpClient *http.Client, args *GetLEDStateArgs) (*GetLEDStateResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetLEDState`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetLEDState: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetLEDState == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetLEDState()`)
|
||||
}
|
||||
|
||||
return r.Body.GetLEDState, nil
|
||||
}
|
||||
|
||||
type AddBondedZonesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ChannelMapSet string `xml:"ChannelMapSet"`
|
||||
}
|
||||
type AddBondedZonesResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) AddBondedZones(httpClient *http.Client, args *AddBondedZonesArgs) (*AddBondedZonesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`AddBondedZones`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{AddBondedZones: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.AddBondedZones == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.AddBondedZones()`)
|
||||
}
|
||||
|
||||
return r.Body.AddBondedZones, nil
|
||||
}
|
||||
|
||||
type RemoveBondedZonesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ChannelMapSet string `xml:"ChannelMapSet"`
|
||||
KeepGrouped bool `xml:"KeepGrouped"`
|
||||
}
|
||||
type RemoveBondedZonesResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RemoveBondedZones(httpClient *http.Client, args *RemoveBondedZonesArgs) (*RemoveBondedZonesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RemoveBondedZones`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RemoveBondedZones: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RemoveBondedZones == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.RemoveBondedZones()`)
|
||||
}
|
||||
|
||||
return r.Body.RemoveBondedZones, nil
|
||||
}
|
||||
|
||||
type CreateStereoPairArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ChannelMapSet string `xml:"ChannelMapSet"`
|
||||
}
|
||||
type CreateStereoPairResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) CreateStereoPair(httpClient *http.Client, args *CreateStereoPairArgs) (*CreateStereoPairResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`CreateStereoPair`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{CreateStereoPair: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.CreateStereoPair == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.CreateStereoPair()`)
|
||||
}
|
||||
|
||||
return r.Body.CreateStereoPair, nil
|
||||
}
|
||||
|
||||
type SeparateStereoPairArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ChannelMapSet string `xml:"ChannelMapSet"`
|
||||
}
|
||||
type SeparateStereoPairResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SeparateStereoPair(httpClient *http.Client, args *SeparateStereoPairArgs) (*SeparateStereoPairResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SeparateStereoPair`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SeparateStereoPair: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SeparateStereoPair == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.SeparateStereoPair()`)
|
||||
}
|
||||
|
||||
return r.Body.SeparateStereoPair, nil
|
||||
}
|
||||
|
||||
type SetZoneAttributesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
DesiredZoneName string `xml:"DesiredZoneName"`
|
||||
DesiredIcon string `xml:"DesiredIcon"`
|
||||
DesiredConfiguration string `xml:"DesiredConfiguration"`
|
||||
}
|
||||
type SetZoneAttributesResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetZoneAttributes(httpClient *http.Client, args *SetZoneAttributesArgs) (*SetZoneAttributesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetZoneAttributes`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetZoneAttributes: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetZoneAttributes == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetZoneAttributes()`)
|
||||
}
|
||||
|
||||
return r.Body.SetZoneAttributes, nil
|
||||
}
|
||||
|
||||
type GetZoneAttributesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetZoneAttributesResponse struct {
|
||||
CurrentZoneName string `xml:"CurrentZoneName"`
|
||||
CurrentIcon string `xml:"CurrentIcon"`
|
||||
CurrentConfiguration string `xml:"CurrentConfiguration"`
|
||||
}
|
||||
|
||||
func (s *Service) GetZoneAttributes(httpClient *http.Client, args *GetZoneAttributesArgs) (*GetZoneAttributesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetZoneAttributes`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetZoneAttributes: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetZoneAttributes == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetZoneAttributes()`)
|
||||
}
|
||||
|
||||
return r.Body.GetZoneAttributes, nil
|
||||
}
|
||||
|
||||
type GetHouseholdIDArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetHouseholdIDResponse struct {
|
||||
CurrentHouseholdID string `xml:"CurrentHouseholdID"`
|
||||
}
|
||||
|
||||
func (s *Service) GetHouseholdID(httpClient *http.Client, args *GetHouseholdIDArgs) (*GetHouseholdIDResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetHouseholdID`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetHouseholdID: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetHouseholdID == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetHouseholdID()`)
|
||||
}
|
||||
|
||||
return r.Body.GetHouseholdID, nil
|
||||
}
|
||||
|
||||
type GetZoneInfoArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetZoneInfoResponse struct {
|
||||
SerialNumber string `xml:"SerialNumber"`
|
||||
SoftwareVersion string `xml:"SoftwareVersion"`
|
||||
DisplaySoftwareVersion string `xml:"DisplaySoftwareVersion"`
|
||||
HardwareVersion string `xml:"HardwareVersion"`
|
||||
IPAddress string `xml:"IPAddress"`
|
||||
MACAddress string `xml:"MACAddress"`
|
||||
CopyrightInfo string `xml:"CopyrightInfo"`
|
||||
ExtraInfo string `xml:"ExtraInfo"`
|
||||
HTAudioIn uint32 `xml:"HTAudioIn"`
|
||||
Flags uint32 `xml:"Flags"`
|
||||
}
|
||||
|
||||
func (s *Service) GetZoneInfo(httpClient *http.Client, args *GetZoneInfoArgs) (*GetZoneInfoResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetZoneInfo`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetZoneInfo: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetZoneInfo == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetZoneInfo()`)
|
||||
}
|
||||
|
||||
return r.Body.GetZoneInfo, nil
|
||||
}
|
||||
|
||||
type SetAutoplayLinkedZonesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
IncludeLinkedZones bool `xml:"IncludeLinkedZones"`
|
||||
Source string `xml:"Source"`
|
||||
}
|
||||
type SetAutoplayLinkedZonesResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetAutoplayLinkedZones(httpClient *http.Client, args *SetAutoplayLinkedZonesArgs) (*SetAutoplayLinkedZonesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetAutoplayLinkedZones`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetAutoplayLinkedZones: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetAutoplayLinkedZones == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetAutoplayLinkedZones()`)
|
||||
}
|
||||
|
||||
return r.Body.SetAutoplayLinkedZones, nil
|
||||
}
|
||||
|
||||
type GetAutoplayLinkedZonesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Source string `xml:"Source"`
|
||||
}
|
||||
type GetAutoplayLinkedZonesResponse struct {
|
||||
IncludeLinkedZones bool `xml:"IncludeLinkedZones"`
|
||||
}
|
||||
|
||||
func (s *Service) GetAutoplayLinkedZones(httpClient *http.Client, args *GetAutoplayLinkedZonesArgs) (*GetAutoplayLinkedZonesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetAutoplayLinkedZones`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetAutoplayLinkedZones: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetAutoplayLinkedZones == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetAutoplayLinkedZones()`)
|
||||
}
|
||||
|
||||
return r.Body.GetAutoplayLinkedZones, nil
|
||||
}
|
||||
|
||||
type SetAutoplayRoomUUIDArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
RoomUUID string `xml:"RoomUUID"`
|
||||
Source string `xml:"Source"`
|
||||
}
|
||||
type SetAutoplayRoomUUIDResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetAutoplayRoomUUID(httpClient *http.Client, args *SetAutoplayRoomUUIDArgs) (*SetAutoplayRoomUUIDResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetAutoplayRoomUUID`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetAutoplayRoomUUID: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetAutoplayRoomUUID == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetAutoplayRoomUUID()`)
|
||||
}
|
||||
|
||||
return r.Body.SetAutoplayRoomUUID, nil
|
||||
}
|
||||
|
||||
type GetAutoplayRoomUUIDArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Source string `xml:"Source"`
|
||||
}
|
||||
type GetAutoplayRoomUUIDResponse struct {
|
||||
RoomUUID string `xml:"RoomUUID"`
|
||||
}
|
||||
|
||||
func (s *Service) GetAutoplayRoomUUID(httpClient *http.Client, args *GetAutoplayRoomUUIDArgs) (*GetAutoplayRoomUUIDResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetAutoplayRoomUUID`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetAutoplayRoomUUID: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetAutoplayRoomUUID == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetAutoplayRoomUUID()`)
|
||||
}
|
||||
|
||||
return r.Body.GetAutoplayRoomUUID, nil
|
||||
}
|
||||
|
||||
type SetAutoplayVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
// Allowed Range: 0 -> 100 step: 1
|
||||
Volume uint16 `xml:"Volume"`
|
||||
Source string `xml:"Source"`
|
||||
}
|
||||
type SetAutoplayVolumeResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetAutoplayVolume(httpClient *http.Client, args *SetAutoplayVolumeArgs) (*SetAutoplayVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetAutoplayVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetAutoplayVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetAutoplayVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetAutoplayVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.SetAutoplayVolume, nil
|
||||
}
|
||||
|
||||
type GetAutoplayVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Source string `xml:"Source"`
|
||||
}
|
||||
type GetAutoplayVolumeResponse struct {
|
||||
CurrentVolume uint16 `xml:"CurrentVolume"`
|
||||
}
|
||||
|
||||
func (s *Service) GetAutoplayVolume(httpClient *http.Client, args *GetAutoplayVolumeArgs) (*GetAutoplayVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetAutoplayVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetAutoplayVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetAutoplayVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetAutoplayVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.GetAutoplayVolume, nil
|
||||
}
|
||||
|
||||
type SetUseAutoplayVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
UseVolume bool `xml:"UseVolume"`
|
||||
Source string `xml:"Source"`
|
||||
}
|
||||
type SetUseAutoplayVolumeResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetUseAutoplayVolume(httpClient *http.Client, args *SetUseAutoplayVolumeArgs) (*SetUseAutoplayVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetUseAutoplayVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetUseAutoplayVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetUseAutoplayVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetUseAutoplayVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.SetUseAutoplayVolume, nil
|
||||
}
|
||||
|
||||
type GetUseAutoplayVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Source string `xml:"Source"`
|
||||
}
|
||||
type GetUseAutoplayVolumeResponse struct {
|
||||
UseVolume bool `xml:"UseVolume"`
|
||||
}
|
||||
|
||||
func (s *Service) GetUseAutoplayVolume(httpClient *http.Client, args *GetUseAutoplayVolumeArgs) (*GetUseAutoplayVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetUseAutoplayVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetUseAutoplayVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetUseAutoplayVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetUseAutoplayVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.GetUseAutoplayVolume, nil
|
||||
}
|
||||
|
||||
type AddHTSatelliteArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
HTSatChanMapSet string `xml:"HTSatChanMapSet"`
|
||||
}
|
||||
type AddHTSatelliteResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) AddHTSatellite(httpClient *http.Client, args *AddHTSatelliteArgs) (*AddHTSatelliteResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`AddHTSatellite`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{AddHTSatellite: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.AddHTSatellite == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.AddHTSatellite()`)
|
||||
}
|
||||
|
||||
return r.Body.AddHTSatellite, nil
|
||||
}
|
||||
|
||||
type RemoveHTSatelliteArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
SatRoomUUID string `xml:"SatRoomUUID"`
|
||||
}
|
||||
type RemoveHTSatelliteResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RemoveHTSatellite(httpClient *http.Client, args *RemoveHTSatelliteArgs) (*RemoveHTSatelliteResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RemoveHTSatellite`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RemoveHTSatellite: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RemoveHTSatellite == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.RemoveHTSatellite()`)
|
||||
}
|
||||
|
||||
return r.Body.RemoveHTSatellite, nil
|
||||
}
|
||||
|
||||
type EnterConfigModeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Mode string `xml:"Mode"`
|
||||
Options string `xml:"Options"`
|
||||
}
|
||||
type EnterConfigModeResponse struct {
|
||||
State string `xml:"State"`
|
||||
}
|
||||
|
||||
func (s *Service) EnterConfigMode(httpClient *http.Client, args *EnterConfigModeArgs) (*EnterConfigModeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`EnterConfigMode`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{EnterConfigMode: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.EnterConfigMode == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.EnterConfigMode()`)
|
||||
}
|
||||
|
||||
return r.Body.EnterConfigMode, nil
|
||||
}
|
||||
|
||||
type ExitConfigModeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Options string `xml:"Options"`
|
||||
}
|
||||
type ExitConfigModeResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) ExitConfigMode(httpClient *http.Client, args *ExitConfigModeArgs) (*ExitConfigModeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ExitConfigMode`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ExitConfigMode: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ExitConfigMode == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.ExitConfigMode()`)
|
||||
}
|
||||
|
||||
return r.Body.ExitConfigMode, nil
|
||||
}
|
||||
|
||||
type GetButtonStateArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetButtonStateResponse struct {
|
||||
State string `xml:"State"`
|
||||
}
|
||||
|
||||
func (s *Service) GetButtonState(httpClient *http.Client, args *GetButtonStateArgs) (*GetButtonStateResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetButtonState`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetButtonState: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetButtonState == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetButtonState()`)
|
||||
}
|
||||
|
||||
return r.Body.GetButtonState, nil
|
||||
}
|
||||
|
||||
type SetButtonLockStateArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
// Allowed Value: On
|
||||
// Allowed Value: Off
|
||||
DesiredButtonLockState string `xml:"DesiredButtonLockState"`
|
||||
}
|
||||
type SetButtonLockStateResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetButtonLockState(httpClient *http.Client, args *SetButtonLockStateArgs) (*SetButtonLockStateResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetButtonLockState`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetButtonLockState: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetButtonLockState == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetButtonLockState()`)
|
||||
}
|
||||
|
||||
return r.Body.SetButtonLockState, nil
|
||||
}
|
||||
|
||||
type GetButtonLockStateArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetButtonLockStateResponse struct {
|
||||
CurrentButtonLockState string `xml:"CurrentButtonLockState"`
|
||||
}
|
||||
|
||||
func (s *Service) GetButtonLockState(httpClient *http.Client, args *GetButtonLockStateArgs) (*GetButtonLockStateResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetButtonLockState`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetButtonLockState: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetButtonLockState == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetButtonLockState()`)
|
||||
}
|
||||
|
||||
return r.Body.GetButtonLockState, nil
|
||||
}
|
||||
-200
@@ -1,200 +0,0 @@
|
||||
package groupmanagement
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:GroupManagement:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/GroupManagement/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/GroupManagement/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
AddMember *AddMemberArgs `xml:"u:AddMember,omitempty"`
|
||||
RemoveMember *RemoveMemberArgs `xml:"u:RemoveMember,omitempty"`
|
||||
ReportTrackBufferingResult *ReportTrackBufferingResultArgs `xml:"u:ReportTrackBufferingResult,omitempty"`
|
||||
SetSourceAreaIds *SetSourceAreaIdsArgs `xml:"u:SetSourceAreaIds,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
AddMember *AddMemberResponse `xml:"AddMemberResponse,omitempty"`
|
||||
RemoveMember *RemoveMemberResponse `xml:"RemoveMemberResponse,omitempty"`
|
||||
ReportTrackBufferingResult *ReportTrackBufferingResultResponse `xml:"ReportTrackBufferingResultResponse,omitempty"`
|
||||
SetSourceAreaIds *SetSourceAreaIdsResponse `xml:"SetSourceAreaIdsResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type AddMemberArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
MemberID string `xml:"MemberID"`
|
||||
BootSeq uint32 `xml:"BootSeq"`
|
||||
}
|
||||
type AddMemberResponse struct {
|
||||
CurrentTransportSettings string `xml:"CurrentTransportSettings"`
|
||||
CurrentURI string `xml:"CurrentURI"`
|
||||
GroupUUIDJoined string `xml:"GroupUUIDJoined"`
|
||||
ResetVolumeAfter bool `xml:"ResetVolumeAfter"`
|
||||
VolumeAVTransportURI string `xml:"VolumeAVTransportURI"`
|
||||
}
|
||||
|
||||
func (s *Service) AddMember(httpClient *http.Client, args *AddMemberArgs) (*AddMemberResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`AddMember`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{AddMember: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.AddMember == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling groupmanagement.AddMember()`)
|
||||
}
|
||||
|
||||
return r.Body.AddMember, nil
|
||||
}
|
||||
|
||||
type RemoveMemberArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
MemberID string `xml:"MemberID"`
|
||||
}
|
||||
type RemoveMemberResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RemoveMember(httpClient *http.Client, args *RemoveMemberArgs) (*RemoveMemberResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RemoveMember`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RemoveMember: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RemoveMember == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling groupmanagement.RemoveMember()`)
|
||||
}
|
||||
|
||||
return r.Body.RemoveMember, nil
|
||||
}
|
||||
|
||||
type ReportTrackBufferingResultArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
MemberID string `xml:"MemberID"`
|
||||
ResultCode int32 `xml:"ResultCode"`
|
||||
}
|
||||
type ReportTrackBufferingResultResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) ReportTrackBufferingResult(httpClient *http.Client, args *ReportTrackBufferingResultArgs) (*ReportTrackBufferingResultResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ReportTrackBufferingResult`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ReportTrackBufferingResult: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ReportTrackBufferingResult == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling groupmanagement.ReportTrackBufferingResult()`)
|
||||
}
|
||||
|
||||
return r.Body.ReportTrackBufferingResult, nil
|
||||
}
|
||||
|
||||
type SetSourceAreaIdsArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
DesiredSourceAreaIds string `xml:"DesiredSourceAreaIds"`
|
||||
}
|
||||
type SetSourceAreaIdsResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetSourceAreaIds(httpClient *http.Client, args *SetSourceAreaIdsArgs) (*SetSourceAreaIdsResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetSourceAreaIds`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetSourceAreaIds: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetSourceAreaIds == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling groupmanagement.SetSourceAreaIds()`)
|
||||
}
|
||||
|
||||
return r.Body.SetSourceAreaIds, nil
|
||||
}
|
||||
-254
@@ -1,254 +0,0 @@
|
||||
package grouprenderingcontrol
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:GroupRenderingControl:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/MediaRenderer/GroupRenderingControl/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/MediaRenderer/GroupRenderingControl/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
GetGroupMute *GetGroupMuteArgs `xml:"u:GetGroupMute,omitempty"`
|
||||
SetGroupMute *SetGroupMuteArgs `xml:"u:SetGroupMute,omitempty"`
|
||||
GetGroupVolume *GetGroupVolumeArgs `xml:"u:GetGroupVolume,omitempty"`
|
||||
SetGroupVolume *SetGroupVolumeArgs `xml:"u:SetGroupVolume,omitempty"`
|
||||
SetRelativeGroupVolume *SetRelativeGroupVolumeArgs `xml:"u:SetRelativeGroupVolume,omitempty"`
|
||||
SnapshotGroupVolume *SnapshotGroupVolumeArgs `xml:"u:SnapshotGroupVolume,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
GetGroupMute *GetGroupMuteResponse `xml:"GetGroupMuteResponse,omitempty"`
|
||||
SetGroupMute *SetGroupMuteResponse `xml:"SetGroupMuteResponse,omitempty"`
|
||||
GetGroupVolume *GetGroupVolumeResponse `xml:"GetGroupVolumeResponse,omitempty"`
|
||||
SetGroupVolume *SetGroupVolumeResponse `xml:"SetGroupVolumeResponse,omitempty"`
|
||||
SetRelativeGroupVolume *SetRelativeGroupVolumeResponse `xml:"SetRelativeGroupVolumeResponse,omitempty"`
|
||||
SnapshotGroupVolume *SnapshotGroupVolumeResponse `xml:"SnapshotGroupVolumeResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type GetGroupMuteArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type GetGroupMuteResponse struct {
|
||||
CurrentMute bool `xml:"CurrentMute"`
|
||||
}
|
||||
|
||||
func (s *Service) GetGroupMute(httpClient *http.Client, args *GetGroupMuteArgs) (*GetGroupMuteResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetGroupMute`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetGroupMute: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetGroupMute == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.GetGroupMute()`)
|
||||
}
|
||||
|
||||
return r.Body.GetGroupMute, nil
|
||||
}
|
||||
|
||||
type SetGroupMuteArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
DesiredMute bool `xml:"DesiredMute"`
|
||||
}
|
||||
type SetGroupMuteResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetGroupMute(httpClient *http.Client, args *SetGroupMuteArgs) (*SetGroupMuteResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetGroupMute`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetGroupMute: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetGroupMute == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.SetGroupMute()`)
|
||||
}
|
||||
|
||||
return r.Body.SetGroupMute, nil
|
||||
}
|
||||
|
||||
type GetGroupVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type GetGroupVolumeResponse struct {
|
||||
CurrentVolume uint16 `xml:"CurrentVolume"`
|
||||
}
|
||||
|
||||
func (s *Service) GetGroupVolume(httpClient *http.Client, args *GetGroupVolumeArgs) (*GetGroupVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetGroupVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetGroupVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetGroupVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.GetGroupVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.GetGroupVolume, nil
|
||||
}
|
||||
|
||||
type SetGroupVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Range: 0 -> 100 step: 1
|
||||
DesiredVolume uint16 `xml:"DesiredVolume"`
|
||||
}
|
||||
type SetGroupVolumeResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetGroupVolume(httpClient *http.Client, args *SetGroupVolumeArgs) (*SetGroupVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetGroupVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetGroupVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetGroupVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.SetGroupVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.SetGroupVolume, nil
|
||||
}
|
||||
|
||||
type SetRelativeGroupVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
Adjustment int32 `xml:"Adjustment"`
|
||||
}
|
||||
type SetRelativeGroupVolumeResponse struct {
|
||||
NewVolume uint16 `xml:"NewVolume"`
|
||||
}
|
||||
|
||||
func (s *Service) SetRelativeGroupVolume(httpClient *http.Client, args *SetRelativeGroupVolumeArgs) (*SetRelativeGroupVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetRelativeGroupVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetRelativeGroupVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetRelativeGroupVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.SetRelativeGroupVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.SetRelativeGroupVolume, nil
|
||||
}
|
||||
|
||||
type SnapshotGroupVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type SnapshotGroupVolumeResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SnapshotGroupVolume(httpClient *http.Client, args *SnapshotGroupVolumeArgs) (*SnapshotGroupVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SnapshotGroupVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SnapshotGroupVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SnapshotGroupVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.SnapshotGroupVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.SnapshotGroupVolume, nil
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Matthew Szatmary
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
-169
@@ -1,169 +0,0 @@
|
||||
package musicservices
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:MusicServices:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/MusicServices/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/MusicServices/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
GetSessionId *GetSessionIdArgs `xml:"u:GetSessionId,omitempty"`
|
||||
ListAvailableServices *ListAvailableServicesArgs `xml:"u:ListAvailableServices,omitempty"`
|
||||
UpdateAvailableServices *UpdateAvailableServicesArgs `xml:"u:UpdateAvailableServices,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
GetSessionId *GetSessionIdResponse `xml:"GetSessionIdResponse,omitempty"`
|
||||
ListAvailableServices *ListAvailableServicesResponse `xml:"ListAvailableServicesResponse,omitempty"`
|
||||
UpdateAvailableServices *UpdateAvailableServicesResponse `xml:"UpdateAvailableServicesResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type GetSessionIdArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
ServiceId uint32 `xml:"ServiceId"`
|
||||
Username string `xml:"Username"`
|
||||
}
|
||||
type GetSessionIdResponse struct {
|
||||
SessionId string `xml:"SessionId"`
|
||||
}
|
||||
|
||||
func (s *Service) GetSessionId(httpClient *http.Client, args *GetSessionIdArgs) (*GetSessionIdResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetSessionId`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetSessionId: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetSessionId == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling musicservices.GetSessionId()`)
|
||||
}
|
||||
|
||||
return r.Body.GetSessionId, nil
|
||||
}
|
||||
|
||||
type ListAvailableServicesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type ListAvailableServicesResponse struct {
|
||||
AvailableServiceDescriptorList string `xml:"AvailableServiceDescriptorList"`
|
||||
AvailableServiceTypeList string `xml:"AvailableServiceTypeList"`
|
||||
AvailableServiceListVersion string `xml:"AvailableServiceListVersion"`
|
||||
}
|
||||
|
||||
func (s *Service) ListAvailableServices(httpClient *http.Client, args *ListAvailableServicesArgs) (*ListAvailableServicesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ListAvailableServices`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ListAvailableServices: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ListAvailableServices == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling musicservices.ListAvailableServices()`)
|
||||
}
|
||||
|
||||
return r.Body.ListAvailableServices, nil
|
||||
}
|
||||
|
||||
type UpdateAvailableServicesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type UpdateAvailableServicesResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) UpdateAvailableServices(httpClient *http.Client, args *UpdateAvailableServicesArgs) (*UpdateAvailableServicesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`UpdateAvailableServices`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{UpdateAvailableServices: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.UpdateAvailableServices == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling musicservices.UpdateAvailableServices()`)
|
||||
}
|
||||
|
||||
return r.Body.UpdateAvailableServices, nil
|
||||
}
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
package qplay
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:QPlay:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/QPlay/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/QPlay/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
QPlayAuth *QPlayAuthArgs `xml:"u:QPlayAuth,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
QPlayAuth *QPlayAuthResponse `xml:"QPlayAuthResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type QPlayAuthArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
Seed string `xml:"Seed"`
|
||||
}
|
||||
type QPlayAuthResponse struct {
|
||||
Code string `xml:"Code"`
|
||||
MID string `xml:"MID"`
|
||||
DID string `xml:"DID"`
|
||||
}
|
||||
|
||||
func (s *Service) QPlayAuth(httpClient *http.Client, args *QPlayAuthArgs) (*QPlayAuthResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`QPlayAuth`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{QPlayAuth: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.QPlayAuth == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling qplay.QPlayAuth()`)
|
||||
}
|
||||
|
||||
return r.Body.QPlayAuth, nil
|
||||
}
|
||||
-435
@@ -1,435 +0,0 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:Queue:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/MediaRenderer/Queue/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/MediaRenderer/Queue/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
AddURI *AddURIArgs `xml:"u:AddURI,omitempty"`
|
||||
AddMultipleURIs *AddMultipleURIsArgs `xml:"u:AddMultipleURIs,omitempty"`
|
||||
AttachQueue *AttachQueueArgs `xml:"u:AttachQueue,omitempty"`
|
||||
Backup *BackupArgs `xml:"u:Backup,omitempty"`
|
||||
Browse *BrowseArgs `xml:"u:Browse,omitempty"`
|
||||
CreateQueue *CreateQueueArgs `xml:"u:CreateQueue,omitempty"`
|
||||
RemoveAllTracks *RemoveAllTracksArgs `xml:"u:RemoveAllTracks,omitempty"`
|
||||
RemoveTrackRange *RemoveTrackRangeArgs `xml:"u:RemoveTrackRange,omitempty"`
|
||||
ReorderTracks *ReorderTracksArgs `xml:"u:ReorderTracks,omitempty"`
|
||||
ReplaceAllTracks *ReplaceAllTracksArgs `xml:"u:ReplaceAllTracks,omitempty"`
|
||||
SaveAsSonosPlaylist *SaveAsSonosPlaylistArgs `xml:"u:SaveAsSonosPlaylist,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
AddURI *AddURIResponse `xml:"AddURIResponse,omitempty"`
|
||||
AddMultipleURIs *AddMultipleURIsResponse `xml:"AddMultipleURIsResponse,omitempty"`
|
||||
AttachQueue *AttachQueueResponse `xml:"AttachQueueResponse,omitempty"`
|
||||
Backup *BackupResponse `xml:"BackupResponse,omitempty"`
|
||||
Browse *BrowseResponse `xml:"BrowseResponse,omitempty"`
|
||||
CreateQueue *CreateQueueResponse `xml:"CreateQueueResponse,omitempty"`
|
||||
RemoveAllTracks *RemoveAllTracksResponse `xml:"RemoveAllTracksResponse,omitempty"`
|
||||
RemoveTrackRange *RemoveTrackRangeResponse `xml:"RemoveTrackRangeResponse,omitempty"`
|
||||
ReorderTracks *ReorderTracksResponse `xml:"ReorderTracksResponse,omitempty"`
|
||||
ReplaceAllTracks *ReplaceAllTracksResponse `xml:"ReplaceAllTracksResponse,omitempty"`
|
||||
SaveAsSonosPlaylist *SaveAsSonosPlaylistResponse `xml:"SaveAsSonosPlaylistResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type AddURIArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
EnqueuedURI string `xml:"EnqueuedURI"`
|
||||
EnqueuedURIMetaData string `xml:"EnqueuedURIMetaData"`
|
||||
DesiredFirstTrackNumberEnqueued uint32 `xml:"DesiredFirstTrackNumberEnqueued"`
|
||||
EnqueueAsNext bool `xml:"EnqueueAsNext"`
|
||||
}
|
||||
type AddURIResponse struct {
|
||||
FirstTrackNumberEnqueued uint32 `xml:"FirstTrackNumberEnqueued"`
|
||||
NumTracksAdded uint32 `xml:"NumTracksAdded"`
|
||||
NewQueueLength uint32 `xml:"NewQueueLength"`
|
||||
NewUpdateID uint32 `xml:"NewUpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) AddURI(httpClient *http.Client, args *AddURIArgs) (*AddURIResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`AddURI`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{AddURI: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.AddURI == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.AddURI()`)
|
||||
}
|
||||
|
||||
return r.Body.AddURI, nil
|
||||
}
|
||||
|
||||
type AddMultipleURIsArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
ContainerURI string `xml:"ContainerURI"`
|
||||
ContainerMetaData string `xml:"ContainerMetaData"`
|
||||
DesiredFirstTrackNumberEnqueued uint32 `xml:"DesiredFirstTrackNumberEnqueued"`
|
||||
EnqueueAsNext bool `xml:"EnqueueAsNext"`
|
||||
NumberOfURIs uint32 `xml:"NumberOfURIs"`
|
||||
EnqueuedURIsAndMetaData string `xml:"EnqueuedURIsAndMetaData"`
|
||||
}
|
||||
type AddMultipleURIsResponse struct {
|
||||
FirstTrackNumberEnqueued uint32 `xml:"FirstTrackNumberEnqueued"`
|
||||
NumTracksAdded uint32 `xml:"NumTracksAdded"`
|
||||
NewQueueLength uint32 `xml:"NewQueueLength"`
|
||||
NewUpdateID uint32 `xml:"NewUpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) AddMultipleURIs(httpClient *http.Client, args *AddMultipleURIsArgs) (*AddMultipleURIsResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`AddMultipleURIs`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{AddMultipleURIs: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.AddMultipleURIs == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.AddMultipleURIs()`)
|
||||
}
|
||||
|
||||
return r.Body.AddMultipleURIs, nil
|
||||
}
|
||||
|
||||
type AttachQueueArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueOwnerID string `xml:"QueueOwnerID"`
|
||||
}
|
||||
type AttachQueueResponse struct {
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
QueueOwnerContext string `xml:"QueueOwnerContext"`
|
||||
}
|
||||
|
||||
func (s *Service) AttachQueue(httpClient *http.Client, args *AttachQueueArgs) (*AttachQueueResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`AttachQueue`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{AttachQueue: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.AttachQueue == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.AttachQueue()`)
|
||||
}
|
||||
|
||||
return r.Body.AttachQueue, nil
|
||||
}
|
||||
|
||||
type BackupArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type BackupResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) Backup(httpClient *http.Client, args *BackupArgs) (*BackupResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Backup`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Backup: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Backup == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.Backup()`)
|
||||
}
|
||||
|
||||
return r.Body.Backup, nil
|
||||
}
|
||||
|
||||
type BrowseArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
StartingIndex uint32 `xml:"StartingIndex"`
|
||||
RequestedCount uint32 `xml:"RequestedCount"`
|
||||
}
|
||||
type BrowseResponse struct {
|
||||
Result string `xml:"Result"`
|
||||
NumberReturned uint32 `xml:"NumberReturned"`
|
||||
TotalMatches uint32 `xml:"TotalMatches"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) Browse(httpClient *http.Client, args *BrowseArgs) (*BrowseResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Browse`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Browse: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Browse == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.Browse()`)
|
||||
}
|
||||
|
||||
return r.Body.Browse, nil
|
||||
}
|
||||
|
||||
type CreateQueueArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueOwnerID string `xml:"QueueOwnerID"`
|
||||
QueueOwnerContext string `xml:"QueueOwnerContext"`
|
||||
QueuePolicy string `xml:"QueuePolicy"`
|
||||
}
|
||||
type CreateQueueResponse struct {
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
}
|
||||
|
||||
func (s *Service) CreateQueue(httpClient *http.Client, args *CreateQueueArgs) (*CreateQueueResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`CreateQueue`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{CreateQueue: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.CreateQueue == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.CreateQueue()`)
|
||||
}
|
||||
|
||||
return r.Body.CreateQueue, nil
|
||||
}
|
||||
|
||||
type RemoveAllTracksArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
}
|
||||
type RemoveAllTracksResponse struct {
|
||||
NewUpdateID uint32 `xml:"NewUpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) RemoveAllTracks(httpClient *http.Client, args *RemoveAllTracksArgs) (*RemoveAllTracksResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RemoveAllTracks`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RemoveAllTracks: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RemoveAllTracks == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.RemoveAllTracks()`)
|
||||
}
|
||||
|
||||
return r.Body.RemoveAllTracks, nil
|
||||
}
|
||||
|
||||
type RemoveTrackRangeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
StartingIndex uint32 `xml:"StartingIndex"`
|
||||
NumberOfTracks uint32 `xml:"NumberOfTracks"`
|
||||
}
|
||||
type RemoveTrackRangeResponse struct {
|
||||
NewUpdateID uint32 `xml:"NewUpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) RemoveTrackRange(httpClient *http.Client, args *RemoveTrackRangeArgs) (*RemoveTrackRangeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RemoveTrackRange`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RemoveTrackRange: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RemoveTrackRange == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.RemoveTrackRange()`)
|
||||
}
|
||||
|
||||
return r.Body.RemoveTrackRange, nil
|
||||
}
|
||||
|
||||
type ReorderTracksArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
StartingIndex uint32 `xml:"StartingIndex"`
|
||||
NumberOfTracks uint32 `xml:"NumberOfTracks"`
|
||||
InsertBefore uint32 `xml:"InsertBefore"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
}
|
||||
type ReorderTracksResponse struct {
|
||||
NewUpdateID uint32 `xml:"NewUpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) ReorderTracks(httpClient *http.Client, args *ReorderTracksArgs) (*ReorderTracksResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ReorderTracks`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ReorderTracks: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ReorderTracks == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.ReorderTracks()`)
|
||||
}
|
||||
|
||||
return r.Body.ReorderTracks, nil
|
||||
}
|
||||
|
||||
type ReplaceAllTracksArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
UpdateID uint32 `xml:"UpdateID"`
|
||||
ContainerURI string `xml:"ContainerURI"`
|
||||
ContainerMetaData string `xml:"ContainerMetaData"`
|
||||
CurrentTrackIndex uint32 `xml:"CurrentTrackIndex"`
|
||||
NewCurrentTrackIndices string `xml:"NewCurrentTrackIndices"`
|
||||
NumberOfURIs uint32 `xml:"NumberOfURIs"`
|
||||
EnqueuedURIsAndMetaData string `xml:"EnqueuedURIsAndMetaData"`
|
||||
}
|
||||
type ReplaceAllTracksResponse struct {
|
||||
NewQueueLength uint32 `xml:"NewQueueLength"`
|
||||
NewUpdateID uint32 `xml:"NewUpdateID"`
|
||||
}
|
||||
|
||||
func (s *Service) ReplaceAllTracks(httpClient *http.Client, args *ReplaceAllTracksArgs) (*ReplaceAllTracksResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ReplaceAllTracks`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ReplaceAllTracks: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ReplaceAllTracks == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.ReplaceAllTracks()`)
|
||||
}
|
||||
|
||||
return r.Body.ReplaceAllTracks, nil
|
||||
}
|
||||
|
||||
type SaveAsSonosPlaylistArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
QueueID uint32 `xml:"QueueID"`
|
||||
Title string `xml:"Title"`
|
||||
ObjectID string `xml:"ObjectID"`
|
||||
}
|
||||
type SaveAsSonosPlaylistResponse struct {
|
||||
AssignedObjectID string `xml:"AssignedObjectID"`
|
||||
}
|
||||
|
||||
func (s *Service) SaveAsSonosPlaylist(httpClient *http.Client, args *SaveAsSonosPlaylistArgs) (*SaveAsSonosPlaylistResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SaveAsSonosPlaylist`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SaveAsSonosPlaylist: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SaveAsSonosPlaylist == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling queue.SaveAsSonosPlaylist()`)
|
||||
}
|
||||
|
||||
return r.Body.SaveAsSonosPlaylist, nil
|
||||
}
|
||||
-940
@@ -1,940 +0,0 @@
|
||||
package renderingcontrol
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:RenderingControl:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/MediaRenderer/RenderingControl/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/MediaRenderer/RenderingControl/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
GetMute *GetMuteArgs `xml:"u:GetMute,omitempty"`
|
||||
SetMute *SetMuteArgs `xml:"u:SetMute,omitempty"`
|
||||
ResetBasicEQ *ResetBasicEQArgs `xml:"u:ResetBasicEQ,omitempty"`
|
||||
ResetExtEQ *ResetExtEQArgs `xml:"u:ResetExtEQ,omitempty"`
|
||||
GetVolume *GetVolumeArgs `xml:"u:GetVolume,omitempty"`
|
||||
SetVolume *SetVolumeArgs `xml:"u:SetVolume,omitempty"`
|
||||
SetRelativeVolume *SetRelativeVolumeArgs `xml:"u:SetRelativeVolume,omitempty"`
|
||||
GetVolumeDB *GetVolumeDBArgs `xml:"u:GetVolumeDB,omitempty"`
|
||||
SetVolumeDB *SetVolumeDBArgs `xml:"u:SetVolumeDB,omitempty"`
|
||||
GetVolumeDBRange *GetVolumeDBRangeArgs `xml:"u:GetVolumeDBRange,omitempty"`
|
||||
GetBass *GetBassArgs `xml:"u:GetBass,omitempty"`
|
||||
SetBass *SetBassArgs `xml:"u:SetBass,omitempty"`
|
||||
GetTreble *GetTrebleArgs `xml:"u:GetTreble,omitempty"`
|
||||
SetTreble *SetTrebleArgs `xml:"u:SetTreble,omitempty"`
|
||||
GetEQ *GetEQArgs `xml:"u:GetEQ,omitempty"`
|
||||
SetEQ *SetEQArgs `xml:"u:SetEQ,omitempty"`
|
||||
GetLoudness *GetLoudnessArgs `xml:"u:GetLoudness,omitempty"`
|
||||
SetLoudness *SetLoudnessArgs `xml:"u:SetLoudness,omitempty"`
|
||||
GetSupportsOutputFixed *GetSupportsOutputFixedArgs `xml:"u:GetSupportsOutputFixed,omitempty"`
|
||||
GetOutputFixed *GetOutputFixedArgs `xml:"u:GetOutputFixed,omitempty"`
|
||||
SetOutputFixed *SetOutputFixedArgs `xml:"u:SetOutputFixed,omitempty"`
|
||||
GetHeadphoneConnected *GetHeadphoneConnectedArgs `xml:"u:GetHeadphoneConnected,omitempty"`
|
||||
RampToVolume *RampToVolumeArgs `xml:"u:RampToVolume,omitempty"`
|
||||
RestoreVolumePriorToRamp *RestoreVolumePriorToRampArgs `xml:"u:RestoreVolumePriorToRamp,omitempty"`
|
||||
SetChannelMap *SetChannelMapArgs `xml:"u:SetChannelMap,omitempty"`
|
||||
SetRoomCalibrationX *SetRoomCalibrationXArgs `xml:"u:SetRoomCalibrationX,omitempty"`
|
||||
GetRoomCalibrationStatus *GetRoomCalibrationStatusArgs `xml:"u:GetRoomCalibrationStatus,omitempty"`
|
||||
SetRoomCalibrationStatus *SetRoomCalibrationStatusArgs `xml:"u:SetRoomCalibrationStatus,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
GetMute *GetMuteResponse `xml:"GetMuteResponse,omitempty"`
|
||||
SetMute *SetMuteResponse `xml:"SetMuteResponse,omitempty"`
|
||||
ResetBasicEQ *ResetBasicEQResponse `xml:"ResetBasicEQResponse,omitempty"`
|
||||
ResetExtEQ *ResetExtEQResponse `xml:"ResetExtEQResponse,omitempty"`
|
||||
GetVolume *GetVolumeResponse `xml:"GetVolumeResponse,omitempty"`
|
||||
SetVolume *SetVolumeResponse `xml:"SetVolumeResponse,omitempty"`
|
||||
SetRelativeVolume *SetRelativeVolumeResponse `xml:"SetRelativeVolumeResponse,omitempty"`
|
||||
GetVolumeDB *GetVolumeDBResponse `xml:"GetVolumeDBResponse,omitempty"`
|
||||
SetVolumeDB *SetVolumeDBResponse `xml:"SetVolumeDBResponse,omitempty"`
|
||||
GetVolumeDBRange *GetVolumeDBRangeResponse `xml:"GetVolumeDBRangeResponse,omitempty"`
|
||||
GetBass *GetBassResponse `xml:"GetBassResponse,omitempty"`
|
||||
SetBass *SetBassResponse `xml:"SetBassResponse,omitempty"`
|
||||
GetTreble *GetTrebleResponse `xml:"GetTrebleResponse,omitempty"`
|
||||
SetTreble *SetTrebleResponse `xml:"SetTrebleResponse,omitempty"`
|
||||
GetEQ *GetEQResponse `xml:"GetEQResponse,omitempty"`
|
||||
SetEQ *SetEQResponse `xml:"SetEQResponse,omitempty"`
|
||||
GetLoudness *GetLoudnessResponse `xml:"GetLoudnessResponse,omitempty"`
|
||||
SetLoudness *SetLoudnessResponse `xml:"SetLoudnessResponse,omitempty"`
|
||||
GetSupportsOutputFixed *GetSupportsOutputFixedResponse `xml:"GetSupportsOutputFixedResponse,omitempty"`
|
||||
GetOutputFixed *GetOutputFixedResponse `xml:"GetOutputFixedResponse,omitempty"`
|
||||
SetOutputFixed *SetOutputFixedResponse `xml:"SetOutputFixedResponse,omitempty"`
|
||||
GetHeadphoneConnected *GetHeadphoneConnectedResponse `xml:"GetHeadphoneConnectedResponse,omitempty"`
|
||||
RampToVolume *RampToVolumeResponse `xml:"RampToVolumeResponse,omitempty"`
|
||||
RestoreVolumePriorToRamp *RestoreVolumePriorToRampResponse `xml:"RestoreVolumePriorToRampResponse,omitempty"`
|
||||
SetChannelMap *SetChannelMapResponse `xml:"SetChannelMapResponse,omitempty"`
|
||||
SetRoomCalibrationX *SetRoomCalibrationXResponse `xml:"SetRoomCalibrationXResponse,omitempty"`
|
||||
GetRoomCalibrationStatus *GetRoomCalibrationStatusResponse `xml:"GetRoomCalibrationStatusResponse,omitempty"`
|
||||
SetRoomCalibrationStatus *SetRoomCalibrationStatusResponse `xml:"SetRoomCalibrationStatusResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type GetMuteArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
// Allowed Value: SpeakerOnly
|
||||
Channel string `xml:"Channel"`
|
||||
}
|
||||
type GetMuteResponse struct {
|
||||
CurrentMute bool `xml:"CurrentMute"`
|
||||
}
|
||||
|
||||
func (s *Service) GetMute(httpClient *http.Client, args *GetMuteArgs) (*GetMuteResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetMute`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetMute: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetMute == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetMute()`)
|
||||
}
|
||||
|
||||
return r.Body.GetMute, nil
|
||||
}
|
||||
|
||||
type SetMuteArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
// Allowed Value: SpeakerOnly
|
||||
Channel string `xml:"Channel"`
|
||||
DesiredMute bool `xml:"DesiredMute"`
|
||||
}
|
||||
type SetMuteResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetMute(httpClient *http.Client, args *SetMuteArgs) (*SetMuteResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetMute`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetMute: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetMute == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetMute()`)
|
||||
}
|
||||
|
||||
return r.Body.SetMute, nil
|
||||
}
|
||||
|
||||
type ResetBasicEQArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type ResetBasicEQResponse struct {
|
||||
Bass int16 `xml:"Bass"`
|
||||
Treble int16 `xml:"Treble"`
|
||||
Loudness bool `xml:"Loudness"`
|
||||
LeftVolume uint16 `xml:"LeftVolume"`
|
||||
RightVolume uint16 `xml:"RightVolume"`
|
||||
}
|
||||
|
||||
func (s *Service) ResetBasicEQ(httpClient *http.Client, args *ResetBasicEQArgs) (*ResetBasicEQResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ResetBasicEQ`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ResetBasicEQ: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ResetBasicEQ == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.ResetBasicEQ()`)
|
||||
}
|
||||
|
||||
return r.Body.ResetBasicEQ, nil
|
||||
}
|
||||
|
||||
type ResetExtEQArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
EQType string `xml:"EQType"`
|
||||
}
|
||||
type ResetExtEQResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) ResetExtEQ(httpClient *http.Client, args *ResetExtEQArgs) (*ResetExtEQResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ResetExtEQ`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ResetExtEQ: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ResetExtEQ == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.ResetExtEQ()`)
|
||||
}
|
||||
|
||||
return r.Body.ResetExtEQ, nil
|
||||
}
|
||||
|
||||
type GetVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
}
|
||||
type GetVolumeResponse struct {
|
||||
CurrentVolume uint16 `xml:"CurrentVolume"`
|
||||
}
|
||||
|
||||
func (s *Service) GetVolume(httpClient *http.Client, args *GetVolumeArgs) (*GetVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.GetVolume, nil
|
||||
}
|
||||
|
||||
type SetVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
// Allowed Range: 0 -> 100 step: 1
|
||||
DesiredVolume uint16 `xml:"DesiredVolume"`
|
||||
}
|
||||
type SetVolumeResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetVolume(httpClient *http.Client, args *SetVolumeArgs) (*SetVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.SetVolume, nil
|
||||
}
|
||||
|
||||
type SetRelativeVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
Adjustment int32 `xml:"Adjustment"`
|
||||
}
|
||||
type SetRelativeVolumeResponse struct {
|
||||
NewVolume uint16 `xml:"NewVolume"`
|
||||
}
|
||||
|
||||
func (s *Service) SetRelativeVolume(httpClient *http.Client, args *SetRelativeVolumeArgs) (*SetRelativeVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetRelativeVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetRelativeVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetRelativeVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetRelativeVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.SetRelativeVolume, nil
|
||||
}
|
||||
|
||||
type GetVolumeDBArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
}
|
||||
type GetVolumeDBResponse struct {
|
||||
CurrentVolume int16 `xml:"CurrentVolume"`
|
||||
}
|
||||
|
||||
func (s *Service) GetVolumeDB(httpClient *http.Client, args *GetVolumeDBArgs) (*GetVolumeDBResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetVolumeDB`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetVolumeDB: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetVolumeDB == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetVolumeDB()`)
|
||||
}
|
||||
|
||||
return r.Body.GetVolumeDB, nil
|
||||
}
|
||||
|
||||
type SetVolumeDBArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
DesiredVolume int16 `xml:"DesiredVolume"`
|
||||
}
|
||||
type SetVolumeDBResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetVolumeDB(httpClient *http.Client, args *SetVolumeDBArgs) (*SetVolumeDBResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetVolumeDB`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetVolumeDB: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetVolumeDB == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetVolumeDB()`)
|
||||
}
|
||||
|
||||
return r.Body.SetVolumeDB, nil
|
||||
}
|
||||
|
||||
type GetVolumeDBRangeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
}
|
||||
type GetVolumeDBRangeResponse struct {
|
||||
MinValue int16 `xml:"MinValue"`
|
||||
MaxValue int16 `xml:"MaxValue"`
|
||||
}
|
||||
|
||||
func (s *Service) GetVolumeDBRange(httpClient *http.Client, args *GetVolumeDBRangeArgs) (*GetVolumeDBRangeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetVolumeDBRange`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetVolumeDBRange: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetVolumeDBRange == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetVolumeDBRange()`)
|
||||
}
|
||||
|
||||
return r.Body.GetVolumeDBRange, nil
|
||||
}
|
||||
|
||||
type GetBassArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type GetBassResponse struct {
|
||||
CurrentBass int16 `xml:"CurrentBass"`
|
||||
}
|
||||
|
||||
func (s *Service) GetBass(httpClient *http.Client, args *GetBassArgs) (*GetBassResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetBass`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetBass: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetBass == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetBass()`)
|
||||
}
|
||||
|
||||
return r.Body.GetBass, nil
|
||||
}
|
||||
|
||||
type SetBassArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Range: -10 -> 10 step: 1
|
||||
DesiredBass int16 `xml:"DesiredBass"`
|
||||
}
|
||||
type SetBassResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetBass(httpClient *http.Client, args *SetBassArgs) (*SetBassResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetBass`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetBass: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetBass == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetBass()`)
|
||||
}
|
||||
|
||||
return r.Body.SetBass, nil
|
||||
}
|
||||
|
||||
type GetTrebleArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type GetTrebleResponse struct {
|
||||
CurrentTreble int16 `xml:"CurrentTreble"`
|
||||
}
|
||||
|
||||
func (s *Service) GetTreble(httpClient *http.Client, args *GetTrebleArgs) (*GetTrebleResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetTreble`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetTreble: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetTreble == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetTreble()`)
|
||||
}
|
||||
|
||||
return r.Body.GetTreble, nil
|
||||
}
|
||||
|
||||
type SetTrebleArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Range: -10 -> 10 step: 1
|
||||
DesiredTreble int16 `xml:"DesiredTreble"`
|
||||
}
|
||||
type SetTrebleResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetTreble(httpClient *http.Client, args *SetTrebleArgs) (*SetTrebleResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetTreble`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetTreble: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetTreble == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetTreble()`)
|
||||
}
|
||||
|
||||
return r.Body.SetTreble, nil
|
||||
}
|
||||
|
||||
type GetEQArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
EQType string `xml:"EQType"`
|
||||
}
|
||||
type GetEQResponse struct {
|
||||
CurrentValue int16 `xml:"CurrentValue"`
|
||||
}
|
||||
|
||||
func (s *Service) GetEQ(httpClient *http.Client, args *GetEQArgs) (*GetEQResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetEQ`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetEQ: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetEQ == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetEQ()`)
|
||||
}
|
||||
|
||||
return r.Body.GetEQ, nil
|
||||
}
|
||||
|
||||
type SetEQArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
EQType string `xml:"EQType"`
|
||||
DesiredValue int16 `xml:"DesiredValue"`
|
||||
}
|
||||
type SetEQResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetEQ(httpClient *http.Client, args *SetEQArgs) (*SetEQResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetEQ`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetEQ: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetEQ == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetEQ()`)
|
||||
}
|
||||
|
||||
return r.Body.SetEQ, nil
|
||||
}
|
||||
|
||||
type GetLoudnessArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
}
|
||||
type GetLoudnessResponse struct {
|
||||
CurrentLoudness bool `xml:"CurrentLoudness"`
|
||||
}
|
||||
|
||||
func (s *Service) GetLoudness(httpClient *http.Client, args *GetLoudnessArgs) (*GetLoudnessResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetLoudness`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetLoudness: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetLoudness == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetLoudness()`)
|
||||
}
|
||||
|
||||
return r.Body.GetLoudness, nil
|
||||
}
|
||||
|
||||
type SetLoudnessArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
DesiredLoudness bool `xml:"DesiredLoudness"`
|
||||
}
|
||||
type SetLoudnessResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetLoudness(httpClient *http.Client, args *SetLoudnessArgs) (*SetLoudnessResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetLoudness`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetLoudness: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetLoudness == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetLoudness()`)
|
||||
}
|
||||
|
||||
return r.Body.SetLoudness, nil
|
||||
}
|
||||
|
||||
type GetSupportsOutputFixedArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type GetSupportsOutputFixedResponse struct {
|
||||
CurrentSupportsFixed bool `xml:"CurrentSupportsFixed"`
|
||||
}
|
||||
|
||||
func (s *Service) GetSupportsOutputFixed(httpClient *http.Client, args *GetSupportsOutputFixedArgs) (*GetSupportsOutputFixedResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetSupportsOutputFixed`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetSupportsOutputFixed: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetSupportsOutputFixed == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetSupportsOutputFixed()`)
|
||||
}
|
||||
|
||||
return r.Body.GetSupportsOutputFixed, nil
|
||||
}
|
||||
|
||||
type GetOutputFixedArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type GetOutputFixedResponse struct {
|
||||
CurrentFixed bool `xml:"CurrentFixed"`
|
||||
}
|
||||
|
||||
func (s *Service) GetOutputFixed(httpClient *http.Client, args *GetOutputFixedArgs) (*GetOutputFixedResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetOutputFixed`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetOutputFixed: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetOutputFixed == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetOutputFixed()`)
|
||||
}
|
||||
|
||||
return r.Body.GetOutputFixed, nil
|
||||
}
|
||||
|
||||
type SetOutputFixedArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
DesiredFixed bool `xml:"DesiredFixed"`
|
||||
}
|
||||
type SetOutputFixedResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetOutputFixed(httpClient *http.Client, args *SetOutputFixedArgs) (*SetOutputFixedResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetOutputFixed`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetOutputFixed: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetOutputFixed == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetOutputFixed()`)
|
||||
}
|
||||
|
||||
return r.Body.SetOutputFixed, nil
|
||||
}
|
||||
|
||||
type GetHeadphoneConnectedArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type GetHeadphoneConnectedResponse struct {
|
||||
CurrentHeadphoneConnected bool `xml:"CurrentHeadphoneConnected"`
|
||||
}
|
||||
|
||||
func (s *Service) GetHeadphoneConnected(httpClient *http.Client, args *GetHeadphoneConnectedArgs) (*GetHeadphoneConnectedResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetHeadphoneConnected`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetHeadphoneConnected: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetHeadphoneConnected == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetHeadphoneConnected()`)
|
||||
}
|
||||
|
||||
return r.Body.GetHeadphoneConnected, nil
|
||||
}
|
||||
|
||||
type RampToVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
// Allowed Value: SLEEP_TIMER_RAMP_TYPE
|
||||
// Allowed Value: ALARM_RAMP_TYPE
|
||||
// Allowed Value: AUTOPLAY_RAMP_TYPE
|
||||
RampType string `xml:"RampType"`
|
||||
// Allowed Range: 0 -> 100 step: 1
|
||||
DesiredVolume uint16 `xml:"DesiredVolume"`
|
||||
ResetVolumeAfter bool `xml:"ResetVolumeAfter"`
|
||||
ProgramURI string `xml:"ProgramURI"`
|
||||
}
|
||||
type RampToVolumeResponse struct {
|
||||
RampTime uint32 `xml:"RampTime"`
|
||||
}
|
||||
|
||||
func (s *Service) RampToVolume(httpClient *http.Client, args *RampToVolumeArgs) (*RampToVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RampToVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RampToVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RampToVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.RampToVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.RampToVolume, nil
|
||||
}
|
||||
|
||||
type RestoreVolumePriorToRampArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
// Allowed Value: Master
|
||||
// Allowed Value: LF
|
||||
// Allowed Value: RF
|
||||
Channel string `xml:"Channel"`
|
||||
}
|
||||
type RestoreVolumePriorToRampResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RestoreVolumePriorToRamp(httpClient *http.Client, args *RestoreVolumePriorToRampArgs) (*RestoreVolumePriorToRampResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RestoreVolumePriorToRamp`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RestoreVolumePriorToRamp: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RestoreVolumePriorToRamp == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.RestoreVolumePriorToRamp()`)
|
||||
}
|
||||
|
||||
return r.Body.RestoreVolumePriorToRamp, nil
|
||||
}
|
||||
|
||||
type SetChannelMapArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
ChannelMap string `xml:"ChannelMap"`
|
||||
}
|
||||
type SetChannelMapResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetChannelMap(httpClient *http.Client, args *SetChannelMapArgs) (*SetChannelMapResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetChannelMap`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetChannelMap: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetChannelMap == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetChannelMap()`)
|
||||
}
|
||||
|
||||
return r.Body.SetChannelMap, nil
|
||||
}
|
||||
|
||||
type SetRoomCalibrationXArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
CalibrationID string `xml:"CalibrationID"`
|
||||
Coefficients string `xml:"Coefficients"`
|
||||
CalibrationMode string `xml:"CalibrationMode"`
|
||||
}
|
||||
type SetRoomCalibrationXResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetRoomCalibrationX(httpClient *http.Client, args *SetRoomCalibrationXArgs) (*SetRoomCalibrationXResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetRoomCalibrationX`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetRoomCalibrationX: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetRoomCalibrationX == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetRoomCalibrationX()`)
|
||||
}
|
||||
|
||||
return r.Body.SetRoomCalibrationX, nil
|
||||
}
|
||||
|
||||
type GetRoomCalibrationStatusArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type GetRoomCalibrationStatusResponse struct {
|
||||
RoomCalibrationEnabled bool `xml:"RoomCalibrationEnabled"`
|
||||
RoomCalibrationAvailable bool `xml:"RoomCalibrationAvailable"`
|
||||
}
|
||||
|
||||
func (s *Service) GetRoomCalibrationStatus(httpClient *http.Client, args *GetRoomCalibrationStatusArgs) (*GetRoomCalibrationStatusResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetRoomCalibrationStatus`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetRoomCalibrationStatus: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetRoomCalibrationStatus == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetRoomCalibrationStatus()`)
|
||||
}
|
||||
|
||||
return r.Body.GetRoomCalibrationStatus, nil
|
||||
}
|
||||
|
||||
type SetRoomCalibrationStatusArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
RoomCalibrationEnabled bool `xml:"RoomCalibrationEnabled"`
|
||||
}
|
||||
type SetRoomCalibrationStatusResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetRoomCalibrationStatus(httpClient *http.Client, args *SetRoomCalibrationStatusArgs) (*SetRoomCalibrationStatusResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetRoomCalibrationStatus`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetRoomCalibrationStatus: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetRoomCalibrationStatus == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetRoomCalibrationStatus()`)
|
||||
}
|
||||
|
||||
return r.Body.SetRoomCalibrationStatus, nil
|
||||
}
|
||||
-576
@@ -1,576 +0,0 @@
|
||||
package systemproperties
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:SystemProperties:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/SystemProperties/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/SystemProperties/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
SetString *SetStringArgs `xml:"u:SetString,omitempty"`
|
||||
GetString *GetStringArgs `xml:"u:GetString,omitempty"`
|
||||
Remove *RemoveArgs `xml:"u:Remove,omitempty"`
|
||||
GetWebCode *GetWebCodeArgs `xml:"u:GetWebCode,omitempty"`
|
||||
ProvisionCredentialedTrialAccountX *ProvisionCredentialedTrialAccountXArgs `xml:"u:ProvisionCredentialedTrialAccountX,omitempty"`
|
||||
AddAccountX *AddAccountXArgs `xml:"u:AddAccountX,omitempty"`
|
||||
AddOAuthAccountX *AddOAuthAccountXArgs `xml:"u:AddOAuthAccountX,omitempty"`
|
||||
RemoveAccount *RemoveAccountArgs `xml:"u:RemoveAccount,omitempty"`
|
||||
EditAccountPasswordX *EditAccountPasswordXArgs `xml:"u:EditAccountPasswordX,omitempty"`
|
||||
SetAccountNicknameX *SetAccountNicknameXArgs `xml:"u:SetAccountNicknameX,omitempty"`
|
||||
RefreshAccountCredentialsX *RefreshAccountCredentialsXArgs `xml:"u:RefreshAccountCredentialsX,omitempty"`
|
||||
EditAccountMd *EditAccountMdArgs `xml:"u:EditAccountMd,omitempty"`
|
||||
DoPostUpdateTasks *DoPostUpdateTasksArgs `xml:"u:DoPostUpdateTasks,omitempty"`
|
||||
ResetThirdPartyCredentials *ResetThirdPartyCredentialsArgs `xml:"u:ResetThirdPartyCredentials,omitempty"`
|
||||
EnableRDM *EnableRDMArgs `xml:"u:EnableRDM,omitempty"`
|
||||
GetRDM *GetRDMArgs `xml:"u:GetRDM,omitempty"`
|
||||
ReplaceAccountX *ReplaceAccountXArgs `xml:"u:ReplaceAccountX,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
SetString *SetStringResponse `xml:"SetStringResponse,omitempty"`
|
||||
GetString *GetStringResponse `xml:"GetStringResponse,omitempty"`
|
||||
Remove *RemoveResponse `xml:"RemoveResponse,omitempty"`
|
||||
GetWebCode *GetWebCodeResponse `xml:"GetWebCodeResponse,omitempty"`
|
||||
ProvisionCredentialedTrialAccountX *ProvisionCredentialedTrialAccountXResponse `xml:"ProvisionCredentialedTrialAccountXResponse,omitempty"`
|
||||
AddAccountX *AddAccountXResponse `xml:"AddAccountXResponse,omitempty"`
|
||||
AddOAuthAccountX *AddOAuthAccountXResponse `xml:"AddOAuthAccountXResponse,omitempty"`
|
||||
RemoveAccount *RemoveAccountResponse `xml:"RemoveAccountResponse,omitempty"`
|
||||
EditAccountPasswordX *EditAccountPasswordXResponse `xml:"EditAccountPasswordXResponse,omitempty"`
|
||||
SetAccountNicknameX *SetAccountNicknameXResponse `xml:"SetAccountNicknameXResponse,omitempty"`
|
||||
RefreshAccountCredentialsX *RefreshAccountCredentialsXResponse `xml:"RefreshAccountCredentialsXResponse,omitempty"`
|
||||
EditAccountMd *EditAccountMdResponse `xml:"EditAccountMdResponse,omitempty"`
|
||||
DoPostUpdateTasks *DoPostUpdateTasksResponse `xml:"DoPostUpdateTasksResponse,omitempty"`
|
||||
ResetThirdPartyCredentials *ResetThirdPartyCredentialsResponse `xml:"ResetThirdPartyCredentialsResponse,omitempty"`
|
||||
EnableRDM *EnableRDMResponse `xml:"EnableRDMResponse,omitempty"`
|
||||
GetRDM *GetRDMResponse `xml:"GetRDMResponse,omitempty"`
|
||||
ReplaceAccountX *ReplaceAccountXResponse `xml:"ReplaceAccountXResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type SetStringArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
VariableName string `xml:"VariableName"`
|
||||
StringValue string `xml:"StringValue"`
|
||||
}
|
||||
type SetStringResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetString(httpClient *http.Client, args *SetStringArgs) (*SetStringResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetString`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetString: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetString == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.SetString()`)
|
||||
}
|
||||
|
||||
return r.Body.SetString, nil
|
||||
}
|
||||
|
||||
type GetStringArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
VariableName string `xml:"VariableName"`
|
||||
}
|
||||
type GetStringResponse struct {
|
||||
StringValue string `xml:"StringValue"`
|
||||
}
|
||||
|
||||
func (s *Service) GetString(httpClient *http.Client, args *GetStringArgs) (*GetStringResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetString`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetString: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetString == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.GetString()`)
|
||||
}
|
||||
|
||||
return r.Body.GetString, nil
|
||||
}
|
||||
|
||||
type RemoveArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
VariableName string `xml:"VariableName"`
|
||||
}
|
||||
type RemoveResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) Remove(httpClient *http.Client, args *RemoveArgs) (*RemoveResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Remove`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Remove: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Remove == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.Remove()`)
|
||||
}
|
||||
|
||||
return r.Body.Remove, nil
|
||||
}
|
||||
|
||||
type GetWebCodeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountType uint32 `xml:"AccountType"`
|
||||
}
|
||||
type GetWebCodeResponse struct {
|
||||
WebCode string `xml:"WebCode"`
|
||||
}
|
||||
|
||||
func (s *Service) GetWebCode(httpClient *http.Client, args *GetWebCodeArgs) (*GetWebCodeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetWebCode`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetWebCode: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetWebCode == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.GetWebCode()`)
|
||||
}
|
||||
|
||||
return r.Body.GetWebCode, nil
|
||||
}
|
||||
|
||||
type ProvisionCredentialedTrialAccountXArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountType uint32 `xml:"AccountType"`
|
||||
AccountID string `xml:"AccountID"`
|
||||
AccountPassword string `xml:"AccountPassword"`
|
||||
}
|
||||
type ProvisionCredentialedTrialAccountXResponse struct {
|
||||
IsExpired bool `xml:"IsExpired"`
|
||||
AccountUDN string `xml:"AccountUDN"`
|
||||
}
|
||||
|
||||
func (s *Service) ProvisionCredentialedTrialAccountX(httpClient *http.Client, args *ProvisionCredentialedTrialAccountXArgs) (*ProvisionCredentialedTrialAccountXResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ProvisionCredentialedTrialAccountX`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ProvisionCredentialedTrialAccountX: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ProvisionCredentialedTrialAccountX == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.ProvisionCredentialedTrialAccountX()`)
|
||||
}
|
||||
|
||||
return r.Body.ProvisionCredentialedTrialAccountX, nil
|
||||
}
|
||||
|
||||
type AddAccountXArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountType uint32 `xml:"AccountType"`
|
||||
AccountID string `xml:"AccountID"`
|
||||
AccountPassword string `xml:"AccountPassword"`
|
||||
}
|
||||
type AddAccountXResponse struct {
|
||||
AccountUDN string `xml:"AccountUDN"`
|
||||
}
|
||||
|
||||
func (s *Service) AddAccountX(httpClient *http.Client, args *AddAccountXArgs) (*AddAccountXResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`AddAccountX`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{AddAccountX: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.AddAccountX == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.AddAccountX()`)
|
||||
}
|
||||
|
||||
return r.Body.AddAccountX, nil
|
||||
}
|
||||
|
||||
type AddOAuthAccountXArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountType uint32 `xml:"AccountType"`
|
||||
AccountToken string `xml:"AccountToken"`
|
||||
AccountKey string `xml:"AccountKey"`
|
||||
OAuthDeviceID string `xml:"OAuthDeviceID"`
|
||||
AuthorizationCode string `xml:"AuthorizationCode"`
|
||||
RedirectURI string `xml:"RedirectURI"`
|
||||
UserIdHashCode string `xml:"UserIdHashCode"`
|
||||
AccountTier uint32 `xml:"AccountTier"`
|
||||
}
|
||||
type AddOAuthAccountXResponse struct {
|
||||
AccountUDN string `xml:"AccountUDN"`
|
||||
AccountNickname string `xml:"AccountNickname"`
|
||||
}
|
||||
|
||||
func (s *Service) AddOAuthAccountX(httpClient *http.Client, args *AddOAuthAccountXArgs) (*AddOAuthAccountXResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`AddOAuthAccountX`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{AddOAuthAccountX: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.AddOAuthAccountX == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.AddOAuthAccountX()`)
|
||||
}
|
||||
|
||||
return r.Body.AddOAuthAccountX, nil
|
||||
}
|
||||
|
||||
type RemoveAccountArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountType uint32 `xml:"AccountType"`
|
||||
AccountID string `xml:"AccountID"`
|
||||
}
|
||||
type RemoveAccountResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RemoveAccount(httpClient *http.Client, args *RemoveAccountArgs) (*RemoveAccountResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RemoveAccount`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RemoveAccount: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RemoveAccount == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.RemoveAccount()`)
|
||||
}
|
||||
|
||||
return r.Body.RemoveAccount, nil
|
||||
}
|
||||
|
||||
type EditAccountPasswordXArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountType uint32 `xml:"AccountType"`
|
||||
AccountID string `xml:"AccountID"`
|
||||
NewAccountPassword string `xml:"NewAccountPassword"`
|
||||
}
|
||||
type EditAccountPasswordXResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) EditAccountPasswordX(httpClient *http.Client, args *EditAccountPasswordXArgs) (*EditAccountPasswordXResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`EditAccountPasswordX`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{EditAccountPasswordX: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.EditAccountPasswordX == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.EditAccountPasswordX()`)
|
||||
}
|
||||
|
||||
return r.Body.EditAccountPasswordX, nil
|
||||
}
|
||||
|
||||
type SetAccountNicknameXArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountUDN string `xml:"AccountUDN"`
|
||||
AccountNickname string `xml:"AccountNickname"`
|
||||
}
|
||||
type SetAccountNicknameXResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetAccountNicknameX(httpClient *http.Client, args *SetAccountNicknameXArgs) (*SetAccountNicknameXResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetAccountNicknameX`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetAccountNicknameX: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetAccountNicknameX == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.SetAccountNicknameX()`)
|
||||
}
|
||||
|
||||
return r.Body.SetAccountNicknameX, nil
|
||||
}
|
||||
|
||||
type RefreshAccountCredentialsXArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountType uint32 `xml:"AccountType"`
|
||||
AccountUID uint32 `xml:"AccountUID"`
|
||||
AccountToken string `xml:"AccountToken"`
|
||||
AccountKey string `xml:"AccountKey"`
|
||||
}
|
||||
type RefreshAccountCredentialsXResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RefreshAccountCredentialsX(httpClient *http.Client, args *RefreshAccountCredentialsXArgs) (*RefreshAccountCredentialsXResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RefreshAccountCredentialsX`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RefreshAccountCredentialsX: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RefreshAccountCredentialsX == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.RefreshAccountCredentialsX()`)
|
||||
}
|
||||
|
||||
return r.Body.RefreshAccountCredentialsX, nil
|
||||
}
|
||||
|
||||
type EditAccountMdArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountType uint32 `xml:"AccountType"`
|
||||
AccountID string `xml:"AccountID"`
|
||||
NewAccountMd string `xml:"NewAccountMd"`
|
||||
}
|
||||
type EditAccountMdResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) EditAccountMd(httpClient *http.Client, args *EditAccountMdArgs) (*EditAccountMdResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`EditAccountMd`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{EditAccountMd: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.EditAccountMd == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.EditAccountMd()`)
|
||||
}
|
||||
|
||||
return r.Body.EditAccountMd, nil
|
||||
}
|
||||
|
||||
type DoPostUpdateTasksArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type DoPostUpdateTasksResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) DoPostUpdateTasks(httpClient *http.Client, args *DoPostUpdateTasksArgs) (*DoPostUpdateTasksResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`DoPostUpdateTasks`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{DoPostUpdateTasks: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.DoPostUpdateTasks == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.DoPostUpdateTasks()`)
|
||||
}
|
||||
|
||||
return r.Body.DoPostUpdateTasks, nil
|
||||
}
|
||||
|
||||
type ResetThirdPartyCredentialsArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type ResetThirdPartyCredentialsResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) ResetThirdPartyCredentials(httpClient *http.Client, args *ResetThirdPartyCredentialsArgs) (*ResetThirdPartyCredentialsResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ResetThirdPartyCredentials`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ResetThirdPartyCredentials: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ResetThirdPartyCredentials == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.ResetThirdPartyCredentials()`)
|
||||
}
|
||||
|
||||
return r.Body.ResetThirdPartyCredentials, nil
|
||||
}
|
||||
|
||||
type EnableRDMArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
RDMValue bool `xml:"RDMValue"`
|
||||
}
|
||||
type EnableRDMResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) EnableRDM(httpClient *http.Client, args *EnableRDMArgs) (*EnableRDMResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`EnableRDM`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{EnableRDM: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.EnableRDM == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.EnableRDM()`)
|
||||
}
|
||||
|
||||
return r.Body.EnableRDM, nil
|
||||
}
|
||||
|
||||
type GetRDMArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetRDMResponse struct {
|
||||
RDMValue bool `xml:"RDMValue"`
|
||||
}
|
||||
|
||||
func (s *Service) GetRDM(httpClient *http.Client, args *GetRDMArgs) (*GetRDMResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetRDM`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetRDM: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetRDM == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.GetRDM()`)
|
||||
}
|
||||
|
||||
return r.Body.GetRDM, nil
|
||||
}
|
||||
|
||||
type ReplaceAccountXArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
AccountUDN string `xml:"AccountUDN"`
|
||||
NewAccountID string `xml:"NewAccountID"`
|
||||
NewAccountPassword string `xml:"NewAccountPassword"`
|
||||
AccountToken string `xml:"AccountToken"`
|
||||
AccountKey string `xml:"AccountKey"`
|
||||
OAuthDeviceID string `xml:"OAuthDeviceID"`
|
||||
}
|
||||
type ReplaceAccountXResponse struct {
|
||||
NewAccountUDN string `xml:"NewAccountUDN"`
|
||||
}
|
||||
|
||||
func (s *Service) ReplaceAccountX(httpClient *http.Client, args *ReplaceAccountXArgs) (*ReplaceAccountXResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ReplaceAccountX`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ReplaceAccountX: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ReplaceAccountX == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling systemproperties.ReplaceAccountX()`)
|
||||
}
|
||||
|
||||
return r.Body.ReplaceAccountX, nil
|
||||
}
|
||||
-306
@@ -1,306 +0,0 @@
|
||||
package virtuallinein
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:VirtualLineIn:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/MediaRenderer/VirtualLineIn/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/MediaRenderer/VirtualLineIn/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
StartTransmission *StartTransmissionArgs `xml:"u:StartTransmission,omitempty"`
|
||||
StopTransmission *StopTransmissionArgs `xml:"u:StopTransmission,omitempty"`
|
||||
Play *PlayArgs `xml:"u:Play,omitempty"`
|
||||
Pause *PauseArgs `xml:"u:Pause,omitempty"`
|
||||
Next *NextArgs `xml:"u:Next,omitempty"`
|
||||
Previous *PreviousArgs `xml:"u:Previous,omitempty"`
|
||||
Stop *StopArgs `xml:"u:Stop,omitempty"`
|
||||
SetVolume *SetVolumeArgs `xml:"u:SetVolume,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
StartTransmission *StartTransmissionResponse `xml:"StartTransmissionResponse,omitempty"`
|
||||
StopTransmission *StopTransmissionResponse `xml:"StopTransmissionResponse,omitempty"`
|
||||
Play *PlayResponse `xml:"PlayResponse,omitempty"`
|
||||
Pause *PauseResponse `xml:"PauseResponse,omitempty"`
|
||||
Next *NextResponse `xml:"NextResponse,omitempty"`
|
||||
Previous *PreviousResponse `xml:"PreviousResponse,omitempty"`
|
||||
Stop *StopResponse `xml:"StopResponse,omitempty"`
|
||||
SetVolume *SetVolumeResponse `xml:"SetVolumeResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type StartTransmissionArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
CoordinatorID string `xml:"CoordinatorID"`
|
||||
}
|
||||
type StartTransmissionResponse struct {
|
||||
CurrentTransportSettings string `xml:"CurrentTransportSettings"`
|
||||
}
|
||||
|
||||
func (s *Service) StartTransmission(httpClient *http.Client, args *StartTransmissionArgs) (*StartTransmissionResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`StartTransmission`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{StartTransmission: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.StartTransmission == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling virtuallinein.StartTransmission()`)
|
||||
}
|
||||
|
||||
return r.Body.StartTransmission, nil
|
||||
}
|
||||
|
||||
type StopTransmissionArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
CoordinatorID string `xml:"CoordinatorID"`
|
||||
}
|
||||
type StopTransmissionResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) StopTransmission(httpClient *http.Client, args *StopTransmissionArgs) (*StopTransmissionResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`StopTransmission`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{StopTransmission: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.StopTransmission == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling virtuallinein.StopTransmission()`)
|
||||
}
|
||||
|
||||
return r.Body.StopTransmission, nil
|
||||
}
|
||||
|
||||
type PlayArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
Speed string `xml:"Speed"`
|
||||
}
|
||||
type PlayResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) Play(httpClient *http.Client, args *PlayArgs) (*PlayResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Play`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Play: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Play == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling virtuallinein.Play()`)
|
||||
}
|
||||
|
||||
return r.Body.Play, nil
|
||||
}
|
||||
|
||||
type PauseArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type PauseResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) Pause(httpClient *http.Client, args *PauseArgs) (*PauseResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Pause`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Pause: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Pause == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling virtuallinein.Pause()`)
|
||||
}
|
||||
|
||||
return r.Body.Pause, nil
|
||||
}
|
||||
|
||||
type NextArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type NextResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) Next(httpClient *http.Client, args *NextArgs) (*NextResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Next`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Next: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Next == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling virtuallinein.Next()`)
|
||||
}
|
||||
|
||||
return r.Body.Next, nil
|
||||
}
|
||||
|
||||
type PreviousArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type PreviousResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) Previous(httpClient *http.Client, args *PreviousArgs) (*PreviousResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Previous`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Previous: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Previous == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling virtuallinein.Previous()`)
|
||||
}
|
||||
|
||||
return r.Body.Previous, nil
|
||||
}
|
||||
|
||||
type StopArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
}
|
||||
type StopResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) Stop(httpClient *http.Client, args *StopArgs) (*StopResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`Stop`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{Stop: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.Stop == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling virtuallinein.Stop()`)
|
||||
}
|
||||
|
||||
return r.Body.Stop, nil
|
||||
}
|
||||
|
||||
type SetVolumeArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
InstanceID uint32 `xml:"InstanceID"`
|
||||
DesiredVolume uint16 `xml:"DesiredVolume"`
|
||||
}
|
||||
type SetVolumeResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) SetVolume(httpClient *http.Client, args *SetVolumeArgs) (*SetVolumeResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SetVolume`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SetVolume: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SetVolume == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling virtuallinein.SetVolume()`)
|
||||
}
|
||||
|
||||
return r.Body.SetVolume, nil
|
||||
}
|
||||
-318
@@ -1,318 +0,0 @@
|
||||
package zonegrouptopology
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
_ServiceURN = "urn:schemas-upnp-org:service:ZoneGroupTopology:1"
|
||||
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
|
||||
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ControlEndpoint *url.URL
|
||||
EventEndpoint *url.URL
|
||||
}
|
||||
|
||||
func NewService(deviceUrl *url.URL) *Service {
|
||||
c, err := url.Parse(`/ZoneGroupTopology/Control`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
e, err := url.Parse(`/ZoneGroupTopology/Event`)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
return &Service{
|
||||
ControlEndpoint: deviceUrl.ResolveReference(c),
|
||||
EventEndpoint: deviceUrl.ResolveReference(e),
|
||||
}
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
XMLName xml.Name `xml:"s:Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"s:encodingStyle,attr"`
|
||||
Body Body `xml:"s:Body"`
|
||||
}
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"s:Body"`
|
||||
CheckForUpdate *CheckForUpdateArgs `xml:"u:CheckForUpdate,omitempty"`
|
||||
BeginSoftwareUpdate *BeginSoftwareUpdateArgs `xml:"u:BeginSoftwareUpdate,omitempty"`
|
||||
ReportUnresponsiveDevice *ReportUnresponsiveDeviceArgs `xml:"u:ReportUnresponsiveDevice,omitempty"`
|
||||
ReportAlarmStartedRunning *ReportAlarmStartedRunningArgs `xml:"u:ReportAlarmStartedRunning,omitempty"`
|
||||
SubmitDiagnostics *SubmitDiagnosticsArgs `xml:"u:SubmitDiagnostics,omitempty"`
|
||||
RegisterMobileDevice *RegisterMobileDeviceArgs `xml:"u:RegisterMobileDevice,omitempty"`
|
||||
GetZoneGroupAttributes *GetZoneGroupAttributesArgs `xml:"u:GetZoneGroupAttributes,omitempty"`
|
||||
GetZoneGroupState *GetZoneGroupStateArgs `xml:"u:GetZoneGroupState,omitempty"`
|
||||
}
|
||||
type EnvelopeResponse struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Xmlns string `xml:"xmlns:s,attr"`
|
||||
EncodingStyle string `xml:"encodingStyle,attr"`
|
||||
Body BodyResponse `xml:"Body"`
|
||||
}
|
||||
type BodyResponse struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
CheckForUpdate *CheckForUpdateResponse `xml:"CheckForUpdateResponse,omitempty"`
|
||||
BeginSoftwareUpdate *BeginSoftwareUpdateResponse `xml:"BeginSoftwareUpdateResponse,omitempty"`
|
||||
ReportUnresponsiveDevice *ReportUnresponsiveDeviceResponse `xml:"ReportUnresponsiveDeviceResponse,omitempty"`
|
||||
ReportAlarmStartedRunning *ReportAlarmStartedRunningResponse `xml:"ReportAlarmStartedRunningResponse,omitempty"`
|
||||
SubmitDiagnostics *SubmitDiagnosticsResponse `xml:"SubmitDiagnosticsResponse,omitempty"`
|
||||
RegisterMobileDevice *RegisterMobileDeviceResponse `xml:"RegisterMobileDeviceResponse,omitempty"`
|
||||
GetZoneGroupAttributes *GetZoneGroupAttributesResponse `xml:"GetZoneGroupAttributesResponse,omitempty"`
|
||||
GetZoneGroupState *GetZoneGroupStateResponse `xml:"GetZoneGroupStateResponse,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
|
||||
marshaled, err := xml.Marshal(envelope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postBody := []byte(`<?xml version="1.0"?>`)
|
||||
postBody = append(postBody, marshaled...)
|
||||
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
|
||||
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var envelopeResponse EnvelopeResponse
|
||||
err = xml.Unmarshal(responseBody, &envelopeResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeResponse, nil
|
||||
}
|
||||
|
||||
type CheckForUpdateArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
// Allowed Value: All
|
||||
// Allowed Value: Software
|
||||
UpdateType string `xml:"UpdateType"`
|
||||
CachedOnly bool `xml:"CachedOnly"`
|
||||
Version string `xml:"Version"`
|
||||
}
|
||||
type CheckForUpdateResponse struct {
|
||||
UpdateItem string `xml:"UpdateItem"`
|
||||
}
|
||||
|
||||
func (s *Service) CheckForUpdate(httpClient *http.Client, args *CheckForUpdateArgs) (*CheckForUpdateResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`CheckForUpdate`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{CheckForUpdate: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.CheckForUpdate == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.CheckForUpdate()`)
|
||||
}
|
||||
|
||||
return r.Body.CheckForUpdate, nil
|
||||
}
|
||||
|
||||
type BeginSoftwareUpdateArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
UpdateURL string `xml:"UpdateURL"`
|
||||
Flags uint32 `xml:"Flags"`
|
||||
ExtraOptions string `xml:"ExtraOptions"`
|
||||
}
|
||||
type BeginSoftwareUpdateResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) BeginSoftwareUpdate(httpClient *http.Client, args *BeginSoftwareUpdateArgs) (*BeginSoftwareUpdateResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`BeginSoftwareUpdate`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{BeginSoftwareUpdate: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.BeginSoftwareUpdate == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.BeginSoftwareUpdate()`)
|
||||
}
|
||||
|
||||
return r.Body.BeginSoftwareUpdate, nil
|
||||
}
|
||||
|
||||
type ReportUnresponsiveDeviceArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
DeviceUUID string `xml:"DeviceUUID"`
|
||||
// Allowed Value: Remove
|
||||
// Allowed Value: TopologyMonitorProbe
|
||||
// Allowed Value: VerifyThenRemoveSystemwide
|
||||
DesiredAction string `xml:"DesiredAction"`
|
||||
}
|
||||
type ReportUnresponsiveDeviceResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) ReportUnresponsiveDevice(httpClient *http.Client, args *ReportUnresponsiveDeviceArgs) (*ReportUnresponsiveDeviceResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ReportUnresponsiveDevice`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ReportUnresponsiveDevice: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ReportUnresponsiveDevice == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.ReportUnresponsiveDevice()`)
|
||||
}
|
||||
|
||||
return r.Body.ReportUnresponsiveDevice, nil
|
||||
}
|
||||
|
||||
type ReportAlarmStartedRunningArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type ReportAlarmStartedRunningResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) ReportAlarmStartedRunning(httpClient *http.Client, args *ReportAlarmStartedRunningArgs) (*ReportAlarmStartedRunningResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`ReportAlarmStartedRunning`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{ReportAlarmStartedRunning: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.ReportAlarmStartedRunning == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.ReportAlarmStartedRunning()`)
|
||||
}
|
||||
|
||||
return r.Body.ReportAlarmStartedRunning, nil
|
||||
}
|
||||
|
||||
type SubmitDiagnosticsArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
IncludeControllers bool `xml:"IncludeControllers"`
|
||||
Type string `xml:"Type"`
|
||||
}
|
||||
type SubmitDiagnosticsResponse struct {
|
||||
DiagnosticID uint32 `xml:"DiagnosticID"`
|
||||
}
|
||||
|
||||
func (s *Service) SubmitDiagnostics(httpClient *http.Client, args *SubmitDiagnosticsArgs) (*SubmitDiagnosticsResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`SubmitDiagnostics`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{SubmitDiagnostics: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.SubmitDiagnostics == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.SubmitDiagnostics()`)
|
||||
}
|
||||
|
||||
return r.Body.SubmitDiagnostics, nil
|
||||
}
|
||||
|
||||
type RegisterMobileDeviceArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
MobileDeviceName string `xml:"MobileDeviceName"`
|
||||
MobileDeviceUDN string `xml:"MobileDeviceUDN"`
|
||||
MobileIPAndPort string `xml:"MobileIPAndPort"`
|
||||
}
|
||||
type RegisterMobileDeviceResponse struct {
|
||||
}
|
||||
|
||||
func (s *Service) RegisterMobileDevice(httpClient *http.Client, args *RegisterMobileDeviceArgs) (*RegisterMobileDeviceResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`RegisterMobileDevice`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{RegisterMobileDevice: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.RegisterMobileDevice == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.RegisterMobileDevice()`)
|
||||
}
|
||||
|
||||
return r.Body.RegisterMobileDevice, nil
|
||||
}
|
||||
|
||||
type GetZoneGroupAttributesArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetZoneGroupAttributesResponse struct {
|
||||
CurrentZoneGroupName string `xml:"CurrentZoneGroupName"`
|
||||
CurrentZoneGroupID string `xml:"CurrentZoneGroupID"`
|
||||
CurrentZonePlayerUUIDsInGroup string `xml:"CurrentZonePlayerUUIDsInGroup"`
|
||||
CurrentMuseHouseholdId string `xml:"CurrentMuseHouseholdId"`
|
||||
}
|
||||
|
||||
func (s *Service) GetZoneGroupAttributes(httpClient *http.Client, args *GetZoneGroupAttributesArgs) (*GetZoneGroupAttributesResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetZoneGroupAttributes`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetZoneGroupAttributes: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetZoneGroupAttributes == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.GetZoneGroupAttributes()`)
|
||||
}
|
||||
|
||||
return r.Body.GetZoneGroupAttributes, nil
|
||||
}
|
||||
|
||||
type GetZoneGroupStateArgs struct {
|
||||
Xmlns string `xml:"xmlns:u,attr"`
|
||||
}
|
||||
type GetZoneGroupStateResponse struct {
|
||||
ZoneGroupState string `xml:"ZoneGroupState"`
|
||||
}
|
||||
|
||||
func (s *Service) GetZoneGroupState(httpClient *http.Client, args *GetZoneGroupStateArgs) (*GetZoneGroupStateResponse, error) {
|
||||
args.Xmlns = _ServiceURN
|
||||
r, err := s.exec(`GetZoneGroupState`, httpClient,
|
||||
&Envelope{
|
||||
EncodingStyle: _EncodingSchema,
|
||||
Xmlns: _EnvelopeSchema,
|
||||
Body: Body{GetZoneGroupState: args},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body.GetZoneGroupState == nil {
|
||||
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.GetZoneGroupState()`)
|
||||
}
|
||||
|
||||
return r.Body.GetZoneGroupState, nil
|
||||
}
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
package sonos
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
mx = 5
|
||||
st = "urn:schemas-upnp-org:device:ZonePlayer:1"
|
||||
bcastaddr = "239.255.255.250:1900"
|
||||
)
|
||||
|
||||
type Sonos struct {
|
||||
// Context Context
|
||||
listenSocket *net.UDPConn
|
||||
udpReader *bufio.Reader
|
||||
found chan *ZonePlayer
|
||||
}
|
||||
|
||||
func NewSonos() (*Sonos, error) {
|
||||
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: []byte{0, 0, 0, 0}, Port: 0, Zone: ""})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := Sonos{
|
||||
listenSocket: conn,
|
||||
udpReader: bufio.NewReader(conn),
|
||||
found: make(chan *ZonePlayer),
|
||||
}
|
||||
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
func (s *Sonos) Close() {
|
||||
s.listenSocket.Close()
|
||||
}
|
||||
|
||||
func (s *Sonos) Search() (chan *ZonePlayer, error) {
|
||||
go func() {
|
||||
for {
|
||||
response, err := http.ReadResponse(s.udpReader, nil)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
location, err := url.Parse(response.Header.Get("Location"))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
zp, err := NewZonePlayer(location)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if zp.IsCoordinator() {
|
||||
s.found <- zp
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// MX should be set to use timeout value in integer seconds
|
||||
pkt := []byte(fmt.Sprintf("M-SEARCH * HTTP/1.1\r\nHOST: %s\r\nMAN: \"ssdp:discover\"\r\nMX: %d\r\nST: %s\r\n\r\n", bcastaddr, mx, st))
|
||||
bcast, err := net.ResolveUDPAddr("udp", bcastaddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = s.listenSocket.WriteTo(pkt, bcast)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.found, nil
|
||||
}
|
||||
|
||||
func FindRoom(room string, timeout time.Duration) (*ZonePlayer, error) {
|
||||
son, err := NewSonos()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer son.Close()
|
||||
|
||||
found, _ := son.Search()
|
||||
to := time.After(timeout)
|
||||
for {
|
||||
select {
|
||||
case <-to:
|
||||
return nil, errors.New("timeout")
|
||||
case zp := <-found:
|
||||
if zp.RoomName() == room {
|
||||
return zp, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
package sonos
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
type VanishedDevice struct {
|
||||
XMLName xml.Name `xml:"VanishedDevice"`
|
||||
UUID string `xml:"UUID"`
|
||||
Location string `xml:"Location"`
|
||||
ZoneName string `xml:"ZoneName"`
|
||||
Icon string `xml:"Icon"`
|
||||
Configuration string `xml:"Configuration"`
|
||||
SoftwareVersion string `xml:"SoftwareVersion"`
|
||||
SWGen string `xml:"SWGen"`
|
||||
MinCompatibleVersion string `xml:"MinCompatibleVersion"`
|
||||
LegacyCompatibleVersion string `xml:"LegacyCompatibleVersion"`
|
||||
BootSeq string `xml:"BootSeq"`
|
||||
TVConfigurationError string `xml:"TVConfigurationError"`
|
||||
HdmiCecAvailable string `xml:"HdmiCecAvailable"`
|
||||
WirelessMode string `xml:"WirelessMode"`
|
||||
WirelessLeafOnly string `xml:"WirelessLeafOnly"`
|
||||
HasConfiguredSSID string `xml:"HasConfiguredSSID"`
|
||||
ChannelFreq string `xml:"ChannelFreq"`
|
||||
BehindWifiExtender string `xml:"BehindWifiExtender"`
|
||||
WifiEnabled string `xml:"WifiEnabled"`
|
||||
Orientation string `xml:"Orientation"`
|
||||
RoomCalibrationState string `xml:"RoomCalibrationState"`
|
||||
SecureRegState string `xml:"SecureRegState"`
|
||||
VoiceConfigState string `xml:"VoiceConfigState"`
|
||||
MicEnabled string `xml:"MicEnabled"`
|
||||
AirPlayEnabled string `xml:"AirPlayEnabled"`
|
||||
IdleState string `xml:"IdleState"`
|
||||
MoreInfo string `xml:"MoreInfo"`
|
||||
}
|
||||
|
||||
type Satellite struct {
|
||||
XMLName xml.Name `xml:"Satellite"`
|
||||
UUID string `xml:"UUID"`
|
||||
Location string `xml:"Location"`
|
||||
ZoneName string `xml:"ZoneName"`
|
||||
Icon string `xml:"Icon"`
|
||||
Configuration string `xml:"Configuration"`
|
||||
SoftwareVersion string `xml:"SoftwareVersion"`
|
||||
SWGen string `xml:"SWGen"`
|
||||
MinCompatibleVersion string `xml:"MinCompatibleVersion"`
|
||||
LegacyCompatibleVersion string `xml:"LegacyCompatibleVersion"`
|
||||
BootSeq string `xml:"BootSeq"`
|
||||
TVConfigurationError string `xml:"TVConfigurationError"`
|
||||
HdmiCecAvailable string `xml:"HdmiCecAvailable"`
|
||||
WirelessMode string `xml:"WirelessMode"`
|
||||
WirelessLeafOnly string `xml:"WirelessLeafOnly"`
|
||||
HasConfiguredSSID string `xml:"HasConfiguredSSID"`
|
||||
ChannelFreq string `xml:"ChannelFreq"`
|
||||
BehindWifiExtender string `xml:"BehindWifiExtender"`
|
||||
WifiEnabled string `xml:"WifiEnabled"`
|
||||
Orientation string `xml:"Orientation"`
|
||||
RoomCalibrationState string `xml:"RoomCalibrationState"`
|
||||
SecureRegState string `xml:"SecureRegState"`
|
||||
VoiceConfigState string `xml:"VoiceConfigState"`
|
||||
MicEnabled string `xml:"MicEnabled"`
|
||||
AirPlayEnabled string `xml:"AirPlayEnabled"`
|
||||
IdleState string `xml:"IdleState"`
|
||||
MoreInfo string `xml:"MoreInfo"`
|
||||
}
|
||||
|
||||
type ZoneGroupMember struct {
|
||||
XMLName xml.Name `xml:"ZoneGroupMember"`
|
||||
UUID string `xml:"UUID"`
|
||||
Location string `xml:"Location"`
|
||||
ZoneName string `xml:"ZoneName"`
|
||||
Icon string `xml:"Icon"`
|
||||
Configuration string `xml:"Configuration"`
|
||||
SoftwareVersion string `xml:"SoftwareVersion"`
|
||||
SWGen string `xml:"SWGen"`
|
||||
MinCompatibleVersion string `xml:"MinCompatibleVersion"`
|
||||
LegacyCompatibleVersion string `xml:"LegacyCompatibleVersion"`
|
||||
BootSeq string `xml:"BootSeq"`
|
||||
TVConfigurationError string `xml:"TVConfigurationError"`
|
||||
HdmiCecAvailable string `xml:"HdmiCecAvailable"`
|
||||
WirelessMode string `xml:"WirelessMode"`
|
||||
WirelessLeafOnly string `xml:"WirelessLeafOnly"`
|
||||
HasConfiguredSSID string `xml:"HasConfiguredSSID"`
|
||||
ChannelFreq string `xml:"ChannelFreq"`
|
||||
BehindWifiExtender string `xml:"BehindWifiExtender"`
|
||||
WifiEnabled string `xml:"WifiEnabled"`
|
||||
Orientation string `xml:"Orientation"`
|
||||
RoomCalibrationState string `xml:"RoomCalibrationState"`
|
||||
SecureRegState string `xml:"SecureRegState"`
|
||||
VoiceConfigState string `xml:"VoiceConfigState"`
|
||||
MicEnabled string `xml:"MicEnabled"`
|
||||
AirPlayEnabled string `xml:"AirPlayEnabled"`
|
||||
IdleState string `xml:"IdleState"`
|
||||
MoreInfo string `xml:"MoreInfo"`
|
||||
Satellite []Satellite `xml:"Satellite>Satellite"`
|
||||
VanishedDevice []VanishedDevice `xml:"VanishedDevices>VanishedDevice"`
|
||||
}
|
||||
|
||||
type ZoneGroup struct {
|
||||
XMLName xml.Name `xml:"ZoneGroup"`
|
||||
Coordinator string `xml:"Coordinator,attr"`
|
||||
ID string `xml:"ID,attr"`
|
||||
ZoneGroupMember []ZoneGroupMember `xml:"ZoneGroupMember"`
|
||||
}
|
||||
|
||||
type ZoneGroupState struct {
|
||||
XMLName xml.Name `xml:"ZoneGroupState"`
|
||||
ZoneGroups []ZoneGroup `xml:"ZoneGroups>ZoneGroup"`
|
||||
}
|
||||
-236
@@ -1,236 +0,0 @@
|
||||
package sonos
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
avt "github.com/szatmary/sonos/AVTransport"
|
||||
clk "github.com/szatmary/sonos/AlarmClock"
|
||||
con "github.com/szatmary/sonos/ConnectionManager"
|
||||
dir "github.com/szatmary/sonos/ContentDirectory"
|
||||
dev "github.com/szatmary/sonos/DeviceProperties"
|
||||
gmn "github.com/szatmary/sonos/GroupManagement"
|
||||
rcg "github.com/szatmary/sonos/GroupRenderingControl"
|
||||
mus "github.com/szatmary/sonos/MusicServices"
|
||||
ply "github.com/szatmary/sonos/QPlay"
|
||||
que "github.com/szatmary/sonos/Queue"
|
||||
ren "github.com/szatmary/sonos/RenderingControl"
|
||||
sys "github.com/szatmary/sonos/SystemProperties"
|
||||
vli "github.com/szatmary/sonos/VirtualLineIn"
|
||||
zgt "github.com/szatmary/sonos/ZoneGroupTopology"
|
||||
)
|
||||
|
||||
type SpecVersion struct {
|
||||
XMLName xml.Name `xml:"specVersion"`
|
||||
Major int `xml:"major"`
|
||||
Minor int `xml:"minor"`
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
XMLName xml.Name `xml:"service"`
|
||||
ServiceType string `xml:"serviceType"`
|
||||
ServiceId string `xml:"serviceId"`
|
||||
ControlURL string `xml:"controlURL"`
|
||||
EventSubURL string `xml:"eventSubURL"`
|
||||
SCPDURL string `xml:"SCPDURL"`
|
||||
}
|
||||
|
||||
type Icon struct {
|
||||
XMLName xml.Name `xml:"icon"`
|
||||
Id string `xml:"id"`
|
||||
Mimetype string `xml:"mimetype"`
|
||||
Width int `xml:"width"`
|
||||
Height int `xml:"height"`
|
||||
Depth int `xml:"depth"`
|
||||
Url url.URL `xml:"url"`
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
XMLName xml.Name `xml:"device"`
|
||||
DeviceType string `xml:"deviceType"`
|
||||
FriendlyName string `xml:"friendlyName"`
|
||||
Manufacturer string `xml:"manufacturer"`
|
||||
ManufacturerURL string `xml:"manufacturerURL"`
|
||||
ModelNumber string `xml:"modelNumber"`
|
||||
ModelDescription string `xml:"modelDescription"`
|
||||
ModelName string `xml:"modelName"`
|
||||
ModelURL string `xml:"modelURL"`
|
||||
SoftwareVersion string `xml:"softwareVersion"`
|
||||
SwGen string `xml:"swGen"`
|
||||
HardwareVersion string `xml:"hardwareVersion"`
|
||||
SerialNum string `xml:"serialNum"`
|
||||
MACAddress string `xml:"MACAddress"`
|
||||
UDN string `xml:"UDN"`
|
||||
Icons []Icon `xml:"iconList>icon"`
|
||||
MinCompatibleVersion string `xml:"minCompatibleVersion"`
|
||||
LegacyCompatibleVersion string `xml:"legacyCompatibleVersion"`
|
||||
ApiVersion string `xml:"apiVersion"`
|
||||
MinApiVersion string `xml:"minApiVersion"`
|
||||
DisplayVersion string `xml:"displayVersion"`
|
||||
ExtraVersion string `xml:"extraVersion"`
|
||||
RoomName string `xml:"roomName"`
|
||||
DisplayName string `xml:"displayName"`
|
||||
ZoneType int `xml:"zoneType"`
|
||||
Feature1 string `xml:"feature1"`
|
||||
Feature2 string `xml:"feature2"`
|
||||
Feature3 string `xml:"feature3"`
|
||||
Seriesid string `xml:"seriesid"`
|
||||
Variant int `xml:"variant"`
|
||||
InternalSpeakerSize float32 `xml:"internalSpeakerSize"`
|
||||
BassExtension float32 `xml:"bassExtension"`
|
||||
SatGainOffset float32 `xml:"satGainOffset"`
|
||||
Memory int `xml:"memory"`
|
||||
Flash int `xml:"flash"`
|
||||
FlashRepartitioned int `xml:"flashRepartitioned"`
|
||||
AmpOnTime int `xml:"ampOnTime"`
|
||||
RetailMode int `xml:"retailMode"`
|
||||
Services []Service `xml:"serviceList>service"`
|
||||
Devices []Device `xml:"deviceList>device"`
|
||||
}
|
||||
|
||||
type Root struct {
|
||||
XMLName xml.Name `xml:"root"`
|
||||
Xmlns string `xml:"xmlns,attr"`
|
||||
SpecVersion SpecVersion `xml:"specVersion"`
|
||||
Device Device `xml:"device"`
|
||||
}
|
||||
|
||||
type ZonePlayer struct {
|
||||
Root *Root
|
||||
HttpClient *http.Client
|
||||
DeviceDescriptionURL *url.URL
|
||||
// services
|
||||
AlarmClock *clk.Service
|
||||
AVTransport *avt.Service
|
||||
ConnectionManager *con.Service
|
||||
ContentDirectory *dir.Service
|
||||
DeviceProperties *dev.Service
|
||||
GroupManagement *gmn.Service
|
||||
GroupRenderingControl *rcg.Service
|
||||
MusicServices *mus.Service
|
||||
QPlay *ply.Service
|
||||
Queue *que.Service
|
||||
RenderingControl *ren.Service
|
||||
SystemProperties *sys.Service
|
||||
VirtualLineIn *vli.Service
|
||||
ZoneGroupTopology *zgt.Service
|
||||
}
|
||||
|
||||
func NewZonePlayer(deviceDescriptionURL *url.URL) (*ZonePlayer, error) {
|
||||
zp := ZonePlayer{
|
||||
Root: &Root{},
|
||||
HttpClient: &http.Client{},
|
||||
DeviceDescriptionURL: deviceDescriptionURL,
|
||||
AlarmClock: clk.NewService(deviceDescriptionURL),
|
||||
AVTransport: avt.NewService(deviceDescriptionURL),
|
||||
ConnectionManager: con.NewService(deviceDescriptionURL),
|
||||
ContentDirectory: dir.NewService(deviceDescriptionURL),
|
||||
DeviceProperties: dev.NewService(deviceDescriptionURL),
|
||||
GroupManagement: gmn.NewService(deviceDescriptionURL),
|
||||
GroupRenderingControl: rcg.NewService(deviceDescriptionURL),
|
||||
MusicServices: mus.NewService(deviceDescriptionURL),
|
||||
QPlay: ply.NewService(deviceDescriptionURL),
|
||||
Queue: que.NewService(deviceDescriptionURL),
|
||||
RenderingControl: ren.NewService(deviceDescriptionURL),
|
||||
SystemProperties: sys.NewService(deviceDescriptionURL),
|
||||
VirtualLineIn: vli.NewService(deviceDescriptionURL),
|
||||
ZoneGroupTopology: zgt.NewService(deviceDescriptionURL),
|
||||
}
|
||||
|
||||
resp, err := zp.HttpClient.Get(zp.DeviceDescriptionURL.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
err = xml.Unmarshal(body, zp.Root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &zp, nil
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) RoomName() string {
|
||||
return z.Root.Device.RoomName
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) ModelName() string {
|
||||
return z.Root.Device.ModelName
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) HardwareVersion() string {
|
||||
return z.Root.Device.HardwareVersion
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) SerialNum() string {
|
||||
return z.Root.Device.SerialNum
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) IsCoordinator() bool {
|
||||
zoneGroupState, err := z.GetZoneGroupState()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, group := range zoneGroupState.ZoneGroups {
|
||||
if "uuid:"+group.Coordinator == z.Root.Device.UDN {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Convience functions
|
||||
|
||||
func (z *ZonePlayer) GetZoneGroupState() (*ZoneGroupState, error) {
|
||||
zoneGroupStateResponse, err := z.ZoneGroupTopology.GetZoneGroupState(z.HttpClient, &zgt.GetZoneGroupStateArgs{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var zoneGroupState ZoneGroupState
|
||||
err = xml.Unmarshal([]byte(zoneGroupStateResponse.ZoneGroupState), &zoneGroupState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &zoneGroupState, nil
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) GetVolume() (int, error) {
|
||||
res, err := z.RenderingControl.GetVolume(z.HttpClient, &ren.GetVolumeArgs{Channel: "Master"})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int(res.CurrentVolume), err
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) SetVolume(desiredVolume int) error {
|
||||
_, err := z.RenderingControl.SetVolume(z.HttpClient, &ren.SetVolumeArgs{
|
||||
Channel: "Master",
|
||||
DesiredVolume: uint16(desiredVolume),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) Play() error {
|
||||
_, err := z.AVTransport.Play(z.HttpClient, &avt.PlayArgs{
|
||||
Speed: "1.0",
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (z *ZonePlayer) SetAVTransportURI(url string) error {
|
||||
_, err := z.AVTransport.SetAVTransportURI(z.HttpClient, &avt.SetAVTransportURIArgs{
|
||||
CurrentURI: url,
|
||||
})
|
||||
return err
|
||||
}
|
||||
Vendored
-20
@@ -79,9 +79,6 @@ github.com/hashicorp/mdns
|
||||
# github.com/holoplot/go-evdev v0.0.0-20230626094006-70c9462cc0f2
|
||||
## explicit; go 1.18
|
||||
github.com/holoplot/go-evdev
|
||||
# github.com/ianr0bkny/go-sonos v0.0.0-20171025003233-056585059953
|
||||
## explicit
|
||||
github.com/ianr0bkny/go-sonos/ssdp
|
||||
# github.com/json-iterator/go v1.1.12
|
||||
## explicit; go 1.12
|
||||
github.com/json-iterator/go
|
||||
@@ -217,23 +214,6 @@ github.com/pmezard/go-difflib/difflib
|
||||
## explicit; go 1.20
|
||||
github.com/stretchr/testify/assert
|
||||
github.com/stretchr/testify/require
|
||||
# github.com/szatmary/sonos v0.0.0-20191204204454-000c9219ff0e
|
||||
## explicit
|
||||
github.com/szatmary/sonos
|
||||
github.com/szatmary/sonos/AVTransport
|
||||
github.com/szatmary/sonos/AlarmClock
|
||||
github.com/szatmary/sonos/ConnectionManager
|
||||
github.com/szatmary/sonos/ContentDirectory
|
||||
github.com/szatmary/sonos/DeviceProperties
|
||||
github.com/szatmary/sonos/GroupManagement
|
||||
github.com/szatmary/sonos/GroupRenderingControl
|
||||
github.com/szatmary/sonos/MusicServices
|
||||
github.com/szatmary/sonos/QPlay
|
||||
github.com/szatmary/sonos/Queue
|
||||
github.com/szatmary/sonos/RenderingControl
|
||||
github.com/szatmary/sonos/SystemProperties
|
||||
github.com/szatmary/sonos/VirtualLineIn
|
||||
github.com/szatmary/sonos/ZoneGroupTopology
|
||||
# github.com/tinyzimmer/go-glib v0.0.25
|
||||
## explicit; go 1.16
|
||||
github.com/tinyzimmer/go-glib/glib
|
||||
|
||||
Reference in New Issue
Block a user