Helper functions on devices, minor fixes.

This commit is contained in:
John Beisley 2013-10-03 20:38:23 +01:00
parent 61577bd15b
commit 80bd2aa934
4 changed files with 63 additions and 14 deletions

View File

@ -19,16 +19,7 @@ func (i indentLevel) String() string {
func displayDevice(indent indentLevel, device *goupnp.Device) { func displayDevice(indent indentLevel, device *goupnp.Device) {
fmt.Println(indent.String(), device) fmt.Println(indent.String(), device)
for _, srv := range device.Services { for _, srv := range device.Services {
fmt.Println((indent + 1).String(), srv, srv.SCPDURL.URL.String(), srv.ControlURL.URL.String()) fmt.Printf("%sService %s\n", indent+1, srv.ServiceType)
fmt.Println(goupnp.ServiceTypeWANPPPConnection, srv.ServiceType)
if srv.ServiceType == goupnp.ServiceTypeWANPPPConnection {
results, err := goupnp.PerformSoapAction(goupnp.ServiceTypeWANPPPConnection, "GetExternalIPAddress", &srv.ControlURL.URL, nil)
if err != nil {
fmt.Println("Error calling GetExternalIPAddress:", err)
} else {
fmt.Println(results)
}
}
} }
for i := range device.Devices { for i := range device.Devices {
displayDevice(indent+1, &device.Devices[i]) displayDevice(indent+1, &device.Devices[i])
@ -43,9 +34,26 @@ func main() {
for _, maybeRootDevice := range results { for _, maybeRootDevice := range results {
if maybeRootDevice.Err != nil { if maybeRootDevice.Err != nil {
fmt.Println(maybeRootDevice.Err) fmt.Println(maybeRootDevice.Err)
} else { continue
displayDevice(0, &maybeRootDevice.Root.Device) }
}
device := &maybeRootDevice.Root.Device
displayDevice(0, device)
wanPPPSrvs := device.FindService(goupnp.ServiceTypeWANPPPConnection)
if len(wanPPPSrvs) < 1 {
fmt.Printf("Could not find expected service on device %s\n", device.FriendlyName)
continue
} else if len(wanPPPSrvs) > 1 {
fmt.Printf("Got more than one expected service on device %s\n", device.FriendlyName)
}
srv := wanPPPSrvs[0]
results, err := goupnp.PerformSoapAction(goupnp.ServiceTypeWANPPPConnection, "GetExternalIPAddress", &srv.ControlURL.URL, nil)
if err != nil {
fmt.Printf("Failed to GetExternalIPAddress from %s: %v\n", device.FriendlyName, err)
continue
}
fmt.Printf("Got GetExternalIPAddress result from %s: %v\n", device.FriendlyName, results)
} }
} }
} }

View File

@ -17,7 +17,7 @@ const (
// description" in // description" in
// http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf // http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
type RootDevice struct { type RootDevice struct {
Name xml.Name `xml:"root` XMLName xml.Name `xml:"root"`
SpecVersion SpecVersion `xml:"specVersion"` SpecVersion SpecVersion `xml:"specVersion"`
URLBase url.URL `xml:"-"` URLBase url.URL `xml:"-"`
URLBaseStr string `xml:"URLBase"` URLBaseStr string `xml:"URLBase"`
@ -55,6 +55,32 @@ type Device struct {
PresentationURL URLField `xml:"presentationURL"` PresentationURL URLField `xml:"presentationURL"`
} }
func (device *Device) VisitDevices(visitor func(*Device)) {
visitor(device)
for i := range device.Devices {
device.Devices[i].VisitDevices(visitor)
}
}
func (device *Device) VisitServices(visitor func(*Service)) {
device.VisitDevices(func(d *Device) {
for i := range device.Services {
visitor(&d.Services[i])
}
})
}
func (device *Device) FindService(serviceType string) []*Service {
var services []*Service
device.VisitServices(func(s *Service) {
fmt.Println(s.ServiceType)
if s.ServiceType == serviceType {
services = append(services, s)
}
})
return services
}
func (device *Device) SetURLBase(urlBase *url.URL) { func (device *Device) SetURLBase(urlBase *url.URL) {
device.ManufacturerURL.SetURLBase(urlBase) device.ManufacturerURL.SetURLBase(urlBase)
device.ModelURL.SetURLBase(urlBase) device.ModelURL.SetURLBase(urlBase)

View File

@ -12,7 +12,7 @@ const (
// description" in // description" in
// http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf // http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
type SCPD struct { type SCPD struct {
Name xml.Name `xml:"scpd"` XMLName xml.Name `xml:"scpd"`
ConfigId string `xml:"configId,attr"` ConfigId string `xml:"configId,attr"`
SpecVersion SpecVersion `xml:"specVersion"` SpecVersion SpecVersion `xml:"specVersion"`
Actions []Action `xml:"actionList>action"` Actions []Action `xml:"actionList>action"`

15
soap.go
View File

@ -74,6 +74,10 @@ func PerformSoapAction(actionNamespace, actionName string, url *url.URL, argumen
return nil, err return nil, err
} }
if responseEnv.Body.Fault != nil {
return nil, responseEnv.Body.Fault
}
results := make([]NameValue, len(responseEnv.Body.Action.Arguments)) results := make([]NameValue, len(responseEnv.Body.Action.Arguments))
for i, soapArg := range responseEnv.Body.Action.Arguments { for i, soapArg := range responseEnv.Body.Action.Arguments {
results[i] = NameValue{ results[i] = NameValue{
@ -92,9 +96,20 @@ type SoapEnvelope struct {
} }
type SoapBody struct { type SoapBody struct {
Fault *SoapFault `xml:"Fault"`
Action SoapAction `xml:",any"` Action SoapAction `xml:",any"`
} }
type SoapFault struct {
FaultCode string `xml:"faultcode"`
FaultString string `xml:"faultstring"`
Detail string `xml:"detail"`
}
func (err *SoapFault) Error() string {
return fmt.Sprintf("SOAP fault: %s", err.FaultString)
}
type SoapAction struct { type SoapAction struct {
XMLName xml.Name XMLName xml.Name
Arguments []SoapArgument `xml:",any"` Arguments []SoapArgument `xml:",any"`