package upnp import ( "fmt" "net/http" "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/actions" "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables" "github.com/beevik/etree" log "github.com/sirupsen/logrus" ) type ServiceInstance struct { name string identifier string version int device *DeviceInstance statevariables statevariables.StateVarInstanceSet actions actions.ActionInstanceSet } func (si *ServiceInstance) Name() string { return si.name } func (svc *ServiceInstance) TypeID() string { return "ServiceInstance" } func (si *ServiceInstance) Identifier() string { return si.identifier } func (svc *ServiceInstance) ServiceType() string { return fmt.Sprintf("urn:schemas-upnp-org:service:%s:%d", svc.name, svc.version) } func (svc *ServiceInstance) ServiceId() string { return fmt.Sprintf("urn:upnp-org:serviceId:%s", svc.identifier) } func (svc *ServiceInstance) BaseRoute() string { return fmt.Sprintf("%s/service/%s", svc.device.BaseRoute(), svc.Name()) } func (svc *ServiceInstance) ControlURL() string { return fmt.Sprintf("%s/control", svc.BaseRoute()) } func (svc *ServiceInstance) EventSubURL() string { return fmt.Sprintf("%s/event", svc.BaseRoute()) } func (svc *ServiceInstance) SCPDURL() string { return fmt.Sprintf("%s/desc.xml", svc.BaseRoute()) } func (svc *ServiceInstance) RegisterURLs() error { mux, ok := svc.device.server.httpSrv.Handler.(*http.ServeMux) if mux == nil || !ok { return fmt.Errorf("❌ Device %s the server handler is not correctly defined", svc.Name()) } mux.HandleFunc( svc.SCPDURL(), svc.device.server.ServeXML(svc.SPCDElement), ) log.Infof( "✅ Service description for %s:%s available at : %s%s", svc.device.Name(), svc.Name(), svc.device.server.BaseURL(), svc.SCPDURL(), ) return nil } func (svc *ServiceInstance) SPCDElement() *etree.Element { elem := etree.NewElement("scpd") elem.CreateAttr("xmlns", "urn:schemas-upnp-org:service-1-0") spec := elem.CreateElement("specVersion") spec.CreateElement("major").SetText("1") spec.CreateElement("minor").SetText("0") if len(svc.actions) > 0 { elem.AddChild(svc.actions.ToXMLElement()) } if len(svc.statevariables) > 0 { elem.AddChild(svc.statevariables.ToXMLElement()) } return elem } func (svc *ServiceInstance) ToXMLElement() *etree.Element { elem := etree.NewElement("service") st := elem.CreateElement("serviceType") st.SetText(svc.ServiceType()) sid := elem.CreateElement("serviceId") sid.SetText(svc.ServiceId()) spcd := elem.CreateElement("SCPDURL") spcd.SetText(svc.SCPDURL()) ctrl := elem.CreateElement("controlURL") ctrl.SetText(svc.ControlURL()) event := elem.CreateElement("eventSubURL") event.SetText(svc.EventSubURL()) return elem }