Script-driven VMS integrations

A new mechanism for VMS integration is introduced, which is based on scripting and allows an independent JS developer to add support for 3rd party VMS.

TL;DR: Viinex adds support for VMS integration mechanism based on custom builtin scripts. A ECMAScript 5 code can now govern how exactly Viinex communicates with third-party VMS to get video streams and related information, -- in terms of parameterizing of HTTP and RTSP. This is sufficient to do a VMS integration not in all but in quite a number of cases. As a proof of concept, we implemented the integration with Hikvision and Dahua NVRs using this mechanism. The API for script-driven integrations is documented, so Viinex' clients may perform more integrations on their own, not necessarily relying on us.

Throughout the last year and a half, we've been adding VMS integrations to Viinex SDK, so that the latter can retrieve and re-stream media from a third party system to a web-oriented client's application. Viinex provides a uniform programming interface for clients who use these integrations. However, until some critical mass was reached, it wasn't always obvious to us how much is there in common for all of these integrations, in the sense of what's left "behind the scenes", that is -- what comprises not only the programming interface visible to clients (which is always the same), but also the body of integration.

In a while we got a notion that some of integration implementations indeed have certain common parts. Yes, there are difficult cases, when a VMS only provides a C++ API (like with Geutebrueck G-Core), or when there's a need to implement the proprietary network protocol which a VMS understands and speaks (like with Milestone XProtect or AxxonSoft Intellect). But there are also easy or mild cases, when the VMS uses standard RTSP for streaming, and some kind of HTTP-based RPC for everything else.

It brought to our mind that an existing mechanism of Viinex builtin scripts may be used to implement VMS integrations in such mild cases. In order to not make things more complex than they need to be, we decided to literally use an existing implementation "script" object for this new purpose. There's an "Updateable" programming interface, which actually provides the means to pass all kinds of data to and from the script (that's an "onupdate" method within the script). So we designed a convention for the "onupdate" calls from Viinex to the script, which serve the same purpose of implementing the VMS integration methods for Viinex: we need to construct the RTSP URLs for retreiving media, to get the snapshot images, and to get video archive contents. The script needs to follow this convention to provide Viinex with necessary information, while Viinex uses this convention to get this information and do the rest, -- that is, create RTSP sessions, or make HTTP requests, and so on.

To prove that the idea is viable, we implemented the integrations with Hikvision and Dahua NVRs using this mechanism. Not that it was a piece of cake, -- in one case the integration script needs to handle XML returned by the NVR software, and thus employ some XML parser (which needs to be executed within Viinex, and our scripting engine only allows ECMAScript 5, so we had to transpile the parser into a module loadable by Viinex), while in other case one request from Viinex' perspective actually needs to be executed as multiple requests to the NVR, and there was also the need for the script to implement support for some token-based authentication against NVR's API... however eventually both integrations were done, and it's about a few hundred lines of JS code in both cases. They are now shipped with Viinex distributions in source code, so they may be referred to, if someone decides to develop another integration for some other system, not relying on Viinex' development and not going for the heavy weapon (by which we mean "native" VMS integration API, which is still available).