Add non-discovery ServiceClient constructor functions.

This commit is contained in:
John Beisley 2015-06-06 11:35:31 +01:00
parent 9f336b0025
commit c4f4be704b

View File

@ -2,19 +2,26 @@ package goupnp
import ( import (
"fmt" "fmt"
"net/url"
"github.com/huin/goupnp/soap" "github.com/huin/goupnp/soap"
) )
// ServiceClient is a SOAP client, root device and the service for the SOAP // ServiceClient is a SOAP client, root device and the service for the SOAP
// client rolled into one value. The root device and service are intended to be // client rolled into one value. The root device, location, and service are
// informational. // intended to be informational. Location can be used to later recreate a
// ServiceClient with NewServiceClientByURL if the service is still present;
// bypassing the discovery process.
type ServiceClient struct { type ServiceClient struct {
SOAPClient *soap.SOAPClient SOAPClient *soap.SOAPClient
RootDevice *RootDevice RootDevice *RootDevice
Location *url.URL
Service *Service Service *Service
} }
// NewServiceClients discovers services, and returns clients for them. err will
// report any error with the discovery process (blocking any device/service
// discovery), errors reports errors on a per-root-device basis.
func NewServiceClients(searchTarget string) (clients []ServiceClient, errors []error, err error) { func NewServiceClients(searchTarget string) (clients []ServiceClient, errors []error, err error) {
var maybeRootDevices []MaybeRootDevice var maybeRootDevices []MaybeRootDevice
if maybeRootDevices, err = DiscoverDevices(searchTarget); err != nil { if maybeRootDevices, err = DiscoverDevices(searchTarget); err != nil {
@ -29,26 +36,50 @@ func NewServiceClients(searchTarget string) (clients []ServiceClient, errors []e
continue continue
} }
device := &maybeRootDevice.Root.Device deviceClients, err := NewServiceClientsFromRootDevice(maybeRootDevice.Root, maybeRootDevice.Location, searchTarget)
srvs := device.FindService(searchTarget) if err != nil {
if len(srvs) == 0 { errors = append(errors, err)
errors = append(errors, fmt.Errorf("goupnp: service %q not found within device %q (UDN=%q)",
searchTarget, device.FriendlyName, device.UDN))
continue continue
} }
clients = append(clients, deviceClients...)
for _, srv := range srvs {
clients = append(clients, ServiceClient{
SOAPClient: srv.NewSOAPClient(),
RootDevice: maybeRootDevice.Root,
Service: srv,
})
}
} }
return return
} }
// NewServiceClientsByURL creates client(s) for the given service URN, for a
// root device at the given URL.
func NewServiceClientsByURL(loc *url.URL, searchTarget string) ([]ServiceClient, error) {
rootDevice, err := DeviceByURL(loc)
if err != nil {
return nil, err
}
return NewServiceClientsFromRootDevice(rootDevice, loc, searchTarget)
}
// NewServiceClientsFromDevice creates client(s) for the given service URN, for
// a given root device. The location parameter is simply assigned to the
// Location attribute of the returned ServiceClient.
func NewServiceClientsFromRootDevice(rootDevice *RootDevice, location *url.URL, searchTarget string) ([]ServiceClient, error) {
device := &rootDevice.Device
srvs := device.FindService(searchTarget)
if len(srvs) == 0 {
return nil, fmt.Errorf("goupnp: service %q not found within device %q (UDN=%q)",
searchTarget, device.FriendlyName, device.UDN)
}
clients := make([]ServiceClient, 0, len(srvs))
for _, srv := range srvs {
clients = append(clients, ServiceClient{
SOAPClient: srv.NewSOAPClient(),
RootDevice: rootDevice,
Location: location,
Service: srv,
})
}
return clients, nil
}
// GetServiceClient returns the ServiceClient itself. This is provided so that the // GetServiceClient returns the ServiceClient itself. This is provided so that the
// service client attributes can be accessed via an interface method on a // service client attributes can be accessed via an interface method on a
// wrapping type. // wrapping type.