Das hat mir keine Ruhe gelassen ... und ich hab mal was gebastelt:
Ein nodejs-script, das die timers.conf überwacht und Aktivität entwickelt, wenn die Datei vom vdr (oder wem auch immer) angefasst wurde.
Da der vdr die timers.conf bei Start und Ende einer Aufnahme anpackt, habe ich damit einen "echten" before recording_hook und einen Einstieg, um den Sundtek-Reciever zu mounten, wenn er gebraucht wird und später wieder abzuschalten.
Das script kann vermutlich ziemlich einfach modifiziert werden, um timer-Konflikte rauszuwerfen und einen anderen trigger bekommen.
Nodejs habe ich genommen, weil es event basiert ist - also den Trigger mitbringt, es die json-Objekte der restful api nativ versteht und http.gets schön einfach gehalten werden können.
Möglicherweise hilft das script ja dem einen oder anderen mit einer ähnlichen Problemstellung.
Achtung! ... ich bin kein Programmierer und schuster sowas nur zusammen - vieles geht sicher "kürzer" und "besser" ... nur keine Scheu ... das Script kann natürlich nach Wunsch verändert werden.
#!/usr/bin/node
//this script watches the vdr timers.conf for changes including touches.
//In the end it can deliver the number of needed recievers (real conflicting recordings!) or an array of
//parallel running recordings (not necessarly conflicting in the view of recievers!) for the time the timers.conf
//was changed lastly.
//
//The script depends on a working nodejs environment.
//For deamonized running this scrip use for example 'forever'
//
//before using this script "hot", you should examine, if fs.watchFile behaves as expected
//
// file to watch in yaVDR /var/lib/vdr/timers.conf
var http= require('http');
var exec = require("child_process").exec;
var async= require('async'); //needs to be installed separatedly ex. 'npm install async'
var fs = require('fs');
var _ = require('underscore'); //needs to be installed separatedly
var vdr_host = 'localhost';
//watch timers.conf for changes
//the "main"-part ... goes into deep chaos looking code ...
fs.watchFile('/var/lib/vdr/timers.conf', function (curr, prev) {
if ((curr.mtime.getTime() - prev.mtime.getTime()) > 16500){
// first action is to get timers from restfull-api and store as json.object
setTimeout(function() {
var options = {
hostname:vdr_host,
path: '/timers.json',
port:8002,
method:'GET'
};
var req = http.request(options, function(res) {
var body = '';
res.on('data', function(d) {
body += d;
});
res.on('end', function() {
var parsed = JSON.parse(body);
do_something(parsed.timers); // we have the timers ... now do something
});
});
req.end();
}, 15000); //timeout ende ... sleep for some milliseconds to get multiple changes in timers.conf
}
});
//end watching-part
function do_something(timers) {
var pending = _.where(timers, {is_pending: true});
var log_time = new Date().toISOString().replace('T', ' ').substr(0, 19)
get_channels('', function (channels){ //we need channels/transponders for conflict detection
get_transponders(pending,channels,function(used_transponders){ //add the transponder info on the pending timers
// in pending are the timers which are now 'is_pending=true' on restful api
// vdr sets 'is_pending=true' BEFORE actually starting the recording
// so this should be the perfect BEFORE-recording_hook.
// in used_transponders are the actually needed transponders.
// here you should put whatever you wish to do.
// as example we print to stdout ... you may call a shell script to start another reciever
console.log('******* timers.conf change at time: '+log_time);
console.log('Pending timers: '+pending.length);
console.log(pending);
console.log('Needed recievers: '+used_transponders.length);
if (used_transponders.length > 1){
var cmd = '/home/ralf/dev/sundtek_on_from_js.sh';
console.log('Need more transponder...');
child = exec(cmd, function (error, stdout, stderr) {
if (error !== null) {
console.log("exec error: " + error);
return;
}
if (stderr !== ""){
console.log("script exec error: " + stderr);
return;
}
});
} //ende if mount more
if (used_transponders.length == 1){
var cmd = '/home/ralf/dev/sundtek_off.sh';
console.log('Maybe switch off transponder...');
child = exec(cmd, function (error, stdout, stderr) {
if (error !== null) {
console.log("exec error: " + error);
return;
}
if (stderr !== ""){
console.log("script exec error: " + stderr);
return;
}
});
} //ende if switch off
});
});
};
function get_channels(param,callback){
//nothing special here ... just a http.get on restfull api for channels in a json-object
var options = {
hostname:vdr_host,
path: '/channels.json',
port:8002,
method:'GET' };
var req = http.request(options, function(res) {
var body = '';
res.on('data', function(d) {
body += d;
});
res.on('end', function() {
var parsed = JSON.parse(body);
callback(parsed.channels);
});
});
req.end();
};
function get_transponders(timers,channels,callback){
var used =[];
async.each(timers, function work(timer,callback){
transponder = _.findWhere(channels, {name: timer.channel_name}).transponder;
timer.transponder=transponder;
used.push(transponder);
callback();
}, //1st async end 1st function / parameter
function(err){
//kick doubles
//multiple timers can use the same transponder -> no extra reciever needed
used_clear = used.filter(function(elem, pos) {
return used.indexOf(elem) == pos;
})
callback(used_clear);
}
);//end async
}; //end function
Alles anzeigen