diff --git a/internal/onvif/onvif.go b/internal/onvif/onvif.go
index 65f8599a..c305b706 100644
--- a/internal/onvif/onvif.go
+++ b/internal/onvif/onvif.go
@@ -74,8 +74,10 @@ func onvifDeviceService(w http.ResponseWriter, r *http.Request) {
log.Trace().Msgf("[onvif] server request %s %s:\n%s", r.Method, r.RequestURI, b)
switch operation {
- case onvif.DeviceGetNetworkInterfaces, // important for Hass
+ case onvif.ServiceGetServiceCapabilities, // important for Hass
+ onvif.DeviceGetNetworkInterfaces, // important for Hass
onvif.DeviceGetSystemDateAndTime, // important for Hass
+ onvif.DeviceSetSystemDateAndTime, // return just OK
onvif.DeviceGetDiscoveryMode,
onvif.DeviceGetDNS,
onvif.DeviceGetHostname,
@@ -83,8 +85,10 @@ func onvifDeviceService(w http.ResponseWriter, r *http.Request) {
onvif.DeviceGetNetworkProtocols,
onvif.DeviceGetNTP,
onvif.DeviceGetScopes,
+ onvif.MediaGetVideoEncoderConfiguration,
onvif.MediaGetVideoEncoderConfigurations,
onvif.MediaGetAudioEncoderConfigurations,
+ onvif.MediaGetVideoEncoderConfigurationOptions,
onvif.MediaGetAudioSources,
onvif.MediaGetAudioSourceConfigurations:
b = onvif.StaticResponse(operation)
@@ -100,11 +104,6 @@ func onvifDeviceService(w http.ResponseWriter, r *http.Request) {
// important for Hass: SerialNumber (unique server ID)
b = onvif.GetDeviceInformationResponse("", "go2rtc", app.Version, r.Host)
- case onvif.ServiceGetServiceCapabilities:
- // important for Hass
- // TODO: check path links to media
- b = onvif.GetMediaServiceCapabilitiesResponse()
-
case onvif.DeviceSystemReboot:
b = onvif.StaticResponse(operation)
@@ -134,8 +133,7 @@ func onvifDeviceService(w http.ResponseWriter, r *http.Request) {
case onvif.MediaGetStreamUri:
host, _, err := net.SplitHostPort(r.Host)
if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
+ host = r.Host // in case of Host without port
}
uri := "rtsp://" + host + ":" + rtsp.Port + "/" + onvif.FindTagValue(b, "ProfileToken")
diff --git a/pkg/onvif/envelope.go b/pkg/onvif/envelope.go
index f0e1b29c..76a41260 100644
--- a/pkg/onvif/envelope.go
+++ b/pkg/onvif/envelope.go
@@ -15,14 +15,9 @@ type Envelope struct {
}
const (
- prefix1 = `
-
-`
- prefix2 = `
-`
- suffix = `
-
-`
+ prefix1 = ``
+ prefix2 = ``
+ suffix = ``
)
func NewEnvelope() *Envelope {
@@ -54,8 +49,7 @@ func NewEnvelopeWithUser(user *url.Userinfo) *Envelope {
%s
-
-`,
+`,
user.Username(),
base64.StdEncoding.EncodeToString(h.Sum(nil)),
base64.StdEncoding.EncodeToString([]byte(nonce)),
diff --git a/pkg/onvif/server.go b/pkg/onvif/server.go
index 54272798..94e42fc7 100644
--- a/pkg/onvif/server.go
+++ b/pkg/onvif/server.go
@@ -21,21 +21,24 @@ const (
DeviceGetScopes = "GetScopes"
DeviceGetServices = "GetServices"
DeviceGetSystemDateAndTime = "GetSystemDateAndTime"
+ DeviceSetSystemDateAndTime = "SetSystemDateAndTime"
DeviceSystemReboot = "SystemReboot"
)
const (
- MediaGetAudioEncoderConfigurations = "GetAudioEncoderConfigurations"
- MediaGetAudioSources = "GetAudioSources"
- MediaGetAudioSourceConfigurations = "GetAudioSourceConfigurations"
- MediaGetProfile = "GetProfile"
- MediaGetProfiles = "GetProfiles"
- MediaGetSnapshotUri = "GetSnapshotUri"
- MediaGetStreamUri = "GetStreamUri"
- MediaGetVideoEncoderConfigurations = "GetVideoEncoderConfigurations"
- MediaGetVideoSources = "GetVideoSources"
- MediaGetVideoSourceConfiguration = "GetVideoSourceConfiguration"
- MediaGetVideoSourceConfigurations = "GetVideoSourceConfigurations"
+ MediaGetAudioEncoderConfigurations = "GetAudioEncoderConfigurations"
+ MediaGetAudioSources = "GetAudioSources"
+ MediaGetAudioSourceConfigurations = "GetAudioSourceConfigurations"
+ MediaGetProfile = "GetProfile"
+ MediaGetProfiles = "GetProfiles"
+ MediaGetSnapshotUri = "GetSnapshotUri"
+ MediaGetStreamUri = "GetStreamUri"
+ MediaGetVideoEncoderConfiguration = "GetVideoEncoderConfiguration"
+ MediaGetVideoEncoderConfigurations = "GetVideoEncoderConfigurations"
+ MediaGetVideoEncoderConfigurationOptions = "GetVideoEncoderConfigurationOptions"
+ MediaGetVideoSources = "GetVideoSources"
+ MediaGetVideoSourceConfiguration = "GetVideoSourceConfiguration"
+ MediaGetVideoSourceConfigurations = "GetVideoSourceConfigurations"
)
func GetRequestAction(b []byte) string {
@@ -54,13 +57,13 @@ func GetRequestAction(b []byte) string {
func GetCapabilitiesResponse(host string) []byte {
e := NewEnvelope()
- e.Append(`
+ e.Appendf(`
- http://`, host, `/onvif/device_service
+ http://%s/onvif/device_service
- http://`, host, `/onvif/media_service
+ http://%s/onvif/media_service
false
false
@@ -68,24 +71,24 @@ func GetCapabilitiesResponse(host string) []byte {
-`)
+`, host, host)
return e.Bytes()
}
func GetServicesResponse(host string) []byte {
e := NewEnvelope()
- e.Append(`
+ e.Appendf(`
http://www.onvif.org/ver10/device/wsdl
- http://`, host, `/onvif/device_service
+ http://%s/onvif/device_service
25
http://www.onvif.org/ver10/media/wsdl
- http://`, host, `/onvif/media_service
+ http://%s/onvif/media_service
25
-`)
+`, host, host)
return e.Bytes()
}
@@ -120,30 +123,19 @@ func GetSystemDateAndTimeResponse() []byte {
func GetDeviceInformationResponse(manuf, model, firmware, serial string) []byte {
e := NewEnvelope()
- e.Append(`
- `, manuf, `
- `, model, `
- `, firmware, `
- `, serial, `
+ e.Appendf(`
+ %s
+ %s
+ %s
+ %s
1.00
-`)
- return e.Bytes()
-}
-
-func GetMediaServiceCapabilitiesResponse() []byte {
- e := NewEnvelope()
- e.Append(`
-
-
-
-`)
+`, manuf, model, firmware, serial)
return e.Bytes()
}
func GetProfilesResponse(names []string) []byte {
e := NewEnvelope()
- e.Append(`
-`)
+ e.Append(``)
for _, name := range names {
appendProfile(e, "Profiles", name)
}
@@ -153,38 +145,40 @@ func GetProfilesResponse(names []string) []byte {
func GetProfileResponse(name string) []byte {
e := NewEnvelope()
- e.Append(`
-`)
+ e.Append(``)
appendProfile(e, "Profile", name)
e.Append(``)
return e.Bytes()
}
func appendProfile(e *Envelope, tag, name string) {
- // empty `RateControl` important for UniFi Protect
- e.Append(`
- `, name, `
-
- VSC
- `, name, `
-
-
-
- VEC
- H264
- 19201080
-
-
-
-`)
+ // go2rtc name = ONVIF Profile Name = ONVIF Profile token
+ e.Appendf(``, tag, name)
+ e.Appendf(`%s`, name)
+ appendVideoSourceConfiguration(e, "VideoSourceConfiguration", name)
+ appendVideoEncoderConfiguration(e, "VideoEncoderConfiguration")
+ e.Appendf(``, tag)
+}
+
+func GetVideoSourcesResponse(names []string) []byte {
+ // go2rtc name = ONVIF VideoSource token
+ e := NewEnvelope()
+ e.Append(``)
+ for _, name := range names {
+ e.Appendf(`
+ 30.000000
+ 19201080
+`, name)
+ }
+ e.Append(``)
+ return e.Bytes()
}
func GetVideoSourceConfigurationsResponse(names []string) []byte {
e := NewEnvelope()
- e.Append(`
-`)
+ e.Append(``)
for _, name := range names {
- appendProfile(e, "Configurations", name)
+ appendVideoSourceConfiguration(e, "Configurations", name)
}
e.Append(``)
return e.Bytes()
@@ -192,46 +186,56 @@ func GetVideoSourceConfigurationsResponse(names []string) []byte {
func GetVideoSourceConfigurationResponse(name string) []byte {
e := NewEnvelope()
- e.Append(`
-`)
+ e.Append(``)
appendVideoSourceConfiguration(e, "Configuration", name)
e.Append(``)
return e.Bytes()
}
func appendVideoSourceConfiguration(e *Envelope, tag, name string) {
- e.Append(`
+ // go2rtc name = ONVIF VideoSourceConfiguration token
+ e.Appendf(`
VSC
- `, name, `
+ %s
-
-`)
+`, tag, name, name, tag)
}
-func GetVideoSourcesResponse(names []string) []byte {
+func GetVideoEncoderConfigurationsResponse() []byte {
e := NewEnvelope()
- e.Append(`
-`)
- for _, name := range names {
- e.Append(`
- 30.000000
- 19201080
-
-`)
- }
- e.Append(``)
+ e.Append(``)
+ appendVideoEncoderConfiguration(e, "VideoEncoderConfigurations")
+ e.Append(``)
return e.Bytes()
}
+func GetVideoEncoderConfigurationResponse() []byte {
+ e := NewEnvelope()
+ e.Append(``)
+ appendVideoEncoderConfiguration(e, "VideoEncoderConfiguration")
+ e.Append(``)
+ return e.Bytes()
+}
+
+func appendVideoEncoderConfiguration(e *Envelope, tag string) {
+ // empty `RateControl` important for UniFi Protect
+ e.Appendf(`
+ VEC
+ H264
+ 19201080
+
+ `, tag, tag)
+}
+
func GetStreamUriResponse(uri string) []byte {
e := NewEnvelope()
- e.Append(``, uri, ``)
+ e.Appendf(`%s`, uri)
return e.Bytes()
}
func GetSnapshotUriResponse(uri string) []byte {
e := NewEnvelope()
- e.Append(``, uri, ``)
+ e.Appendf(`%s`, uri)
return e.Bytes()
}
@@ -239,6 +243,10 @@ func StaticResponse(operation string) []byte {
switch operation {
case DeviceGetSystemDateAndTime:
return GetSystemDateAndTimeResponse()
+ case MediaGetVideoEncoderConfiguration:
+ return GetVideoEncoderConfigurationResponse()
+ case MediaGetVideoEncoderConfigurations:
+ return GetVideoEncoderConfigurationsResponse()
}
e := NewEnvelope()
@@ -247,11 +255,18 @@ func StaticResponse(operation string) []byte {
}
var responses = map[string]string{
+ ServiceGetServiceCapabilities: `
+
+
+
+`,
+
DeviceGetDiscoveryMode: `Discoverable`,
DeviceGetDNS: ``,
DeviceGetHostname: ``,
DeviceGetNetworkDefaultGateway: ``,
DeviceGetNTP: ``,
+ DeviceSetSystemDateAndTime: ``,
DeviceSystemReboot: `OK`,
DeviceGetNetworkInterfaces: ``,
@@ -263,16 +278,20 @@ var responses = map[string]string{
Fixedonvif://www.onvif.org/type/Network_Video_Transmitter
`,
- MediaGetVideoEncoderConfigurations: `
-
- VEC
- H264
- 19201080
-
-
-`,
-
MediaGetAudioEncoderConfigurations: ``,
MediaGetAudioSources: ``,
MediaGetAudioSourceConfigurations: ``,
+
+ MediaGetVideoEncoderConfigurationOptions: `
+
+ 16
+
+ 19201080
+ 0100
+ 130
+ 1100
+ Main
+
+
+`,
}