Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Onvif Device URLs #52

Open
Mudrekh opened this issue Nov 9, 2021 · 5 comments
Open

Onvif Device URLs #52

Mudrekh opened this issue Nov 9, 2021 · 5 comments

Comments

@Mudrekh
Copy link
Contributor

Mudrekh commented Nov 9, 2021

Hi @patrickmichalina

We came accross an issue with certain devices relating to the URLs used to interface with the device. The default url to interface with the device is at http://<IP>/onvif/device_service. While some manufacturers seem to publish the entire ONVIF API on the device_service route, some do not. For example, we were using an ADVIDIA camera that actually only published services on their specific routes. For reference, I believe the actual ONVIF interface guide recommends that you actually call Device.GetCapabilities first to determine what services the device supports as well as get the URLs for different services.

Have you come upon this issue and thought about how you would solve it using the 'Managed' api? Based on the 'Ad Hoc' usage you could probably get around it, but having to supply the configs everytime seems tedius and more error prone.

The ADVIDIA camera we were testing with returns this data for Capabilities. Using the XAddr's supplied for each service returns correctly, where as calls made to services not on the default URL result in 'Optional Operation Not Supported'

{
  "Capabilities": {
    "Analytics": {
      "XAddr": "http://192.168.1.91/onvif/Analytics",
      "RuleSupport": true,
      "AnalyticsModuleSupport": true
    },
    "Device": {
      "XAddr": "http://192.168.1.91/onvif/device_service",
      "Network": {
        "IPFilter": true,
        "ZeroConfiguration": true,
        "IPVersion6": true,
        "DynDNS": true,
        "Extension": {
          "Dot11Configuration": false,
          "Extension": {
            "DHCPv6": true,
            "Dot1XConfigurations": "0"
          }
        }
      },
      "System": {
        "DiscoveryResolve": false,
        "DiscoveryBye": true,
        "RemoteDiscovery": false,
        "SystemBackup": false,
        "SystemLogging": true,
        "FirmwareUpgrade": true,
        "SupportedVersions": [
          {
            "Major": "16",
            "Minor": "12"
          },
          {
            "Major": "2",
            "Minor": "60"
          },
          {
            "Major": "2",
            "Minor": "40"
          },
          {
            "Major": "2",
            "Minor": "20"
          },
          {
            "Major": "2",
            "Minor": "10"
          },
          {
            "Major": "2",
            "Minor": "0"
          }
        ],
        "Extension": {
          "HttpFirmwareUpgrade": true,
          "HttpSystemBackup": false,
          "HttpSystemLogging": false,
          "HttpSupportInformation": false
        }
      },
      "IO": {
        "InputConnectors": "0",
        "RelayOutputs": "0",
        "Extension": {
          "Auxiliary": false,
          "AuxiliaryCommands": "nothing",
          "Extension": {}
        }
      },
      "Security": {
        "TLS1.1": true,
        "TLS1.2": true,
        "OnboardKeyGeneration": false,
        "AccessPolicyConfig": false,
        "X.509Token": false,
        "SAMLToken": false,
        "KerberosToken": false,
        "RELToken": false,
        "Extension": {
          "TLS1.0": true,
          "Extension": {
            "Dot1X": false,
            "SupportedEAPMethod": "0",
            "RemoteUserHandling": false
          }
        }
      }
    },
    "Events": {
      "XAddr": "http://192.168.1.91/onvif/Events",
      "WSSubscriptionPolicySupport": true,
      "WSPullPointSupport": true,
      "WSPausableSubscriptionManagerInterfaceSupport": false
    },
    "Imaging": {
      "XAddr": "http://192.168.1.91/onvif/Imaging"
    },
    "Media": {
      "XAddr": "http://192.168.1.91/onvif/Media",
      "StreamingCapabilities": {
        "RTPMulticast": true,
        "RTP_TCP": true,
        "RTP_RTSP_TCP": true
      },
      "Extension": {
        "ProfileCapabilities": {
          "MaximumNumberOfProfiles": "10"
        }
      }
    },
    "Extension": {
      "extCapabilities": {
        "XAddr": "http://192.168.1.91/onvif/onvif_ext",
        "IOInputSupport": false,
        "PrivacyMaskSupport": true,
        "PTZ3DZoomSupport": false,
        "PTZPatternSupport": true,
        "Language": "2"
      },
      "DeviceIO": {
        "XAddr": "http://192.168.1.91/onvif/DeviceIO",
        "VideoSources": "1",
        "VideoOutputs": "0",
        "AudioSources": "0",
        "AudioOutputs": "0",
        "RelayOutputs": "0"
      },
      "Recording": {
        "XAddr": "http://192.168.1.91/onvif/Recording",
        "ReceiverSource": false,
        "MediaProfileSource": true,
        "DynamicRecordings": false,
        "DynamicTracks": false,
        "MaxStringLength": "64"
      },
      "Search": {
        "XAddr": "http://192.168.1.91/onvif/SearchRecording",
        "MetadataSearch": false
      },
      "Replay": {
        "XAddr": "http://192.168.1.91/onvif/Replay"
      }
    }
  }
}
@patrickmichalina
Copy link
Owner

I am reviewing this and will get back to you thanks.

@Mudrekh
Copy link
Contributor Author

Mudrekh commented Feb 15, 2022

@patrickmichalina Did you have a chance to review this further? If it helps, I'm currently using a snippet like this to 'override' certain URLs so that they work.

const debug = require('debug')('onvif-rx');
const _ = require('lodash');

const services = [
  'Event',
  'Media',
  'Analytics',
  'Display',
  'Imaging',
  'Provisioning',
  'PTZ',
  'Receiver',
  'Recording',
  'Replay',
  'Search',
  'AdvancedSecurity'
];

const OnvifRxCamera = {
  create({ ip, port, username, password }) {
    const rxcam = onvifrx.createManagedDeviceInNode({
      username,
      password,
      deviceUrl: `http://${ip}:${port || 80}/onvif/device_service`
    });

    rxcam.connect = async function () {
      const { Capabilities } = await this.api.Device.GetCapabilities();
      debug(ip, port, Capabilities);
      services.forEach((service) => {
        const { XAddr } = Capabilities[service] || Capabilities[`${service}s`] || {};
        if (!XAddr) return;

        const conf = _.omit(rxcam.api.Device.config, ['deviceUrl']);
        const url = new URL(XAddr);
        conf.deviceUrl = `http://${ip}:${port || 80}${url.pathname}`;
        debug(ip, port, service, conf.deviceUrl);
        rxcam.api[service].config = conf;
      });
    };
    return rxcam;
  }
};
module.exports = OnvifRxCamera;

@patrickmichalina
Copy link
Owner

@Mudrekh Kinda. I was actually just rewriting the library, but it hasn't been a priority at the moment.

@patrickmichalina
Copy link
Owner

@Mudrekh I remember I needed to do this from the start but was being a little lazy and didn't get around to it because the Amcrest cameras I was testing against were happy using the default.

@Mudrekh
Copy link
Contributor Author

Mudrekh commented Feb 17, 2022

@patrickmichalina OK, no problem. For now the snippet I have works, but would would love to have a built-in solution.

@patrickmichalina patrickmichalina added bug Something isn't working and removed bug Something isn't working labels Oct 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants