├── .gitignore ├── go.mod ├── README.md ├── go.sum ├── examples ├── discovery │ └── discovery.go └── recording │ └── recording.go ├── discovery └── discovery.go ├── wsdl ├── uplink.wsdl ├── replay.wsdl ├── bin │ └── fixgen.py ├── common.xsd ├── receiver.wsdl ├── display.wsdl ├── provisioning.wsdl └── imaging.wsdl ├── soap └── soap.go ├── LICENSE └── profiles └── accessrules └── accessrules.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.pcap 2 | ptz_onvif -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/videonext/onvif 2 | 3 | go 1.24.0 4 | 5 | toolchain go1.24.4 6 | 7 | require ( 8 | github.com/clbanning/mxj v1.8.4 9 | github.com/kr/pretty v0.1.0 10 | github.com/satori/go.uuid v1.2.0 11 | ) 12 | 13 | require ( 14 | github.com/kr/text v0.1.0 // indirect 15 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Golang ONVIF client 2 | Goal is create full featured golang client using ONVIF specifications. Project is in alpha stage. All profiles defined in the [https://www.onvif.org/profiles/specifications/](https://www.onvif.org/profiles/specifications/) implemented, but was not carefully tested. See examples directory for usage details. 3 | 4 | ## Credits 5 | - [https://github.com/hooklift/gowsdl](https://github.com/hooklift/gowsdl) 6 | - [https://github.com/RadhiFadlillah/go-onvif/](https://github.com/RadhiFadlillah/go-onvif/) 7 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= 2 | github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= 3 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 4 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 5 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 6 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 7 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 8 | github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= 9 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 10 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 11 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 12 | -------------------------------------------------------------------------------- /examples/discovery/discovery.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | 8 | "github.com/kr/pretty" 9 | "github.com/videonext/onvif/discovery" 10 | "github.com/videonext/onvif/profiles/devicemgmt" 11 | "github.com/videonext/onvif/soap" 12 | ) 13 | 14 | func main() { 15 | 16 | // discovery devices 17 | devices, err := discovery.StartDiscovery(5 * time.Second) 18 | if err != nil { 19 | fmt.Println(err.Error()) 20 | } 21 | if len(devices) == 0 { 22 | fmt.Printf("No devices descovered\n") 23 | 24 | return 25 | } 26 | 27 | fmt.Printf("Discovered %d devices\n", len(devices)) 28 | pretty.Println(devices) 29 | 30 | // Create soap client 31 | client := soap.NewClient( 32 | soap.WithTimeout(time.Second * 5), 33 | ) 34 | client.AddHeader(soap.NewWSSSecurityHeader("root", "rootpass")) 35 | 36 | for _, d := range devices { 37 | // Create devicemgmt service instance and specify xaddr (which could be received in the discovery) 38 | dev := devicemgmt.NewDevice(client, d.XAddr) 39 | 40 | log.Println("devicemgmt.GetDeviceInformation", d.XAddr) 41 | { 42 | reply, err := dev.GetDeviceInformation(&devicemgmt.GetDeviceInformation{}) 43 | if err != nil { 44 | if serr, ok := err.(*soap.SOAPFault); ok { 45 | pretty.Println(serr) 46 | } 47 | log.Fatalf("Request failed: %s", err.Error()) 48 | } 49 | pretty.Println(reply) 50 | } 51 | 52 | log.Println("devicemgmt.GetServices", d.XAddr) 53 | { 54 | reply, err := dev.GetServices(&devicemgmt.GetServices{}) 55 | if err != nil { 56 | if serr, ok := err.(*soap.SOAPFault); ok { 57 | pretty.Println(serr) 58 | } 59 | log.Fatalf("Request failed: %s", err.Error()) 60 | } 61 | pretty.Println(reply) 62 | } 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /examples/recording/recording.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | 8 | "github.com/kr/pretty" 9 | "github.com/videonext/onvif/profiles/recording" 10 | "github.com/videonext/onvif/soap" 11 | ) 12 | 13 | func main() { 14 | 15 | // Create soap client 16 | client := soap.NewClient( 17 | soap.WithTimeout(time.Second * 5), 18 | ) 19 | client.AddHeader(soap.NewWSSSecurityHeader("root", "pass")) 20 | 21 | var token recording.RecordingReference 22 | // Create service instance and specify xaddr (which could be received in the devicemgmt.GetServices()) 23 | r := recording.NewRecordingPort(client, "http://192.168.27.66/onvif/services") 24 | { 25 | cr := recording.CreateRecording{RecordingConfiguration: recording.RecordingConfiguration{}} 26 | cr.RecordingConfiguration.Content = "mycontent" 27 | cr.RecordingConfiguration.MaximumRetentionTime = "P7D" //"PT0M30S" 28 | cr.RecordingConfiguration.Source = 29 | recording.RecordingSourceInformation{ 30 | SourceId: "http://192.168.27.66/onvif/services", 31 | Name: "mysourcename", 32 | Location: "mysourcelocation", 33 | Description: "mysourcedescription", 34 | Address: "http://192.168.27.66/onvif/services"} 35 | 36 | reply, err := r.CreateRecording(&cr) 37 | 38 | if err != nil { 39 | if serr, ok := err.(*soap.SOAPFault); ok { 40 | pretty.Println(serr) 41 | } 42 | log.Fatalf("Request failed: %s", err.Error()) 43 | } 44 | pretty.Println(reply) 45 | token = reply.RecordingToken 46 | fmt.Printf("Token: %s\n", token) 47 | 48 | dr := recording.DeleteRecording{RecordingToken: token} 49 | reply2, err := r.DeleteRecording(&dr) 50 | if err != nil { 51 | if serr, ok := err.(*soap.SOAPFault); ok { 52 | pretty.Println(serr) 53 | } 54 | log.Fatalf("Request failed: %s", err.Error()) 55 | } 56 | pretty.Println(reply2) 57 | 58 | fmt.Println("Getting all records") 59 | reply3, err := r.GetRecordings(&recording.GetRecordings{}) 60 | if err != nil { 61 | if serr, ok := err.(*soap.SOAPFault); ok { 62 | pretty.Println(serr) 63 | } 64 | log.Fatalf("Request failed: %s", err.Error()) 65 | } 66 | pretty.Println(reply3) 67 | 68 | } 69 | 70 | // ............. 71 | 72 | } 73 | -------------------------------------------------------------------------------- /discovery/discovery.go: -------------------------------------------------------------------------------- 1 | package discovery 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "regexp" 7 | "strings" 8 | "time" 9 | 10 | "github.com/clbanning/mxj" 11 | uuid "github.com/satori/go.uuid" 12 | ) 13 | 14 | var errWrongDiscoveryResponse = errors.New("Response is not related to discovery request") 15 | 16 | // Device contains data of ONVIF camera 17 | type Device struct { 18 | ID string 19 | Name string 20 | XAddr string 21 | } 22 | 23 | // StartDiscovery send a WS-Discovery message and wait for all matching device to respond 24 | func StartDiscovery(duration time.Duration) ([]Device, error) { 25 | // Get list of interface address 26 | addrs, err := net.InterfaceAddrs() 27 | if err != nil { 28 | return []Device{}, err 29 | } 30 | 31 | // Fetch IPv4 address 32 | ipAddrs := []string{} 33 | for _, addr := range addrs { 34 | ipAddr, ok := addr.(*net.IPNet) 35 | if ok && !ipAddr.IP.IsLoopback() && ipAddr.IP.To4() != nil { 36 | ipAddrs = append(ipAddrs, ipAddr.IP.String()) 37 | } 38 | } 39 | 40 | // Create initial discovery results 41 | discoveryResults := []Device{} 42 | 43 | // Discover device on each interface's network 44 | for _, ipAddr := range ipAddrs { 45 | devices, err := discoverDevices(ipAddr, duration) 46 | if err != nil { 47 | // return []Device{}, err 48 | continue 49 | } 50 | 51 | for _, dd := range devices { 52 | var found bool 53 | 54 | for _, d := range discoveryResults { 55 | if d.ID == dd.ID { 56 | found = true 57 | break 58 | } 59 | } 60 | 61 | if !found { 62 | discoveryResults = append(discoveryResults, dd) 63 | } 64 | } 65 | 66 | } 67 | 68 | if len(discoveryResults) == 0 && err != nil { 69 | return []Device{}, err 70 | } 71 | 72 | return discoveryResults, nil 73 | } 74 | 75 | func discoverDevices(ipAddr string, duration time.Duration) ([]Device, error) { 76 | // Create WS-Discovery request 77 | requestID := "uuid:" + uuid.NewV4().String() 78 | request := ` 79 | 80 | 85 | 86 | ` + requestID + ` 87 | urn:schemas-xmlsoap-org:ws:2005:04:discovery 88 | http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe 89 | 90 | 91 | 92 | 93 | dn:NetworkVideoTransmitter 94 | 95 | 96 | ` 97 | 98 | // Clean WS-Discovery message 99 | request = regexp.MustCompile(`\>\s+\<`).ReplaceAllString(request, "><") 100 | request = regexp.MustCompile(`\s+`).ReplaceAllString(request, " ") 101 | 102 | // Create UDP address for local and multicast address 103 | localAddress, err := net.ResolveUDPAddr("udp4", ipAddr+":0") 104 | if err != nil { 105 | return []Device{}, err 106 | } 107 | 108 | multicastAddress, err := net.ResolveUDPAddr("udp4", "239.255.255.250:3702") 109 | if err != nil { 110 | return []Device{}, err 111 | } 112 | 113 | // Create UDP connection to listen for respond from matching device 114 | conn, err := net.ListenUDP("udp", localAddress) 115 | if err != nil { 116 | return []Device{}, err 117 | } 118 | defer conn.Close() 119 | 120 | // Set connection's timeout 121 | err = conn.SetDeadline(time.Now().Add(duration)) 122 | if err != nil { 123 | return []Device{}, err 124 | } 125 | 126 | // Send WS-Discovery request to multicast address 127 | _, err = conn.WriteToUDP([]byte(request), multicastAddress) 128 | if err != nil { 129 | return []Device{}, err 130 | } 131 | 132 | // Create initial discovery results 133 | discoveryResults := []Device{} 134 | 135 | // Keep reading UDP message until timeout 136 | for { 137 | // Create buffer and receive UDP response 138 | buffer := make([]byte, 10*1024) 139 | _, _, err = conn.ReadFromUDP(buffer) 140 | 141 | //fmt.Println(string(buffer)) 142 | // pretty.Println(buffer) 143 | // Check if connection timeout 144 | if err != nil { 145 | if udpErr, ok := err.(net.Error); ok && udpErr.Timeout() { 146 | break 147 | } else { 148 | return discoveryResults, err 149 | } 150 | } 151 | 152 | // Read and parse WS-Discovery response 153 | device, err := readDiscoveryResponse(requestID, buffer) 154 | if err != nil && err != errWrongDiscoveryResponse { 155 | return discoveryResults, err 156 | } 157 | 158 | // Push device to results 159 | discoveryResults = append(discoveryResults, device) 160 | } 161 | 162 | return discoveryResults, nil 163 | } 164 | 165 | // readDiscoveryResponse reads and parses WS-Discovery response 166 | func readDiscoveryResponse(messageID string, buffer []byte) (Device, error) { 167 | // Inital result 168 | result := Device{} 169 | 170 | // fmt.Println("!!!!readDiscoveryResponse") 171 | 172 | // Parse XML to map 173 | mapXML, err := mxj.NewMapXml(buffer) 174 | if err != nil { 175 | return result, err 176 | } 177 | 178 | // Check if this response is for our request 179 | responseMessageID, _ := mapXML.ValueForPathString("Envelope.Header.RelatesTo") 180 | if responseMessageID != messageID { 181 | return result, errWrongDiscoveryResponse 182 | } 183 | 184 | // Get device's ID and clean it 185 | deviceID, _ := mapXML.ValueForPathString("Envelope.Body.ProbeMatches.ProbeMatch.EndpointReference.Address") 186 | deviceID = strings.Replace(deviceID, "urn:uuid:", "", 1) 187 | 188 | // Get device's name 189 | deviceName := "" 190 | scopes, _ := mapXML.ValueForPathString("Envelope.Body.ProbeMatches.ProbeMatch.Scopes") 191 | for _, scope := range strings.Split(scopes, " ") { 192 | if strings.HasPrefix(scope, "onvif://www.onvif.org/name/") { 193 | deviceName = strings.Replace(scope, "onvif://www.onvif.org/name/", "", 1) 194 | deviceName = strings.Replace(deviceName, "_", " ", -1) 195 | break 196 | } 197 | } 198 | 199 | // Get device's xAddrs 200 | xAddrs, _ := mapXML.ValueForPathString("Envelope.Body.ProbeMatches.ProbeMatch.XAddrs") 201 | listXAddr := strings.Split(xAddrs, " ") 202 | if len(listXAddr) == 0 { 203 | return result, errors.New("Device does not have any xAddr") 204 | } 205 | 206 | // Finalize result 207 | result.ID = deviceID 208 | result.Name = deviceName 209 | result.XAddr = listXAddr[0] 210 | 211 | return result, nil 212 | } 213 | -------------------------------------------------------------------------------- /wsdl/uplink.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | The capabilities for the uplink service is returned in the Capabilities element. 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Maximum number of uplink connections that can be configured. 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Uniform resource locator by which the remote client can be reached. 58 | 59 | 60 | ID of the certificate to be used for client authentication. 61 | 62 | 63 | Authorization level that will be assigned to the uplink connection. 64 | 65 | 66 | Current connection status (see tup:ConnectionStatus for possible values). 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | List of configured uplinks. 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | SConfiguration to be added or modified. 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | Uniform resource locator of the configuration to be deleted. 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 | Returns the capabilities of the uplink service. 150 | 151 | 152 | 153 | 154 | 155 | A device supporting uplinks shall support this command to retrieve the configured uplink configurations. 156 | The Status field shall signal whether a connection is Offline, Connecting or Online. 157 | 158 | 159 | 160 | 161 | 162 | 163 | A device supporting uplinks shall support this command to add or modify an uplink configuration. 164 | The Status property of the UplinkConfiguration shall be ignored by the device. A device shall 165 | use the field RemoteAddress to decide whether to update an existing entry or create a new entry. 166 | 167 | 168 | 169 | 170 | 171 | 172 | A device supporting uplinks shall support this command to remove an uplink configuration. 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /wsdl/replay.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | The capabilities for the replay service is returned in the Capabilities element. 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Indicator that the Device supports reverse playback as defined in the ONVIF Streaming Specification. 41 | 42 | 43 | 44 | 45 | The list contains two elements defining the minimum and maximum valid values supported as session timeout in seconds. 46 | 47 | 48 | 49 | 50 | Indicates support for RTP/RTSP/TCP. 51 | 52 | 53 | 54 | 55 | If playback streaming over WebSocket is supported, this shall return the RTSP WebSocket URI as described in Streaming Specification Section 5.1.1.5. 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Specifies the connection parameters to be used for the stream. The URI that is returned may depend on these parameters. 68 | 69 | 70 | 71 | 72 | The identifier of the recording to be streamed. 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | The URI to which the client should connect in order to stream the recording. 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Description of the new replay configuration parameters. 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | The current replay configuration parameters. 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 | Returns the capabilities of the replay service. The result is returned in a typed answer. 152 | 153 | 154 | 155 | 156 | 157 | Requests a URI that can be used to initiate playback of a recorded stream 158 | using RTSP as the control protocol. The URI is valid only as it is 159 | specified in the response. 160 | This operation is mandatory. 161 | 162 | 163 | 164 | 165 | 166 | 167 | Returns the current configuration of the replay service. 168 | This operation is mandatory. 169 | 170 | 171 | 172 | 173 | 174 | 175 | Changes the current configuration of the replay service. 176 | This operation is mandatory. 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /soap/soap.go: -------------------------------------------------------------------------------- 1 | package soap 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "crypto/rand" 7 | "crypto/sha1" 8 | "crypto/tls" 9 | "encoding/base64" 10 | "encoding/xml" 11 | "net" 12 | "net/http" 13 | "reflect" 14 | "time" 15 | 16 | "golang.org/x/net/html/charset" 17 | ) 18 | 19 | type SOAPEncoder interface { 20 | Encode(v interface{}) error 21 | Flush() error 22 | } 23 | 24 | type SOAPDecoder interface { 25 | Decode(v interface{}) error 26 | } 27 | 28 | type SOAPHeader struct { 29 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Header"` 30 | Headers []interface{} `xml:"http://www.w3.org/2003/05/soap-envelope Header"` 31 | } 32 | 33 | type SOAPEnvelope struct { 34 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Envelope"` 35 | Header SOAPHeader 36 | Body SOAPBody 37 | } 38 | 39 | type SOAPBody struct { 40 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Body"` 41 | 42 | Fault *SOAPFault `xml:",omitempty"` 43 | Content interface{} `xml:",omitempty"` 44 | } 45 | 46 | // UnmarshalXML unmarshals SOAPBody xml 47 | func (b *SOAPBody) UnmarshalXML(d *Decoder, _ StartElement) error { 48 | if b.Content == nil { 49 | return xml.UnmarshalError("Content must be a pointer to a struct") 50 | } 51 | 52 | var ( 53 | token xml.Token 54 | err error 55 | consumed bool 56 | ) 57 | 58 | Loop: 59 | for { 60 | if token, err = d.Token(); err != nil { 61 | return err 62 | } 63 | 64 | if token == nil { 65 | break 66 | } 67 | 68 | switch se := token.(type) { 69 | case StartElement: 70 | if consumed { 71 | return xml.UnmarshalError("Found multiple elements inside SOAP body; not wrapped-document/literal WS-I compliant") 72 | } else if se.Name.Space == "http://www.w3.org/2003/05/soap-envelope" && se.Name.Local == "Fault" { 73 | b.Fault = &SOAPFault{} 74 | b.Content = nil 75 | 76 | err = d.DecodeElement(b.Fault, &se) 77 | if err != nil { 78 | return err 79 | } 80 | 81 | consumed = true 82 | } else { 83 | if err = d.DecodeElement(b.Content, &se); err != nil { 84 | return err 85 | } 86 | 87 | consumed = true 88 | } 89 | case EndElement: 90 | break Loop 91 | 92 | } 93 | } 94 | 95 | return nil 96 | } 97 | 98 | type SOAPFaultSubCode struct { 99 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Subcode"` 100 | 101 | Value string 102 | } 103 | 104 | type SOAPFaultCode struct { 105 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Code"` 106 | 107 | Value string 108 | Subcode SOAPFaultSubCode 109 | } 110 | 111 | type SOAPFaultReason struct { 112 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Reason"` 113 | 114 | Text string 115 | } 116 | 117 | type SOAPFaultDetail struct { 118 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Detail"` 119 | 120 | Text string 121 | } 122 | 123 | type SOAPFault struct { 124 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Fault"` 125 | 126 | Code SOAPFaultCode 127 | Reason SOAPFaultReason `xml:",omitempty"` 128 | Detail SOAPFaultDetail `xml:",omitempty"` 129 | } 130 | 131 | func (f *SOAPFault) Error() string { 132 | s := f.Reason.Text 133 | if f.Detail.Text != "" { 134 | s += ". Details: " + f.Detail.Text 135 | } 136 | if s == "" { 137 | if f.Code.Value != "" { 138 | s = f.Code.Value + ". " 139 | } 140 | 141 | if f.Code.Subcode.Value != "" { 142 | s += f.Code.Subcode.Value 143 | } 144 | } 145 | return s 146 | } 147 | 148 | const ( 149 | // Predefined WSS namespaces to be used in 150 | WssNsWSSE string = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 151 | WssNsWSU string = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 152 | WssNsType string = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" 153 | mtomContentType string = `multipart/related; start-info="application/soap+xml"; type="application/xop+xml"; boundary="%s"` 154 | ) 155 | 156 | type WSSPassword struct { 157 | Type string `xml:",attr"` 158 | Value string `xml:",chardata"` 159 | } 160 | 161 | type WSSNonce struct { 162 | EncodingType string `xml:",attr"` 163 | Value string `xml:",chardata"` 164 | } 165 | 166 | type WSSCreated struct { 167 | XMLName xml.Name `xml:"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Created"` 168 | Value string `xml:",chardata"` 169 | } 170 | 171 | type WSSUsernameToken struct { 172 | Username string 173 | 174 | Password WSSPassword 175 | 176 | Nonce WSSNonce 177 | 178 | Created WSSCreated 179 | } 180 | 181 | type WSSSecurityHeader struct { 182 | XMLName xml.Name `xml:"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd Security"` 183 | 184 | MustUnderstand string `xml:"mustUnderstand,attr"` 185 | 186 | UsernameToken WSSUsernameToken 187 | } 188 | 189 | // NewWSSSecurityHeader creates WSSSecurityHeader instance 190 | func NewWSSSecurityHeader(user, pass string, created time.Time) *WSSSecurityHeader { 191 | hdr := &WSSSecurityHeader{MustUnderstand: "1"} 192 | 193 | // Username 194 | hdr.UsernameToken.Username = user 195 | 196 | // Created 197 | if created.Year() != 0 { 198 | hdr.UsernameToken.Created.Value = created.Format("2006-01-02T15:04:05.999") + "Z" 199 | //fmt.Println("------", hdr.UsernameToken.Created.Value, created.Nanosecond()) 200 | 201 | } else { 202 | hdr.UsernameToken.Created.Value = time.Now().Format("2006-01-02T15:04:05.999") + "Z" 203 | } 204 | 205 | // Nonce 206 | b := make([]byte, 16) 207 | rand.Read(b) 208 | hdr.UsernameToken.Nonce.EncodingType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" 209 | hdr.UsernameToken.Nonce.Value = base64.StdEncoding.EncodeToString(b) 210 | 211 | // Password 212 | h := sha1.New() 213 | h.Write([]byte(hdr.UsernameToken.Nonce.Value + hdr.UsernameToken.Created.Value + pass)) 214 | hdr.UsernameToken.Password.Type = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest" 215 | hdr.UsernameToken.Password.Value = base64.StdEncoding.EncodeToString(h.Sum(nil)) 216 | 217 | return hdr 218 | } 219 | 220 | type basicAuth struct { 221 | Login string 222 | Password string 223 | } 224 | 225 | type options struct { 226 | tlsCfg *tls.Config 227 | auth *basicAuth 228 | timeout time.Duration 229 | contimeout time.Duration 230 | tlshshaketimeout time.Duration 231 | client HTTPClient 232 | httpHeaders map[string]string 233 | wssCallback func() *WSSSecurityHeader 234 | } 235 | 236 | var defaultOptions = options{ 237 | timeout: time.Duration(30 * time.Second), 238 | contimeout: time.Duration(90 * time.Second), 239 | tlshshaketimeout: time.Duration(15 * time.Second), 240 | } 241 | 242 | // A Option sets options such as credentials, tls, etc. 243 | type Option func(*options) 244 | 245 | // WithWSSCallback is an Option to set the callback for WSSSecurityHeader 246 | func WithWSSCallback(c func() *WSSSecurityHeader) Option { 247 | return func(o *options) { 248 | o.wssCallback = c 249 | } 250 | } 251 | 252 | // WithHTTPClient is an Option to set the HTTP client to use 253 | // This cannot be used with WithTLSHandshakeTimeout, WithTLS, 254 | // WithTimeout options 255 | func WithHTTPClient(c HTTPClient) Option { 256 | return func(o *options) { 257 | o.client = c 258 | } 259 | } 260 | 261 | // WithTLSHandshakeTimeout is an Option to set default tls handshake timeout 262 | // This option cannot be used with WithHTTPClient 263 | func WithTLSHandshakeTimeout(t time.Duration) Option { 264 | return func(o *options) { 265 | o.tlshshaketimeout = t 266 | } 267 | } 268 | 269 | // WithRequestTimeout is an Option to set default end-end connection timeout 270 | // This option cannot be used with WithHTTPClient 271 | func WithRequestTimeout(t time.Duration) Option { 272 | return func(o *options) { 273 | o.contimeout = t 274 | } 275 | } 276 | 277 | // WithBasicAuth is an Option to set BasicAuth 278 | func WithBasicAuth(login, password string) Option { 279 | return func(o *options) { 280 | o.auth = &basicAuth{Login: login, Password: password} 281 | } 282 | } 283 | 284 | // WithTLS is an Option to set tls config 285 | // This option cannot be used with WithHTTPClient 286 | func WithTLS(tls *tls.Config) Option { 287 | return func(o *options) { 288 | o.tlsCfg = tls 289 | } 290 | } 291 | 292 | // WithTimeout is an Option to set default HTTP dial timeout 293 | func WithTimeout(t time.Duration) Option { 294 | return func(o *options) { 295 | o.timeout = t 296 | } 297 | } 298 | 299 | // WithHTTPHeaders is an Option to set global HTTP headers for all requests 300 | func WithHTTPHeaders(headers map[string]string) Option { 301 | return func(o *options) { 302 | o.httpHeaders = headers 303 | } 304 | } 305 | 306 | // Client is soap client 307 | type Client struct { 308 | opts *options 309 | headers []interface{} 310 | } 311 | 312 | // HTTPClient is a client which can make HTTP requests 313 | // An example implementation is net/http.Client 314 | type HTTPClient interface { 315 | Do(req *http.Request) (*http.Response, error) 316 | } 317 | 318 | // NewClient creates new SOAP client instance 319 | func NewClient(opt ...Option) *Client { 320 | opts := defaultOptions 321 | for _, o := range opt { 322 | o(&opts) 323 | } 324 | return &Client{ 325 | opts: &opts, 326 | } 327 | } 328 | 329 | // AddHeader adds envelope header 330 | func (s *Client) AddHeader(header interface{}) { 331 | s.headers = append(s.headers, header) 332 | } 333 | 334 | // ReplaceHeader replaces envelope header matching by Type 335 | func (s *Client) ReplaceHeader(header interface{}) { 336 | found := false 337 | i := 0 338 | for i = 0; i < len(s.headers); i++ { 339 | if reflect.TypeOf(s.headers[i]).Name() == reflect.TypeOf(header).Name() { 340 | found = true 341 | break 342 | } 343 | } 344 | if found { 345 | s.headers[i] = s.headers[len(s.headers)-1] // Copy last element to index i. 346 | s.headers[len(s.headers)-1] = "" // Erase last element (write zero value). 347 | s.headers = s.headers[:len(s.headers)-1] // Truncate slice. 348 | } 349 | s.headers = append(s.headers, header) 350 | } 351 | 352 | // CallContext performs HTTP POST request with a context 353 | func (s *Client) CallContext(ctx context.Context, xaddr string, soapAction string, request, response interface{}) error { 354 | return s.call(ctx, xaddr, soapAction, request, response) 355 | } 356 | 357 | // Call performs HTTP POST request 358 | func (s *Client) Call(xaddr string, soapAction string, request, response interface{}) error { 359 | return s.call(context.Background(), xaddr, soapAction, request, response) 360 | } 361 | 362 | func (s *Client) call(ctx context.Context, xaddr string, soapAction string, request, response interface{}) error { 363 | envelope := SOAPEnvelope{} 364 | 365 | if s.opts.wssCallback != nil { 366 | wssHdr := s.opts.wssCallback() 367 | if wssHdr != nil { 368 | s.ReplaceHeader(wssHdr) 369 | } 370 | } 371 | if s.headers != nil && len(s.headers) > 0 { 372 | envelope.Header.Headers = s.headers 373 | } 374 | 375 | envelope.Body.Content = request 376 | buffer := new(bytes.Buffer) 377 | var encoder SOAPEncoder 378 | encoder = xml.NewEncoder(buffer) 379 | 380 | if err := encoder.Encode(envelope); err != nil { 381 | return err 382 | } 383 | 384 | if err := encoder.Flush(); err != nil { 385 | return err 386 | } 387 | 388 | req, err := http.NewRequest("POST", xaddr, buffer) 389 | if err != nil { 390 | return err 391 | } 392 | if s.opts.auth != nil { 393 | req.SetBasicAuth(s.opts.auth.Login, s.opts.auth.Password) 394 | } 395 | 396 | req.WithContext(ctx) 397 | 398 | req.Header.Add("Content-Type", "application/soap+xml; charset=utf-8; action=\""+soapAction+"\"") 399 | req.Header.Add("Soapaction", "\""+soapAction+"\"") 400 | req.Header.Set("User-Agent", "videonext-onvif-go/0.1") 401 | if s.opts.httpHeaders != nil { 402 | for k, v := range s.opts.httpHeaders { 403 | req.Header.Set(k, v) 404 | } 405 | } 406 | req.Close = true 407 | 408 | client := s.opts.client 409 | if client == nil { 410 | tr := &http.Transport{ 411 | TLSClientConfig: s.opts.tlsCfg, 412 | DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { 413 | d := net.Dialer{Timeout: s.opts.timeout} 414 | return d.DialContext(ctx, network, addr) 415 | }, 416 | TLSHandshakeTimeout: s.opts.tlshshaketimeout, 417 | } 418 | client = &http.Client{Timeout: s.opts.contimeout, Transport: tr} 419 | } 420 | 421 | res, err := client.Do(req) 422 | if err != nil { 423 | return err 424 | } 425 | defer res.Body.Close() 426 | 427 | respEnvelope := new(SOAPEnvelope) 428 | respEnvelope.Body = SOAPBody{Content: response} 429 | 430 | dec := NewDecoder(res.Body) 431 | dec.CharsetReader = charset.NewReaderLabel 432 | 433 | if err := dec.Decode(respEnvelope); err != nil { 434 | return err 435 | } 436 | 437 | fault := respEnvelope.Body.Fault 438 | if fault != nil { 439 | return fault 440 | } 441 | 442 | return nil 443 | } 444 | -------------------------------------------------------------------------------- /wsdl/bin/fixgen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import os 4 | import re 5 | from urllib.request import urlopen 6 | 7 | # How to use: 8 | # go get github.com/hooklift/gowsdl/... 9 | # ./fixgen.py [onvif profile file name without .wsdl] 10 | 11 | if len(sys.argv) != 2: 12 | print("Usage:\n./fixgen.py [path to profile file without .wsdl]") 13 | exit(1) 14 | 15 | go_package = os.path.basename(sys.argv[1]) 16 | go_src = os.path.basename(sys.argv[1]) + '.go' 17 | wsdl_file = sys.argv[1] + '.wsdl' 18 | 19 | with open(wsdl_file, 'r', encoding="utf-8") as file: 20 | wsdl = file.read() 21 | 22 | r = re.findall(r'targetNamespace="(http://www.onvif.org/.+)"', wsdl) 23 | if len(r): 24 | targetNamespace = r[0] 25 | 26 | os.system('gowsdl -o ' + go_src + ' -p ' + go_package + ' ' + wsdl_file + ' | grep -v expected') 27 | 28 | with open(go_package + '/' + go_src, 'r', encoding="utf-8") as file: 29 | data = file.read() 30 | 31 | data = data.replace('// Code generated by gowsdl DO NOT EDIT.', '') 32 | print(' - Replace import') 33 | data = data.replace('"github.com/hooklift/gowsdl/soap"', 34 | '"github.com/videonext/onvif/soap"') 35 | ######################################################################## 36 | 37 | print(' - Working around some bugs in the gowsdl') 38 | data = data.replace('interface{}', '') 39 | data = data.replace('TLS1.0 bool', 'TLS1_0 bool') 40 | data = data.replace('TLS1.1 bool', 'TLS1_1 bool') 41 | data = data.replace('TLS1.2 bool', 'TLS1_2 bool') 42 | data = data.replace('X.509Token bool', 'X_509Token bool') 43 | ######################################################################## 44 | 45 | print(' - Adding wsdl\'s namespace and method name to the SOAP action') 46 | data = re.sub(r'(?s)func \(service (\*\w+\)) (\w+)Context\s*\(ctx context.Context, request (\*\w+\)) \((\*\w+), error\)(.+?)service\.client\.CallContext\(ctx, "(\'\')",', 47 | r'func (service \1 \2Context(ctx context.Context, request \3 (\4, error)\5service.client.CallContext(ctx, "' + targetNamespace + '/' + r'\2",', data) 48 | ######################################################################## 49 | 50 | print(' - Patching object, CallContext and New* functions: add xaddr field/arg') 51 | data = re.sub(r'(?s)type\s+(\w+?)\s+struct\s+\{\s+?client\s+\*soap\.Client', 52 | r'type \1 struct {\nclient *soap.Client\nxaddr string\n', data) 53 | data = data.replace('service.client.CallContext(ctx,', 'service.client.CallContext(ctx, service.xaddr,') 54 | data = re.sub(r'(?s)func New(.+?)\(client \*soap.Client\) (.+?) \{.+?return \&(\w+)\{.+?}', 55 | r'func New\1(client *soap.Client, xaddr string) \2 {\n return &\3{\nclient: client,\nxaddr: xaddr,\n}', data) 56 | ######################################################################## 57 | 58 | print(' - Fixing namespaces in the xsd types') 59 | type_map = {} 60 | xsds = ['http://www.onvif.org/ver10/schema/common.xsd', 61 | 'http://www.onvif.org/ver10/schema/onvif.xsd', 62 | 'http://www.w3.org/2001/xml.xsd', 63 | 'http://www.onvif.org/ver10/schema/metadatastream.xsd', 64 | 'http://www.onvif.org/ver10/pacs/types.xsd', 65 | 'http://www.onvif.org/ver20/analytics/rules.xsd', 66 | 'http://www.onvif.org/ver20/analytics/radiometry.xsd'] 67 | for xsd in xsds: 68 | xsd_data = urlopen(xsd).read().decode('utf-8') 69 | r = re.findall(r'targetNamespace="(http://.+?)"', xsd_data) 70 | if len(r): 71 | ns = r[0] 72 | else: 73 | raise Exception('No namespace in the ' + xsd) 74 | r = re.findall(r'\', xsd_data) 75 | for t in r: 76 | if not t[0].isupper(): 77 | t = t.title() 78 | if t in type_map: 79 | continue 80 | type_map[t] = ns 81 | # reading used types from onvif.xsd 82 | onvif_xsd_data = urlopen('http://www.onvif.org/ver10/schema/onvif.xsd').read().decode('utf-8') 83 | r = re.findall(r'type="xs:(.+?)"', onvif_xsd_data) 84 | for t in r: 85 | if not t[0].isupper(): 86 | t = t.title() 87 | if t in type_map: 88 | continue 89 | type_map[t] = 'http://www.onvif.org/ver10/schema' 90 | # reading used types from common.xsd 91 | common_xsd_data = urlopen('http://www.onvif.org/ver10/schema/common.xsd').read().decode('utf-8') 92 | r = re.findall(r'type="xs:(.+?)"', common_xsd_data) 93 | for t in r: 94 | if not t[0].isupper(): 95 | t = t.title() 96 | if t in type_map: 97 | continue 98 | type_map[t] = 'http://www.onvif.org/ver10/schema' 99 | # reading types from wsdl 100 | r = re.findall(r'\', wsdl) 101 | for t in r: 102 | if not t[0].isupper(): 103 | t = t.title() 104 | if t in type_map: 105 | continue 106 | type_map[t] = targetNamespace 107 | # some other types 108 | type_map['String'] = 'http://www.onvif.org/ver10/schema' 109 | type_map['string'] = 'http://www.onvif.org/ver10/schema' 110 | type_map['time.Time'] = 'http://www.onvif.org/ver10/schema' 111 | type_map['byte'] = 'http://www.onvif.org/ver10/schema' 112 | type_map['int'] = 'http://www.onvif.org/ver10/schema' 113 | type_map['uint'] = 'http://www.onvif.org/ver10/schema' 114 | type_map['int8'] = 'http://www.onvif.org/ver10/schema' 115 | type_map['uint8'] = 'http://www.onvif.org/ver10/schema' 116 | type_map['int16'] = 'http://www.onvif.org/ver10/schema' 117 | type_map['uint16'] = 'http://www.onvif.org/ver10/schema' 118 | type_map['int32'] = 'http://www.onvif.org/ver10/schema' 119 | type_map['uint32'] = 'http://www.onvif.org/ver10/schema' 120 | type_map['int64'] = 'http://www.onvif.org/ver10/schema' 121 | type_map['uint64'] = 'http://www.onvif.org/ver10/schema' 122 | type_map['float32'] = 'http://www.onvif.org/ver10/schema' 123 | type_map['float64'] = 'http://www.onvif.org/ver10/schema' 124 | type_map['bool'] = 'http://www.onvif.org/ver10/schema' 125 | type_map['[]string'] = 'http://www.onvif.org/ver10/schema' 126 | type_map['ReferenceToken'] = 'http://www.onvif.org/ver10/schema' 127 | type_map['time.Time'] = 'http://www.onvif.org/ver10/schema' 128 | type_map['NonNegativeInteger'] = 'http://www.onvif.org/ver10/schema' 129 | if type_map['Anyuri'] != None: 130 | type_map['AnyURI'] = type_map['Anyuri'] 131 | # print(type_map) 132 | for k, v in type_map.items(): 133 | ns = v 134 | # # check if type used in the wsdl we are processing 135 | r = re.findall(r'type="\w+:' + re.escape(k), wsdl) 136 | # if len(r) and (re.search(r'complexType name="' + k + '"', common_xsd_data) or re.search(r'complexType name="' + k + '"', onvif_xsd_data)): 137 | # ns = targetNamespace 138 | if len(r): 139 | ns = targetNamespace 140 | data = re.sub(r"(?s)(\w+)\s+\*" + re.escape(k) + r"\s+`xml:\"\1(.*?)\"`", 141 | r"\1 *" + k + r' `xml:"' + ns + r' \1\2"`', 142 | data) 143 | data = re.sub(r"(?s)(\w+)\s+\[\]\*" + re.escape(k) + r"\s+`xml:\"\1(.*?)\"`", 144 | r"\1 []*" + k + r' `xml:"' + ns + r' \1\2"`', 145 | data) 146 | data = re.sub(r"(?s)(\w+)\s+\[\]" + re.escape(k) + r"\s+`xml:\"\1(.*?)\"`", 147 | r"\1 []" + k + r' `xml:"' + ns + r' \1\2"`', 148 | data) 149 | data = re.sub(r"(?s)(\w+)\s+" + re.escape(k) + r"\s+`xml:\"\1(.*?)\"`", 150 | r"\1 " + k + r' `xml:"' + ns + r' \1\2"`', 151 | data) 152 | ######################################################################## 153 | 154 | with open(go_package + '/' + go_src, 'w', encoding="utf-8") as file: 155 | file.write(data) 156 | 157 | os.system("gofmt -w " + go_package + '/' + go_src) 158 | 159 | with open(go_package + '/' + go_src, 'r', encoding="utf-8") as file: 160 | data = file.read() 161 | 162 | print(' - Adding missed simple types') 163 | data += "\ntype AnyURI string\n" 164 | data += "type Duration string\n" 165 | data += "type QName string\n" 166 | data += "type NCName string\n" 167 | data += "type NonNegativeInteger int64\n" 168 | data += "type PositiveInteger int64\n" 169 | data += "type NonPositiveInteger int64\n" 170 | data += "type AnySimpleType string\n" 171 | data += "type String string\n" 172 | ######################################################################## 173 | 174 | print(' - Removing unused types') 175 | for k, v in type_map.items(): 176 | r0 = re.findall(r"(\w+)\s+" + re.escape(k) + r"\s+`xml:\"", data) 177 | r1 = re.findall(r"(\w+)\s+\*" + re.escape(k) + r"\s+`xml:\"", data) 178 | r2 = re.findall(r"(\w+)\s+\[\]" + re.escape(k) + r"\s+`xml:\"", data) 179 | r3 = re.findall(r"(\w+)\s+\[\]\*" + re.escape(k) + r"\s+`xml:\"", data) 180 | r4 = re.findall(r"\*" + re.escape(k), data) 181 | r5 = re.findall(r"\[\]" + re.escape(k), data) 182 | r6 = re.findall(re.escape(k) + r' = ', data) 183 | r7 = re.findall(r'type \w+ ' + re.escape(k), data) 184 | if len(r0) == 0 and len(r1) == 0 and len(r2) == 0 and len(r3) == 0 and len(r4) == 0 and len(r5) == 0 and len(r6) == 0 and len(r7) == 0: 185 | regex = re.compile(r"(?s)type\s+" + re.escape(k) + r"\s+struct\s+\{(.+?)^\}", re.MULTILINE) 186 | data = re.sub(regex, '', data) 187 | regex = re.compile(r"(?s)type\s+" + re.escape(k) + r"\s+\w+\n", re.MULTILINE) 188 | data = re.sub(regex, '', data) 189 | r = re.findall(r"type (\w+) ", data) 190 | for t in r: 191 | r0 = re.findall(r"(\w+)\s+" + re.escape(t) + r"\s+`xml:\"", data) 192 | r1 = re.findall(r"(\w+)\s+\*" + re.escape(t) + r"\s+`xml:\"", data) 193 | r2 = re.findall(r"(\w+)\s+\[\]" + re.escape(t) + r"\s+`xml:\"", data) 194 | r3 = re.findall(r"(\w+)\s+\[\]\*" + re.escape(t) + r"\s+`xml:\"", data) 195 | r4 = re.findall(r"\*" + re.escape(t), data) 196 | r5 = re.findall(r"\[\]" + re.escape(t), data) 197 | r6 = re.findall(re.escape(t) + r' = ', data) 198 | r7 = re.findall(r'type \w+ ' + re.escape(t), data) 199 | if len(r0) == 0 and len(r1) == 0 and len(r2) == 0 and len(r3) == 0 and len(r4) == 0 and len(r5) == 0 and len(r6) == 0 and len(r7) == 0: 200 | regex = re.compile(r"(?s)type\s+" + re.escape(t) + r"\s+struct\s+\{(.+?)^\}", re.MULTILINE) 201 | data = re.sub(regex, '', data) 202 | regex = re.compile(r"(?s)type\s+" + re.escape(t) + r"\s+\w+\n", re.MULTILINE) 203 | data = re.sub(regex, '', data) 204 | 205 | 206 | ######################################################################## 207 | 208 | print(' - Removing pointers for simple types') 209 | data = data.replace('*AnyURI', 'AnyURI') 210 | data = data.replace('*Duration', 'Duration') 211 | data = data.replace('*QName', 'QName') 212 | data = data.replace('*NonNegativeInteger', 'NonNegativeInteger') 213 | data = data.replace('*PositiveInteger', 'PositiveInteger') 214 | data = data.replace('*NonPositiveInteger', 'NonPositiveInteger') 215 | data = data.replace('*AnySimpleType', 'AnySimpleType') 216 | data = data.replace('*Description', 'Description') 217 | data = data.replace('*Name `xml', 'Name `xml') 218 | data = data.replace('*string `xml', 'string `xml') 219 | data = data.replace('*String `xml', 'String `xml') 220 | data = data.replace('*int32 `xml', 'int32 `xml') 221 | data = data.replace('*float32 `xml', 'float32 `xml') 222 | data = data.replace('*bool `xml', 'bool `xml') 223 | data = data.replace('*time.Time `xml', 'string `xml') 224 | data = data.replace('time.Time `xml', 'string `xml') 225 | data = data.replace('[]*', '[]') 226 | data = data.replace('*NCName', 'NCName') 227 | ######################################################################## 228 | 229 | print(' - Removing duplicated types') 230 | data = re.sub(r'type \b(\w+)\s+\1\b', '', data) 231 | data = data.replace('type IntList IntAttrList', '') 232 | data = data.replace('type FloatList FloatAttrList', '') 233 | data = data.replace('type Capabilities DeviceServiceCapabilities', '') 234 | data = data.replace('type FaultcodeEnum *QName', 'type FaultcodeEnum QName') 235 | data = data.replace('type FaultCodesType *QName', 'type FaultCodesType QName') 236 | data = data.replace('type RelationshipType *AnyURI', 'type RelationshipType AnyURI') 237 | data = re.sub(r'(?s)type QueryExpressionType struct \{\n\s+XMLName xml\.Name `xml:"http://docs\.oasis-open\.org/wsn/b-2 ProducerProperties(.+?)\}', 238 | r'// Removed QueryExpressionType', data) 239 | r = re.findall(r'(?s)(type Capabilities struct(.+?)\})', data) 240 | if len(r) == 2: 241 | data = data.replace(r[1][0], '/* Removed ' + r[1][0] + ' Removed*/') 242 | ######################################################################## 243 | 244 | print(' - Removing pointers to xml data types') 245 | data = re.sub(r"(\w+)\s+\*(\w+)\s+`xml:\"(.*?)\"`", 246 | r'\1 \2 `xml:"\3"`', 247 | data) 248 | data = re.sub(r"(\w+)\s+\[\]\*(\w+)\s+`xml:\"(.*?)\"`", 249 | r'\1 []\2 `xml:"\3"`', 250 | data) 251 | # keep some of them to prevent recursion 252 | data = data.replace('Extension NetworkZeroConfigurationExtension `xml:"', 'Extension *NetworkZeroConfigurationExtension `xml:"') 253 | data = data.replace('Tunnel Transport `xml:"', 'Tunnel *Transport `xml:"') 254 | data = data.replace('Subcode Subcode `xml:"', 'Subcode *Subcode `xml:"') 255 | data = data.replace('*Ref', 'Ref') 256 | ######################################################################## 257 | 258 | # add comments to exported types 259 | regex = re.compile(r'^type\s+(.+?)\s+', re.MULTILINE) 260 | data = re.sub(regex, r'// \1 type\ntype \1 ', data) 261 | # add comments to exported constants 262 | regex = re.compile(r'(\w+) (\w+) = "(.+?)"', re.MULTILINE) 263 | data = re.sub(regex, r'// \1 const\n\1 \2 = "\3" ', data) 264 | 265 | # remove ns from *Response* types 266 | regex = re.compile(r'(?s)^(type \w+Response\w+ struct \{.+?\})', re.MULTILINE) 267 | r = re.findall(regex, data) 268 | regex = re.compile(r'(?s)^(type \w+Response struct \{.+?\})', re.MULTILINE) 269 | r += re.findall(regex, data) 270 | for block in r: 271 | block2 = re.sub(r'xml:"http.+? ', 'xml:"', block) 272 | data = data.replace(block, block2) 273 | 274 | 275 | with open(go_package + '/' + go_src, 'w', encoding="utf-8") as file: 276 | file.write(data) 277 | 278 | 279 | os.system("gofmt -w " + go_package + '/' + go_src) 280 | 281 | 282 | print('Done') 283 | -------------------------------------------------------------------------------- /wsdl/common.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Unique identifier for a physical or logical resource. 10 | Tokens should be assigned such that they are unique within a device. Tokens must be at least unique within its class. 11 | Length up to 64 characters. 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Range of values greater equal Min value and less equal Max value. 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | Pan/tilt coordinate space selector. The following options are defined:
    37 |
  • http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace
  • 38 |
  • http://www.onvif.org/ver10/tptz/PanTiltSpaces/TranslationGenericSpace
  • 39 |
  • http://www.onvif.org/ver10/tptz/PanTiltSpaces/VelocityGenericSpace
  • 40 |
  • http://www.onvif.org/ver10/tptz/PanTiltSpaces/GenericSpeedSpace
  • 41 |
42 |
43 |
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | Zoom coordinate space selector. The following options are defined:
    52 |
  • http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace
  • 53 |
  • http://www.onvif.org/ver10/tptz/ZoomSpaces/TranslationGenericSpace
  • 54 |
  • http://www.onvif.org/ver10/tptz/ZoomSpaces/VelocityGenericSpace
  • 55 |
  • http://www.onvif.org/ver10/tptz/ZoomSpaces/ZoomGenericSpeedSpace
  • 56 |
57 |
58 |
59 |
60 |
61 | 62 | 63 | 64 | 65 | Pan and tilt position. The x component corresponds to pan and the y component to tilt. 66 | 67 | 68 | 69 | 70 | 71 | A zoom position. 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | Specifies the absolute position of the PTZ unit together with the Space references. The default absolute spaces of the corresponding PTZ configuration MUST be referenced within the Position element. 83 | 84 | 85 | 86 | 87 | 88 | 89 | Indicates if the Pan/Tilt/Zoom device unit is currently moving, idle or in an unknown state. 90 | 91 | 92 | 93 | 94 | 95 | 96 | States a current PTZ error. 97 | 98 | 99 | 100 | 101 | 102 | 103 | Specifies the UTC time when this status was generated. 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 | Acceptable values: 161 |
    162 |
  • http://www.onvif.org/ver10/colorspace/YCbCr - YCbCr 163 |
    • X attribute = Y value
    • 164 |
    • Y attribute = Cb value
    • 165 |
    • Z attribute = Cr value
    166 |
  • 167 |
  • http://www.onvif.org/ver10/colorspace/RGB - RGB 168 |
    • X attribute = R value
    • 169 |
    • Y attribute = G value
    • 170 |
    • Z attribute = B value
    171 |
  • 172 |
173 | If the Colorspace attribute is absent, YCbCr is implied. 174 | 175 | Deprecated values: 176 |
    177 |
  • http://www.onvif.org/ver10/colorspace/CIELUV - CIE LUV
  • 178 |
  • http://www.onvif.org/ver10/colorspace/CIELAB - CIE 1976 (L*a*b*)
  • 179 |
  • http://www.onvif.org/ver10/colorspace/HSV - HSV
  • 180 |
181 |
182 |
183 |
184 |
185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | Acceptable values are the same as in tt:Color. 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | East west location as angle. 226 | 227 | 228 | 229 | 230 | North south location as angle. 231 | 232 | 233 | 234 | 235 | Hight in meters above sea level. 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | Rotation around the x axis. 248 | 249 | 250 | 251 | 252 | Rotation around the y axis. 253 | 254 | 255 | 256 | 257 | Rotation around the z axis. 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | East west location as angle. 270 | 271 | 272 | 273 | 274 | North south location as angle. 275 | 276 | 277 | 278 | 279 | Offset in meters from the sea level. 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | Rotation around the y axis. 292 | 293 | 294 | 295 | 296 | Rotation around the z axis. 297 | 298 | 299 | 300 | 301 | Rotation around the x axis. 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | Location on earth. 319 | 320 | 321 | Orientation relative to earth. 322 | 323 | 324 | Indoor location offset. 325 | 326 | 327 | Indoor orientation offset. 328 | 329 | 330 | 331 | Entity type the entry refers to, use a value from the tt:Entity enumeration. 332 | 333 | 334 | Optional entity token. 335 | 336 | 337 | If this value is true the entity cannot be deleted. 338 | 339 | 340 | Optional reference to the XAddr of another devices DeviceManagement service. 341 | 342 | 343 | If set the geo location is obtained internally. 344 | 345 | 346 | 347 |
348 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /wsdl/receiver.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | The capabilities for the receiver service is returned in the Capabilities element. 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Indicates that the device can receive RTP multicast streams. 41 | 42 | 43 | 44 | 45 | Indicates that the device can receive RTP/TCP streams 46 | 47 | 48 | 49 | 50 | Indicates that the device can receive RTP/RTSP/TCP streams. 51 | 52 | 53 | 54 | 55 | The maximum number of receivers supported by the device. 56 | 57 | 58 | 59 | 60 | The maximum allowed length for RTSP URIs (Minimum and default value is 128 octet). 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | A list of all receivers that currently exist on the device. 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | The token of the receiver to be retrieved. 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | The details of the receiver. 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | The initial configuration for the new receiver. 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | The details of the receiver that was created. 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | The token of the receiver to be deleted. 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | The token of the receiver to be configured. 151 | 152 | 153 | 154 | 155 | The new configuration for the receiver. 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | The token of the receiver to be changed. 173 | 174 | 175 | 176 | 177 | The new receiver mode. Options available are: 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | The token of the receiver to be queried. 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | Description of the current receiver state. 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | Returns the capabilities of the receiver service. The result is returned in a typed answer. 264 | 265 | 266 | 267 | 268 | 269 | Lists all receivers currently present on a device. This operation is mandatory. 270 | 271 | 272 | 273 | 274 | 275 | 276 | Retrieves the details of a specific receiver. This operation is mandatory. 277 | 278 | 279 | 280 | 281 | 282 | 283 | Creates a new receiver. This operation is mandatory, although the service may 284 | raise a fault if the receiver cannot be created. 285 | 286 | 287 | 288 | 289 | 290 | 291 | Deletes an existing receiver. A receiver may be deleted only if it is not 292 | currently in use; otherwise a fault shall be raised. 293 | This operation is mandatory. 294 | 295 | 296 | 297 | 298 | 299 | 300 | Configures an existing receiver. This operation is mandatory. 301 | 302 | 303 | 304 | 305 | 306 | 307 | Sets the mode of the receiver without affecting the rest of its configuration. 308 | This operation is mandatory. 309 | 310 | 311 | 312 | 313 | 314 | 315 | Determines whether the receiver is currently disconnected, connected or 316 | attempting to connect. 317 | This operation is mandatory. 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | -------------------------------------------------------------------------------- /profiles/accessrules/accessrules.go: -------------------------------------------------------------------------------- 1 | package accessrules 2 | 3 | import ( 4 | "context" 5 | "encoding/xml" 6 | "github.com/videonext/onvif/soap" 7 | "time" 8 | ) 9 | 10 | // against "unused imports" 11 | var _ time.Time 12 | var _ xml.Name 13 | 14 | // GetServiceCapabilities type 15 | type GetServiceCapabilities struct { 16 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl GetServiceCapabilities"` 17 | } 18 | 19 | // GetServiceCapabilitiesResponse type 20 | type GetServiceCapabilitiesResponse struct { 21 | XMLName xml.Name `xml:"GetServiceCapabilitiesResponse"` 22 | 23 | // The capability response message contains the requested access rules 24 | // service capabilities using a hierarchical XML capability structure. 25 | // 26 | Capabilities ServiceCapabilities `xml:"Capabilities,omitempty"` 27 | } 28 | 29 | // GetAccessProfileInfo type 30 | type GetAccessProfileInfo struct { 31 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl GetAccessProfileInfo"` 32 | 33 | // Tokens of AccessProfileInfo items to get. 34 | Token []ReferenceToken `xml:"http://www.onvif.org/ver10/accessrules/wsdl Token,omitempty"` 35 | } 36 | 37 | // GetAccessProfileInfoResponse type 38 | type GetAccessProfileInfoResponse struct { 39 | XMLName xml.Name `xml:"GetAccessProfileInfoResponse"` 40 | 41 | // List of AccessProfileInfo items. 42 | AccessProfileInfo []AccessProfileInfo `xml:"AccessProfileInfo,omitempty"` 43 | } 44 | 45 | // GetAccessProfileInfoList type 46 | type GetAccessProfileInfoList struct { 47 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl GetAccessProfileInfoList"` 48 | 49 | // Maximum number of entries to return. If not specified, less than one 50 | // or higher than what the device supports, the number of items is determined by the 51 | // device. 52 | // 53 | Limit int32 `xml:"http://www.onvif.org/ver10/schema Limit,omitempty"` 54 | 55 | // Start returning entries from this start reference. If not specified, 56 | // entries shall start from the beginning of the dataset. 57 | // 58 | StartReference string `xml:"http://www.onvif.org/ver10/accessrules/wsdl StartReference,omitempty"` 59 | } 60 | 61 | // GetAccessProfileInfoListResponse type 62 | type GetAccessProfileInfoListResponse struct { 63 | XMLName xml.Name `xml:"GetAccessProfileInfoListResponse"` 64 | 65 | // StartReference to use in next call to get the following items. If 66 | // absent, no more items to get. 67 | // 68 | NextStartReference string `xml:"NextStartReference,omitempty"` 69 | 70 | // List of AccessProfileInfo items. 71 | AccessProfileInfo []AccessProfileInfo `xml:"AccessProfileInfo,omitempty"` 72 | } 73 | 74 | // GetAccessProfiles type 75 | type GetAccessProfiles struct { 76 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl GetAccessProfiles"` 77 | 78 | // Tokens of AccessProfile items to get. 79 | Token []ReferenceToken `xml:"http://www.onvif.org/ver10/accessrules/wsdl Token,omitempty"` 80 | } 81 | 82 | // GetAccessProfilesResponse type 83 | type GetAccessProfilesResponse struct { 84 | XMLName xml.Name `xml:"GetAccessProfilesResponse"` 85 | 86 | // List of Access Profile items. 87 | AccessProfile []AccessProfile `xml:"AccessProfile,omitempty"` 88 | } 89 | 90 | // GetAccessProfileList type 91 | type GetAccessProfileList struct { 92 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl GetAccessProfileList"` 93 | 94 | // Maximum number of entries to return. If not specified, less than one 95 | // or higher than what the device supports, the number of items is determined by the 96 | // device. 97 | // 98 | Limit int32 `xml:"http://www.onvif.org/ver10/schema Limit,omitempty"` 99 | 100 | // Start returning entries from this start reference. If not specified, 101 | // entries shall start from the beginning of the dataset. 102 | // 103 | StartReference string `xml:"http://www.onvif.org/ver10/accessrules/wsdl StartReference,omitempty"` 104 | } 105 | 106 | // GetAccessProfileListResponse type 107 | type GetAccessProfileListResponse struct { 108 | XMLName xml.Name `xml:"GetAccessProfileListResponse"` 109 | 110 | // StartReference to use in next call to get the following items. If 111 | // absent, no more items to get. 112 | // 113 | NextStartReference string `xml:"NextStartReference,omitempty"` 114 | 115 | // List of Access Profile items. 116 | AccessProfile []AccessProfile `xml:"AccessProfile,omitempty"` 117 | } 118 | 119 | // CreateAccessProfile type 120 | type CreateAccessProfile struct { 121 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl CreateAccessProfile"` 122 | 123 | // The AccessProfile to create. 124 | AccessProfile AccessProfile `xml:"http://www.onvif.org/ver10/accessrules/wsdl AccessProfile,omitempty"` 125 | } 126 | 127 | // CreateAccessProfileResponse type 128 | type CreateAccessProfileResponse struct { 129 | XMLName xml.Name `xml:"CreateAccessProfileResponse"` 130 | 131 | // The Token of created AccessProfile. 132 | Token ReferenceToken `xml:"Token,omitempty"` 133 | } 134 | 135 | // ModifyAccessProfile type 136 | type ModifyAccessProfile struct { 137 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl ModifyAccessProfile"` 138 | 139 | // The details of Access Profile 140 | AccessProfile AccessProfile `xml:"http://www.onvif.org/ver10/accessrules/wsdl AccessProfile,omitempty"` 141 | } 142 | 143 | // ModifyAccessProfileResponse type 144 | type ModifyAccessProfileResponse struct { 145 | XMLName xml.Name `xml:"ModifyAccessProfileResponse"` 146 | } 147 | 148 | // SetAccessProfile type 149 | type SetAccessProfile struct { 150 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl SetAccessProfile"` 151 | 152 | // The AccessProfile item to create or modify 153 | AccessProfile AccessProfile `xml:"http://www.onvif.org/ver10/accessrules/wsdl AccessProfile,omitempty"` 154 | } 155 | 156 | // SetAccessProfileResponse type 157 | type SetAccessProfileResponse struct { 158 | XMLName xml.Name `xml:"SetAccessProfileResponse"` 159 | } 160 | 161 | // DeleteAccessProfile type 162 | type DeleteAccessProfile struct { 163 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl DeleteAccessProfile"` 164 | 165 | // The token of the access profile to delete. 166 | Token ReferenceToken `xml:"http://www.onvif.org/ver10/accessrules/wsdl Token,omitempty"` 167 | } 168 | 169 | // DeleteAccessProfileResponse type 170 | type DeleteAccessProfileResponse struct { 171 | XMLName xml.Name `xml:"DeleteAccessProfileResponse"` 172 | } 173 | 174 | // ServiceCapabilities type 175 | type ServiceCapabilities struct { 176 | XMLName xml.Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl Capabilities"` 177 | 178 | // 179 | // The maximum number of entries returned by a single GetList or Get 180 | // request. The device shall never return more than this number of entities in a single 181 | // response. 182 | // 183 | 184 | MaxLimit uint32 `xml:"http://www.onvif.org/ver10/schema MaxLimit,attr,omitempty"` 185 | 186 | // 187 | // Indicates the maximum number of access profiles supported by the device. 188 | // 189 | 190 | MaxAccessProfiles uint32 `xml:"http://www.onvif.org/ver10/schema MaxAccessProfiles,attr,omitempty"` 191 | 192 | // 193 | // Indicates the maximum number of access policies per access profile supported by the device. 194 | // 195 | 196 | MaxAccessPoliciesPerAccessProfile uint32 `xml:"http://www.onvif.org/ver10/schema MaxAccessPoliciesPerAccessProfile,attr,omitempty"` 197 | 198 | // 199 | // Indicates whether or not several access policies can refer to the same access point in an 200 | // access profile. 201 | // 202 | 203 | MultipleSchedulesPerAccessPointSupported bool `xml:"http://www.onvif.org/ver10/accessrules/wsdl MultipleSchedulesPerAccessPointSupported,attr,omitempty"` 204 | 205 | // 206 | // Indicates that the client is allowed to supply the token when creating access profiles. To 207 | // enable the use of the command SetAccessProfile, the value must be set to true. 208 | // 209 | 210 | ClientSuppliedTokenSupported bool `xml:"http://www.onvif.org/ver10/accessrules/wsdl ClientSuppliedTokenSupported,attr,omitempty"` 211 | } 212 | 213 | // AccessPolicy type 214 | type AccessPolicy struct { 215 | 216 | // Reference to the schedule used by the access policy. 217 | ScheduleToken ReferenceToken `xml:"http://www.onvif.org/ver10/accessrules/wsdl ScheduleToken,omitempty"` 218 | 219 | // 220 | // Reference to the entity used by the rule engine, the entity type may be specified by the 221 | // optional EntityType field explained below but is typically an access point. 222 | // 223 | Entity ReferenceToken `xml:"http://www.onvif.org/ver10/accessrules/wsdl Entity,omitempty"` 224 | 225 | // 226 | // Optional entity type; if missing, an access point type as defined by the ONVIF Access 227 | // Control Service Specification should be assumed. This can also be represented by the 228 | // QName value “tac:AccessPoint” where tac is the namespace of ONVIF Access Control 229 | // Service Specification. This field is provided for future extensions; it will allow an 230 | // access policy being extended to cover entity types other than access points as well. 231 | // 232 | EntityType QName `xml:"http://www.onvif.org/ver10/accessrules/wsdl EntityType,omitempty"` 233 | 234 | Extension AccessPolicyExtension `xml:"http://www.onvif.org/ver10/accessrules/wsdl Extension,omitempty"` 235 | } 236 | 237 | // AccessPolicyExtension type 238 | type AccessPolicyExtension struct { 239 | } 240 | 241 | // AccessProfileInfo type 242 | type AccessProfileInfo struct { 243 | *DataEntity 244 | 245 | // A user readable name. It shall be up to 64 characters. 246 | // 247 | Name Name `xml:"http://www.onvif.org/ver10/accessrules/wsdl Name,omitempty"` 248 | 249 | // User readable description for the access profile. It shall be up 250 | // to 1024 characters. 251 | // 252 | Description Description `xml:"http://www.onvif.org/ver10/accessrules/wsdl Description,omitempty"` 253 | } 254 | 255 | // AccessProfile type 256 | type AccessProfile struct { 257 | *AccessProfileInfo 258 | 259 | // A list of access policy structures, where each access policy 260 | // defines during which schedule an access point can be accessed. 261 | // 262 | AccessPolicy []AccessPolicy `xml:"http://www.onvif.org/ver10/accessrules/wsdl AccessPolicy,omitempty"` 263 | 264 | Extension AccessProfileExtension `xml:"http://www.onvif.org/ver10/accessrules/wsdl Extension,omitempty"` 265 | } 266 | 267 | // AccessProfileExtension type 268 | type AccessProfileExtension struct { 269 | } 270 | 271 | // Type used to reference logical and physical entities. 272 | 273 | // ReferenceToken type 274 | type ReferenceToken string 275 | 276 | // Type used for names of logical and physical entities. 277 | 278 | // Name type 279 | type Name string 280 | 281 | // Description is optional and the maximum length is device specific. 282 | // If the length is more than maximum length, it is silently chopped to the maximum length 283 | // supported by the device/service (which may be 0). 284 | // 285 | 286 | // Description type 287 | type Description string 288 | 289 | // Type used to represent the numbers from 1 ,2 , 3,... 290 | 291 | // DataEntity type 292 | type DataEntity struct { 293 | 294 | // A service-unique identifier of the item. 295 | 296 | Token ReferenceToken `xml:"token,attr,omitempty"` 297 | } 298 | 299 | // AccessRulesPort type 300 | type AccessRulesPort interface { 301 | 302 | /* This operation returns the capabilities of the access rules service. 303 | */ 304 | GetServiceCapabilities(request *GetServiceCapabilities) (*GetServiceCapabilitiesResponse, error) 305 | 306 | GetServiceCapabilitiesContext(ctx context.Context, request *GetServiceCapabilities) (*GetServiceCapabilitiesResponse, error) 307 | 308 | /* 309 | This operation requests a list of AccessProfileInfo items matching the given tokens. The device shall 310 | ignore tokens it cannot resolve and shall return an empty list if there are no items matching the 311 | specified tokens. The device shall not return a fault in this case. 312 | If the number of requested items is greater than MaxLimit, a TooManyItems fault shall be returned. 313 | */ 314 | GetAccessProfileInfo(request *GetAccessProfileInfo) (*GetAccessProfileInfoResponse, error) 315 | 316 | GetAccessProfileInfoContext(ctx context.Context, request *GetAccessProfileInfo) (*GetAccessProfileInfoResponse, error) 317 | 318 | /* 319 | This operation requests a list of all of AccessProfileInfo items provided by the device. 320 | A call to this method shall return a StartReference when not all data is returned and more data is 321 | available. The reference shall be valid for retrieving the next set of data. 322 | The number of items returned shall not be greater than the Limit parameter. 323 | */ 324 | GetAccessProfileInfoList(request *GetAccessProfileInfoList) (*GetAccessProfileInfoListResponse, error) 325 | 326 | GetAccessProfileInfoListContext(ctx context.Context, request *GetAccessProfileInfoList) (*GetAccessProfileInfoListResponse, error) 327 | 328 | /* 329 | This operation returns the specified access profile item matching the given tokens. 330 | The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items 331 | matching specified tokens. The device shall not return a fault in this case. 332 | If the number of requested items is greater than MaxLimit, a TooManyItems fault shall be returned. 333 | */ 334 | GetAccessProfiles(request *GetAccessProfiles) (*GetAccessProfilesResponse, error) 335 | 336 | GetAccessProfilesContext(ctx context.Context, request *GetAccessProfiles) (*GetAccessProfilesResponse, error) 337 | 338 | /* 339 | This operation requests a list of all of access profile items provided by the device. 340 | A call to this method shall return a StartReference when not all data is returned and more data is 341 | available. The reference shall be valid for retrieving the next set of data. 342 | The number of items returned shall not be greater than the Limit parameter. 343 | */ 344 | GetAccessProfileList(request *GetAccessProfileList) (*GetAccessProfileListResponse, error) 345 | 346 | GetAccessProfileListContext(ctx context.Context, request *GetAccessProfileList) (*GetAccessProfileListResponse, error) 347 | 348 | /* 349 | This operation creates the specified access profile in the device. The token field of the access profile shall be 350 | empty, the service shall allocate a token for the access profile. The allocated token shall be returned 351 | in the response. If the client sends any value in the token field, the device shall return InvalidArgVal 352 | as generic fault code. 353 | In an access profile, if several access policies specifying different schedules for the same access 354 | point will result in a union of the schedules. 355 | */ 356 | CreateAccessProfile(request *CreateAccessProfile) (*CreateAccessProfileResponse, error) 357 | 358 | CreateAccessProfileContext(ctx context.Context, request *CreateAccessProfile) (*CreateAccessProfileResponse, error) 359 | 360 | /* 361 | This operation will modify the access profile for the specified access profile token. The token of the 362 | access profile to modify is specified in the token field of the AccessProile structure and shall not 363 | be empty. All other fields in the structure shall overwrite the fields in the specified access profile. 364 | If several access policies specifying different schedules for the same access point will result in a 365 | union of the schedules. 366 | If the device could not store the access profile information then a fault will be generated. 367 | */ 368 | ModifyAccessProfile(request *ModifyAccessProfile) (*ModifyAccessProfileResponse, error) 369 | 370 | ModifyAccessProfileContext(ctx context.Context, request *ModifyAccessProfile) (*ModifyAccessProfileResponse, error) 371 | 372 | /* 373 | This operation will synchronize an access profile in a client with the device. 374 | If an access profile with the specified token does not exist in the device, the access profile is 375 | created. If an access profile with the specified token exists, then the access profile is modified. 376 | A call to this method takes an access profile structure as input parameter. The token field of the 377 | access profile must not be empty. 378 | A device that signals support for the ClientSuppliedTokenSupported capability shall implement this command. 379 | */ 380 | SetAccessProfile(request *SetAccessProfile) (*SetAccessProfileResponse, error) 381 | 382 | SetAccessProfileContext(ctx context.Context, request *SetAccessProfile) (*SetAccessProfileResponse, error) 383 | 384 | /* 385 | This operation will delete the specified access profile. 386 | If the access profile is deleted, all access policies associated to the access profile will also be 387 | deleted. 388 | If it is associated with one or more entities some devices may not be able to delete the access profile, 389 | and consequently a ReferenceInUse fault shall be generated. 390 | */ 391 | DeleteAccessProfile(request *DeleteAccessProfile) (*DeleteAccessProfileResponse, error) 392 | 393 | DeleteAccessProfileContext(ctx context.Context, request *DeleteAccessProfile) (*DeleteAccessProfileResponse, error) 394 | } 395 | 396 | // accessRulesPort type 397 | type accessRulesPort struct { 398 | client *soap.Client 399 | xaddr string 400 | } 401 | 402 | func NewAccessRulesPort(client *soap.Client, xaddr string) AccessRulesPort { 403 | return &accessRulesPort{ 404 | client: client, 405 | xaddr: xaddr, 406 | } 407 | } 408 | 409 | func (service *accessRulesPort) GetServiceCapabilitiesContext(ctx context.Context, request *GetServiceCapabilities) (*GetServiceCapabilitiesResponse, error) { 410 | response := new(GetServiceCapabilitiesResponse) 411 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/GetServiceCapabilities", request, response) 412 | if err != nil { 413 | return nil, err 414 | } 415 | 416 | return response, nil 417 | } 418 | 419 | func (service *accessRulesPort) GetServiceCapabilities(request *GetServiceCapabilities) (*GetServiceCapabilitiesResponse, error) { 420 | return service.GetServiceCapabilitiesContext( 421 | context.Background(), 422 | request, 423 | ) 424 | } 425 | 426 | func (service *accessRulesPort) GetAccessProfileInfoContext(ctx context.Context, request *GetAccessProfileInfo) (*GetAccessProfileInfoResponse, error) { 427 | response := new(GetAccessProfileInfoResponse) 428 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/GetAccessProfileInfo", request, response) 429 | if err != nil { 430 | return nil, err 431 | } 432 | 433 | return response, nil 434 | } 435 | 436 | func (service *accessRulesPort) GetAccessProfileInfo(request *GetAccessProfileInfo) (*GetAccessProfileInfoResponse, error) { 437 | return service.GetAccessProfileInfoContext( 438 | context.Background(), 439 | request, 440 | ) 441 | } 442 | 443 | func (service *accessRulesPort) GetAccessProfileInfoListContext(ctx context.Context, request *GetAccessProfileInfoList) (*GetAccessProfileInfoListResponse, error) { 444 | response := new(GetAccessProfileInfoListResponse) 445 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/GetAccessProfileInfoList", request, response) 446 | if err != nil { 447 | return nil, err 448 | } 449 | 450 | return response, nil 451 | } 452 | 453 | func (service *accessRulesPort) GetAccessProfileInfoList(request *GetAccessProfileInfoList) (*GetAccessProfileInfoListResponse, error) { 454 | return service.GetAccessProfileInfoListContext( 455 | context.Background(), 456 | request, 457 | ) 458 | } 459 | 460 | func (service *accessRulesPort) GetAccessProfilesContext(ctx context.Context, request *GetAccessProfiles) (*GetAccessProfilesResponse, error) { 461 | response := new(GetAccessProfilesResponse) 462 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/GetAccessProfiles", request, response) 463 | if err != nil { 464 | return nil, err 465 | } 466 | 467 | return response, nil 468 | } 469 | 470 | func (service *accessRulesPort) GetAccessProfiles(request *GetAccessProfiles) (*GetAccessProfilesResponse, error) { 471 | return service.GetAccessProfilesContext( 472 | context.Background(), 473 | request, 474 | ) 475 | } 476 | 477 | func (service *accessRulesPort) GetAccessProfileListContext(ctx context.Context, request *GetAccessProfileList) (*GetAccessProfileListResponse, error) { 478 | response := new(GetAccessProfileListResponse) 479 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/GetAccessProfileList", request, response) 480 | if err != nil { 481 | return nil, err 482 | } 483 | 484 | return response, nil 485 | } 486 | 487 | func (service *accessRulesPort) GetAccessProfileList(request *GetAccessProfileList) (*GetAccessProfileListResponse, error) { 488 | return service.GetAccessProfileListContext( 489 | context.Background(), 490 | request, 491 | ) 492 | } 493 | 494 | func (service *accessRulesPort) CreateAccessProfileContext(ctx context.Context, request *CreateAccessProfile) (*CreateAccessProfileResponse, error) { 495 | response := new(CreateAccessProfileResponse) 496 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/CreateAccessProfile", request, response) 497 | if err != nil { 498 | return nil, err 499 | } 500 | 501 | return response, nil 502 | } 503 | 504 | func (service *accessRulesPort) CreateAccessProfile(request *CreateAccessProfile) (*CreateAccessProfileResponse, error) { 505 | return service.CreateAccessProfileContext( 506 | context.Background(), 507 | request, 508 | ) 509 | } 510 | 511 | func (service *accessRulesPort) ModifyAccessProfileContext(ctx context.Context, request *ModifyAccessProfile) (*ModifyAccessProfileResponse, error) { 512 | response := new(ModifyAccessProfileResponse) 513 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/ModifyAccessProfile", request, response) 514 | if err != nil { 515 | return nil, err 516 | } 517 | 518 | return response, nil 519 | } 520 | 521 | func (service *accessRulesPort) ModifyAccessProfile(request *ModifyAccessProfile) (*ModifyAccessProfileResponse, error) { 522 | return service.ModifyAccessProfileContext( 523 | context.Background(), 524 | request, 525 | ) 526 | } 527 | 528 | func (service *accessRulesPort) SetAccessProfileContext(ctx context.Context, request *SetAccessProfile) (*SetAccessProfileResponse, error) { 529 | response := new(SetAccessProfileResponse) 530 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/SetAccessProfile", request, response) 531 | if err != nil { 532 | return nil, err 533 | } 534 | 535 | return response, nil 536 | } 537 | 538 | func (service *accessRulesPort) SetAccessProfile(request *SetAccessProfile) (*SetAccessProfileResponse, error) { 539 | return service.SetAccessProfileContext( 540 | context.Background(), 541 | request, 542 | ) 543 | } 544 | 545 | func (service *accessRulesPort) DeleteAccessProfileContext(ctx context.Context, request *DeleteAccessProfile) (*DeleteAccessProfileResponse, error) { 546 | response := new(DeleteAccessProfileResponse) 547 | err := service.client.CallContext(ctx, service.xaddr, "http://www.onvif.org/ver10/accessrules/wsdl/DeleteAccessProfile", request, response) 548 | if err != nil { 549 | return nil, err 550 | } 551 | 552 | return response, nil 553 | } 554 | 555 | func (service *accessRulesPort) DeleteAccessProfile(request *DeleteAccessProfile) (*DeleteAccessProfileResponse, error) { 556 | return service.DeleteAccessProfileContext( 557 | context.Background(), 558 | request, 559 | ) 560 | } 561 | 562 | // QName type 563 | type QName string 564 | -------------------------------------------------------------------------------- /wsdl/display.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | The capabilities for the display service is returned in the Capabilities element. 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Indication that the SetLayout command supports only predefined layouts. 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Token of the Video Output whose Layout is requested 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Current layout of the video output. 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | Token of the Video Output whose Layout shall be changed. 74 | 75 | 76 | 77 | 78 | Layout to be set 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Token of the Video Output whose options are requested 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | The LayoutOptions describe the fixed and predefined layouts of a device. If the device does 113 | not offer fixed layouts and allows setting the layout free this element is empty. 114 | 115 | 116 | 117 | 118 | decoding and encoding capabilities of the device 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | Reference Token of the Video Output whose Pane Configurations are requested 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | Contains a list of defined Panes of the specified VideoOutput. Each VideoOutput has at least one PaneConfiguration. 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | Reference Token of the Video Output the requested pane belongs to 157 | 158 | 159 | 160 | 161 | Reference Token of the Pane whose Configuration is requested 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | returns the configuration of the requested pane. 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | Token of the video output whose panes to set. 188 | 189 | 190 | 191 | 192 | Pane Configuration to be set. 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | Token of the video output whose panes to set. 213 | 214 | 215 | 216 | 217 | Pane Configuration to be set. 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | Token of the video output where the pane shall be created. 239 | 240 | 241 | 242 | 243 | Configuration of the pane to be created. 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | Token of the new pane configuration. 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | Token of the video output where the pane shall be deleted. 270 | 271 | 272 | 273 | 274 | Token of the pane to be deleted. 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | Returns the capabilities of the display service. The result is returned in a typed answer. 354 | 355 | 356 | 357 | 358 | Return the current layout of a video output. The Layout assigns a pane configuration to a certain area of the display. The layout settings 359 | directly affect a specific video output. The layout consists of a list of PaneConfigurations and 360 | their associated display areas. 361 | 362 | 363 | 364 | 365 | Change the layout of a display (e.g. change from 366 | single view to split screen view).The Layout assigns a pane configuration to a certain area of the display. The layout settings 367 | directly affect a specific video output. The layout consists of a list of PaneConfigurations and 368 | their associated display areas.
369 | A device implementation shall be tolerant against rounding errors when matching a layout against its fixed set of layouts by accepting differences of at least one percent. 370 |
371 | 372 | 373 |
374 | 375 | The Display Options contain the supported layouts (LayoutOptions) and the decoding and 376 | encoding capabilities (CodingCapabilities) of the device. The GetDisplayOptions command 377 | returns both, Layout and Coding Capabilities, of a VideoOutput. 378 | 379 | 380 | 381 | 382 | List all currently defined panes of a device for a specified video output 383 | (regardless if this pane is visible at a moment). A Pane is a display area on the monitor that is attached to a video output. A pane has a 384 | PaneConfiguration that describes which entities are associated with the pane. A client has to configure the pane according to the connection to be established by setting the 385 | AudioOutput and/or AudioSourceToken. If a Token is not set, the corresponding session will 386 | not be established. 387 | 388 | 389 | 390 | 391 | Retrieve the pane configuration for a pane token. 392 | 393 | 394 | 395 | 396 | Modify one or more configurations of the specified video output. 397 | This method will only modify the provided configurations and leave the others unchanged. 398 | Use DeletePaneConfiguration to remove pane configurations. 399 | 400 | 401 | 402 | 403 | This command changes the configuration of the specified pane (tbd) 404 | 405 | 406 | 407 | 408 | Create a new pane configuration describing the streaming and coding settings for a display area.
409 | This optional method is only supported by devices that signal support of dynamic pane creation via their capabilities.
410 | The content of the Token field may be ignored by the device. 411 |
412 | 413 | 414 |
415 | 416 | Delete a pane configuration. A service must respond with an error if the pane configuration 417 | is in use by the current layout.
418 | This optional method is only supported by devices that signal support of dynamic pane creation via their capabilities. 419 |
420 | 421 | 422 |
423 |
424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 |
518 | -------------------------------------------------------------------------------- /wsdl/provisioning.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | The direction for PanMove to move the device. 21 | 22 | 23 | 24 | 25 | Move left in relation to the video source image. 26 | 27 | 28 | 29 | 30 | Move right in relation to the video source image. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | The direction for TiltMove to move the device. 39 | 40 | 41 | 42 | 43 | Move up in relation to the video source image. 44 | 45 | 46 | 47 | 48 | Move down in relation to the video source image. 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | The direction for ZoomMove to change the focal length in relation to the video source. 57 | 58 | 59 | 60 | 61 | Move video source lens toward a wider field of view. 62 | 63 | 64 | 65 | 66 | Move video source lens toward a narrower field of view. 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | The direction for RollMove to move the device. 75 | 76 | 77 | 78 | 79 | Move clockwise in relation to the video source image. 80 | 81 | 82 | 83 | 84 | Move counterclockwise in relation to the video source image. 85 | 86 | 87 | 88 | 89 | Automatically level the device in relation to the video source image. 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | The direction for FocusMove to move the focal plane in relation to the video source. 98 | 99 | 100 | 101 | 102 | Move to focus on close objects. 103 | 104 | 105 | 106 | 107 | Move to focus on distant objects. 108 | 109 | 110 | 111 | 112 | Automatically focus for the sharpest video source image. 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | The quantity of movement events that have occured over the lifetime of the device. 121 | 122 | 123 | 124 | 125 | The quantity of pan movement events over the life of the device. 126 | 127 | 128 | 129 | 130 | The quantity of tilt movement events over the life of the device. 131 | 132 | 133 | 134 | 135 | The quantity of zoom movement events over the life of the device. 136 | 137 | 138 | 139 | 140 | The quantity of roll movement events over the life of the device. 141 | 142 | 143 | 144 | 145 | The quantity of focus movement events over the life of the device. 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | The provisioning capabilities of a video source on the device. 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | Unique identifier of a video source. 165 | 166 | 167 | 168 | 169 | Lifetime limit of pan moves for this video source. Presence of this attribute indicates support of pan move. 170 | 171 | 172 | 173 | 174 | Lifetime limit of tilt moves for this video source. Presence of this attribute indicates support of tilt move. 175 | 176 | 177 | 178 | 179 | Lifetime limit of zoom moves for this video source. Presence of this attribute indicates support of zoom move. 180 | 181 | 182 | 183 | 184 | Lifetime limit of roll moves for this video source. Presence of this attribute indicates support of roll move. 185 | 186 | 187 | 188 | 189 | Indicates "auto" as a valid enum for Direction in RollMove. 190 | 191 | 192 | 193 | 194 | Lifetime limit of focus moves for this video source. Presence of this attribute indicates support of focus move. 195 | 196 | 197 | 198 | 199 | Indicates "auto" as a valid enum for Direction in FocusMove. 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | The capabilities of Provisioning Service on the device. 208 | 209 | 210 | 211 | 212 | Maximum time before stopping movement after a move operation. 213 | 214 | 215 | 216 | 217 | Capabilities per video source. 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | The capabilities for the provisioning service on this device. 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | The video source associated with the provisioning. 252 | 253 | 254 | 255 | 256 | "left" or "right". 257 | 258 | 259 | 260 | 261 | "Operation timeout, if less than default timeout. 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | The video source associated with the provisioning. 279 | 280 | 281 | 282 | 283 | "up" or "down". 284 | 285 | 286 | 287 | 288 | "Operation timeout, if less than default timeout. 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | The video source associated with the provisioning. 306 | 307 | 308 | 309 | 310 | "wide" or "telephoto". 311 | 312 | 313 | 314 | 315 | "Operation timeout, if less than default timeout. 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | The video source associated with the provisioning. 333 | 334 | 335 | 336 | 337 | "clockwise", "counterclockwise", or "auto". 338 | 339 | 340 | 341 | 342 | "Operation timeout, if less than default timeout. 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | The video source associated with the provisioning. 360 | 361 | 362 | 363 | 364 | "near", "far", or "auto". 365 | 366 | 367 | 368 | 369 | "Operation timeout, if less than default timeout. 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | The video source associated with the provisioning. 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | The video source associated with the provisioning. 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | The set of lifetime usage values for the provisioning associated with the video source. 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | Functionality for all provisioning service operations. 472 | 473 | Returns the capabilities of the provisioning service. 474 | 475 | 476 | 477 | 478 | Moves device on the pan axis. 479 | 480 | 481 | 482 | 483 | Moves device on the tilt axis. 484 | 485 | 486 | 487 | 488 | Moves device on the zoom axis. 489 | 490 | 491 | 492 | 493 | Moves device on the roll axis. 494 | 495 | 496 | 497 | 498 | Moves device on the focus axis. 499 | 500 | 501 | 502 | 503 | Stops device motion on all axes. 504 | 505 | 506 | 507 | 508 | Returns the lifetime move counts. 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | -------------------------------------------------------------------------------- /wsdl/imaging.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | The capabilities for the imaging service is returned in the Capabilities element. 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Indicates whether or not Image Stabilization feature is supported. 41 | The use of this capability is deprecated, a client should use GetOption to find out if image stabilization is supported. 42 | 43 | 44 | 45 | 46 | Indicates whether or not Imaging Presets feature is supported. 47 | 48 | 49 | 50 | 51 | Indicates whether or not imaging preset settings can be updated. 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Reference token to the VideoSource for which the ImagingSettings. 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | ImagingSettings for the VideoSource that was requested. 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 | Reference token to the VideoSource for which the imaging parameter options are requested. 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | Valid ranges for the imaging parameters that are categorized as device specific. 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | Reference to the VideoSource for the requested move (focus) operation. 132 | 133 | 134 | 135 | 136 | 137 | 138 | Content of the requested move (focus) operation. 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | Reference token to the VideoSource for the requested move options. 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | Valid ranges for the focus lens move options. 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | Reference token to the VideoSource where the focus movement should be stopped. 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | Reference token to the VideoSource where the imaging status should be requested. 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | Requested imaging status. 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | Describes standard Imaging Preset types, used to facilitate Multi-language support and client display. 228 | "Custom" Type shall be used when Imaging Preset Name does not match any of the types included in the standard classification. 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | Type describing the Imaging Preset settings. 261 | 262 | 263 | 264 | 265 | Human readable name of the Imaging Preset. 266 | 267 | 268 | 269 | 270 | 271 | Unique identifier of this Imaging Preset. 272 | 273 | 274 | 275 | 276 | Indicates Imaging Preset Type. Use timg:ImagingPresetType. 277 | Used for multi-language support and display. 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | A reference to the VideoSource where the operation should take place. 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | List of Imaging Presets which are available for the requested VideoSource. 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | Reference token to the VideoSource where the current Imaging Preset should be requested. 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | Current Imaging Preset in use for the specified Video Source. 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | Reference token to the VideoSource to which the specified Imaging Preset should be applied. 340 | 341 | 342 | 343 | 344 | 345 | Reference token to the Imaging Preset to be applied to the specified Video Source. 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | Returns the capabilities of the imaging service. The result is returned in a typed answer. 428 | 429 | 430 | 431 | 432 | Get the ImagingConfiguration for the requested VideoSource. 433 | 434 | 435 | 436 | 437 | Set the ImagingConfiguration for the requested VideoSource. 438 | 439 | 440 | 441 | 442 | This operation gets the valid ranges for the imaging parameters that have device specific ranges. 443 | This command is mandatory for all device implementing the imaging service. The command returns all supported parameters and their ranges 444 | such that these can be applied to the SetImagingSettings command.
445 | For read-only parameters which cannot be modified via the SetImagingSettings command only a single option or identical Min and Max values 446 | is provided.
447 | 448 | 449 |
450 | 451 | The Move command moves the focus lens in an absolute, a relative or in a continuous manner from its current position. 452 | The speed argument is optional for absolute and relative control, but required for continuous. If no speed argument is used, the default speed is used. 453 | Focus adjustments through this operation will turn off the autofocus. A device with support for remote focus control should support absolute, 454 | relative or continuous control through the Move operation. The supported MoveOpions are signalled via the GetMoveOptions command. 455 | At least one focus control capability is required for this operation to be functional.
456 | The move operation contains the following commands:
457 | Absolute – Requires position parameter and optionally takes a speed argument. A unitless type is used by default for focus positioning and speed. Optionally, if supported, the position may be requested in m-1 units.
458 | Relative – Requires distance parameter and optionally takes a speed argument. Negative distance means negative direction. 459 | Continuous – Requires a speed argument. Negative speed argument means negative direction. 460 |
461 | 462 | 463 |
464 | 465 | Imaging move operation options supported for the Video source. 466 | 467 | 468 | 469 | 470 | The Stop command stops all ongoing focus movements of the lense. A device with support for remote focus control as signalled via 471 | the GetMoveOptions supports this command.
The operation will not affect ongoing autofocus operation.
472 | 473 | 474 |
475 | 476 | Via this command the current status of the Move operation can be requested. Supported for this command is available if the support for the Move operation is signalled via GetMoveOptions. 477 | 478 | 479 | 480 | 481 | Via this command the list of available Imaging Presets can be requested. 482 | 483 | 484 | 485 | 486 | Via this command the last Imaging Preset applied can be requested. 487 | If the camera configuration does not match any of the existing Imaging Presets, the output of GetCurrentPreset shall be Empty. 488 | GetCurrentPreset shall return 0 if Imaging Presets are not supported by the Video Source. 489 | 490 | 491 | 492 | 493 | The SetCurrentPreset command shall request a given Imaging Preset to be applied to the specified Video Source. 494 | SetCurrentPreset shall only be available for Video Sources with Imaging Presets Capability. 495 | Imaging Presets are defined by the Manufacturer, and offered as a tool to simplify Imaging Settings adjustments for specific scene content. 496 | When the new Imaging Preset is applied by SetCurrentPreset, the Device shall adjust the Video Source settings to match those defined by the specified Imaging Preset. 497 | 498 | 499 | 500 |
501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 |
604 | --------------------------------------------------------------------------------