zm-watcher
Version:
Library provides possibility to watch for new files in ZoneMinder events directory (per camera)
125 lines (109 loc) • 3.24 kB
JavaScript
var path = require("path");
var fs = require("fs");
var util = require("util");
function Watcher(eventsPath, monitors, callback){
var roots = [];
this.roots = roots;
var node;
for (var monitor of monitors){
console.log(`Adding monitor ${monitor} for path ${eventsPath}`);
node = createNode(path.join(eventsPath, monitor), {
eventsPath: eventsPath,
monitor: monitor,
callback: callback
});
roots.push(node);
}
}
Watcher.prototype.unwatch = function(){
for(var root of this.roots){
unwatchNode(root);
}
}
function findLastSubdir(dir){
var subdirs = fs.readdirSync(dir);
var result = null;
var stat;
for(var name of subdirs){
stat = fs.statSync(path.join(dir, name));
if (stat.isDirectory() && (result == null || result < name)){
result = name;
}
}
return result;
}
function watchNode(node, childName){
console.log(`Setuping node for path ${node.path}`);
if (childName === undefined){
childName = findLastSubdir(node.path);
}
if (node.child){
console.log(`Unwatching path ${node.child.path}`);
unwatchNode(node.child);
}
if (childName){
var child = createNode(
path.join(node.path, childName),
node.extra);
node.child = child;
}
else {
node.child = null;
}
if (!node.fswatcher){
node.fswatcher = fs.watch(node.path, (event, name) => {
//console.log(`event is: ${event}, name: ${name}`);
if (event == "rename"){
var subdir = path.join(node.path, name);
try {
fs.accessSync(subdir, fs.R_OK);
}
catch(e){
console.log(`File ${subdir} does not exist anymore`);
return;
}
var stat = fs.statSync(subdir);
if (stat.isDirectory()){
watchNode(node, name);
}
else{
var relativePath = path.relative(node.extra.eventsPath, subdir);
node.extra.callback(relativePath);
}
}
});
}
}
function unwatchNode(node){
var current = node;
while(current){
current.fswatcher.close();
current = current.child;
}
}
function createNode(path, extra){
var node = {
path: path,
child: null,
fswatcher: null,
extra:extra
};
watchNode(node);
return node;
}
/*
Watches for one or more cameras changes
parameters:
eventsPath - the path to events directory
cam1, cam2, cam3... - names of monitors to watch
callback(filePath) - callback for a new file. filePath - relative path to file, the first segment will be the monitor name
*/
function watch(eventsPath){
var monitors = Array.prototype.slice.call(arguments, 1, -1);
console.log(`Arguremnts for watch: eventsPath = ${eventsPath}, monitors=${util.inspect(monitors)}`);
var callback = arguments[arguments.length-1];
return new Watcher(eventsPath, monitors, callback);
}
module.exports = {
watch: watch
}