Skip to content

Instantly share code, notes, and snippets.

@hawkeye64
Created December 15, 2017 13:51
Show Gist options
  • Save hawkeye64/a30e43c8301626f7687b985b5e7b04bd to your computer and use it in GitHub Desktop.
Save hawkeye64/a30e43c8301626f7687b985b5e7b04bd to your computer and use it in GitHub Desktop.
How to get snapshoutUri and finally snapshot from ONVIF camera
/* this is a partial gist */
const Promise = require('bluebird')
const axios = require('axios')
const Camera = require('onvif').Cam
class OnvifManager {
//...
this.cameras = {}
//...
readCamerasFromDatabase () {
//...
let onvif = // code to read from database
let options = {}
options.hostname = onvif.address
options.username = onvif.login
options.password = onvif.password
if (onvif.port && onvif.port !== 80) {
options.port = onvif.port
}
let camera = new Camera(options, error => {
camera.onvif = onvif
// assign to list of cameras
this.cameras[onvif.id] = camera
if (error === null) {
camera.getSnapshotUri({}, (error, data, xml) => {
if (error) {
console.error(`Cannot get snapshot URI for ${camera.onvif.name}/${camera.onvif.address}`)
}
else {
camera.snapshotUri = data
}
})
}
}
// call this function whenever a snapshot from the onvif camera is desired
commandFetchSnapshot (id) {
return new Promise((resolve, reject) => {
let camera = this.cameras[id]
if (!camera) {
let results = {
message: 'Not Found',
status: 404
}
reject(new Error(results))
}
else {
// check that we have a snapshotUri attached to this camera
if ('snapshotUri' in camera) {
let snapshotUri = camera.snapshotUri.uri
// using axios.get with options { responseType: 'arraybuffer' }
// did not work at all. The data returned was transformed somehow.
// This way works!
axios.request({
responseType: 'arraybuffer',
url: snapshotUri,
method: 'get',
headers: {
'Content-Type': 'image/*'
},
auth: {
username: camera.username,
password: camera.password
}
})
.then((results) => {
let mimeType = results.headers['content-type']
// using nodejs Buffer to encode the inary to base64
let b64encoded = Buffer.from(results.data, 'binary').toString('base64')
let image = 'data:' + mimeType + ';base64,' + b64encoded
let data = {
mimeType: mimeType,
image: image
}
// uncomment to write image to disk for testing
// const outputFilename = '/tmp/testfile.jpg'
// fs.writeFileSync(outputFilename, results.data)
resolve(data)
})
.catch(error => {
console.error('commandFetchSnapshot error', error)
let results = {
message: 'fetchSnapshot error',
status: 250,
error: error
}
reject(new Error(results))
})
}
else {
let results = {
message: 'Unknown in commandFetchSnapshot',
status: 250
}
reject(new Error(results))
}
}
})
}
}
@hawkeye64
Copy link
Author

hawkeye64 commented Dec 29, 2017

Axios couldn't handle working with Axis camera authentication because it uses Realm Digest. I have since changed my code to use the 'request' package.

New gist here: https://gist.github.com/hawkeye64/e67cb5aae8f46d9c94ea2c9a4bb9247b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment