├── .gitignore ├── LICENSE ├── README.md ├── device ├── device.wsdl └── types.go ├── deviceService.go ├── events ├── addressing.go ├── events.wsdl └── types.go ├── eventsService.go ├── go.mod ├── go.sum ├── main └── main.go ├── media ├── media.wsdl └── types.go ├── mediaService.go ├── onvif ├── common.xsd ├── itemlist.go ├── message.go ├── onvif.xsd ├── posix_timezone.go └── types.go ├── onvifClient.go ├── onvifdevice.go ├── pullPointSubscription.go ├── soap ├── client.go ├── types.go └── wsSecurity.go └── xsd ├── anytype.go ├── duration.go └── types.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.exe 3 | *.DS_Store 4 | .project 5 | .vscode/ 6 | coverage.out 7 | debug 8 | *.dll 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 faceterteam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # onvif4go 2 | 3 | ``` 4 | device := onvif4go.NewOnvifDevice("192.168.1.1:80") 5 | device.Auth("admin", "1234456") 6 | err := device.Initialize() 7 | ... 8 | ``` 9 | 10 | ``` 11 | deviceInformation, err := device.Device.GetDeviceInformation() 12 | ... 13 | ``` 14 | 15 | ``` 16 | err := device.Media.AddVideoAnalyticsConfiguration("Profile_0", "VideoAnalyticsConfiguration_000") 17 | ... 18 | ``` 19 | 20 | ``` 21 | response := CustomDeviceResponse{} 22 | err := device.Device.Call(CustomDeviceRequest{}, &response) 23 | ... 24 | ``` 25 | 26 | ``` 27 | response := trt.GetProfilesResponse{} 28 | media, ok := device.On("media") 29 | err := media.Call(trt.GetProfiles{}, &response) 30 | ... 31 | ``` 32 | 33 | ``` 34 | response := xsd.AnyType{} 35 | analytics, _ := device.On("analytics") 36 | err = analytics.Call(xsd.AnyType{ 37 | XMLName: xml.Name{"http://www.onvif.org/ver20/analytics/wsdl", "GetSupportedAnalyticsModules"}, 38 | Childs: []xsd.AnyType{ 39 | xsd.AnyType{ 40 | XMLName: xml.Name{"http://www.onvif.org/ver20/analytics/wsdl", "ConfigurationToken"}, 41 | Text: "VideoAnalyticsConfiguration_000", 42 | }, 43 | }, 44 | }, &response) 45 | ``` -------------------------------------------------------------------------------- /device/types.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/faceterteam/onvif4go/onvif" 7 | "github.com/faceterteam/onvif4go/xsd" 8 | ) 9 | 10 | type Service struct { 11 | Namespace xsd.AnyURI 12 | XAddr xsd.AnyURI 13 | Capabilities 14 | Version onvif.OnvifVersion 15 | } 16 | 17 | type Capabilities struct { 18 | Any string 19 | } 20 | 21 | type DeviceServiceCapabilities struct { 22 | Network NetworkCapabilities 23 | Security SecurityCapabilities 24 | System SystemCapabilities 25 | Misc *MiscCapabilities 26 | } 27 | 28 | type NetworkCapabilities struct { 29 | IPFilter bool `xml:"IPFilter,attr"` 30 | ZeroConfiguration bool `xml:"ZeroConfiguration,attr"` 31 | IPVersion6 bool `xml:"IPVersion6,attr"` 32 | DynDNS bool `xml:"DynDNS,attr"` 33 | Dot11Configuration bool `xml:"Dot11Configuration,attr"` 34 | Dot1XConfigurations int `xml:"Dot1XConfigurations,attr"` 35 | HostnameFromDHCP bool `xml:"HostnameFromDHCP,attr"` 36 | NTP int `xml:"NTP,attr"` 37 | DHCPv6 bool `xml:"DHCPv6,attr"` 38 | } 39 | 40 | type SecurityCapabilities struct { 41 | TLS1_0 bool `xml:"TLS1_0,attr"` 42 | TLS1_1 bool `xml:"TLS1_1,attr"` 43 | TLS1_2 bool `xml:"TLS1_2,attr"` 44 | OnboardKeyGeneration bool `xml:"OnboardKeyGeneration,attr"` 45 | AccessPolicyConfig bool `xml:"AccessPolicyConfig,attr"` 46 | DefaultAccessPolicy bool `xml:"DefaultAccessPolicy,attr"` 47 | Dot1X bool `xml:"Dot1X,attr"` 48 | RemoteUserHandling bool `xml:"RemoteUserHandling,attr"` 49 | X509Token bool `xml:"X_509Token,attr"` 50 | SAMLToken bool `xml:"SAMLToken,attr"` 51 | KerberosToken bool `xml:"KerberosToken,attr"` 52 | UsernameToken bool `xml:"UsernameToken,attr"` 53 | HTTPDigest bool `xml:"HttpDigest,attr"` 54 | RELToken bool `xml:"RELToken,attr"` 55 | SupportedEAPMethods EAPMethodTypes `xml:"SupportedEAPMethods,attr"` 56 | MaxUsers int `xml:"MaxUsers,attr"` 57 | MaxUserNameLength int `xml:"MaxUserNameLength,attr"` 58 | MaxPasswordLength int `xml:"MaxPasswordLength,attr"` 59 | } 60 | 61 | //TODO: 62 | type EAPMethodTypes struct { 63 | Types []int 64 | } 65 | 66 | type SystemCapabilities struct { 67 | DiscoveryResolve bool `xml:"DiscoveryResolve,attr"` 68 | DiscoveryBye bool `xml:"DiscoveryBye,attr"` 69 | RemoteDiscovery bool `xml:"RemoteDiscovery,attr"` 70 | SystemBackup bool `xml:"SystemBackup,attr"` 71 | SystemLogging bool `xml:"SystemLogging,attr"` 72 | FirmwareUpgrade bool `xml:"FirmwareUpgrade,attr"` 73 | HTTPFirmwareUpgrade bool `xml:"HttpFirmwareUpgrade,attr"` 74 | HTTPSystemBackup bool `xml:"HttpSystemBackup,attr"` 75 | HTTPSystemLogging bool `xml:"HttpSystemLogging,attr"` 76 | HTTPSupportInformation bool `xml:"HttpSupportInformation,attr"` 77 | StorageConfiguration bool `xml:"StorageConfiguration,attr"` 78 | MaxStorageConfigurations int `xml:"MaxStorageConfigurations,attr"` 79 | GeoLocationEntries int `xml:"GeoLocationEntries,attr"` 80 | AutoGeo string `xml:"AutoGeo,attr"` 81 | } 82 | 83 | type MiscCapabilities struct { 84 | AuxiliaryCommands onvif.StringAttrList `xml:"AuxiliaryCommands,attr"` 85 | } 86 | 87 | type StorageConfiguration struct { 88 | onvif.DeviceEntity 89 | Data StorageConfigurationData `xml:"http://www.onvif.org/ver10/device/wsdl Data"` 90 | } 91 | 92 | type StorageConfigurationData struct { 93 | Type string `xml:"type,attr"` 94 | LocalPath *xsd.AnyURI `xml:"http://www.onvif.org/ver10/device/wsdl LocalPath"` 95 | StorageURI *xsd.AnyURI `xml:"http://www.onvif.org/ver10/device/wsdl StorageUri"` 96 | User *UserCredential `xml:"http://www.onvif.org/ver10/device/wsdl User"` 97 | Extension *xsd.AnyType `xml:"http://www.onvif.org/ver10/device/wsdl Extension"` 98 | } 99 | 100 | type UserCredential struct { 101 | UserName string `xml:"http://www.onvif.org/ver10/device/wsdl UserName"` 102 | Password *string `xml:"http://www.onvif.org/ver10/device/wsdl Password"` 103 | Extension *xsd.AnyType `xml:"http://www.onvif.org/ver10/device/wsdl Extension"` 104 | } 105 | 106 | type GetServices struct { 107 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetServices"` 108 | IncludeCapability bool `xml:"http://www.onvif.org/ver10/device/wsdl IncludeCapability"` 109 | } 110 | 111 | type GetServicesResponse struct { 112 | Service []Service 113 | } 114 | 115 | type GetServiceCapabilities struct { 116 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetServiceCapabilities"` 117 | } 118 | 119 | type GetServiceCapabilitiesResponse struct { 120 | Capabilities DeviceServiceCapabilities 121 | } 122 | 123 | type GetDeviceInformation struct { 124 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDeviceInformation"` 125 | } 126 | 127 | type GetDeviceInformationResponse struct { 128 | Manufacturer string `xml:"http://www.onvif.org/ver10/device/wsdl Manufacturer"` 129 | Model string `xml:"http://www.onvif.org/ver10/device/wsdl Model"` 130 | FirmwareVersion string `xml:"http://www.onvif.org/ver10/device/wsdl FirmwareVersion"` 131 | SerialNumber string `xml:"http://www.onvif.org/ver10/device/wsdl SerialNumber"` 132 | HardwareID string `xml:"http://www.onvif.org/ver10/device/wsdl HardwareId"` 133 | } 134 | 135 | type SetSystemDateAndTime struct { 136 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetSystemDateAndTime"` 137 | DateTimeType onvif.SetDateTimeType `xml:"http://www.onvif.org/ver10/device/wsdl DateTimeType"` 138 | DaylightSavings bool `xml:"http://www.onvif.org/ver10/device/wsdl DaylightSavings"` 139 | TimeZone *onvif.TimeZone `xml:"http://www.onvif.org/ver10/device/wsdl TimeZone"` 140 | UTCDateTime *onvif.DateTime `xml:"http://www.onvif.org/ver10/device/wsdl UTCDateTime"` 141 | } 142 | 143 | func NewSetSystemDateAndTimeNTP(timeZone string, useDST bool) (s SetSystemDateAndTime, err error) { 144 | if timeZone != "" { 145 | var ns xsd.NormalizedString 146 | ns, err = xsd.NewNormalizedString(timeZone) 147 | if err != nil { 148 | return 149 | } 150 | 151 | var token xsd.Token 152 | token, err = xsd.NewToken(ns) 153 | if err != nil { 154 | return 155 | } 156 | tz := onvif.TimeZone{TZ:token} 157 | s.TimeZone = &tz 158 | } 159 | 160 | s.DaylightSavings = useDST 161 | 162 | s.DateTimeType = onvif.SetDateTimeType("NTP") 163 | 164 | return 165 | } 166 | 167 | func NewSetSystemDateAndTimeManual(datetime time.Time, timeZone string, useDST bool) (s SetSystemDateAndTime, err error) { 168 | if timeZone != "" { 169 | var ns xsd.NormalizedString 170 | ns, err = xsd.NewNormalizedString(timeZone) 171 | if err != nil { 172 | return 173 | } 174 | 175 | var token xsd.Token 176 | token, err = xsd.NewToken(ns) 177 | if err != nil { 178 | return 179 | } 180 | tz := onvif.TimeZone{TZ:token} 181 | s.TimeZone = &tz 182 | } 183 | 184 | dt := onvif.DateTime{ 185 | Time: onvif.Time{ 186 | Hour: datetime.Hour(), 187 | Minute: datetime.Minute(), 188 | Second: datetime.Second(), 189 | }, 190 | Date: onvif.Date{ 191 | Day: datetime.Day(), 192 | Month: int(datetime.Month()), 193 | Year: datetime.Year(), 194 | }, 195 | } 196 | 197 | s.UTCDateTime = &dt 198 | s.DaylightSavings = useDST 199 | 200 | s.DateTimeType = onvif.SetDateTimeType("Manual") 201 | 202 | return 203 | } 204 | 205 | type SetSystemDateAndTimeResponse struct { 206 | } 207 | 208 | type GetSystemDateAndTime struct { 209 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetSystemDateAndTime"` 210 | } 211 | 212 | type GetSystemDateAndTimeResponse struct { 213 | SystemDateAndTime onvif.SystemDateTime 214 | } 215 | 216 | type SetSystemFactoryDefault struct { 217 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetSystemFactoryDefault"` 218 | FactoryDefault onvif.FactoryDefaultType `xml:"http://www.onvif.org/ver10/device/wsdl FactoryDefault"` 219 | } 220 | 221 | type SetSystemFactoryDefaultResponse struct { 222 | } 223 | 224 | type UpgradeSystemFirmware struct { 225 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl UpgradeSystemFirmware"` 226 | Firmware onvif.AttachmentData `xml:"http://www.onvif.org/ver10/device/wsdl Firmware"` 227 | } 228 | 229 | type UpgradeSystemFirmwareResponse struct { 230 | Message string 231 | } 232 | 233 | type SystemReboot struct { 234 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SystemReboot"` 235 | } 236 | 237 | type SystemRebootResponse struct { 238 | Message string 239 | } 240 | 241 | type RestoreSystem struct { 242 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl RestoreSystem"` 243 | BackupFiles []onvif.BackupFile `xml:"http://www.onvif.org/ver10/device/wsdl BackupFiles"` 244 | } 245 | 246 | type RestoreSystemResponse struct { 247 | } 248 | 249 | type GetSystemBackup struct { 250 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetSystemBackup"` 251 | } 252 | 253 | type GetSystemBackupResponse struct { 254 | BackupFiles []onvif.BackupFile 255 | } 256 | 257 | type GetSystemLog struct { 258 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetSystemLog"` 259 | LogType onvif.SystemLogType `xml:"http://www.onvif.org/ver10/device/wsdl LogType"` 260 | } 261 | 262 | type GetSystemLogResponse struct { 263 | SystemLog onvif.SystemLog 264 | } 265 | 266 | type GetSystemSupportInformation struct { 267 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetSystemSupportInformation"` 268 | } 269 | 270 | type GetSystemSupportInformationResponse struct { 271 | SupportInformation onvif.SupportInformation 272 | } 273 | 274 | type GetScopes struct { 275 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetScopes"` 276 | } 277 | 278 | type GetScopesResponse struct { 279 | Scopes []onvif.Scope 280 | } 281 | 282 | type SetScopes struct { 283 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetScopes"` 284 | Scopes []xsd.AnyURI `xml:"http://www.onvif.org/ver10/device/wsdl Scopes"` 285 | } 286 | 287 | type SetScopesResponse struct { 288 | } 289 | 290 | type AddScopes struct { 291 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl AddScopes"` 292 | ScopeItem []xsd.AnyURI `xml:"http://www.onvif.org/ver10/device/wsdl ScopeItem"` 293 | } 294 | 295 | type AddScopesResponse struct { 296 | } 297 | 298 | type RemoveScopes struct { 299 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl RemoveScopes"` 300 | ScopeItem []xsd.AnyURI `xml:"http://www.onvif.org/ver10/schema onvif:ScopeItem"` 301 | } 302 | 303 | type RemoveScopesResponse struct { 304 | ScopeItem []xsd.AnyURI `xml:"http://www.onvif.org/ver10/device/wsdl ScopeItem"` 305 | } 306 | 307 | type GetDiscoveryMode struct { 308 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDiscoveryMode"` 309 | } 310 | 311 | type GetDiscoveryModeResponse struct { 312 | DiscoveryMode onvif.DiscoveryMode 313 | } 314 | 315 | type SetDiscoveryMode struct { 316 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetDiscoveryMode"` 317 | DiscoveryMode onvif.DiscoveryMode `xml:"http://www.onvif.org/ver10/device/wsdl DiscoveryMode"` 318 | } 319 | 320 | type SetDiscoveryModeResponse struct { 321 | } 322 | 323 | type GetRemoteDiscoveryMode struct { 324 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetRemoteDiscoveryMode"` 325 | } 326 | 327 | type GetRemoteDiscoveryModeResponse struct { 328 | RemoteDiscoveryMode onvif.DiscoveryMode 329 | } 330 | 331 | type SetRemoteDiscoveryMode struct { 332 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetRemoteDiscoveryMode"` 333 | RemoteDiscoveryMode onvif.DiscoveryMode `xml:"http://www.onvif.org/ver10/device/wsdl RemoteDiscoveryMode"` 334 | } 335 | 336 | type SetRemoteDiscoveryModeResponse struct { 337 | } 338 | 339 | type GetDPAddresses struct { 340 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDPAddresses"` 341 | } 342 | 343 | type GetDPAddressesResponse struct { 344 | DPAddress []onvif.NetworkHost 345 | } 346 | 347 | type SetDPAddresses struct { 348 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetDPAddresses"` 349 | DPAddress []onvif.NetworkHost `xml:"http://www.onvif.org/ver10/device/wsdl DPAddress"` 350 | } 351 | 352 | type SetDPAddressesResponse struct { 353 | } 354 | 355 | type GetEndpointReference struct { 356 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetEndpointReference"` 357 | } 358 | 359 | type GetEndpointReferenceResponse struct { 360 | GUID string 361 | } 362 | 363 | type GetRemoteUser struct { 364 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetRemoteUser"` 365 | } 366 | 367 | type GetRemoteUserResponse struct { 368 | RemoteUser *onvif.RemoteUser 369 | } 370 | 371 | type SetRemoteUser struct { 372 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetRemoteUser"` 373 | RemoteUser *onvif.RemoteUser `xml:"http://www.onvif.org/ver10/device/wsdl RemoteUser"` 374 | } 375 | 376 | type SetRemoteUserResponse struct { 377 | } 378 | 379 | type GetUsers struct { 380 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetUsers"` 381 | } 382 | 383 | type GetUsersResponse struct { 384 | User []onvif.User 385 | } 386 | 387 | type CreateUsers struct { 388 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl CreateUsers"` 389 | Users []onvif.User `xml:"http://www.onvif.org/ver10/device/wsdl User"` 390 | } 391 | 392 | type CreateUsersResponse struct { 393 | } 394 | 395 | type DeleteUsers struct { 396 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl DeleteUsers"` 397 | Usernames []string `xml:"http://www.onvif.org/ver10/device/wsdl Username"` 398 | } 399 | 400 | type DeleteUsersResponse struct { 401 | } 402 | 403 | type SetUser struct { 404 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetUser"` 405 | Users []onvif.User `xml:"http://www.onvif.org/ver10/device/wsdl User"` 406 | } 407 | 408 | type SetUserResponse struct { 409 | } 410 | 411 | type GetWsdlUrl struct { 412 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetWsdlUrl"` 413 | } 414 | 415 | type GetWsdlUrlResponse struct { 416 | WsdlURL xsd.AnyURI `xml:"http://www.onvif.org/ver10/device/wsdl WsdlUrl"` 417 | } 418 | 419 | type GetCapabilities struct { 420 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetCapabilities"` 421 | Category []onvif.CapabilityCategory `xml:"http://www.onvif.org/ver10/device/wsdl Category"` 422 | } 423 | 424 | type GetCapabilitiesResponse struct { 425 | Capabilities onvif.Capabilities 426 | } 427 | 428 | type GetHostname struct { 429 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetHostname"` 430 | } 431 | 432 | type GetHostnameResponse struct { 433 | HostnameInformation onvif.HostnameInformation 434 | } 435 | 436 | type SetHostname struct { 437 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetHostname"` 438 | Name xsd.Token `xml:"http://www.onvif.org/ver10/device/wsdl Name"` 439 | } 440 | 441 | type SetHostnameResponse struct { 442 | } 443 | 444 | type SetHostnameFromDHCP struct { 445 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetHostnameFromDHCP"` 446 | FromDHCP bool `xml:"http://www.onvif.org/ver10/device/wsdl FromDHCP"` 447 | } 448 | 449 | type SetHostnameFromDHCPResponse struct { 450 | RebootNeeded bool 451 | } 452 | 453 | type GetDNS struct { 454 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDNS"` 455 | } 456 | 457 | type GetDNSResponse struct { 458 | DNSInformation onvif.DNSInformation 459 | } 460 | 461 | type SetDNS struct { 462 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetDNS"` 463 | FromDHCP bool `xml:"http://www.onvif.org/ver10/device/wsdl FromDHCP"` 464 | SearchDomain []xsd.Token `xml:"http://www.onvif.org/ver10/device/wsdl SearchDomain"` 465 | DNSManual []onvif.IPAddress `xml:"http://www.onvif.org/ver10/device/wsdl DNSManual"` 466 | } 467 | 468 | type SetDNSResponse struct { 469 | } 470 | 471 | type GetNTP struct { 472 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetNTP"` 473 | } 474 | 475 | type GetNTPResponse struct { 476 | NTPInformation onvif.NTPInformation 477 | } 478 | 479 | type SetNTP struct { 480 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetNTP"` 481 | FromDHCP bool `xml:"http://www.onvif.org/ver10/device/wsdl FromDHCP"` 482 | NTPManual []onvif.NetworkHost `xml:"http://www.onvif.org/ver10/device/wsdl NTPManual"` 483 | } 484 | 485 | type SetNTPResponse struct { 486 | } 487 | 488 | type GetDynamicDNS struct { 489 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDynamicDNS"` 490 | } 491 | 492 | type GetDynamicDNSResponse struct { 493 | DynamicDNSInformation onvif.DynamicDNSInformation 494 | } 495 | 496 | type SetDynamicDNS struct { 497 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetDynamicDNS"` 498 | Type onvif.DynamicDNSType `xml:"http://www.onvif.org/ver10/device/wsdl Type"` 499 | Name *onvif.DNSName `xml:"http://www.onvif.org/ver10/device/wsdl Name"` 500 | TTL *xsd.Duration `xml:"http://www.onvif.org/ver10/device/wsdl TTL"` 501 | } 502 | 503 | type SetDynamicDNSResponse struct { 504 | } 505 | 506 | type GetNetworkInterfaces struct { 507 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetNetworkInterfaces"` 508 | } 509 | 510 | type GetNetworkInterfacesResponse struct { 511 | NetworkInterfaces []onvif.NetworkInterface 512 | } 513 | 514 | type SetNetworkInterfaces struct { 515 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetNetworkInterfaces"` 516 | InterfaceToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl InterfaceToken"` 517 | NetworkInterface onvif.NetworkInterfaceSetConfiguration `xml:"http://www.onvif.org/ver10/device/wsdl NetworkInterface"` 518 | } 519 | 520 | type SetNetworkInterfacesResponse struct { 521 | RebootNeeded bool 522 | } 523 | 524 | type GetNetworkProtocols struct { 525 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetNetworkProtocols"` 526 | } 527 | 528 | type GetNetworkProtocolsResponse struct { 529 | NetworkProtocols []onvif.NetworkProtocol 530 | } 531 | 532 | type SetNetworkProtocols struct { 533 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetNetworkProtocols"` 534 | NetworkProtocols []onvif.NetworkProtocol `xml:"http://www.onvif.org/ver10/device/wsdl NetworkProtocols"` 535 | } 536 | 537 | type SetNetworkProtocolsResponse struct { 538 | } 539 | 540 | type GetNetworkDefaultGateway struct { 541 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetNetworkDefaultGateway"` 542 | } 543 | 544 | type GetNetworkDefaultGatewayResponse struct { 545 | NetworkGateway onvif.NetworkGateway 546 | } 547 | 548 | type SetNetworkDefaultGateway struct { 549 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetNetworkDefaultGateway"` 550 | IPv4Address []onvif.IPv4Address `xml:"http://www.onvif.org/ver10/device/wsdl IPv4Address"` 551 | IPv6Address []onvif.IPv6Address `xml:"http://www.onvif.org/ver10/device/wsdl IPv6Address"` 552 | } 553 | 554 | type SetNetworkDefaultGatewayResponse struct { 555 | } 556 | 557 | type GetZeroConfiguration struct { 558 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetZeroConfiguration"` 559 | } 560 | 561 | type GetZeroConfigurationResponse struct { 562 | ZeroConfiguration onvif.NetworkZeroConfiguration 563 | } 564 | 565 | type SetZeroConfiguration struct { 566 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetZeroConfiguration"` 567 | InterfaceToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl InterfaceToken"` 568 | Enabled bool `xml:"http://www.onvif.org/ver10/device/wsdl Enabled"` 569 | } 570 | 571 | type SetZeroConfigurationResponse struct { 572 | } 573 | 574 | type GetIPAddressFilter struct { 575 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetIPAddressFilter"` 576 | } 577 | 578 | type GetIPAddressFilterResponse struct { 579 | IPAddressFilter onvif.IPAddressFilter 580 | } 581 | 582 | type SetIPAddressFilter struct { 583 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetIPAddressFilter"` 584 | IPAddressFilter onvif.IPAddressFilter `xml:"http://www.onvif.org/ver10/device/wsdl IPAddressFilter"` 585 | } 586 | 587 | type SetIPAddressFilterResponse struct { 588 | } 589 | 590 | type AddIPAddressFilter struct { 591 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl AddIPAddressFilter"` 592 | IPAddressFilter onvif.IPAddressFilter `xml:"http://www.onvif.org/ver10/device/wsdl IPAddressFilter"` 593 | } 594 | 595 | type AddIPAddressFilterResponse struct { 596 | } 597 | 598 | type RemoveIPAddressFilter struct { 599 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl RemoveIPAddressFilter"` 600 | IPAddressFilter onvif.IPAddressFilter `xml:"http://www.onvif.org/ver10/schema onvif:IPAddressFilter"` 601 | } 602 | 603 | type RemoveIPAddressFilterResponse struct { 604 | } 605 | 606 | type GetAccessPolicy struct { 607 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetAccessPolicy"` 608 | } 609 | 610 | type GetAccessPolicyResponse struct { 611 | PolicyFile onvif.BinaryData 612 | } 613 | 614 | type SetAccessPolicy struct { 615 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetAccessPolicy"` 616 | PolicyFile onvif.BinaryData `xml:"http://www.onvif.org/ver10/device/wsdl PolicyFile"` 617 | } 618 | 619 | type SetAccessPolicyResponse struct { 620 | } 621 | 622 | type CreateCertificate struct { 623 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl CreateCertificate"` 624 | CertificateID *xsd.Token `xml:"http://www.onvif.org/ver10/device/wsdl CertificateID,omitempty"` 625 | Subject *string `xml:"http://www.onvif.org/ver10/device/wsdl Subject,omitempty"` 626 | ValidNotBefore *xsd.DateTime `xml:"http://www.onvif.org/ver10/device/wsdl ValidNotBefore,omitempty"` 627 | ValidNotAfter *xsd.DateTime `xml:"http://www.onvif.org/ver10/device/wsdl ValidNotAfter,omitempty"` 628 | } 629 | 630 | type CreateCertificateResponse struct { 631 | NvtCertificate onvif.Certificate 632 | } 633 | 634 | type GetCertificates struct { 635 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetCertificates"` 636 | } 637 | 638 | type GetCertificatesResponse struct { 639 | NvtCertificate []onvif.Certificate `xml:"http://www.onvif.org/ver10/device/wsdl NvtCertificate"` 640 | } 641 | 642 | type GetCertificatesStatus struct { 643 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetCertificatesStatus"` 644 | } 645 | 646 | type GetCertificatesStatusResponse struct { 647 | CertificateStatus []onvif.CertificateStatus `xml:"http://www.onvif.org/ver10/device/wsdl CertificateStatus"` 648 | } 649 | 650 | type SetCertificatesStatus struct { 651 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetCertificatesStatus"` 652 | CertificateStatus []onvif.CertificateStatus `xml:"http://www.onvif.org/ver10/device/wsdl CertificateStatus"` 653 | } 654 | 655 | type SetCertificatesStatusResponse struct { 656 | } 657 | 658 | type DeleteCertificates struct { 659 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl DeleteCertificates"` 660 | CertificateID []xsd.Token `xml:"http://www.onvif.org/ver10/device/wsdl CertificateID"` 661 | } 662 | 663 | type DeleteCertificatesResponse struct { 664 | } 665 | 666 | type GetPkcs10Request struct { 667 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetPkcs10Request"` 668 | CertificateID xsd.Token `xml:"http://www.onvif.org/ver10/device/wsdl CertificateID"` 669 | Subject *string `xml:"http://www.onvif.org/ver10/device/wsdl Subject"` 670 | Attributes *onvif.BinaryData `xml:"http://www.onvif.org/ver10/device/wsdl Attributes"` 671 | } 672 | 673 | type GetPkcs10RequestResponse struct { 674 | Pkcs10Request onvif.BinaryData 675 | } 676 | 677 | type LoadCertificates struct { 678 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl LoadCertificates"` 679 | NVTCertificate []onvif.Certificate `xml:"http://www.onvif.org/ver10/device/wsdl NVTCertificate"` 680 | } 681 | 682 | type LoadCertificatesResponse struct { 683 | } 684 | 685 | type GetClientCertificateMode struct { 686 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetClientCertificateMode"` 687 | } 688 | 689 | type GetClientCertificateModeResponse struct { 690 | Enabled bool 691 | } 692 | 693 | type SetClientCertificateMode struct { 694 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetClientCertificateMode"` 695 | Enabled bool `xml:"http://www.onvif.org/ver10/device/wsdl Enabled"` 696 | } 697 | 698 | type SetClientCertificateModeResponse struct { 699 | } 700 | 701 | type GetRelayOutputs struct { 702 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetRelayOutputs"` 703 | } 704 | 705 | type GetRelayOutputsResponse struct { 706 | RelayOutputs []onvif.RelayOutput `xml:"http://www.onvif.org/ver10/device/wsdl RelayOutputs"` 707 | } 708 | 709 | type SetRelayOutputSettings struct { 710 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetRelayOutputSettings"` 711 | RelayOutputToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl RelayOutputToken"` 712 | Properties onvif.RelayOutputSettings `xml:"http://www.onvif.org/ver10/device/wsdl Properties"` 713 | } 714 | 715 | type SetRelayOutputSettingsResponse struct { 716 | } 717 | 718 | type SetRelayOutputState struct { 719 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetRelayOutputState"` 720 | RelayOutputToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl RelayOutputToken"` 721 | LogicalState onvif.RelayLogicalState `xml:"http://www.onvif.org/ver10/device/wsdl LogicalState"` 722 | } 723 | 724 | type SetRelayOutputStateResponse struct { 725 | } 726 | 727 | type SendAuxiliaryCommand struct { 728 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SendAuxiliaryCommand"` 729 | AuxiliaryCommand onvif.AuxiliaryData `xml:"http://www.onvif.org/ver10/device/wsdl AuxiliaryCommand"` 730 | } 731 | 732 | type SendAuxiliaryCommandResponse struct { 733 | AuxiliaryCommandResponse *onvif.AuxiliaryData 734 | } 735 | 736 | type GetCACertificates struct { 737 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetCACertificates"` 738 | } 739 | 740 | type GetCACertificatesResponse struct { 741 | CACertificate []onvif.Certificate 742 | } 743 | 744 | type LoadCertificateWithPrivateKey struct { 745 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl LoadCertificateWithPrivateKey"` 746 | CertificateWithPrivateKey []onvif.CertificateWithPrivateKey `xml:"http://www.onvif.org/ver10/device/wsdl CertificateWithPrivateKey"` 747 | } 748 | 749 | type LoadCertificateWithPrivateKeyResponse struct { 750 | } 751 | 752 | type GetCertificateInformation struct { 753 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetCertificateInformation"` 754 | CertificateID xsd.Token `xml:"http://www.onvif.org/ver10/device/wsdl CertificateID"` 755 | } 756 | 757 | type GetCertificateInformationResponse struct { 758 | CertificateInformation onvif.CertificateInformation 759 | } 760 | 761 | type LoadCACertificates struct { 762 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl LoadCACertificates"` 763 | CACertificate []onvif.Certificate `xml:"http://www.onvif.org/ver10/device/wsdl CACertificate"` 764 | } 765 | 766 | type LoadCACertificatesResponse struct { 767 | } 768 | 769 | type CreateDot1XConfiguration struct { 770 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl CreateDot1XConfiguration"` 771 | Dot1XConfiguration onvif.Dot1XConfiguration `xml:"http://www.onvif.org/ver10/device/wsdl Dot1XConfiguration"` 772 | } 773 | 774 | type CreateDot1XConfigurationResponse struct { 775 | } 776 | 777 | type SetDot1XConfiguration struct { 778 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetDot1XConfiguration"` 779 | Dot1XConfiguration onvif.Dot1XConfiguration `xml:"http://www.onvif.org/ver10/device/wsdl Dot1XConfiguration"` 780 | } 781 | 782 | type SetDot1XConfigurationResponse struct { 783 | } 784 | 785 | type GetDot1XConfiguration struct { 786 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDot1XConfiguration"` 787 | Dot1XConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl Dot1XConfigurationToken"` 788 | } 789 | 790 | type GetDot1XConfigurationResponse struct { 791 | Dot1XConfiguration onvif.Dot1XConfiguration 792 | } 793 | 794 | type GetDot1XConfigurations struct { 795 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDot1XConfigurations"` 796 | } 797 | 798 | type GetDot1XConfigurationsResponse struct { 799 | Dot1XConfiguration []onvif.Dot1XConfiguration 800 | } 801 | 802 | type DeleteDot1XConfiguration struct { 803 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl DeleteDot1XConfiguration"` 804 | Dot1XConfigurationToken []onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl Dot1XConfigurationToken"` 805 | } 806 | 807 | type DeleteDot1XConfigurationResponse struct { 808 | } 809 | 810 | type GetDot11Capabilities struct { 811 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDot11Capabilities"` 812 | } 813 | 814 | type GetDot11CapabilitiesResponse struct { 815 | Capabilities onvif.Dot11Capabilities 816 | } 817 | 818 | type GetDot11Status struct { 819 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetDot11Status"` 820 | InterfaceToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl InterfaceToken"` 821 | } 822 | 823 | type GetDot11StatusResponse struct { 824 | Status onvif.Dot11Status 825 | } 826 | 827 | type ScanAvailableDot11Networks struct { 828 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl ScanAvailableDot11Networks"` 829 | InterfaceToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl InterfaceToken"` 830 | } 831 | 832 | type ScanAvailableDot11NetworksResponse struct { 833 | Networks []onvif.Dot11AvailableNetworks `xml:"http://www.onvif.org/ver10/device/wsdl Networks"` 834 | } 835 | 836 | type GetSystemUris struct { 837 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetSystemUris"` 838 | } 839 | 840 | type GetSystemUrisResponse struct { 841 | SystemLogUris *onvif.SystemLogUriList `xml:"http://www.onvif.org/ver10/device/wsdl SystemLogUris"` 842 | SupportInfoURI *xsd.AnyURI `xml:"http://www.onvif.org/ver10/device/wsdl SupportInfoUri"` 843 | SystemBackupURI *xsd.AnyURI `xml:"http://www.onvif.org/ver10/device/wsdl SystemBackupUri"` 844 | Extension *xsd.AnyType `xml:"http://www.onvif.org/ver10/device/wsdl Extension"` 845 | } 846 | 847 | type StartFirmwareUpgrade struct { 848 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl StartFirmwareUpgrade"` 849 | } 850 | 851 | type StartFirmwareUpgradeResponse struct { 852 | UploadUri xsd.AnyURI 853 | UploadDelay xsd.Duration 854 | ExpectedDownTime xsd.Duration 855 | } 856 | 857 | type StartSystemRestore struct { 858 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl StartSystemRestore"` 859 | } 860 | 861 | type StartSystemRestoreResponse struct { 862 | UploadUri xsd.AnyURI 863 | ExpectedDownTime xsd.Duration 864 | } 865 | 866 | type GetStorageConfigurations struct { 867 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetStorageConfigurations"` 868 | } 869 | 870 | type GetStorageConfigurationsResponse struct { 871 | StorageConfigurations []StorageConfiguration `xml:"http://www.onvif.org/ver10/device/wsdl StorageConfigurations"` 872 | } 873 | 874 | type CreateStorageConfiguration struct { 875 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl CreateStorageConfiguration"` 876 | StorageConfiguration StorageConfigurationData 877 | } 878 | 879 | type CreateStorageConfigurationResponse struct { 880 | Token onvif.ReferenceToken 881 | } 882 | 883 | type GetStorageConfiguration struct { 884 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetStorageConfiguration"` 885 | Token onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl Token"` 886 | } 887 | 888 | type GetStorageConfigurationResponse struct { 889 | StorageConfiguration StorageConfiguration 890 | } 891 | 892 | type SetStorageConfiguration struct { 893 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetStorageConfiguration"` 894 | StorageConfiguration StorageConfiguration `xml:"http://www.onvif.org/ver10/device/wsdl StorageConfiguration"` 895 | } 896 | 897 | type SetStorageConfigurationResponse struct { 898 | } 899 | 900 | type DeleteStorageConfiguration struct { 901 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl DeleteStorageConfiguration"` 902 | Token onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/device/wsdl Token"` 903 | } 904 | 905 | type DeleteStorageConfigurationResponse struct { 906 | } 907 | 908 | type GetGeoLocation struct { 909 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl GetGeoLocation"` 910 | } 911 | 912 | type GetGeoLocationResponse struct { 913 | Location []onvif.LocationEntity `xml:"http://www.onvif.org/ver10/device/wsdl Location"` 914 | } 915 | 916 | type SetGeoLocation struct { 917 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl SetGeoLocation"` 918 | Location []onvif.LocationEntity `xml:"http://www.onvif.org/ver10/device/wsdl Location"` 919 | } 920 | 921 | type SetGeoLocationResponse struct { 922 | } 923 | 924 | type DeleteGeoLocation struct { 925 | XMLName string `xml:"http://www.onvif.org/ver10/device/wsdl DeleteGeoLocation"` 926 | Location []onvif.LocationEntity `xml:"http://www.onvif.org/ver10/device/wsdl Location"` 927 | } 928 | 929 | type DeleteGeoLocationResponse struct { 930 | } 931 | -------------------------------------------------------------------------------- /events/addressing.go: -------------------------------------------------------------------------------- 1 | package events 2 | 3 | import "encoding/xml" 4 | 5 | type addressingAction struct { 6 | XMLName xml.Name `xml:"http://www.w3.org/2005/08/addressing Action"` 7 | Value string `xml:",chardata"` 8 | } 9 | 10 | type addressingMessageID struct { 11 | XMLName xml.Name `xml:"http://www.w3.org/2005/08/addressing MessageID"` 12 | Value string `xml:",chardata"` // urn:uuid:5e6558cf-e5dc-42e5-9417-6372b3ed9a65 13 | } 14 | 15 | type addressingReplyTo struct { 16 | XMLName xml.Name `xml:"http://www.w3.org/2005/08/addressing ReplyTo"` 17 | Address string `xml:"http://www.w3.org/2005/08/addressing Address"` // http://www.w3.org/2005/08/addressing/anonymous 18 | } 19 | 20 | type addressingTo struct { 21 | XMLName xml.Name `xml:"http://www.w3.org/2005/08/addressing To"` 22 | Value string `xml:",chardata"` 23 | } 24 | 25 | func MakeAnonymousAddressingHeaders(action, to string) []interface{} { 26 | return []interface{}{ 27 | addressingAction { 28 | Value: action, 29 | }, 30 | addressingReplyTo { 31 | Address: "http://www.w3.org/2005/08/addressing/anonymous", 32 | }, 33 | addressingTo { 34 | Value: to, 35 | }, 36 | } 37 | } 38 | 39 | // http://www.onvif.org/ver10/events/wsdl/PullPointSubscription/PullMessagesRequest 40 | // urn:uuid:5e6558cf-e5dc-42e5-9417-6372b3ed9a65 41 | // 42 | // http://www.w3.org/2005/08/addressing/anonymous 43 | // 44 | // http://10.110.3.252/onvif/event/subsription_4352 45 | // http://www.w3.org/2005/08/addressing/anonymous 46 | // 47 | // http://10.110.3.252/onvif/event/subsription_4352 48 | -------------------------------------------------------------------------------- /events/events.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | The capabilities for the event service is returned in the Capabilities element. 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Indicates that the WS Subscription policy is supported. 46 | 47 | 48 | 49 | 50 | Indicates that the WS Pull Point is supported. 51 | 52 | 53 | 54 | 55 | Indicates that the WS Pausable Subscription Manager Interface is supported. 56 | 57 | 58 | 59 | 60 | Maximum number of supported notification producers as defined by WS-BaseNotification. 61 | 62 | 63 | 64 | 65 | Maximum supported number of notification pull points. 66 | 67 | 68 | 69 | 70 | Indication if the device supports persistent notification storage. 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | Optional XPATH expression to select specific topics. 83 | 84 | 85 | 86 | 87 | Initial termination time. 88 | 89 | 90 | 91 | 92 | Refer to Web Services Base Notification 1.3 (WS-BaseNotification). 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | Endpoint reference of the subscription to be used for pulling the messages. 110 | 111 | 112 | 113 | 114 | Current time of the server for synchronization purposes. 115 | 116 | 117 | 118 | 119 | Date time when the PullPoint will be shut down without further pull requests. 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | Maximum time to block until this method returns. 133 | 134 | 135 | 136 | 137 | Upper limit for the number of messages to return at once. A server implementation may decide to return less messages. 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | The date and time when the messages have been delivered by the web server to the client. 150 | 151 | 152 | 153 | 154 | Date time when the PullPoint will be shut down without further pull requests. 155 | 156 | 157 | 158 | 159 | List of messages. This list shall be empty in case of a timeout. 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | Maximum timeout supported by the device. 171 | 172 | 173 | 174 | 175 | Maximum message limit supported by the device. 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | The date and time to match against stored messages. 187 | Reverse the pull direction of PullMessages. 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 | List of topic namespaces supported. 220 | 221 | 222 | 223 | 224 | True when topicset is fixed for all times. 225 | 226 | 227 | 228 | 229 | Set of topics supported. 230 | 231 | 232 | 233 | 234 | 235 | Defines the XPath expression syntax supported for matching topic expressions.
236 | The following TopicExpressionDialects are mandatory for an ONVIF compliant device : 237 |
    238 |
  • http://docs.oasis-open.org/wsn/t-1/TopicExpression/Concrete
  • 239 |
  • http://www.onvif.org/ver10/tev/topicExpression/ConcreteSet.
  • 240 |
241 |
242 |
243 |
244 | 245 | 246 | 247 | Defines the XPath function set supported for message content filtering.
248 | The following MessageContentFilterDialects should be returned if a device supports the message content filtering: 249 |
    250 |
  • http://www.onvif.org/ver10/tev/messageContentFilter/ItemFilter.
  • 251 |
252 | A device that does not support any MessageContentFilterDialect returns a single empty url. 253 |
254 |
255 |
256 | 257 | 258 | 259 | Optional ProducerPropertiesDialects. Refer to Web Services Base Notification 1.3 (WS-BaseNotification) for advanced filtering. 260 | 261 | 262 | 263 | 264 | 265 | The Message Content Description Language allows referencing 266 | of vendor-specific types. In order to ease the integration of such types into a client application, 267 | the GetEventPropertiesResponse shall list all URI locations to schema files whose types are 268 | used in the description of notifications, with MessageContentSchemaLocation elements.
269 | This list shall at least contain the URI of the ONVIF schema file.
270 |
271 |
272 | 273 | 274 | 275 | 276 | 277 |
278 |
279 |
280 | 281 | 282 | Optional ONVIF defined pull point subscription policies 283 | 284 | 285 | 286 | 287 | The pullpoint should not provide Initialized nor Deleted events for Properties. 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 | Returns the capabilities of the event service. The result is returned in a typed answer. 336 | 337 | 338 | 339 | 340 | This method returns a PullPointSubscription that can be polled using PullMessages. 341 | This message contains the same elements as the SubscriptionRequest of the WS-BaseNotification without the ConsumerReference.
342 | If no Filter is specified the pullpoint notifies all occurring events to the client.
343 | This method is mandatory.
344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 |
359 | 360 | The WS-BaseNotification specification defines a set of OPTIONAL WS-ResouceProperties. 361 | This specification does not require the implementation of the WS-ResourceProperty interface. 362 | Instead, the subsequent direct interface shall be implemented by an ONVIF compliant device 363 | in order to provide information about the FilterDialects, Schema files and topics supported by 364 | the device. 365 | 366 | 367 | 368 |
369 | 370 | 371 | 372 | This method pulls one or more messages from a PullPoint. 373 | The device shall provide the following PullMessages command for all SubscriptionManager 374 | endpoints returned by the CreatePullPointSubscription command. This method shall not wait until 375 | the requested number of messages is available but return as soon as at least one message is available.
376 | The command shall at least support a Timeout of one minute. In case a device supports retrieval of less messages 377 | than requested it shall return these without generating a fault.
378 | 379 | 380 | 381 |
382 | 383 | 384 | This method readjusts the pull pointer into the past. 385 | A device supporting persistent notification storage shall provide the 386 | following Seek command for all SubscriptionManager endpoints returned by 387 | the CreatePullPointSubscription command. The optional Reverse argument can 388 | be used to reverse the pull direction of the PullMessages command.
389 | The UtcTime argument will be matched against the UtcTime attribute on a 390 | NotificationMessage. 391 |
392 | 393 | 394 |
395 | 396 | Properties inform a client about property creation, changes and 397 | deletion in a uniform way. When a client wants to synchronize its properties with the 398 | properties of the device, it can request a synchronization point which repeats the current 399 | status of all properties to which a client has subscribed. The PropertyOperation of all 400 | produced notifications is set to “Initialized”. The Synchronization Point is 401 | requested directly from the SubscriptionManager which was returned in either the 402 | SubscriptionResponse or in the CreatePullPointSubscriptionResponse. The property update is 403 | transmitted via the notification transportation of the notification interface. This method is mandatory. 404 | 405 | 406 | 407 | 408 | 409 | The device shall provide the following Unsubscribe command for all SubscriptionManager endpoints returned by the CreatePullPointSubscription command.
410 | This command shall terminate the lifetime of a pull point. 411 |
412 | 413 | 414 | 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 | 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 | 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 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 |
767 | -------------------------------------------------------------------------------- /events/types.go: -------------------------------------------------------------------------------- 1 | package events 2 | 3 | import ( 4 | "time" 5 | 6 | tt "github.com/faceterteam/onvif4go/onvif" 7 | "github.com/faceterteam/onvif4go/xsd" 8 | ) 9 | 10 | type FilterType string 11 | 12 | // AbsoluteOrRelativeTimeType 13 | type AbsoluteOrRelativeTimeType struct { //wsnt http://docs.oasis-open.org/wsn/b-2.xsd 14 | duration *xsd.Duration 15 | dateTime *time.Time 16 | } 17 | 18 | // UnmarshalText unmarshal AbsoluteOrRelativeTimeType from text 19 | func (v *AbsoluteOrRelativeTimeType) UnmarshalText(text []byte) error { 20 | str := string(text) 21 | if str[0] == 'P' { 22 | var duration xsd.Duration 23 | err := duration.UnmarshalText(text) 24 | if err != nil { 25 | return err 26 | } 27 | v.duration = &duration 28 | } else { 29 | t, err := time.Parse(time.RFC3339Nano, str) 30 | if err != nil { 31 | return err 32 | } 33 | v.dateTime = &t 34 | } 35 | 36 | return nil 37 | } 38 | 39 | // MarshalText marshal AbsoluteOrRelativeTimeType to text 40 | func (v AbsoluteOrRelativeTimeType) MarshalText() ([]byte, error) { 41 | if v.duration == nil { 42 | return v.dateTime.MarshalText() 43 | } 44 | return v.duration.MarshalText() 45 | } 46 | 47 | // NewAbsoluteTimeType make *AbsoluteOrRelativeTimeType from time.Time 48 | func NewAbsoluteTimeType(dateTime time.Time) *AbsoluteOrRelativeTimeType { 49 | return &AbsoluteOrRelativeTimeType{dateTime: &dateTime} 50 | } 51 | 52 | // NewRelativeTimeType make *AbsoluteOrRelativeTimeType from time.Duration 53 | func NewRelativeTimeType(duration time.Duration) *AbsoluteOrRelativeTimeType { 54 | d := xsd.Duration(duration) 55 | return &AbsoluteOrRelativeTimeType{duration: &d} 56 | } 57 | 58 | type SubscriptionPolicy struct { //tev http://www.onvif.org/ver10/events/wsdl 59 | ChangedOnly bool `xml:"ChangedOnly,attr"` 60 | } 61 | 62 | type Capabilities struct { //tev 63 | WSSubscriptionPolicySupport bool `xml:"WSSubscriptionPolicySupport,attr"` 64 | WSPullPointSupport bool `xml:"WSPullPointSupport,attr"` 65 | WSPausableSubscriptionManagerInterfaceSupport bool `xml:"WSPausableSubscriptionManagerInterfaceSupport,attr"` 66 | MaxNotificationProducers int `xml:"MaxNotificationProducers,attr"` 67 | MaxPullPoints int `xml:"MaxPullPoints,attr"` 68 | PersistentNotificationStorage bool `xml:"PersistentNotificationStorage,attr"` 69 | } 70 | 71 | type EndpointReferenceType struct { //wsa http://www.w3.org/2005/08/addressing/ws-addr.xsd 72 | Address AttributedURIType `xml:"http://www.w3.org/2005/08/addressing Address"` 73 | ReferenceParameters *ReferenceParametersType 74 | Metadata 75 | } 76 | 77 | type AttributedURIType struct { //wsa https://www.w3.org/2005/08/addressing/ws-addr.xsd 78 | Content xsd.AnyURI `xml:",chardata"` 79 | //Here can be anyAttribute 80 | } 81 | 82 | type ReferenceParametersType struct { //wsa https://www.w3.org/2005/08/addressing/ws-addr.xsd 83 | Any string 84 | //Here can be anyAttribute 85 | } 86 | 87 | type Metadata MetadataType //wsa https://www.w3.org/2005/08/addressing/ws-addr.xsd 88 | 89 | type MetadataType struct { //wsa https://www.w3.org/2005/08/addressing/ws-addr.xsd 90 | Any string 91 | //Here can be anyAttribute 92 | } 93 | 94 | type CurrentTime xsd.DateTime //wsnt http://docs.oasis-open.org/wsn/b-2.xsd 95 | type TerminationTime xsd.DateTime //wsnt http://docs.oasis-open.org/wsn/b-2.xsd 96 | type FixedTopicSet bool //wsnt http://docs.oasis-open.org/wsn/b-2.xsd 97 | 98 | type TopicSet TopicSetType //wstop http://docs.oasis-open.org/wsn/t-1.xsd 99 | 100 | type TopicSetType struct { //wstop http://docs.oasis-open.org/wsn/t-1.xsd 101 | ExtensibleDocumented 102 | //here can be any element 103 | } 104 | 105 | type ExtensibleDocumented struct { //wstop http://docs.oasis-open.org/wsn/t-1.xsd 106 | Documentation Documentation //к xsd-документе documentation с маленькой буквы начинается 107 | //here can be anyAttribute 108 | } 109 | 110 | type Documentation xsd.AnyType //wstop http://docs.oasis-open.org/wsn/t-1.xsd 111 | 112 | type TopicExpressionDialect xsd.AnyURI 113 | 114 | type NotificationMessage NotificationMessageHolderType //wsnt http://docs.oasis-open.org/wsn/b-2.xsd 115 | 116 | type NotificationMessageHolderType struct { 117 | SubscriptionReference *SubscriptionReference //wsnt http://docs.oasis-open.org/wsn/b-2.xsd 118 | Topic Topic 119 | ProducerReference *ProducerReference 120 | Message OnvifEventsMessage 121 | } 122 | 123 | type SubscriptionReference EndpointReferenceType 124 | type Topic TopicExpressionType 125 | type ProducerReference EndpointReferenceType 126 | 127 | type OnvifEventsMessage struct { 128 | Messages []tt.Message `xml:"http://www.onvif.org/ver10/schema Message"` 129 | } 130 | 131 | type TopicExpressionType struct { //wsnt http://docs.oasis-open.org/wsn/b-2.xsd 132 | Dialect xsd.AnyURI `xml:"Dialect,attr"` 133 | Value string `xml:",chardata"` 134 | } 135 | 136 | //Event main types 137 | 138 | type GetServiceCapabilities struct { 139 | XMLName string `xml:"http://www.onvif.org/ver10/events/wsdl GetServiceCapabilities"` 140 | } 141 | 142 | type GetServiceCapabilitiesResponse struct { 143 | Capabilities Capabilities 144 | } 145 | 146 | type CreatePullPointSubscription struct { 147 | XMLName string `xml:"http://www.onvif.org/ver10/events/wsdl CreatePullPointSubscription"` 148 | Filter FilterType `xml:"http://www.onvif.org/ver10/events/wsdl Filter,omitempty"` 149 | InitialTerminationTime *AbsoluteOrRelativeTimeType `xml:"http://www.onvif.org/ver10/events/wsdl InitialTerminationTime,omitempty"` 150 | SubscriptionPolicy *SubscriptionPolicy `xml:"http://www.onvif.org/ver10/events/wsdl SubscriptionPolicy,omitempty"` 151 | } 152 | 153 | type CreatePullPointSubscriptionResponse struct { 154 | SubscriptionReference EndpointReferenceType `xml:"http://www.onvif.org/ver10/events/wsdl SubscriptionReference"` 155 | CurrentTime CurrentTime 156 | TerminationTime TerminationTime 157 | } 158 | 159 | type ResourceUnknownFault struct { 160 | } 161 | 162 | type InvalidFilterFault struct { 163 | } 164 | 165 | type TopicExpressionDialectUnknownFault struct { 166 | } 167 | 168 | type InvalidTopicExpressionFault struct { 169 | } 170 | 171 | type TopicNotSupportedFault struct { 172 | } 173 | 174 | type InvalidProducerPropertiesExpressionFault struct { 175 | } 176 | 177 | type InvalidMessageContentExpressionFault struct { 178 | } 179 | 180 | type UnacceptableInitialTerminationTimeFault struct { 181 | } 182 | 183 | type UnrecognizedPolicyRequestFault struct { 184 | } 185 | 186 | type UnsupportedPolicyRequestFault struct { 187 | } 188 | 189 | type NotifyMessageNotSupportedFault struct { 190 | } 191 | 192 | type SubscribeCreationFailedFault struct { 193 | } 194 | 195 | type GetEventProperties struct { 196 | XMLName string `xml:"http://www.onvif.org/ver10/events/wsdl GetEventProperties"` 197 | } 198 | 199 | type GetEventPropertiesResponse struct { 200 | TopicNamespaceLocation xsd.AnyURI 201 | FixedTopicSet FixedTopicSet 202 | TopicSet TopicSet 203 | TopicExpressionDialect TopicExpressionDialect 204 | MessageContentFilterDialect xsd.AnyURI 205 | ProducerPropertiesFilterDialect xsd.AnyURI 206 | MessageContentSchemaLocation xsd.AnyURI 207 | } 208 | 209 | //Port type PullPointSubscription 210 | 211 | type PullMessages struct { 212 | XMLName string `xml:"http://www.onvif.org/ver10/events/wsdl PullMessages"` 213 | Timeout xsd.Duration `xml:"http://www.onvif.org/ver10/events/wsdl Timeout"` 214 | MessageLimit int `xml:"http://www.onvif.org/ver10/events/wsdl MessageLimit"` 215 | } 216 | 217 | type PullMessagesResponse struct { 218 | CurrentTime CurrentTime 219 | TerminationTime TerminationTime 220 | NotificationMessages []NotificationMessage `xml:"http://docs.oasis-open.org/wsn/b-2 NotificationMessage"` 221 | } 222 | 223 | type PullMessagesFaultResponse struct { 224 | MaxTimeout xsd.Duration 225 | MaxMessageLimit int 226 | } 227 | 228 | type Seek struct { 229 | XMLName string `xml:"http://www.onvif.org/ver10/events/wsdl Seek"` 230 | UtcTime xsd.DateTime `xml:"http://www.onvif.org/ver10/events/wsdl UtcTime"` 231 | Reverse bool `xml:"http://www.onvif.org/ver10/events/wsdl Reverse"` 232 | } 233 | 234 | type SeekResponse struct { 235 | } 236 | 237 | type SetSynchronizationPoint struct { 238 | XMLName string `xml:"http://www.onvif.org/ver10/events/wsdl SetSynchronizationPoint"` 239 | } 240 | 241 | type SetSynchronizationPointResponse struct { 242 | } 243 | 244 | type UnsubscribeRequest struct { 245 | XMLName string `xml:"http://www.onvif.org/ver10/events/wsdl UnsubscribeRequest"` 246 | } 247 | 248 | type UnsubscribeResponse struct { 249 | } 250 | -------------------------------------------------------------------------------- /eventsService.go: -------------------------------------------------------------------------------- 1 | package onvif4go 2 | 3 | import ( 4 | tev "github.com/faceterteam/onvif4go/events" 5 | ) 6 | 7 | type EventsService struct { 8 | Client onvifCaller 9 | endpoint string 10 | } 11 | 12 | func NewEventsService(endpoint string, onvifDevice *OnvifDevice) *EventsService { 13 | return &EventsService{ 14 | Client: NewOnvifClient(endpoint, &onvifDevice.auth), 15 | endpoint: endpoint, 16 | } 17 | } 18 | 19 | func (s *EventsService) makeAddressingHeaders(action string) []interface{} { 20 | return tev.MakeAnonymousAddressingHeaders(action, s.endpoint) 21 | } 22 | 23 | // GetServiceCapabilities returns the capabilities of the event service. 24 | func (s *EventsService) GetServiceCapabilities() (res tev.GetServiceCapabilitiesResponse, err error) { 25 | headers := s.makeAddressingHeaders("http://www.onvif.org/ver10/events/wsdl/EventPortType/GetServiceCapabilitiesRequest") 26 | err = s.Client.Call(tev.GetServiceCapabilities{}, &res, headers...) 27 | return 28 | } 29 | 30 | /* 31 | GetEventProperties returns information about the FilterDialects, Schema files and 32 | topics supported by the device. 33 | 34 | The WS-BaseNotification specification defines a set of OPTIONAL WS-ResouceProperties. 35 | This specification does not require the implementation of the WS-ResourceProperty interface. 36 | Instead, the subsequent direct interface shall be implemented by an ONVIF compliant device 37 | in order to provide information about the FilterDialects, Schema files and topics supported by 38 | the device. 39 | */ 40 | func (s *EventsService) GetEventProperties() (res tev.GetEventPropertiesResponse, err error) { 41 | headers := s.makeAddressingHeaders("http://www.onvif.org/ver10/events/wsdl/EventPortType/GetEventPropertiesRequest") 42 | err = s.Client.Call(tev.GetEventProperties{}, &res, headers...) 43 | return 44 | } 45 | 46 | /* 47 | CreatePullPointSubscription returns a PullPointSubscription that can be polled using PullMessages. 48 | This message contains the same elements as the SubscriptionRequest of the WS-BaseNotification 49 | without the ConsumerReference. 50 | 51 | If no Filter is specified the pullpoint notifies all occurring events to the client. 52 | */ 53 | func (s *EventsService) CreatePullPointSubscription(filter string, changeOnly bool, initialTerminationTime *tev.AbsoluteOrRelativeTimeType) (res tev.CreatePullPointSubscriptionResponse, err error) { 54 | headers := s.makeAddressingHeaders("http://www.onvif.org/ver10/events/wsdl/EventPortType/CreatePullPointSubscriptionRequest") 55 | err = s.Client.Call(tev.CreatePullPointSubscription{ 56 | Filter: tev.FilterType(filter), 57 | SubscriptionPolicy: &tev.SubscriptionPolicy{ 58 | ChangedOnly: changeOnly, 59 | }, 60 | InitialTerminationTime: initialTerminationTime, 61 | }, &res, headers...) 62 | 63 | /* 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | */ 77 | 78 | return 79 | } 80 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/faceterteam/onvif4go 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/faceterteam/onvif4go/8994ff013c81b76917ecb8954d1d409a632a2e92/go.sum -------------------------------------------------------------------------------- /main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "time" 7 | 8 | "github.com/faceterteam/onvif4go" 9 | tev "github.com/faceterteam/onvif4go/events" 10 | ) 11 | 12 | func main() { 13 | camera := onvif4go.NewOnvifDevice("10.110.3.235:8899") // OK 14 | 15 | camera.Auth("admin", "12345678q") 16 | 17 | err := camera.Initialize() 18 | if err != nil { 19 | fmt.Println("camera.Initialize error:", err.Error()) 20 | return 21 | } 22 | 23 | di, err := camera.Device.GetDeviceInformation() 24 | fmt.Println(di) 25 | users, err := camera.Device.GetUsers() 26 | fmt.Println(users) 27 | 28 | //camera.Media.Client.SetLogger(logClient, logClient) 29 | // profiles, _ := camera.Media.GetProfiles() 30 | // for _, profile := range profiles.Profiles { 31 | // fmt.Println(profile.VideoEncoderConfiguration.SessionTimeout.String()) 32 | // } 33 | 34 | eventServiceCapabilities, err := camera.Events.GetServiceCapabilities() 35 | if err != nil { 36 | fmt.Println("Events.GetServiceCapabilities error:", err.Error()) 37 | //return 38 | } else { 39 | fmt.Println(eventServiceCapabilities.Capabilities) 40 | } 41 | 42 | //camera.Events.Client.SetLogger(logClient, logClient) 43 | 44 | pullPoint, err := camera.Events.CreatePullPointSubscription("", false, tev.NewRelativeTimeType(time.Second*600)) 45 | if err != nil { 46 | fmt.Println("Events.CreatePullPointSubscription error:", err.Error()) 47 | return 48 | } 49 | 50 | fmt.Println(pullPoint.SubscriptionReference.Address.Content) 51 | 52 | pullPointSubscription := onvif4go.NewPullPointSubscription(pullPoint, camera) 53 | //pullPointSubscription.Client.SetLogger(logClient, logClient) 54 | 55 | pullPointTicker := time.NewTicker(time.Second * 30) 56 | 57 | go func() { 58 | 59 | //currentTime := time.Now() 60 | currentState := false 61 | 62 | for { 63 | select { 64 | case _ = <-pullPointTicker.C: 65 | //fmt.Println("SetSynchronizationPoint", t) 66 | 67 | err := pullPointSubscription.SetSynchronizationPoint() 68 | if err != nil { 69 | fmt.Println("pullPoint.SetSynchronizationPoint error:", err.Error()) 70 | } 71 | default: 72 | messages, err := pullPointSubscription.PullMessages(time.Second*5, 1024) 73 | if err != nil { 74 | fmt.Println("pullPoint.PullMessages error:", err.Error()) 75 | return 76 | } 77 | 78 | //fmt.Println(messages.CurrentTime, messages.TerminationTime, len(messages.NotificationMessages)) 79 | 80 | for _, message := range messages.NotificationMessages { 81 | if message.Topic.Value == "tns1:RuleEngine/CellMotionDetector/Motion" { 82 | for _, onvifMessage := range message.Message.Messages { 83 | isMotion, _ := strconv.ParseBool(onvifMessage.Data.SimpleItems["IsMotion"]) 84 | if currentState != isMotion { 85 | currentState = isMotion 86 | //currentTime = onvifMessage.UtcTime 87 | 88 | fmt.Println( 89 | message.Topic.Value, 90 | *onvifMessage.PropertyOperation, 91 | onvifMessage.UtcTime, 92 | onvifMessage.Data.SimpleItems["IsMotion"]) 93 | } 94 | } 95 | } else if message.Topic.Value == "tns1:VideoSource/MotionAlarm" { 96 | for _, onvifMessage := range message.Message.Messages { 97 | state, _ := strconv.ParseBool(onvifMessage.Data.SimpleItems["State"]) 98 | 99 | if currentState != state { 100 | currentState = state 101 | //currentTime = onvifMessage.UtcTime 102 | 103 | fmt.Println( 104 | message.Topic.Value, 105 | *onvifMessage.PropertyOperation, 106 | onvifMessage.UtcTime, 107 | onvifMessage.Data.SimpleItems["State"]) 108 | } 109 | } 110 | } else { 111 | fmt.Println(message.Topic.Value) 112 | } 113 | } 114 | } 115 | } 116 | 117 | pullPointSubscription.Unsubscribe() 118 | }() 119 | 120 | time.Sleep(60 * time.Minute) 121 | } 122 | 123 | func logClient(message string) { 124 | fmt.Println(message) 125 | } 126 | -------------------------------------------------------------------------------- /media/types.go: -------------------------------------------------------------------------------- 1 | package media 2 | 3 | import ( 4 | "github.com/faceterteam/onvif4go/onvif" 5 | ) 6 | 7 | type Capabilities struct { 8 | SnapshotUri bool `xml:"SnapshotUri,attr"` 9 | Rotation bool `xml:"Rotation,attr"` 10 | VideoSourceMode bool `xml:"VideoSourceMode,attr"` 11 | OSD bool `xml:"OSD,attr"` 12 | TemporaryOSDText bool `xml:"TemporaryOSDText,attr"` 13 | EXICompression bool `xml:"EXICompression,attr"` 14 | ProfileCapabilities ProfileCapabilities 15 | StreamingCapabilities StreamingCapabilities 16 | } 17 | 18 | type ProfileCapabilities struct { 19 | MaximumNumberOfProfiles int `xml:"MaximumNumberOfProfiles,attr"` 20 | } 21 | 22 | type StreamingCapabilities struct { 23 | RTPMulticast bool `xml:"RTPMulticast,attr"` 24 | RTP_TCP bool `xml:"RTP_TCP,attr"` 25 | RTP_RTSP_TCP bool `xml:"RTP_RTSP_TCP,attr"` 26 | NonAggregateControl bool `xml:"NonAggregateControl,attr"` 27 | NoRTSPStreaming bool `xml:"NoRTSPStreaming,attr"` 28 | } 29 | 30 | //Media main types 31 | 32 | type GetServiceCapabilities struct { 33 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetServiceCapabilities"` 34 | } 35 | 36 | type GetServiceCapabilitiesResponse struct { 37 | Capabilities Capabilities 38 | } 39 | 40 | type GetVideoSources struct { 41 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoSources"` 42 | } 43 | 44 | type GetVideoSourcesResponse struct { 45 | VideoSources []onvif.VideoSource 46 | } 47 | 48 | type GetAudioSources struct { 49 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioSources"` 50 | } 51 | 52 | type GetAudioSourcesResponse struct { 53 | AudioSources []onvif.AudioSource 54 | } 55 | 56 | type GetAudioOutputs struct { 57 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioOutputs"` 58 | } 59 | 60 | type GetAudioOutputsResponse struct { 61 | AudioOutputs []onvif.AudioOutput 62 | } 63 | 64 | type CreateProfile struct { 65 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl CreateProfile"` 66 | Name onvif.Name `xml:"http://www.onvif.org/ver10/media/wsdl Name"` 67 | Token onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl Token"` 68 | } 69 | 70 | type CreateProfileResponse struct { 71 | Profile onvif.Profile 72 | } 73 | 74 | type GetProfile struct { 75 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetProfile"` 76 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 77 | } 78 | 79 | type GetProfileResponse struct { 80 | Profiles onvif.Profile 81 | } 82 | 83 | type GetProfiles struct { 84 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetProfiles"` 85 | } 86 | 87 | type GetProfilesResponse struct { 88 | Profiles []onvif.Profile 89 | } 90 | 91 | type AddVideoEncoderConfiguration struct { 92 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddVideoEncoderConfiguration"` 93 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 94 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 95 | } 96 | 97 | type AddVideoEncoderConfigurationResponse struct { 98 | } 99 | 100 | type RemoveVideoEncoderConfiguration struct { 101 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemoveVideoEncoderConfiguration"` 102 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 103 | } 104 | 105 | type RemoveVideoEncoderConfigurationResponse struct { 106 | } 107 | 108 | type AddVideoSourceConfiguration struct { 109 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddVideoSourceConfiguration"` 110 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 111 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 112 | } 113 | 114 | type AddVideoSourceConfigurationResponse struct { 115 | } 116 | 117 | type RemoveVideoSourceConfiguration struct { 118 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemoveVideoSourceConfiguration"` 119 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 120 | } 121 | 122 | type RemoveVideoSourceConfigurationResponse struct { 123 | } 124 | 125 | type AddAudioEncoderConfiguration struct { 126 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddAudioEncoderConfiguration"` 127 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 128 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 129 | } 130 | 131 | type AddAudioEncoderConfigurationResponse struct { 132 | } 133 | 134 | type RemoveAudioEncoderConfiguration struct { 135 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemoveAudioEncoderConfiguration"` 136 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 137 | } 138 | 139 | type RemoveAudioEncoderConfigurationResponse struct { 140 | } 141 | 142 | type AddAudioSourceConfiguration struct { 143 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddAudioSourceConfiguration"` 144 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 145 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 146 | } 147 | 148 | type AddAudioSourceConfigurationResponse struct { 149 | } 150 | 151 | type RemoveAudioSourceConfiguration struct { 152 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemoveAudioSourceConfiguration"` 153 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 154 | } 155 | 156 | type RemoveAudioSourceConfigurationResponse struct { 157 | } 158 | 159 | type AddPTZConfiguration struct { 160 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddPTZConfiguration"` 161 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 162 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 163 | } 164 | 165 | type AddPTZConfigurationResponse struct { 166 | } 167 | 168 | type RemovePTZConfiguration struct { 169 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemovePTZConfiguration"` 170 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 171 | } 172 | 173 | type RemovePTZConfigurationResponse struct { 174 | } 175 | 176 | type AddVideoAnalyticsConfiguration struct { 177 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddVideoAnalyticsConfiguration"` 178 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 179 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 180 | } 181 | 182 | type AddVideoAnalyticsConfigurationResponse struct { 183 | } 184 | 185 | type RemoveVideoAnalyticsConfiguration struct { 186 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemoveVideoAnalyticsConfiguration"` 187 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 188 | } 189 | 190 | type RemoveVideoAnalyticsConfigurationResponse struct { 191 | } 192 | 193 | type AddMetadataConfiguration struct { 194 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddMetadataConfiguration"` 195 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 196 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 197 | } 198 | 199 | type AddMetadataConfigurationResponse struct { 200 | } 201 | 202 | type RemoveMetadataConfiguration struct { 203 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemoveMetadataConfiguration"` 204 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 205 | } 206 | 207 | type RemoveMetadataConfigurationResponse struct { 208 | } 209 | 210 | type AddAudioOutputConfiguration struct { 211 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddAudioOutputConfiguration"` 212 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 213 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 214 | } 215 | 216 | type AddAudioOutputConfigurationResponse struct { 217 | } 218 | 219 | type RemoveAudioOutputConfiguration struct { 220 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemoveAudioOutputConfiguration"` 221 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 222 | } 223 | 224 | type RemoveAudioOutputConfigurationResponse struct { 225 | } 226 | 227 | type AddAudioDecoderConfiguration struct { 228 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl AddAudioDecoderConfiguration"` 229 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 230 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 231 | } 232 | 233 | type AddAudioDecoderConfigurationResponse struct { 234 | } 235 | 236 | type RemoveAudioDecoderConfiguration struct { 237 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl RemoveAudioDecoderConfiguration"` 238 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 239 | } 240 | 241 | type RemoveAudioDecoderConfigurationResponse struct { 242 | } 243 | 244 | type DeleteProfile struct { 245 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl DeleteProfile"` 246 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 247 | } 248 | 249 | type DeleteProfileResponse struct { 250 | } 251 | 252 | type GetVideoSourceConfigurations struct { 253 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoSourceConfigurations"` 254 | } 255 | 256 | type GetVideoSourceConfigurationsResponse struct { 257 | Configurations []onvif.VideoSourceConfiguration 258 | } 259 | 260 | type GetVideoEncoderConfigurations struct { 261 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoEncoderConfigurations"` 262 | } 263 | 264 | type GetVideoEncoderConfigurationsResponse struct { 265 | Configurations []onvif.VideoEncoderConfiguration 266 | } 267 | 268 | type GetAudioSourceConfigurations struct { 269 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioSourceConfigurations"` 270 | } 271 | 272 | type GetAudioSourceConfigurationsResponse struct { 273 | Configurations []onvif.AudioSourceConfiguration 274 | } 275 | 276 | type GetAudioEncoderConfigurations struct { 277 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioEncoderConfigurations"` 278 | } 279 | 280 | type GetAudioEncoderConfigurationsResponse struct { 281 | Configurations []onvif.AudioEncoderConfiguration 282 | } 283 | 284 | type GetVideoAnalyticsConfigurations struct { 285 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoAnalyticsConfigurations"` 286 | } 287 | 288 | type GetVideoAnalyticsConfigurationsResponse struct { 289 | Configurations []onvif.VideoAnalyticsConfiguration 290 | } 291 | 292 | type GetMetadataConfigurations struct { 293 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetMetadataConfigurations"` 294 | } 295 | 296 | type GetMetadataConfigurationsResponse struct { 297 | Configurations []onvif.MetadataConfiguration 298 | } 299 | 300 | type GetAudioOutputConfigurations struct { 301 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioOutputConfigurations"` 302 | } 303 | 304 | type GetAudioOutputConfigurationsResponse struct { 305 | Configurations []onvif.AudioOutputConfiguration 306 | } 307 | 308 | type GetAudioDecoderConfigurations struct { 309 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioDecoderConfigurations"` 310 | } 311 | 312 | type GetAudioDecoderConfigurationsResponse struct { 313 | Configurations []onvif.AudioDecoderConfiguration 314 | } 315 | 316 | type GetVideoSourceConfiguration struct { 317 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoSourceConfiguration"` 318 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 319 | } 320 | 321 | type GetVideoSourceConfigurationResponse struct { 322 | Configuration onvif.VideoSourceConfiguration 323 | } 324 | 325 | type GetVideoEncoderConfiguration struct { 326 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoEncoderConfiguration"` 327 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 328 | } 329 | 330 | type GetVideoEncoderConfigurationResponse struct { 331 | Configuration onvif.VideoEncoderConfiguration 332 | } 333 | 334 | type GetAudioSourceConfiguration struct { 335 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioSourceConfiguration"` 336 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 337 | } 338 | 339 | type GetAudioSourceConfigurationResponse struct { 340 | Configuration onvif.AudioSourceConfiguration 341 | } 342 | 343 | type GetAudioEncoderConfiguration struct { 344 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioEncoderConfiguration"` 345 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 346 | } 347 | 348 | type GetAudioEncoderConfigurationResponse struct { 349 | Configuration onvif.AudioEncoderConfiguration 350 | } 351 | 352 | type GetVideoAnalyticsConfiguration struct { 353 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoAnalyticsConfiguration"` 354 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 355 | } 356 | 357 | type GetVideoAnalyticsConfigurationResponse struct { 358 | Configuration onvif.VideoAnalyticsConfiguration 359 | } 360 | 361 | type GetMetadataConfiguration struct { 362 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetMetadataConfiguration"` 363 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 364 | } 365 | 366 | type GetMetadataConfigurationResponse struct { 367 | Configuration onvif.MetadataConfiguration 368 | } 369 | 370 | type GetAudioOutputConfiguration struct { 371 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioOutputConfiguration"` 372 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 373 | } 374 | 375 | type GetAudioOutputConfigurationResponse struct { 376 | Configuration onvif.AudioOutputConfiguration 377 | } 378 | 379 | type GetAudioDecoderConfiguration struct { 380 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioDecoderConfiguration"` 381 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 382 | } 383 | 384 | type GetAudioDecoderConfigurationResponse struct { 385 | Configuration onvif.AudioDecoderConfiguration 386 | } 387 | 388 | type GetCompatibleVideoEncoderConfigurations struct { 389 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetCompatibleVideoEncoderConfigurations"` 390 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 391 | } 392 | 393 | type GetCompatibleVideoEncoderConfigurationsResponse struct { 394 | Configurations []onvif.VideoEncoderConfiguration 395 | } 396 | 397 | type GetCompatibleVideoSourceConfigurations struct { 398 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetCompatibleVideoSourceConfigurations"` 399 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 400 | } 401 | 402 | type GetCompatibleVideoSourceConfigurationsResponse struct { 403 | Configurations []onvif.VideoSourceConfiguration 404 | } 405 | 406 | type GetCompatibleAudioEncoderConfigurations struct { 407 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetCompatibleAudioEncoderConfigurations"` 408 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 409 | } 410 | 411 | type GetCompatibleAudioEncoderConfigurationsResponse struct { 412 | Configurations []onvif.AudioEncoderConfiguration 413 | } 414 | 415 | type GetCompatibleAudioSourceConfigurations struct { 416 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetCompatibleAudioSourceConfigurations"` 417 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 418 | } 419 | 420 | type GetCompatibleAudioSourceConfigurationsResponse struct { 421 | Configurations []onvif.AudioSourceConfiguration 422 | } 423 | 424 | type GetCompatibleVideoAnalyticsConfigurations struct { 425 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetCompatibleVideoAnalyticsConfigurations"` 426 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 427 | } 428 | 429 | type GetCompatibleVideoAnalyticsConfigurationsResponse struct { 430 | Configurations []onvif.VideoAnalyticsConfiguration 431 | } 432 | 433 | type GetCompatibleMetadataConfigurations struct { 434 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetCompatibleMetadataConfigurations"` 435 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 436 | } 437 | 438 | type GetCompatibleMetadataConfigurationsResponse struct { 439 | Configurations []onvif.MetadataConfiguration 440 | } 441 | 442 | type GetCompatibleAudioOutputConfigurations struct { 443 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetCompatibleAudioOutputConfigurations"` 444 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 445 | } 446 | 447 | type GetCompatibleAudioOutputConfigurationsResponse struct { 448 | Configurations []onvif.AudioOutputConfiguration 449 | } 450 | 451 | type GetCompatibleAudioDecoderConfigurations struct { 452 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetCompatibleAudioDecoderConfigurations"` 453 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 454 | } 455 | 456 | type GetCompatibleAudioDecoderConfigurationsResponse struct { 457 | Configurations []onvif.AudioDecoderConfiguration 458 | } 459 | 460 | type SetVideoSourceConfiguration struct { 461 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetVideoSourceConfiguration"` 462 | Configuration onvif.VideoSourceConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl Configuration"` 463 | ForcePersistence bool `xml:"http://www.onvif.org/ver10/media/wsdl ForcePersistence"` 464 | } 465 | 466 | type SetVideoSourceConfigurationResponse struct { 467 | } 468 | 469 | type SetVideoEncoderConfiguration struct { 470 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetVideoEncoderConfiguration"` 471 | Configuration onvif.VideoEncoderConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl Configuration"` 472 | ForcePersistence bool `xml:"http://www.onvif.org/ver10/media/wsdl ForcePersistence"` 473 | } 474 | 475 | type SetVideoEncoderConfigurationResponse struct { 476 | } 477 | 478 | type SetAudioSourceConfiguration struct { 479 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetAudioSourceConfiguration"` 480 | Configuration onvif.AudioSourceConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl Configuration"` 481 | ForcePersistence bool `xml:"http://www.onvif.org/ver10/media/wsdl ForcePersistence"` 482 | } 483 | 484 | type SetAudioSourceConfigurationResponse struct { 485 | } 486 | 487 | type SetAudioEncoderConfiguration struct { 488 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetAudioEncoderConfiguration"` 489 | Configuration onvif.AudioEncoderConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl Configuration"` 490 | ForcePersistence bool `xml:"http://www.onvif.org/ver10/media/wsdl ForcePersistence"` 491 | } 492 | 493 | type SetAudioEncoderConfigurationResponse struct { 494 | } 495 | 496 | type SetVideoAnalyticsConfiguration struct { 497 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetVideoAnalyticsConfiguration"` 498 | Configuration onvif.VideoAnalyticsConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl Configuration"` 499 | ForcePersistence bool `xml:"http://www.onvif.org/ver10/media/wsdl ForcePersistence"` 500 | } 501 | 502 | type SetVideoAnalyticsConfigurationResponse struct { 503 | } 504 | 505 | type SetMetadataConfiguration struct { 506 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetDeviceInformation"` 507 | Configuration onvif.MetadataConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl Configuration"` 508 | ForcePersistence bool `xml:"http://www.onvif.org/ver10/media/wsdl ForcePersistence"` 509 | } 510 | 511 | type SetMetadataConfigurationResponse struct { 512 | } 513 | 514 | type SetAudioOutputConfiguration struct { 515 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetAudioOutputConfiguration"` 516 | Configuration onvif.AudioOutputConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl Configuration"` 517 | ForcePersistence bool `xml:"http://www.onvif.org/ver10/media/wsdl ForcePersistence"` 518 | } 519 | 520 | type SetAudioOutputConfigurationResponse struct { 521 | } 522 | 523 | type SetAudioDecoderConfiguration struct { 524 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetAudioDecoderConfiguration"` 525 | Configuration onvif.AudioDecoderConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl Configuration"` 526 | ForcePersistence bool `xml:"http://www.onvif.org/ver10/media/wsdl ForcePersistence"` 527 | } 528 | 529 | type SetAudioDecoderConfigurationResponse struct { 530 | } 531 | 532 | type GetVideoSourceConfigurationOptions struct { 533 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoSourceConfigurationOptions"` 534 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 535 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 536 | } 537 | 538 | type GetVideoSourceConfigurationOptionsResponse struct { 539 | Options onvif.VideoSourceConfigurationOptions 540 | } 541 | 542 | type GetVideoEncoderConfigurationOptions struct { 543 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoEncoderConfigurationOptions"` 544 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 545 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 546 | } 547 | 548 | type GetVideoEncoderConfigurationOptionsResponse struct { 549 | Options onvif.VideoEncoderConfigurationOptions 550 | } 551 | 552 | type GetAudioSourceConfigurationOptions struct { 553 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioSourceConfigurationOptions"` 554 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 555 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 556 | } 557 | 558 | type GetAudioSourceConfigurationOptionsResponse struct { 559 | Options onvif.AudioSourceConfigurationOptions 560 | } 561 | 562 | type GetAudioEncoderConfigurationOptions struct { 563 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioEncoderConfigurationOptions"` 564 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 565 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 566 | } 567 | 568 | type GetAudioEncoderConfigurationOptionsResponse struct { 569 | Options onvif.AudioEncoderConfigurationOptions 570 | } 571 | 572 | type GetMetadataConfigurationOptions struct { 573 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetMetadataConfigurationOptions"` 574 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 575 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 576 | } 577 | 578 | type GetMetadataConfigurationOptionsResponse struct { 579 | Options onvif.MetadataConfigurationOptions 580 | } 581 | 582 | type GetAudioOutputConfigurationOptions struct { 583 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioOutputConfigurationOptions"` 584 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 585 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 586 | } 587 | 588 | type GetAudioOutputConfigurationOptionsResponse struct { 589 | Options onvif.AudioOutputConfigurationOptions 590 | } 591 | 592 | type GetAudioDecoderConfigurationOptions struct { 593 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetAudioDecoderConfigurationOptions"` 594 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 595 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 596 | } 597 | 598 | type GetAudioDecoderConfigurationOptionsResponse struct { 599 | Options onvif.AudioDecoderConfigurationOptions 600 | } 601 | 602 | type GetGuaranteedNumberOfVideoEncoderInstances struct { 603 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetGuaranteedNumberOfVideoEncoderInstances"` 604 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 605 | } 606 | 607 | type GetGuaranteedNumberOfVideoEncoderInstancesResponse struct { 608 | TotalNumber int 609 | JPEG int 610 | H264 int 611 | MPEG4 int 612 | } 613 | 614 | type GetStreamUri struct { 615 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetStreamUri"` 616 | StreamSetup onvif.StreamSetup `xml:"http://www.onvif.org/ver10/media/wsdl StreamSetup"` 617 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 618 | } 619 | 620 | type GetStreamUriResponse struct { 621 | MediaUri onvif.MediaUri 622 | } 623 | 624 | type StartMulticastStreaming struct { 625 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl StartMulticastStreaming"` 626 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 627 | } 628 | 629 | type StartMulticastStreamingResponse struct { 630 | } 631 | 632 | type StopMulticastStreaming struct { 633 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl StopMulticastStreaming"` 634 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 635 | } 636 | 637 | type StopMulticastStreamingResponse struct { 638 | } 639 | 640 | type SetSynchronizationPoint struct { 641 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetSynchronizationPoint"` 642 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 643 | } 644 | 645 | type SetSynchronizationPointResponse struct { 646 | } 647 | 648 | type GetSnapshotUri struct { 649 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetSnapshotUri"` 650 | ProfileToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ProfileToken"` 651 | } 652 | 653 | type GetSnapshotUriResponse struct { 654 | MediaUri onvif.MediaUri 655 | } 656 | 657 | type GetVideoSourceModes struct { 658 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetVideoSourceModes"` 659 | VideoSourceToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl VideoSourceToken"` 660 | } 661 | 662 | type GetVideoSourceModesResponse struct { 663 | VideoSourceModes []onvif.VideoSourceMode 664 | } 665 | 666 | type SetVideoSourceMode struct { 667 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetVideoSourceMode"` 668 | VideoSourceToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl VideoSourceToken"` 669 | VideoSourceModeToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl VideoSourceModeToken"` 670 | } 671 | 672 | type SetVideoSourceModeResponse struct { 673 | Reboot bool 674 | } 675 | 676 | type GetOSDs struct { 677 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetOSDs"` 678 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 679 | } 680 | 681 | type GetOSDsResponse struct { 682 | OSDs []onvif.OSDConfiguration 683 | } 684 | 685 | type GetOSD struct { 686 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetOSD"` 687 | OSDToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl OSDToken"` 688 | } 689 | 690 | type GetOSDResponse struct { 691 | OSD onvif.OSDConfiguration 692 | } 693 | 694 | type GetOSDOptions struct { 695 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl GetOSDOptions"` 696 | ConfigurationToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl ConfigurationToken"` 697 | } 698 | 699 | type GetOSDOptionsResponse struct { 700 | OSDOptions onvif.OSDConfigurationOptions 701 | } 702 | 703 | type SetOSD struct { 704 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl SetOSD"` 705 | OSD onvif.OSDConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl OSD"` 706 | } 707 | 708 | type SetOSDResponse struct { 709 | } 710 | 711 | type CreateOSD struct { 712 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl CreateOSD"` 713 | OSD onvif.OSDConfiguration `xml:"http://www.onvif.org/ver10/media/wsdl OSD"` 714 | } 715 | 716 | type CreateOSDResponse struct { 717 | OSDToken onvif.ReferenceToken 718 | } 719 | 720 | type DeleteOSD struct { 721 | XMLName string `xml:"http://www.onvif.org/ver10/media/wsdl DeleteOSD"` 722 | OSDToken onvif.ReferenceToken `xml:"http://www.onvif.org/ver10/media/wsdl OSDToken"` 723 | } 724 | 725 | type DeleteOSDResponse struct { 726 | } 727 | -------------------------------------------------------------------------------- /onvif/common.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Unique identifier for a physical or logical resource. 11 | Tokens should be assigned such that they are unique within a device. Tokens must be at least unique within its class. 12 | Length up to 64 characters. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Pan/tilt coordinate space selector. The following options are defined:
    28 |
  • http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace
  • 29 |
  • http://www.onvif.org/ver10/tptz/PanTiltSpaces/TranslationGenericSpace
  • 30 |
  • http://www.onvif.org/ver10/tptz/PanTiltSpaces/VelocityGenericSpace
  • 31 |
  • http://www.onvif.org/ver10/tptz/PanTiltSpaces/GenericSpeedSpace
  • 32 |
33 |
34 |
35 |
36 |
37 | 38 | 39 | 40 | 41 | 42 | Zoom coordinate space selector. The following options are defined:
    43 |
  • http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace
  • 44 |
  • http://www.onvif.org/ver10/tptz/ZoomSpaces/TranslationGenericSpace
  • 45 |
  • http://www.onvif.org/ver10/tptz/ZoomSpaces/VelocityGenericSpace
  • 46 |
  • http://www.onvif.org/ver10/tptz/ZoomSpaces/ZoomGenericSpeedSpace
  • 47 |
48 |
49 |
50 |
51 |
52 | 53 | 54 | 55 | 56 | Pan and tilt position. The x component corresponds to pan and the y component to tilt. 57 | 58 | 59 | 60 | 61 | 62 | A zoom position. 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 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. 74 | 75 | 76 | 77 | 78 | 79 | 80 | Indicates if the Pan/Tilt/Zoom device unit is currently moving, idle or in an unknown state. 81 | 82 | 83 | 84 | 85 | 86 | 87 | States a current PTZ error. 88 | 89 | 90 | 91 | 92 | 93 | 94 | Specifies the UTC time when this status was generated. 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | East west location as angle. 185 | 186 | 187 | 188 | 189 | North south location as angle. 190 | 191 | 192 | 193 | 194 | Hight in meters above sea level. 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | Rotation around the x axis. 207 | 208 | 209 | 210 | 211 | Rotation around the y axis. 212 | 213 | 214 | 215 | 216 | Rotation around the z axis. 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | East west location as angle. 229 | 230 | 231 | 232 | 233 | North south location as angle. 234 | 235 | 236 | 237 | 238 | Offset in meters from the sea level. 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | Rotation around the y axis. 251 | 252 | 253 | 254 | 255 | Rotation around the z axis. 256 | 257 | 258 | 259 | 260 | Rotation around the x axis. 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | Location on earth. 278 | 279 | 280 | Orientation relative to earth. 281 | 282 | 283 | Indoor location offset. 284 | 285 | 286 | Indoor orientation offset. 287 | 288 | 289 | 290 | Entity type the entry refers to, use a value from the tt:Entity enumeration. 291 | 292 | 293 | Optional entity token. 294 | 295 | 296 | If this value is true the entity cannot be deleted. 297 | 298 | 299 | Optional reference to the XAddr of another devices DeviceManagement service. 300 | 301 | 302 | If set the geo location is obtained internally. 303 | 304 | 305 | 306 |
307 | -------------------------------------------------------------------------------- /onvif/itemlist.go: -------------------------------------------------------------------------------- 1 | package onvif 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/faceterteam/onvif4go/xsd" 7 | ) 8 | 9 | type ItemList struct { 10 | SimpleItems map[string]string `xml:"http://www.onvif.org/ver10/schema SimpleItem"` 11 | ElementItems map[string][]xsd.AnyType `xml:"http://www.onvif.org/ver10/schema ElementItem"` 12 | Extension *ItemListExtension `xml:"http://www.onvif.org/ver10/schema Extension"` 13 | } 14 | 15 | func (l *ItemList) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 16 | *l = ItemList{} 17 | 18 | var ( 19 | token xml.Token 20 | err error 21 | ) 22 | 23 | Loop: 24 | for { 25 | if token, err = d.Token(); err != nil { 26 | return err 27 | } 28 | if token == nil { 29 | break 30 | } 31 | 32 | switch se := token.(type) { 33 | case xml.StartElement: 34 | if se.Name.Space != "http://www.onvif.org/ver10/schema" { 35 | return xml.UnmarshalError("expected tt:SimpleItem, tt:ElementItem... but receive") 36 | } 37 | 38 | if se.Name.Local == "SimpleItem" { 39 | simpleItem := &ItemListSimpleItem{} 40 | err = d.DecodeElement(simpleItem, &se) 41 | if err != nil { 42 | return err 43 | } 44 | if l.SimpleItems == nil { 45 | l.SimpleItems = make(map[string]string, 0) 46 | } 47 | l.SimpleItems[simpleItem.Name] = simpleItem.Value 48 | } else if se.Name.Local == "ElementItem" { 49 | elementItem := &ItemListElementItem{} 50 | err = d.DecodeElement(elementItem, &se) 51 | if err != nil { 52 | return err 53 | } 54 | if l.ElementItems == nil { 55 | l.ElementItems = make(map[string][]xsd.AnyType, 0) 56 | } 57 | l.ElementItems[elementItem.Name] = elementItem.Elements 58 | } else if se.Name.Local == "Extension" { 59 | err = d.DecodeElement(l.Extension, &se) 60 | if err != nil { 61 | return err 62 | } 63 | } else { 64 | return xml.UnmarshalError("expected tt:SimpleItem, tt:ElementItem... but receive") 65 | } 66 | case xml.EndElement: 67 | break Loop 68 | } 69 | } 70 | 71 | return nil 72 | } 73 | 74 | type ItemListSimpleItem struct { 75 | Name string `xml:"Name,attr"` 76 | Value string `xml:"Value,attr"` 77 | } 78 | 79 | type ItemListElementItem struct { 80 | Name string `xml:"Name,attr"` 81 | Elements []xsd.AnyType `xml:",any"` 82 | } 83 | 84 | type ItemListExtension xsd.AnyType 85 | -------------------------------------------------------------------------------- /onvif/message.go: -------------------------------------------------------------------------------- 1 | package onvif 2 | 3 | import ( 4 | "github.com/faceterteam/onvif4go/xsd" 5 | ) 6 | 7 | type Message struct { 8 | UtcTime xsd.DateTime `xml:"UtcTime,attr"` 9 | PropertyOperation *string `xml:"PropertyOperation,attr"` 10 | Source *ItemList `xml:"http://www.onvif.org/ver10/schema Source"` 11 | Key *ItemList `xml:"http://www.onvif.org/ver10/schema Key"` 12 | Data *ItemList `xml:"http://www.onvif.org/ver10/schema Data"` 13 | Extension *MessageExtension `xml:"http://www.onvif.org/ver10/schema Extension"` 14 | } 15 | 16 | type MessageExtension xsd.AnyType 17 | -------------------------------------------------------------------------------- /onvif/posix_timezone.go: -------------------------------------------------------------------------------- 1 | package onvif 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type PosixTimezone struct { 12 | Name string 13 | Offset posixTimezoneOffset 14 | Dailing *posixTimezoneDailing 15 | } 16 | 17 | type posixTimezoneOffset struct { 18 | Hours int 19 | Minutes int 20 | } 21 | 22 | type posixTimezoneDailing struct { 23 | Name string 24 | Offset posixTimezoneOffset 25 | From posixTimezoneTime 26 | To posixTimezoneTime 27 | } 28 | 29 | type posixTimezoneTime struct { 30 | Month int 31 | Week int 32 | Weekday int 33 | Hours int 34 | Minutes int 35 | Seconds int 36 | } 37 | 38 | func newPosixTimezoneDailing(st *posixTimezoneOffset, name string) *posixTimezoneDailing { 39 | return &posixTimezoneDailing{ 40 | Name: name, 41 | Offset: posixTimezoneOffset{ 42 | Hours: st.Hours + 1, //TODO: + или - 43 | }, 44 | From: posixTimezoneTime{ 45 | Month: 3, 46 | Week: 2, 47 | Weekday: 0, 48 | Hours: 2, 49 | }, 50 | To: posixTimezoneTime{ 51 | Month: 11, 52 | Week: 1, 53 | Weekday: 0, 54 | Hours: 2, 55 | }, 56 | } 57 | } 58 | 59 | func ParsePosixTimezone(timezone string) (*PosixTimezone, error) { 60 | type PosixTimezonePart int 61 | const ( 62 | ST PosixTimezonePart = iota + 1 63 | STOFFSET 64 | STOFFSETMINUTES 65 | DT 66 | DTOFFSET 67 | DTOFFSETMINUTES 68 | ) 69 | 70 | var err error 71 | tz := PosixTimezone{} 72 | 73 | parts := strings.Split(timezone, `,`) 74 | if len(parts) != 1 && len(parts) != 3 { 75 | return nil, errors.New("invalid format") 76 | } 77 | 78 | local := parts[0] 79 | state, start := ST, 0 80 | 81 | for i, ch := range local { 82 | nstate, nstart := state, start 83 | 84 | switch state { 85 | case ST: 86 | if ch < 'A' || ch > 'Z' { 87 | tz.Name = local[start:i] 88 | nstate, nstart = STOFFSET, i 89 | } 90 | case STOFFSET: 91 | if ch >= 'A' && ch <= 'Z' { 92 | tz.Offset.Hours, err = strconv.Atoi(local[start:i]) 93 | nstate, nstart = DT, i 94 | } 95 | if ch == ':' || ch == ' ' { 96 | tz.Offset.Hours, err = strconv.Atoi(local[start:i]) 97 | nstate, nstart = STOFFSETMINUTES, i+1 98 | } 99 | case STOFFSETMINUTES: 100 | if ch >= 'A' && ch <= 'Z' { 101 | tz.Offset.Minutes, err = strconv.Atoi(local[start:i]) 102 | nstate, nstart = DT, i 103 | } 104 | case DT: 105 | if ch < 'A' && ch > 'Z' { 106 | tz.Dailing = newPosixTimezoneDailing(&tz.Offset, local[start:i]) 107 | nstate, nstart = DTOFFSET, i 108 | } 109 | case DTOFFSET: 110 | if ch == ':' || ch == ' ' { 111 | tz.Dailing.Offset.Hours, err = strconv.Atoi(local[start:i]) 112 | nstate, nstart = DTOFFSETMINUTES, i+1 113 | } 114 | case DTOFFSETMINUTES: 115 | } 116 | 117 | if err != nil { 118 | //TODO: add state, start to err desc 119 | return nil, err 120 | } 121 | state, start = nstate, nstart 122 | } 123 | 124 | switch state { 125 | case ST: 126 | tz.Name = local[start:] 127 | case STOFFSET: 128 | tz.Offset.Hours, err = strconv.Atoi(local[start:]) 129 | case STOFFSETMINUTES: 130 | tz.Offset.Minutes, err = strconv.Atoi(local[start:]) 131 | case DT: 132 | tz.Dailing = newPosixTimezoneDailing(&tz.Offset, local[start:]) 133 | case DTOFFSET: 134 | tz.Dailing.Offset.Hours, err = strconv.Atoi(local[start:]) 135 | case DTOFFSETMINUTES: 136 | tz.Dailing.Offset.Minutes, err = strconv.Atoi(local[start:]) 137 | } 138 | if err != nil { 139 | //TODO: add state, start to err desc 140 | return nil, err 141 | } 142 | 143 | if len(parts) > 1 { 144 | err = parsePosixTimezoneTime(&tz.Dailing.From, parts[1]) 145 | if err != nil { 146 | return &tz, err 147 | } 148 | err = parsePosixTimezoneTime(&tz.Dailing.To, parts[2]) 149 | if err != nil { 150 | return &tz, err 151 | } 152 | } 153 | 154 | return &tz, nil 155 | } 156 | 157 | // date/time, time is optional. 158 | // Here, date is in the Mm.n.d format, where: 159 | // * Mm (1-12) for 12 months 160 | // * n (1-5) 1 for the first week and 5 for the last week in the month 161 | // * d (0-6) 0 for Sunday and 6 for Saturday 162 | // Example: M3.2.0/2:00:00 163 | func parsePosixTimezoneTime(t *posixTimezoneTime, timePart string) error { 164 | type PosixTimezoneTimePart int 165 | const ( 166 | M PosixTimezoneTimePart = iota + 1 167 | month 168 | week 169 | weekend 170 | hours 171 | minutes 172 | seconds 173 | ) 174 | 175 | state, start := M, 0 176 | 177 | for i, ch := range timePart { 178 | nstate, nstart := state, start 179 | var err error 180 | 181 | switch state { 182 | case M: 183 | if ch != 'M' { 184 | return errors.New("invalid format") 185 | } 186 | nstate, nstart = month, i+1 187 | case month: 188 | if ch == '.' { 189 | t.Month, err = strconv.Atoi(timePart[start:i]) 190 | nstate, nstart = week, i+1 191 | } 192 | case week: 193 | if ch == '.' { 194 | t.Week, err = strconv.Atoi(timePart[start:i]) 195 | nstate, nstart = weekend, i+1 196 | } 197 | case weekend: 198 | if ch == '/' { 199 | t.Weekday, err = strconv.Atoi(timePart[start:i]) 200 | nstate, nstart = hours, i+1 201 | } 202 | case hours: 203 | if ch == ':' { 204 | t.Hours, err = strconv.Atoi(timePart[start:i]) 205 | nstate, nstart = minutes, i+1 206 | } 207 | case minutes: 208 | if ch == ':' { 209 | t.Minutes, err = strconv.Atoi(timePart[start:i]) 210 | nstate, nstart = seconds, i+1 211 | } 212 | case seconds: 213 | } 214 | 215 | if err != nil { 216 | //TODO: add state, start to err desc 217 | return err 218 | } 219 | state, start = nstate, nstart 220 | } 221 | 222 | var err error 223 | switch state { 224 | case weekend: 225 | t.Weekday, err = strconv.Atoi(timePart[start:]) 226 | case hours: 227 | t.Hours, err = strconv.Atoi(timePart[start:]) 228 | t.Minutes, t.Seconds = 0, 0 229 | case minutes: 230 | t.Minutes, err = strconv.Atoi(timePart[start:]) 231 | t.Seconds = 0 232 | case seconds: 233 | t.Seconds, err = strconv.Atoi(timePart[start:]) 234 | } 235 | if err != nil { 236 | //TODO: add state, start to err desc 237 | return err 238 | } 239 | 240 | return nil 241 | } 242 | 243 | func getTimeOfYear(year int, t posixTimezoneTime) time.Time { 244 | res := time.Date( 245 | year, time.Month(t.Month), 1, 246 | t.Hours, t.Minutes, t.Seconds, 0, 247 | time.UTC) 248 | 249 | weekday := int(res.Weekday()) 250 | res = res.AddDate(0, 0, (7-weekday+t.Weekday)%7) 251 | 252 | if t.Week < 5 { 253 | res = res.AddDate(0, 0, 7*(t.Week-1)) 254 | } else { 255 | res = res.AddDate(0, 0, 7*(t.Week-1)) 256 | tt := res.AddDate(0, 0, 7) 257 | if int(tt.Month()) != t.Month { 258 | return res 259 | } else { 260 | return tt 261 | } 262 | } 263 | 264 | return res 265 | } 266 | 267 | func (tz *PosixTimezone) LocalToUTC(t time.Time) time.Time { 268 | offset := tz.Offset 269 | 270 | if tz.Dailing != nil { 271 | from := getTimeOfYear(t.Year(), tz.Dailing.From) 272 | to := getTimeOfYear(t.Year(), tz.Dailing.To) 273 | diffFrom, diffTo := t.Sub(from), t.Sub(to) 274 | 275 | fmt.Println(t, from, to) 276 | 277 | if tz.Dailing.From.Month < tz.Dailing.To.Month { 278 | if int64(diffFrom) > 0 && int64(diffTo) < 0 { 279 | offset = tz.Dailing.Offset 280 | } 281 | } else { 282 | if int64(diffFrom) > 0 || int64(diffTo) < 0 { 283 | offset = tz.Dailing.Offset 284 | } 285 | } 286 | } 287 | 288 | duration := time.Duration(offset.Hours)*time.Hour + time.Duration(offset.Minutes)*time.Minute 289 | 290 | return t.Add(duration) 291 | } 292 | -------------------------------------------------------------------------------- /onvifClient.go: -------------------------------------------------------------------------------- 1 | package onvif4go 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/faceterteam/onvif4go/soap" 7 | ) 8 | 9 | type onvifCaller interface { 10 | Call(request, response interface{}, headers ...interface{}) error 11 | 12 | WithoutAuth() onvifCaller 13 | 14 | SetLogger(logRequest, logResponse func(message string)) 15 | } 16 | 17 | type onvifAuth struct { 18 | login string 19 | password string 20 | timeDiff time.Duration 21 | } 22 | 23 | type onvifClient struct { 24 | soapClient *soap.SoapClient 25 | auth *onvifAuth 26 | } 27 | 28 | func NewOnvifClient(endpoint string, auth *onvifAuth) *onvifClient { 29 | return &onvifClient{ 30 | soapClient: soap.NewSoapClient(endpoint), 31 | auth: auth, 32 | } 33 | } 34 | 35 | func (c *onvifClient) Call(request, response interface{}, headers ...interface{}) error { 36 | if c.auth.login != "" { 37 | headers = append(headers, soap.MakeWSSecurity(c.auth.login, c.auth.password, c.auth.timeDiff)) 38 | } 39 | 40 | return c.soapClient.Do(request, response, headers...) 41 | } 42 | 43 | func (c *onvifClient) SetLogger(logRequest, logResponse func(message string)) { 44 | c.soapClient.LogRequest = logRequest 45 | c.soapClient.LogResponse = logResponse 46 | } 47 | 48 | func (c *onvifClient) WithoutAuth() onvifCaller { 49 | return &onvifClient{ 50 | soapClient: c.soapClient, 51 | auth: &onvifAuth{}, 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /onvifdevice.go: -------------------------------------------------------------------------------- 1 | package onvif4go 2 | 3 | import ( 4 | "errors" 5 | "net/url" 6 | "reflect" 7 | "strings" 8 | "time" 9 | 10 | "github.com/faceterteam/onvif4go/onvif" 11 | "github.com/faceterteam/onvif4go/xsd" 12 | ) 13 | 14 | type OnvifDevice struct { 15 | xaddr string 16 | auth onvifAuth 17 | 18 | Capabilities onvif.Capabilities 19 | 20 | endpoints map[string]onvifCaller 21 | 22 | Device *DeviceService 23 | Media *MediaService 24 | Events *EventsService 25 | } 26 | 27 | func (onvifDevice *OnvifDevice) Call(request, response interface{}) error { 28 | pkgPath := strings.Split(reflect.TypeOf(request).PkgPath(), "/") 29 | pkg := pkgPath[len(pkgPath)-1] 30 | 31 | client, ok := onvifDevice.On(strings.ToLower(pkg)) 32 | if !ok { 33 | return errors.New("no endpoint") 34 | } 35 | return client.Call(request, response) 36 | } 37 | 38 | func (onvifDevice *OnvifDevice) On(endpoint string) (caller onvifCaller, ok bool) { 39 | caller, ok = onvifDevice.endpoints[endpoint] 40 | return 41 | } 42 | 43 | func NewOnvifDevice(xaddr string) *OnvifDevice { 44 | return &OnvifDevice{ 45 | xaddr: xaddr, 46 | endpoints: make(map[string]onvifCaller), 47 | } 48 | } 49 | 50 | func (onvifDevice *OnvifDevice) Auth(login, password string) { 51 | onvifDevice.auth.login = login 52 | onvifDevice.auth.password = password 53 | } 54 | 55 | func fixXAddr(uri xsd.AnyURI, xaddr string) string { 56 | u, _ := url.Parse(string(uri)) 57 | u.Host = xaddr 58 | return u.String() 59 | } 60 | 61 | func (onvifDevice *OnvifDevice) Initialize() error { 62 | deviceService := NewDeviceService(onvifDevice) 63 | 64 | currentTime := time.Now().UTC() 65 | systemDateAndTimeResponse, err := deviceService.WithoutAuth().GetSystemDateAndTime() 66 | if err == nil { 67 | //TODO: warn if GetSystemDateAndTime return err 68 | deviceTime, _ := systemDateAndTimeResponse.SystemDateAndTime.GetUTCTime() 69 | //TODO: error mean parse error of Timezone. deviceTime equal time.Now().UTC() 70 | onvifDevice.auth.timeDiff = deviceTime.Sub(currentTime) 71 | } 72 | 73 | capabilitiesResponse, err := deviceService.GetCapabilities() 74 | if err != nil { 75 | return err 76 | } 77 | 78 | capabilities := capabilitiesResponse.Capabilities 79 | if capabilities.Device != nil { 80 | onvifDevice.endpoints["device"] = deviceService.Client 81 | onvifDevice.Device = deviceService 82 | } 83 | if capabilities.Events != nil { 84 | xaddr := fixXAddr(capabilities.Events.XAddr, onvifDevice.xaddr) 85 | onvifDevice.Events = NewEventsService(xaddr, onvifDevice) 86 | onvifDevice.endpoints["events"] = onvifDevice.Events.Client 87 | } 88 | if capabilities.Media != nil { 89 | mediaURI := fixXAddr(capabilities.Media.XAddr, onvifDevice.xaddr) 90 | onvifDevice.Media = NewMediaService(mediaURI, onvifDevice) 91 | onvifDevice.endpoints["media"] = onvifDevice.Media.Client 92 | } 93 | if capabilities.Imaging != nil { 94 | xaddr := fixXAddr(capabilities.Imaging.XAddr, onvifDevice.xaddr) 95 | onvifDevice.endpoints["imaging"] = NewOnvifClient(xaddr, &onvifDevice.auth) 96 | } 97 | if capabilities.Analytics != nil { 98 | xaddr := fixXAddr(capabilities.Analytics.XAddr, onvifDevice.xaddr) 99 | onvifDevice.endpoints["analytics"] = NewOnvifClient(xaddr, &onvifDevice.auth) 100 | } 101 | if capabilities.PTZ != nil { 102 | xaddr := fixXAddr(capabilities.PTZ.XAddr, onvifDevice.xaddr) 103 | onvifDevice.endpoints["ptz"] = NewOnvifClient(xaddr, &onvifDevice.auth) 104 | } 105 | 106 | if capabilities.Extension != nil { 107 | extension := capabilities.Extension 108 | if extension.AnalyticsDevice != nil { 109 | xaddr := fixXAddr(extension.AnalyticsDevice.XAddr, onvifDevice.xaddr) 110 | onvifDevice.endpoints["analyticsdevice"] = NewOnvifClient(xaddr, &onvifDevice.auth) 111 | } 112 | if extension.DeviceIO != nil { 113 | xaddr := fixXAddr(extension.DeviceIO.XAddr, onvifDevice.xaddr) 114 | onvifDevice.endpoints["deviceio"] = NewOnvifClient(xaddr, &onvifDevice.auth) 115 | } 116 | if extension.Display != nil { 117 | xaddr := fixXAddr(extension.Display.XAddr, onvifDevice.xaddr) 118 | onvifDevice.endpoints["display"] = NewOnvifClient(xaddr, &onvifDevice.auth) 119 | } 120 | if extension.Receiver != nil { 121 | xaddr := fixXAddr(extension.Receiver.XAddr, onvifDevice.xaddr) 122 | onvifDevice.endpoints["receiver"] = NewOnvifClient(xaddr, &onvifDevice.auth) 123 | } 124 | if extension.Recording != nil { 125 | xaddr := fixXAddr(extension.Recording.XAddr, onvifDevice.xaddr) 126 | onvifDevice.endpoints["recording"] = NewOnvifClient(xaddr, &onvifDevice.auth) 127 | } 128 | if extension.Replay != nil { 129 | xaddr := fixXAddr(extension.Replay.XAddr, onvifDevice.xaddr) 130 | onvifDevice.endpoints["replay"] = NewOnvifClient(xaddr, &onvifDevice.auth) 131 | } 132 | if extension.Search != nil { 133 | xaddr := fixXAddr(extension.Search.XAddr, onvifDevice.xaddr) 134 | onvifDevice.endpoints["search"] = NewOnvifClient(xaddr, &onvifDevice.auth) 135 | } 136 | } 137 | 138 | onvifDevice.Capabilities = capabilities 139 | 140 | return nil 141 | } 142 | -------------------------------------------------------------------------------- /pullPointSubscription.go: -------------------------------------------------------------------------------- 1 | package onvif4go 2 | 3 | import ( 4 | "time" 5 | 6 | tev "github.com/faceterteam/onvif4go/events" 7 | "github.com/faceterteam/onvif4go/xsd" 8 | ) 9 | 10 | type PullPointSubscription struct { 11 | Client onvifCaller 12 | Settings tev.CreatePullPointSubscriptionResponse 13 | } 14 | 15 | func NewPullPointSubscription(settings tev.CreatePullPointSubscriptionResponse, onvifDevice *OnvifDevice) *PullPointSubscription { 16 | return &PullPointSubscription{ 17 | Client: NewOnvifClient(string(settings.SubscriptionReference.Address.Content), &onvifDevice.auth), 18 | Settings: settings, 19 | } 20 | } 21 | 22 | func (s *PullPointSubscription) makeAddressingHeaders(action string) []interface{} { 23 | return tev.MakeAnonymousAddressingHeaders(action, string(s.Settings.SubscriptionReference.Address.Content)) 24 | } 25 | 26 | /* 27 | PullMessages pulls one or more messages from a PullPoint. 28 | The device shall provide the following PullMessages command for all SubscriptionManager 29 | endpoints returned by the CreatePullPointSubscription command. This method shall not wait until 30 | the requested number of messages is available but return as soon as at least one message is available. 31 | 32 | The command shall at least support a Timeout of one minute. In case a device supports retrieval 33 | of less messages than requested it shall return these without generating a fault. 34 | */ 35 | func (s *PullPointSubscription) PullMessages(timeout time.Duration, messageLimit int) (res tev.PullMessagesResponse, err error) { 36 | headers := s.makeAddressingHeaders("http://www.onvif.org/ver10/events/wsdl/PullPointSubscription/PullMessagesRequest") 37 | err = s.Client.Call(tev.PullMessages{ 38 | Timeout: xsd.Duration(timeout), 39 | MessageLimit: messageLimit, 40 | }, &res, headers...) 41 | return 42 | // 43 | } 44 | 45 | /* 46 | Unsubscribe shall terminate the lifetime of a pull point 47 | */ 48 | func (s *PullPointSubscription) Unsubscribe() (err error) { 49 | headers := s.makeAddressingHeaders("http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/UnsubscribeRequest") 50 | var res tev.UnsubscribeResponse 51 | err = s.Client.Call(tev.UnsubscribeRequest{}, &res, headers...) 52 | return 53 | // 54 | // 55 | } 56 | 57 | /* 58 | Seek readjusts the pull pointer into the past. 59 | A device supporting persistent notification storage shall provide the 60 | following Seek command for all SubscriptionManager endpoints returned by 61 | the CreatePullPointSubscription command. The optional Reverse argument can 62 | be used to reverse the pull direction of the PullMessages command. 63 | 64 | The UtcTime argument will be matched against the UtcTime attribute on a 65 | NotificationMessage. 66 | */ 67 | func (s *PullPointSubscription) Seek(time time.Time, reverse bool) (err error) { 68 | headers := s.makeAddressingHeaders("http://www.onvif.org/ver10/events/wsdl/PullPointSubscription/SeekRequest") 69 | var res tev.SeekResponse 70 | err = s.Client.Call(tev.Seek{ 71 | UtcTime: xsd.MakeDateTime(time), 72 | Reverse: reverse, 73 | }, &res, headers...) 74 | return 75 | } 76 | 77 | /* 78 | SetSynchronizationPoint inform a client about property creation, changes and 79 | deletion in a uniform way. When a client wants to synchronize its properties with the 80 | properties of the device, it can request a synchronization point which repeats the current 81 | status of all properties to which a client has subscribed. The PropertyOperation of all 82 | produced notifications is set to “Initialized”. The Synchronization Point is 83 | requested directly from the SubscriptionManager which was returned in either the 84 | SubscriptionResponse or in the CreatePullPointSubscriptionResponse. The property update is 85 | transmitted via the notification transportation of the notification interface. This method is mandatory. 86 | */ 87 | func (s *PullPointSubscription) SetSynchronizationPoint() (err error) { 88 | headers := s.makeAddressingHeaders("http://www.onvif.org/ver10/events/wsdl/PullPointSubscription/SetSynchronizationPointRequest") 89 | var res tev.SetSynchronizationPointResponse 90 | err = s.Client.Call(tev.SetSynchronizationPoint{}, &res, headers...) 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /soap/client.go: -------------------------------------------------------------------------------- 1 | package soap 2 | 3 | import ( 4 | "bytes" 5 | "encoding/xml" 6 | "errors" 7 | "io/ioutil" 8 | "net/http" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | type SoapClient struct { 14 | Endpoint string 15 | LogRequest func(request string) 16 | LogResponse func(response string) 17 | } 18 | 19 | func NewSoapClient(endpoint string) *SoapClient { 20 | return &SoapClient{ 21 | Endpoint: endpoint, 22 | } 23 | } 24 | 25 | func readResponse(resp *http.Response) string { 26 | b, err := ioutil.ReadAll(resp.Body) 27 | if err != nil { 28 | panic(err) 29 | } 30 | return string(b) 31 | } 32 | 33 | func (soap *SoapClient) Do(request, response interface{}, headers ...interface{}) error { 34 | envelope := NewSOAPEnvelope(request) 35 | for _, header := range headers { 36 | envelope.AddHeader(header) 37 | } 38 | 39 | message, err := xml.Marshal(envelope) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | if soap.LogRequest != nil { 45 | soap.LogRequest(string(message)) 46 | } 47 | 48 | httpClient := &http.Client{ 49 | Timeout: time.Duration(10 * time.Second), 50 | } 51 | resp, err := httpClient.Post(soap.Endpoint, "application/soap+xml; charset=utf-8", bytes.NewBuffer(message)) 52 | if err != nil { 53 | return err 54 | } 55 | defer resp.Body.Close() 56 | 57 | if resp.StatusCode != http.StatusOK && 58 | resp.StatusCode != http.StatusInternalServerError && 59 | resp.StatusCode != http.StatusBadRequest { 60 | 61 | //respBody := readResponse(resp) 62 | 63 | return errors.New("camera is not available at " + soap.Endpoint + " or it does not support ONVIF services") 64 | } 65 | 66 | responseEnvelope := NewSOAPEnvelope(response) 67 | 68 | respBody := readResponse(resp) 69 | 70 | if soap.LogResponse != nil { 71 | soap.LogResponse(string(respBody)) 72 | } 73 | 74 | decoder := xml.NewDecoder(strings.NewReader(respBody)) 75 | err = decoder.Decode(responseEnvelope) 76 | if err != nil { 77 | return err 78 | } 79 | if responseEnvelope.Body.Fault != nil { 80 | return responseEnvelope.Body.Fault 81 | } 82 | 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /soap/types.go: -------------------------------------------------------------------------------- 1 | package soap 2 | 3 | import "encoding/xml" 4 | 5 | type SOAPEnvelope struct { 6 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Envelope"` 7 | Header SOAPHeader 8 | Body SOAPBody 9 | } 10 | 11 | type SOAPHeader struct { 12 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Header"` 13 | 14 | Headers []interface{} 15 | } 16 | 17 | type SOAPBody struct { 18 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Body"` 19 | 20 | Fault *SOAPFault `xml:",omitempty"` 21 | Content interface{} `xml:",omitempty"` 22 | } 23 | 24 | type SOAPFault struct { 25 | XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Fault"` 26 | 27 | Code SOAPFaultCode `xml:"Code"` 28 | //TODO: text, details 29 | } 30 | 31 | type SOAPFaultCode struct { 32 | Value string `xml:"Value"` 33 | Subcode *SOAPFaultCode `xml:"Subcode,omitempty"` 34 | } 35 | 36 | func (f *SOAPFault) Error() string { 37 | errorString := f.Code.Value 38 | code := &f.Code 39 | for code.Subcode != nil { 40 | errorString = errorString + " > " + code.Subcode.Value 41 | code = code.Subcode 42 | } 43 | return errorString 44 | } 45 | 46 | func (b *SOAPBody) UnmarshalXML(d *xml.Decoder, _ xml.StartElement) error { 47 | if b.Content == nil { 48 | return xml.UnmarshalError("Content must be a pointer to a struct") 49 | } 50 | 51 | var ( 52 | token xml.Token 53 | err error 54 | consumed bool 55 | ) 56 | 57 | Loop: 58 | for { 59 | if token, err = d.Token(); err != nil { 60 | return err 61 | } 62 | 63 | if token == nil { 64 | break 65 | } 66 | 67 | switch se := token.(type) { 68 | case xml.StartElement: 69 | if consumed { 70 | return xml.UnmarshalError("Found multiple elements inside SOAP body; not wrapped-document/literal WS-I compliant") 71 | } else if se.Name.Space == "http://www.w3.org/2003/05/soap-envelope" && se.Name.Local == "Fault" { 72 | b.Fault = &SOAPFault{} 73 | b.Content = nil 74 | 75 | err = d.DecodeElement(b.Fault, &se) 76 | if err != nil { 77 | return err 78 | } 79 | 80 | consumed = true 81 | } else { 82 | if err = d.DecodeElement(b.Content, &se); err != nil { 83 | return err 84 | } 85 | 86 | consumed = true 87 | } 88 | case xml.EndElement: 89 | break Loop 90 | } 91 | } 92 | 93 | return nil 94 | } 95 | 96 | func (envelope *SOAPEnvelope) AddHeader(header interface{}) { 97 | envelope.Header.Headers = append(envelope.Header.Headers, header) 98 | } 99 | 100 | func NewSOAPEnvelope(content interface{}) *SOAPEnvelope { 101 | return &SOAPEnvelope{ 102 | Body: SOAPBody{ 103 | Content: content, 104 | }, 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /soap/wsSecurity.go: -------------------------------------------------------------------------------- 1 | package soap 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/sha1" 6 | "encoding/base64" 7 | "encoding/xml" 8 | "io" 9 | "time" 10 | ) 11 | 12 | type wsSecurity struct { 13 | XMLName xml.Name `xml:"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd Security"` 14 | UsernameToken wssUsernameToken 15 | } 16 | 17 | type wssUsernameToken struct { 18 | XMLName xml.Name `xml:"UsernameToken"` 19 | Username string `xml:"Username"` 20 | Password wssPassword `xml:"Password"` 21 | Nonce wssNonce `xml:"Nonce"` 22 | Created string `xml:"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Created"` 23 | } 24 | 25 | type wssPassword struct { 26 | Type string `xml:"Type,attr"` 27 | Password string `xml:",chardata"` 28 | } 29 | 30 | type wssNonce struct { 31 | Type string `xml:"EncodingType,attr"` 32 | Nonce string `xml:",chardata"` 33 | } 34 | 35 | func newUUIDVer4() ([]byte, error) { 36 | u := new([16]byte) 37 | if _, err := io.ReadFull(rand.Reader, u[:]); err != nil { 38 | return u[:], err 39 | } 40 | // u.SetVersion(V4) 41 | // u.SetVariant(VariantRFC4122) 42 | 43 | return u[:], nil 44 | } 45 | 46 | func MakeWSSecurity(username string, password string, timeDiff time.Duration) wsSecurity { 47 | created := time.Now().UTC().Add(timeDiff).Format(time.RFC3339Nano) 48 | 49 | nonce, _ := newUUIDVer4() 50 | nonce64 := base64.StdEncoding.EncodeToString(nonce) 51 | hasher := sha1.New() 52 | hasher.Write(nonce) 53 | hasher.Write([]byte(created + password)) 54 | shaToken := hasher.Sum(nil) 55 | shaDigest64 := base64.StdEncoding.EncodeToString(shaToken) 56 | 57 | return wsSecurity{ 58 | UsernameToken: wssUsernameToken{ 59 | Username: username, 60 | Created: created, 61 | Password: wssPassword{ 62 | Type: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest", 63 | Password: shaDigest64, 64 | }, 65 | Nonce: wssNonce{ 66 | Type: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary", 67 | Nonce: nonce64, 68 | }, 69 | }, 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /xsd/anytype.go: -------------------------------------------------------------------------------- 1 | package xsd 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | type AnyType struct { 8 | XMLName xml.Name 9 | Attrs []xml.Attr `xml:",any,attr"` 10 | Childs []AnyType `xml:",any"` 11 | Text string `xml:",chardata"` 12 | } 13 | -------------------------------------------------------------------------------- /xsd/duration.go: -------------------------------------------------------------------------------- 1 | package xsd 2 | 3 | import ( 4 | "errors" 5 | "regexp" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | var ( 11 | nanosecondsPerDay = 24 * int64(time.Hour) 12 | nanosecondsPerMonth = 30 * nanosecondsPerDay 13 | nanosecondsPerYear = 365 * nanosecondsPerDay 14 | ) 15 | 16 | /* 17 | Duration is the [ISO 8601] extended format PnYn MnDTnH nMnS, 18 | where nY represents the number of years, nM the number of months, 19 | nD the number of days, 'T' is the date/time separator, 20 | nH the number of hours, nM the number of minutes and nS the number of seconds. 21 | The number of seconds can include decimal digits to arbitrary precision. 22 | PnYnMnDTnHnMnS 23 | 24 | Duration has the following ·constraining facets·: 25 | 26 | • pattern 27 | • enumeration 28 | • whiteSpace 29 | • maxInclusive 30 | • maxExclusive 31 | • minInclusive 32 | • minExclusive 33 | 34 | More info: https://www.w3.org/TR/xmlschema-2/#duration 35 | 36 | TODO: process restrictions 37 | TODO: Look at time.Duration go type 38 | */ 39 | 40 | type Duration time.Duration 41 | 42 | func (d Duration) String() string { 43 | td := time.Duration(d).Nanoseconds() 44 | 45 | seconds := td % int64(time.Minute) 46 | if seconds > 0 { 47 | td -= seconds 48 | seconds = seconds / int64(time.Second) 49 | } 50 | minutes := td % int64(time.Hour) 51 | if minutes > 0 { 52 | td -= minutes 53 | minutes = minutes / int64(time.Minute) 54 | } 55 | hours := td % int64(24*time.Hour) 56 | if hours > 0 { 57 | td -= hours 58 | hours = hours / int64(time.Hour) 59 | } 60 | 61 | days := td / int64(24*time.Hour) 62 | 63 | result := "P" // time duration designator 64 | //years 65 | // if years > 0 { 66 | // result += strconv.FormatInt(years, 10) + "Y" 67 | // } 68 | // if months > 0 { 69 | // result += strconv.FormatInt(months, 10) + "M" 70 | // } 71 | if days > 0 { 72 | result += strconv.FormatInt(days, 10) + "D" 73 | } 74 | 75 | if hours > 0 || minutes > 0 || seconds > 0 { 76 | result += "T" 77 | if hours > 0 { 78 | result += strconv.FormatInt(hours, 10) + "H" 79 | } 80 | if minutes > 0 { 81 | result += strconv.FormatInt(minutes, 10) + "M" 82 | } 83 | if seconds > 0 { 84 | result += strconv.FormatInt(seconds, 10) + "S" 85 | } 86 | } 87 | 88 | if len(result) == 1 { 89 | result += "T0S" 90 | } 91 | 92 | return result 93 | } 94 | 95 | func (d *Duration) UnmarshalText(text []byte) error { 96 | durationRegex, _ := regexp.Compile(`^(-?)P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d*(?:\.\d+)?)S)?)?$`) 97 | 98 | if !durationRegex.MatchString(string(text)) { 99 | return errors.New("invalid format") 100 | } 101 | 102 | groups := durationRegex.FindStringSubmatch(string(text)) 103 | 104 | var duration int64 105 | 106 | if groups[2] != "" { 107 | years, _ := strconv.Atoi(groups[2]) 108 | duration += int64(years) * nanosecondsPerYear 109 | } 110 | if groups[3] != "" { 111 | months, _ := strconv.Atoi(groups[3]) 112 | duration += int64(months) * nanosecondsPerMonth 113 | } 114 | if groups[4] != "" { 115 | days, _ := strconv.Atoi(groups[4]) 116 | duration += int64(days) * nanosecondsPerDay 117 | } 118 | 119 | if groups[5] != "" { 120 | hours, _ := strconv.Atoi(groups[5]) 121 | duration += int64(hours) * int64(time.Hour) 122 | } 123 | if groups[6] != "" { 124 | minutes, _ := strconv.Atoi(groups[6]) 125 | duration += int64(minutes) * int64(time.Minute) 126 | } 127 | if groups[7] != "" { 128 | seconds, _ := strconv.Atoi(groups[7]) 129 | duration += int64(seconds) * int64(time.Second) 130 | } 131 | 132 | *d = Duration(duration) 133 | 134 | return nil 135 | } 136 | 137 | func (d Duration) MarshalText() ([]byte, error) { 138 | return []byte(d.String()), nil 139 | } 140 | -------------------------------------------------------------------------------- /xsd/types.go: -------------------------------------------------------------------------------- 1 | package xsd 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/hex" 6 | "errors" 7 | "net/url" 8 | "regexp" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | /* 14 | TODO: XML SOURCE: https://www.w3.org/2001/05/datatypes.xsd 15 | */ 16 | 17 | type AnySimpleType string 18 | 19 | /*********************************************************** 20 | Non-derived types 21 | ***********************************************************/ 22 | 23 | /* 24 | The string datatype represents character strings in XML. 25 | The ·value space· of string is the set of finite-length sequences of characters. 26 | String has the following constraining facets: 27 | • length 28 | • minLength 29 | • maxLength 30 | • pattern 31 | • enumeration 32 | • whiteSpace 33 | 34 | More info: https://www.w3.org/TR/xmlschema-2/#string 35 | 36 | //TODO: valid/invalid character declaration and process restrictions 37 | */ 38 | type String string 39 | 40 | /* 41 | Construct an instance of xsd String type 42 | */ 43 | func (tp String) NewString(data string) String { 44 | return String(data) 45 | } 46 | 47 | /* 48 | Float is patterned after the IEEE single-precision 32-bit floating point type 49 | Float has the following ·constraining facets·: 50 | • pattern 51 | • enumeration 52 | • whiteSpace 53 | • maxInclusive 54 | • maxExclusive 55 | • minInclusive 56 | • minExclusive 57 | 58 | More info: https://www.w3.org/TR/xmlschema-2/#float 59 | 60 | //TODO: process restrictions 61 | */ 62 | type Float float32 63 | 64 | /* 65 | Construct an instance of xsd Float type 66 | */ 67 | func (tp Float) NewFloat(data float32) Float { 68 | return Float(data) 69 | } 70 | 71 | /* 72 | The double datatype is patterned after the IEEE double-precision 64-bit floating point type 73 | Double has the following ·constraining facets·: 74 | • pattern 75 | • enumeration 76 | • whiteSpace 77 | • maxInclusive 78 | • maxExclusive 79 | • minInclusive 80 | • minExclusive 81 | 82 | More info: https://www.w3.org/TR/xmlschema-2/#double 83 | 84 | //TODO: process restrictions 85 | */ 86 | type Double float64 87 | 88 | /* 89 | Construct an instance of xsd Double type 90 | */ 91 | func (tp Double) NewDouble(data float64) Double { 92 | return Double(data) 93 | } 94 | 95 | /* 96 | The type decimal represents a decimal number of arbitrary precision. 97 | Schema processors vary in the number of significant digits they support, 98 | but a conforming processor must support a minimum of 18 significant digits. 99 | The format of xsd:decimal is a sequence of digits optionally preceded by a sign ("+" or "-") 100 | and optionally containing a period. The value may start or end with a period. 101 | If the fractional part is 0 then the period and trailing zeros may be omitted. 102 | Leading and trailing zeros are permitted, but they are not considered significant. 103 | That is, the decimal values 3.0 and 3.0000 are considered equal. 104 | 105 | Source: http://www.datypic.com/sc/xsd/t-xsd_decimal.html 106 | 107 | Decimal has the following ·constraining facets·: 108 | • totalDigits 109 | • fractionDigits 110 | • pattern 111 | • whiteSpace 112 | • enumeration 113 | • maxInclusive 114 | • maxExclusive 115 | • minInclusive 116 | • minExclusive 117 | 118 | More info: https://www.w3.org/TR/xmlschema-2/#decimal 119 | 120 | //TODO: process restrictions, valid/invalid characters(commas are not permitted; the decimal separator must be a period) 121 | 122 | */ 123 | type Decimal string 124 | 125 | /* 126 | Construct an instance of xsd Decimal type 127 | */ 128 | func (tp Decimal) NewDecimal(data string) Decimal { 129 | return Decimal(data) 130 | } 131 | 132 | /* 133 | DateTime values may be viewed as objects with integer-valued year, month, day, hour 134 | and minute properties, a decimal-valued second property, and a boolean timezoned property. 135 | 136 | 137 | The ·lexical space· of dateTime consists of finite-length sequences of characters of the form: 138 | '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?, 139 | 140 | 141 | DateTime has the following ·constraining facets·: 142 | 143 | • pattern 144 | • enumeration 145 | • whiteSpace 146 | • maxInclusive 147 | • maxExclusive 148 | • minInclusive 149 | • minExclusive 150 | 151 | More info: https://www.w3.org/TR/xmlschema-2/#dateTime 152 | 153 | TODO: decide good type for time with proper format 154 | TODO: process restrictions 155 | */ 156 | type DateTime AnySimpleType 157 | 158 | /* 159 | Construct an instance of xsd dateTime type 160 | */ 161 | func MakeDateTime(time time.Time) DateTime { 162 | return DateTime(time.Format("2002-10-10T12:00:00-05:00")) 163 | } 164 | 165 | /* 166 | Time represents an instant of time that recurs every day. 167 | The ·value space· of time is the space of time of day values 168 | as defined in § 5.3 of [ISO 8601]. Specifically, it is a set 169 | of zero-duration daily time instances. 170 | 171 | Time has the following ·constraining facets·: 172 | 173 | • pattern 174 | • enumeration 175 | • whiteSpace 176 | • maxInclusive 177 | • maxExclusive 178 | • minInclusive 179 | • minExclusive 180 | 181 | More info: https://www.w3.org/TR/xmlschema-2/#time 182 | 183 | TODO: process restrictions 184 | */ 185 | type Time AnySimpleType 186 | 187 | /* 188 | Construct an instance of xsd time type 189 | */ 190 | func (tp DateTime) NewTime(time time.Time) DateTime { 191 | return DateTime(time.Format("15:04:05")) 192 | } 193 | 194 | /* 195 | The ·value space· of date consists of top-open intervals of 196 | exactly one day in length on the timelines of dateTime, beginning 197 | on the beginning moment of each day (in each timezone), 198 | i.e. '00:00:00', up to but not including '24:00:00' 199 | (which is identical with '00:00:00' of the next day). 200 | For nontimezoned values, the top-open intervals disjointly 201 | cover the nontimezoned timeline, one per day. For timezoned 202 | values, the intervals begin at every minute and therefore overlap. 203 | */ 204 | type Date AnySimpleType 205 | 206 | /* 207 | Construct an instance of xsd date type 208 | */ 209 | func (tp Date) NewDate(time time.Time) Date { 210 | return Date(time.Format("2004-04-12-05:00")) 211 | } 212 | 213 | /* 214 | The type xsd:gYearMonth represents a specific month of a specific 215 | year. The letter g signifies "Gregorian." The format of 216 | xsd:gYearMonth is CCYY-MM. No left truncation is allowed on 217 | either part. To represents years later than 9999, additional 218 | digits can be added to the left of the year value. 219 | To represent years before 0001, a preceding minus sign ("-") 220 | is permitted. 221 | 222 | Source: http://www.datypic.com/sc/xsd/t-xsd_gYearMonth.html 223 | 224 | More info: https://www.w3.org/TR/xmlschema-2/#gYearMonth 225 | */ 226 | type GYearMonth AnySimpleType 227 | 228 | /* 229 | Construct an instance of xsd GYearMonth type 230 | */ 231 | func (tp GYearMonth) NewGYearMonth(time time.Time) GYearMonth { 232 | return GYearMonth(time.Format("2006-01")) 233 | } 234 | 235 | /* 236 | The type xsd:gYear represents a specific calendar year. 237 | The letter g signifies "Gregorian." The format of xsd:gYear 238 | is CCYY. No left truncation is allowed. To represent years 239 | later than 9999, additional digits can be added to the left 240 | of the year value. To represent years before 0001, a preceding 241 | minus sign ("-") is allowed. 242 | 243 | Source: http://www.datypic.com/sc/xsd/t-xsd_gYear.html 244 | 245 | More info: https://www.w3.org/TR/xmlschema-2/#gYear 246 | */ 247 | type GYear AnySimpleType 248 | 249 | /* 250 | Construct an instance of xsd GYear type 251 | */ 252 | func (tp GYear) NewGYear(time time.Time) GYear { 253 | return GYear(time.Format("2006")) 254 | } 255 | 256 | /* 257 | The type xsd:gMonthDay represents a specific day that recurs 258 | every year. The letter g signifies "Gregorian." xsd:gMonthDay 259 | can be used to say, for example, that your birthday is on the 260 | 14th of April every year. The format of xsd:gMonthDay is --MM-DD. 261 | 262 | Source: http://www.datypic.com/sc/xsd/t-xsd_gMonthDay.html 263 | 264 | More info: https://www.w3.org/TR/xmlschema-2/#gMonthDay 265 | */ 266 | type GMonthDay AnySimpleType 267 | 268 | // NewGMonthDay Construct an instance of xsd GMonthDay type 269 | func (tp GMonthDay) NewGMonthDay(time time.Time) GMonthDay { 270 | return GMonthDay(time.Format("--01-02")) 271 | } 272 | 273 | /* 274 | The type xsd:gDay represents a day that recurs every month. 275 | The letter g signifies "Gregorian." xsd:gDay can be used to say, 276 | for example, that checks are paid on the 5th of each month. 277 | To represent a duration of days, use the duration type instead. 278 | The format of gDay is ---DD. 279 | 280 | Source: http://www.datypic.com/sc/xsd/t-xsd_gDay.html 281 | 282 | More info: https://www.w3.org/TR/xmlschema-2/#gDay 283 | */ 284 | type GDay AnySimpleType 285 | 286 | // NewGDay Construct an instance of xsd GDay type 287 | func (tp GDay) NewGDay(time time.Time) GDay { 288 | return GDay(time.Format("---02")) 289 | } 290 | 291 | /* 292 | The type xsd:gMonth represents a specific month that recurs 293 | every year. The letter g signifies "Gregorian." xsd:gMonth 294 | can be used to indicate, for example, that fiscal year-end 295 | processing occurs in September of every year. To represent 296 | a duration of months, use the duration type instead. The format 297 | of xsd:gMonth is --MM. 298 | 299 | Source: http://www.datypic.com/sc/xsd/t-xsd_gMonth.html 300 | 301 | More info: https://www.w3.org/TR/xmlschema-2/#gMonth 302 | */ 303 | type GMonth AnySimpleType 304 | 305 | func (tp GMonth) NewGMonth(time time.Time) GMonth { 306 | return GMonth(time.Format("--01")) 307 | } 308 | 309 | /* 310 | The xsd:hexBinary type represents binary data as a sequence 311 | of binary octets. It uses hexadecimal encoding, where each 312 | binary octet is a two-character hexadecimal number. 313 | Lowercase and uppercase letters A through F are permitted. 314 | For example, 0FB8 and 0fb8 are two equal xsd:hexBinary 315 | representations consisting of two octets. 316 | 317 | Source: http://www.datypic.com/sc/xsd/t-xsd_hexBinary.html 318 | 319 | More info: https://www.w3.org/TR/xmlschema-2/#hexBinary 320 | */ 321 | type HexBinary AnySimpleType 322 | 323 | func (tp HexBinary) NewHexBinary(data []byte) HexBinary { 324 | return HexBinary(hex.EncodeToString(data)) 325 | } 326 | 327 | /* 328 | base64Binary represents Base64-encoded arbitrary binary data. 329 | The ·value space· of base64Binary is the set of finite-length sequences of binary octets. 330 | For base64Binary data the entire binary stream is encoded using the Base64 Alphabet in [RFC 2045]. 331 | 332 | base64Binary has the following ·constraining facets·: 333 | • length 334 | • minLength 335 | • maxLength 336 | • pattern 337 | • enumeration 338 | • whiteSpace 339 | 340 | More info: https://www.w3.org/TR/xmlschema-2/#base64Binary 341 | */ 342 | type Base64Binary AnySimpleType 343 | 344 | func (tp Base64Binary) NewBase64Binary(data []byte) Base64Binary { 345 | return Base64Binary(base64.StdEncoding.EncodeToString(data)) 346 | } 347 | 348 | /* 349 | anyURI represents a Uniform Resource Identifier Reference (URI). 350 | An anyURI value can be absolute or relative, and may have an optional 351 | fragment identifier (i.e., it may be a URI Reference). 352 | This type should be used to specify the intention that the 353 | value fulfills the role of a URI as defined by [RFC 2396], as amended by [RFC 2732]. 354 | 355 | anyURI has the following ·constraining facets·: 356 | • length 357 | • minLength 358 | • maxLength 359 | • pattern 360 | • enumeration 361 | • whiteSpace 362 | 363 | More info: https://www.w3.org/TR/xmlschema-2/#anyURI 364 | */ 365 | type AnyURI AnySimpleType 366 | 367 | func (tp AnyURI) NewAnyURI(data url.URL) AnyURI { 368 | return AnyURI(data.String()) 369 | } 370 | 371 | /* 372 | QName represents XML qualified names. The ·value space· of QName is the set of tuples 373 | {namespace name, local part}, where namespace name is an anyURI and local part is an NCName. 374 | The ·lexical space· of QName is the set of strings that ·match· the QName production of [Namespaces in XML]. 375 | 376 | QName has the following ·constraining facets·: 377 | • length 378 | • minLength 379 | • maxLength 380 | • pattern 381 | • enumeration 382 | • whiteSpace 383 | 384 | More info: https://www.w3.org/TR/xmlschema-2/#QName 385 | */ 386 | type QName AnySimpleType 387 | 388 | func (tp QName) NewQName(prefix, local string) QName { 389 | var result string 390 | if len(prefix) == 0 { 391 | result += local 392 | } else { 393 | result = prefix + ":" + local 394 | } 395 | return QName(result) 396 | } 397 | 398 | //TODO: NOTATION datatype 399 | //type NOTATION AnySimpleType 400 | 401 | /* 402 | Derived types 403 | */ 404 | 405 | type NormalizedString String 406 | 407 | //TODO: check normalization 408 | func NewNormalizedString(data string) (NormalizedString, error) { 409 | if strings.ContainsAny(data, "\r\n\t<>&") { 410 | return NormalizedString(""), errors.New("String " + data + " contains forbidden symbols") 411 | } 412 | return NormalizedString(data), nil 413 | } 414 | 415 | type Token NormalizedString 416 | 417 | func NewToken(data NormalizedString) (Token, error) { 418 | trailing_leading_whitespaces := regexp.MustCompile(`^[\s\p{Zs}]+|[\s\p{Zs}]+$`) 419 | multiple_whitespaces := regexp.MustCompile(`[\s\p{Zs}]{2,}`) 420 | //Removing trailing and leading whitespaces and multiple spaces 421 | /*final := re_leadclose_whtsp.ReplaceAllString(data, "") 422 | final = re_inside_whtsp.ReplaceAllString(final, " ")*/ 423 | if strings.ContainsAny(string(data), "\r\n\t<>&") || trailing_leading_whitespaces.MatchString(string(data)) || multiple_whitespaces.MatchString(string(data)) { 424 | return Token(""), errors.New("String " + string(data) + " contains forbidden symbols or whitespaces") 425 | } 426 | 427 | return Token(data), nil 428 | } 429 | 430 | type Language Token 431 | 432 | func (tp Language) NewLanguage(data Token) (Language, error) { 433 | //Pattern was given from https://www.w3.org/2001/05/datatypes.xsd 434 | rgxp := regexp.MustCompile(`([a-zA-Z]{2}|[iI]-[a-zA-Z]+|[xX]-[a-zA-Z]{1,8})(-[a-zA-Z]{1,8})*`) 435 | if rgxp.MatchString(string(data)) { 436 | return Language(""), errors.New("String does not match pattern ([a-zA-Z]{2}|[iI]-[a-zA-Z]+|[xX]-[a-zA-Z]{1,8})(-[a-zA-Z]{1,8})*") 437 | } 438 | return Language(data), nil 439 | } 440 | 441 | type NMTOKEN Token 442 | 443 | //TODO: check for valid symbols: https://www.w3.org/TR/xml/#NT-Nmtoken 444 | func (tp NMTOKEN) NewNMTOKEN(data string) NMTOKEN { 445 | return NMTOKEN(data) 446 | } 447 | 448 | type NMTOKENS []NMTOKEN 449 | 450 | func (tp NMTOKENS) NewNMTOKENS(data []NMTOKEN) NMTOKENS { 451 | result := make(NMTOKENS, len(data)) 452 | for i, j := range data { 453 | result[i] = j 454 | } 455 | return result 456 | } 457 | 458 | type Name Token 459 | 460 | //TODO: implements https://www.w3.org/TR/xml/#NT-Name 461 | func (tp Name) NewName(data Token) Name { 462 | return Name(data) 463 | } 464 | 465 | type NCName Name 466 | 467 | //TODO: https://www.w3.org/TR/REC-xml/#NT-Name and https://www.w3.org/TR/xml-names/#NT-NCName 468 | func (tp NCName) NewNCName(data Name) NCName { 469 | return NCName(data) 470 | } 471 | 472 | //TODO: improve next types to correspond to XMLSchema 473 | type ID NCName 474 | 475 | func (tp ID) NewID(data NCName) ID { 476 | return ID(data) 477 | } 478 | 479 | type IDREF NCName 480 | 481 | func (tp IDREF) NewIDREF(data NCName) IDREF { 482 | return IDREF(data) 483 | } 484 | 485 | type IDREFS []IDREF 486 | 487 | func (tp IDREFS) NewIDREFS(data []IDREF) IDREFS { 488 | result := make(IDREFS, len(data)) 489 | for i, j := range data { 490 | result[i] = j 491 | } 492 | return result 493 | } 494 | 495 | type ENTITY NCName 496 | 497 | func (tp ENTITY) NewENTITY(data NCName) ENTITY { 498 | return ENTITY(data) 499 | } 500 | 501 | type ENTITIES []ENTITY 502 | 503 | func (tp ENTITIES) NewENTITIES(data []ENTITY) ENTITIES { 504 | result := make(ENTITIES, len(data)) 505 | for i, j := range data { 506 | result[i] = j 507 | } 508 | return result 509 | } 510 | 511 | type Integer int64 512 | 513 | func (tp Integer) NewInteger(data int64) Integer { 514 | return Integer(data) 515 | } 516 | 517 | type Short int16 518 | 519 | func (tp Short) NewShort(data int16) Short { 520 | return Short(data) 521 | } 522 | 523 | type Byte int8 524 | 525 | func (tp Byte) NewByte(data int8) Byte { 526 | return Byte(data) 527 | } 528 | 529 | type UnsignedLong uint64 530 | 531 | func (tp UnsignedLong) NewUnsignedLong(data uint64) UnsignedLong { 532 | return UnsignedLong(data) 533 | } 534 | 535 | type UnsignedInt uint32 536 | 537 | func (tp UnsignedInt) NewUnsignedInt(data uint32) UnsignedInt { 538 | return UnsignedInt(data) 539 | } 540 | 541 | type UnsignedShort uint16 542 | 543 | func (tp UnsignedShort) NewUnsignedShort(data uint16) UnsignedShort { 544 | return UnsignedShort(data) 545 | } 546 | 547 | type UnsignedByte uint8 548 | 549 | func (tp UnsignedByte) NewUnsignedByte(data uint8) UnsignedByte { 550 | return UnsignedByte(data) 551 | } 552 | 553 | type PositiveInteger int64 554 | 555 | func (tp PositiveInteger) NewPositiveInteger(data int64) (PositiveInteger, error) { 556 | if data >= 0 { 557 | return 0, errors.New("Value must be more than 0") 558 | } 559 | return PositiveInteger(data), nil 560 | } 561 | --------------------------------------------------------------------------------