Giter VIP home page Giter VIP logo

onvif-rx's Introduction

onvif-rx

Interact with ONVIF cameras and devices using TypeScript and RXJS.

circeci

greenkeeper greenkeeper greenkeeper

semantic-release npm latest version

0930282e-7f18-11e6-948a-00546393fd93

About

This library aims to provide an easy way to interact with ONVIF devices from within Node. It is built with TypeScript to provide IDE's easy access to documentation and typing information.

The API is generated dynamically by reading ONVIF WSDL and XSD files.

This library is very early and not garaunteed to work for evey camera. Feel free to create a Github issue if it's not working for you.

This library does not "discover" devices on the network - for that try onvif-probe-rx

Docs

For more information about the TypeScript API checkout the generated API docs.

Roadmap

  • Generate API with typings and docs from WSDL's and XSD's
  • Execute simple (parameter-less) requests
  • Execute requests with paremeters

Node Installation

This package is designed to be run in both the browser and node environments.

npm i onvif-rx

Browser Installation (expiremental)

<head>
 <!-- simplest method, gets the latest version, but not minifed -->
 <script src="https://unpkg.com/onvif-rx"></script>
 
 <!-- RECOMMENDED: use a specific version to avoid a redirect and get a minified version --> 
 <script src="https://unpkg.com/[email protected]/dist/onvif-rx-umd.min.js"></script>
</head>

Usage

The library is designed to be used in 2 distinct ways.

  • Managed - you construct a manged device using service URL and username/password combo. This makes running commands painless.
  • Ad Hoc - you can call methods individually with different username/passwords if needed.

Managed Usage

import { createManagedDeviceInNode } from 'onvif-rx'

const device = createManagedDeviceInNode({
  deviceUrl: 'http://192.168.1.11/onvif/device_service',
  password: 'admin',
  username: '1234'
})

device.api.Device.GetUsers()
  .toPromise()
  .then(res=> {
    res.match({ // results are wrapped in a managed object for safer processing
      ok: success => console.log(success.json), // successful response object
      fail: railure => console.log(railure.status, railure.statusMessage) // request failure object
    })
  }) 

Ad Hoc Usage

import { Device } from 'onvif-rx'
import { maybe } from 'typescript-monads'

Device.GetUsers()
  .run({
    system: DEFAULT_NODE_ENV,
    deviceUrl: 'http://192.168.1.11/onvif/device_service',
    user: maybe({ // currently requires a wrapper object, will improve in the future
      username: 'admin',
      password: '1234'
    })
  })
  .toPromise()
  .then(res=> {
    res.match({
      ok: success => console.log(success.json), // successful response object
      fail: railure => console.log(railure.status, railure.statusMessage) // request failure object
    })
  }) 

onvif-rx's People

Contributors

mudrekh avatar patrickmichalina avatar redfoxxo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

onvif-rx's Issues

Uncaught TypeError: buffer is undefined

I get this error in Chrome and Edge

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>

<script type="module" src="https://www.unpkg.com/buffer"></script>
<script type="module" src="https://unpkg.com/onvif-rx"></script>
  </head>
  <body>
<script>

</script>
  </body>
</html>

503 service unavailabe - setVideoEncoderConf

Hello,
I'm trying to set the video parameters,
I'm using Flir camera, it has onvif. I succeded to recieve the parameters by get function but when i'm trying to update them I get 503 service unavailable error.

The deviceUrl is: http://ip/onvif/device_service
I tried also media_service and I get the same error.

1603887874495394042983030042627

What should I do?
Thanks.

Onvif Device URLs

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"
      }
    }
  }
}

Incorrect Parameter Destructuring

Hi @patrickmichalina

An error was introduced with this commit. The parameters are incorrectly destructured, especially when they are strings. Here is an example highlighting the issue.

var __assign = function () {
  __assign = Object.assign || function __assign(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
      s = arguments[i];
      for (const p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
    }
    return t;
  };
  return __assign.apply(this, arguments);
};

const params = {
  trt_Name: 'recording',
  trt_Token: 'recording'
};


Object.keys(params).forEach(key => params[key] === undefined ? delete params[key] : {});
const result2 = Object
  .keys(params)
  .reduce((acc, curr) => params[curr] === undefined ? acc : __assign(__assign({}, acc), params[curr]), {});
const result3 = Object
  .keys(params)
  .reduce((acc, curr) => params[curr] === undefined ? acc : { ...acc, ...params[curr] }, {})

console.log(params);
console.log(result2);
console.log(result3);

This is the result:

{ trt_Name: 'recording', trt_Token: 'recording' }
{ '0': 'r',
  '1': 'e',
  '2': 'c',
  '3': 'o',
  '4': 'r',
  '5': 'd',
  '6': 'i',
  '7': 'n',
  '8': 'g' }
{ '0': 'r',
  '1': 'e',
  '2': 'c',
  '3': 'o',
  '4': 'r',
  '5': 'd',
  '6': 'i',
  '7': 'n',
  '8': 'g' }

The first result is the 'expected' output when passed the params with the original 'clean' function. The second version is the TS compiled version, and the 3rd is the current TS.

Optional Parameters

Hi @patrickmichalina,

I was messing around with your library and ran into an issue with optional parameters, specifically using Media.GetVideoEncoderConfigurationOptions. Originally, I could only get the function to complete by specifying both parameters, but it seems based on the specification that I should be able to use the function without needing to supply the params to get 'generic' configuration options for the device.

After some digging, it seems like the issue can be traced to function. When passed no parameters in the calling function, the resulting object passed to this function is something like

{ 
  trt_ConfigurationToken: undefined,
  trt_ProfileToken: undefined 
}

which causes the function to throw an error at Object.keys later in the recursive chain when evaluating undefined. I believe the problem can be solved by replacing the line with return params ? reducer(params)(reqNode)() : ''. However, I am not to familiar with typescipt as well as the other effects this may have in the library. Does this seem correct? Another option would be to add a line like if (!obj[key]) return acc; before this line

The resulting strings w/params and without params after making this change:

<trt:GetVideoSourceConfigurationOptions><trt:ProfileToken>recording</trt:ProfileToken><trt:ConfigurationToken>0</trt:ConfigurationToken></trt:GetVideoSourceConfigurationOptions>

<trt:GetVideoSourceConfigurationOptions></trt:GetVideoSourceConfigurationOptions>

which my device correctly interprets.

400 'The requested action requires authorization'

In most methods the error is returned 400 'The requested action requires authorization'

const onvif = require("onvif-rx");

  const params = {
    deviceUrl: 'http://192.168.1.1/onvif/device_service',
    password: 'pass',
    username: 'user'
  };

 const device =  onvif.createManagedDeviceInNode(params)


device.api.Device.GetServiceCapabilities()
.toPromise()
.then(results => {
    results.match({ // results are wrapped in a managed object for safer processing
        ok: success => console.log(success.json), // successful response object
        fail: railure => console.log(railure.status, railure.statusMessage) // request failure object
    })
})
/*
**The result is:**
{ Capabilities: 
   { Network: { _attributes: [Object] },
     Security: { _attributes: [Object] },
     System: { _attributes: [Object] } } }
*/

device.api.Device.GetUsers()
.toPromise()
.then(results => {
    results.match({ // results are wrapped in a managed object for safer processing
        ok: success => console.log(success.json), // successful response object
        fail: railure => console.log(railure.status, railure.statusMessage) // request failure object
    })
})

/*
**The result is:**
400 'The requested action requires authorization'
*/

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here are some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two Factor Authentication for your account, set its level to "Authorization only" in your account settings. semantic-release cannot publish with the default "
Authorization and writes" level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

Event example

Hi,

Can someone please provide how to use Event API (CreatePullPointSubscription, PullMessages, Seek)?

Like : "I would like to get events from now" and "I would like to get events from yesterday to now"

Vector2D with child elements instead of attributes

Hey,

first of all, thanks for providing this library!

I was playing around with my camera (Reolink E1 Zoom) and noticed, that ContinuousMove was failing without an error, just no movement. To find out what's going wrong, I then tried node-onvif (Link) and it worked immediately.

When comparing the SOAP bodies of the two implementations, I noticed that onvif-rx defines x and y as child elements of tt:PanTilt while node-onvif uses attributes on the element itself:

<tptz:ContinuousMove><tptz:ProfileToken>000</tptz:ProfileToken><tptz:Velocity><tt:PanTilt><tt:x>1</tt:x><tt:y>0</tt:y></tt:PanTilt></tptz:Velocity><tptz:Timeout>PT1S</tptz:Timeout></tptz:ContinuousMove>

vs.

<tptz:ContinuousMove><tptz:ProfileToken>000</tptz:ProfileToken><tptz:Velocity><tt:PanTilt x="1" y="0"></tt:PanTilt></tptz:Velocity><tptz:Timeout>PT1S</tptz:Timeout></tptz:ContinuousMove>

The ONVIZ spec also requires attributes and does not mention child elements, as far as I can see:

image

http://www.onvif.org/specs/srv/ptz/ONVIF-PTZ-Service-Spec-v260.pdf (Page 41)

Is this something where other cameras are more tolerant?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.