Looking for solutions to integrate with Milestone VMS to get camera snapshots

Dear team, one of our clients is using Milestone as their VMS (servers running 2023 r2) and my team is building a solution that requires gathering camera snapshots periodically. Currently we are gathering snapshots by running PowerShell script and connecting to Milestone Management Server, getting VMS Device group for cameras and getting live snapshot for each camera based on camera id. We are looking to replace PS with more reliable and easy to maintain solutions that would suite cloud based architecture and support automated processes.

I came across your RESTfull API, however while we could use it to get list of cameras it seems there isn’t an operation to get camera snapshot right now.

Based on the documentation it looks like the only other way for us would be to use Protocol integration. In this case we would have to write the implementation ourselves and use SOAP services to gather data. Is that correct? Could you please advise whether there are other solutions that would suite our case? Thank you.

In general getting video by use of the protocols you should use the Image Server protocol which resides in the Recording Server. There is an option in the Recorder Command Service SOAP Protocol to retrieve single JPEGs, from what you describe it could be exactly what you need.

https://doc.developer.milestonesys.com/html/index.html?base=recordersoaphelp/index.html&tree=tree_3.html

https://doc.developer.milestonesys.com/html/index.html?base=gettingstarted/intro_soap_protocols.html&tree=tree_3.html

Another option might be to use the Mobile Server, the Mobile Server is free, can be placed in a DMZ, and has samples.

https://doc.developer.milestonesys.com/mipsdkmobile/

https://doc.developer.milestonesys.com/mipsdkmobile/index.html?base=samples/web_thumbnailsample.html&tree=tree_5.html

The RestAPI is, as you correctly write, currently lacking functionality to give you camera snapshots. It has recently been extended with functionality to open a WebRTC stream for H264 cameras. My guess is that this might not be a good fit for retrieving camera snapshots.

https://doc.developer.milestonesys.com/html/index.html?base=samples/protocolsamples/webrtc_javascript/readme.html&tree=tree_3.html

Hello, since Image Server protocol integration seems like what we need, we have decided to try and go with this option. I have followed the documentation and tried to connect to Management Server to get XProtect authentication token first. I’m using Node.js to build the integration and I have found this post in developer forum that I tried to follow.

However, I continue to get Bad Request with no other details so it is not clear what is wrong with my request. Also, in this post one developer says that ‘Basic authentication is somehow different depending on XProtect version’. Is this correct? How should I connect for 2023 r2 version? Any guidance is highly appreciated. Thank you.

My code sample looks like this:

const INTEGRATION_INSTANCE_ID = 'd3cd8c36-bbc9-4528-8509-e7dd8898d24a';
const TOKEN_REQUEST_BODY = `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xpr="http://videoos.net/2/XProtectCSServerCommand"><soapenv:Header/><soapenv:Body><xpr:Login><xpr:instanceId>${INTEGRATION_INSTANCE_ID}</xpr:instanceId></xpr:Login></soapenv:Body></soapenv:Envelope>`;
 
const SOAP_ACTION = 'http://videoos.net/2/XProtectCSServerCommand/IServerCommandService/Login';
const MANAGEMENT_SERVER_HOST = 'http://${HOST_NAME}/ManagementServer/ServerCommandService.svc';
const AUTH = 'Basic {base64_encoded_credentials}';
 
const response = await axios.post(MANAGEMENT_SERVER_HOST,
    TOKEN_REQUEST_BODY,
    {
        headers: {
 
            'content-type': 'application/soap+xml; charset=utf-8',
            'accept': '*/*',
            'SOAPAction': SOAP_ACTION,
            'Content-Length': `${TOKEN_REQUEST_BODY.length}`,
            'Authorization': AUTH
        }
    }).then(res => {
        console.log(res);
    }).catch(err => {
        console.log(err)
    });
 
token = await getToken(response.content)
return token;

Could you please have a look at the samples to see how they do? The LoginDotNetSoap (and ServerCommandWrapper) uses the recommended way and you should be able to follow the code.

https://doc.developer.milestonesys.com/html/index.html?base=samples/protocolsamples/logindotnetsoap/readme.html&tree=tree_3.html

https://github.com/milestonesys