1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
package scpd
import (
"encoding/xml"
"strings"
)
const (
SCPDXMLNamespace = "urn:schemas-upnp-org:service-1-0"
)
func cleanWhitespace(s *string) {
*s = strings.TrimSpace(*s)
}
// SCPD is the service description as described by section 2.5 "Service
// description" in
// http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
type SCPD struct {
XMLName xml.Name `xml:"scpd"`
ConfigId string `xml:"configId,attr"`
SpecVersion SpecVersion `xml:"specVersion"`
Actions []Action `xml:"actionList>action"`
StateVariables []StateVariable `xml:"serviceStateTable>stateVariable"`
}
// Clean attempts to remove stray whitespace etc. in the structure. It seems
// unfortunately common for stray whitespace to be present in SCPD documents,
// this method attempts to make it easy to clean them out.
func (scpd *SCPD) Clean() {
cleanWhitespace(&scpd.ConfigId)
for i := range scpd.Actions {
scpd.Actions[i].clean()
}
for i := range scpd.StateVariables {
scpd.StateVariables[i].clean()
}
}
func (scpd *SCPD) GetStateVariable(variable string) *StateVariable {
for i := range scpd.StateVariables {
v := &scpd.StateVariables[i]
if v.Name == variable {
return v
}
}
return nil
}
func (scpd *SCPD) GetAction(action string) *Action {
for i := range scpd.Actions {
a := &scpd.Actions[i]
if a.Name == action {
return a
}
}
return nil
}
// SpecVersion is part of a SCPD document, describes the version of the
// specification that the data adheres to.
type SpecVersion struct {
Major int32 `xml:"major"`
Minor int32 `xml:"minor"`
}
type Action struct {
Name string `xml:"name"`
Arguments []Argument `xml:"argumentList>argument"`
}
func (action *Action) clean() {
cleanWhitespace(&action.Name)
for i := range action.Arguments {
action.Arguments[i].clean()
}
}
func (action *Action) InputArguments() []*Argument {
var result []*Argument
for i := range action.Arguments {
arg := &action.Arguments[i]
if arg.IsInput() {
result = append(result, arg)
}
}
return result
}
func (action *Action) OutputArguments() []*Argument {
var result []*Argument
for i := range action.Arguments {
arg := &action.Arguments[i]
if arg.IsOutput() {
result = append(result, arg)
}
}
return result
}
type Argument struct {
Name string `xml:"name"`
Direction string `xml:"direction"` // in|out
RelatedStateVariable string `xml:"relatedStateVariable"` // ?
Retval string `xml:"retval"` // ?
}
func (arg *Argument) clean() {
cleanWhitespace(&arg.Name)
cleanWhitespace(&arg.Direction)
cleanWhitespace(&arg.RelatedStateVariable)
cleanWhitespace(&arg.Retval)
}
func (arg *Argument) IsInput() bool {
return arg.Direction == "in"
}
func (arg *Argument) IsOutput() bool {
return arg.Direction == "out"
}
type StateVariable struct {
Name string `xml:"name"`
SendEvents string `xml:"sendEvents,attr"` // yes|no
Multicast string `xml:"multicast,attr"` // yes|no
DataType DataType `xml:"dataType"`
DefaultValue string `xml:"defaultValue"`
AllowedValueRange *AllowedValueRange `xml:"allowedValueRange"`
AllowedValues []string `xml:"allowedValueList>allowedValue"`
}
func (v *StateVariable) clean() {
cleanWhitespace(&v.Name)
cleanWhitespace(&v.SendEvents)
cleanWhitespace(&v.Multicast)
v.DataType.clean()
cleanWhitespace(&v.DefaultValue)
if v.AllowedValueRange != nil {
v.AllowedValueRange.clean()
}
for i := range v.AllowedValues {
cleanWhitespace(&v.AllowedValues[i])
}
}
type AllowedValueRange struct {
Minimum string `xml:"minimum"`
Maximum string `xml:"maximum"`
Step string `xml:"step"`
}
func (r *AllowedValueRange) clean() {
cleanWhitespace(&r.Minimum)
cleanWhitespace(&r.Maximum)
cleanWhitespace(&r.Step)
}
type DataType struct {
Name string `xml:",chardata"`
Type string `xml:"type,attr"`
}
func (dt *DataType) clean() {
cleanWhitespace(&dt.Name)
cleanWhitespace(&dt.Type)
}
|