NEWS
Anfrage: Bild-Kopier-Skript
-
Hallo zusammen,
ich nutze den Motion-Adapter der bei erkannter Bewegung von der IP-Kamera ein Bild abspeichert. Der Dateiname von dem Bild beinhaltet eine laufende Nummer sowie Datum und Uhrzeit, so dass kein Bild überschrieben wird. Der Dateiname von dem letzten Bild ist in den Objekten zu finden.
motion.0 - thread0 - events - last picture.
Ich bräuchte jetzt ein Skript, das das Verzeichnis mit den gespeicherten Bildern auf ein neues Bild prüft (= Objekt "motion.0 - thread0 - events - last picture" hat sich geändert) und dieses in eine Datei mit festem Namen umkopiert (z.B. lastpic.jpg).
Die Datei darf dann ja ruhig bei jedem neuen Bild überschrieben werden, es geht ja nur darum, das jeweils letzte Bild zu zeigen. Javascript beherrsche ich leider so gar nicht, kann mir da jemand helfen?
Danke vorab!
-
Möchtest du einfach in regelmäßigen Abständen prüfen ob ein neues Bild da ist? Oder gibt es ein Datenpunkt auf den du reagieren kannst, weil du etwas schreibst von
Bildern auf ein neues Bild prüft (= Objekt "motion.0 - thread0 - events - last picture" hat sich geändert) `
mein Ansatz wäre, im javascript Adapter in den Einstellungen das "exec" Kommando zu erlauben und dann im Filesystem direkt mit Bash-Befehlen zu arbeiten. Wenn in dem Ordner nur Bilder sind, könntest du etwas in die Richtung machen:schedule('* * * * *', err => { // jede Minute checken exec('ls -Art /*PFAD aller Bilder*/ | tail -n 1', (error, stdout, stderr) => { // hole letztes file in PFAD if(!error) { // let imageName = stdout; exec('mv /*PFAD aller Bilder*/' + stdout + '/*PFAD wo das Zielbild liegen soll/* lastpic.jpg', (error, stdout, stderr) => { if(error) log(stderr, 'error'); // Wenn Fehler beim umbennenen --> logge ihn auf error }); } else { log(stderr, 'error'); // Wenn Fehler dann logge auf error-level } // endElse }); });
-
Es gibt unter Objekten den Datenpunkt "motion.0 - thread0 - events - last picture", d.h. die Änderung könnte der Trigger für die Ausführung des Skripts sein, in dem dann "Bild mit Name "last picture"" nach "lastpic.jpg" umkopiert wird. Das Skript soll also folgendes machen:
Wenn das Objekt "last picture" sich ändert (weil ein neues Bild mit neuem Dateinamen gemacht wurde)
dann kopiere /"last picture" nach /lastpic.jpg (hole Dateiname aus Objekt "last picture" und kopiere das Bild nach "lastpic.jpg")
-
Es gibt unter Objekten den Datenpunkt "motion.0 - thread0 - events - last picture", d.h. die Änderung könnte der Trigger für die Ausführung des Skripts sein, in dem dann "Bild mit Name "last picture"" nach "lastpic.jpg" umkopiert wird. Das Skript soll also folgendes machen:
Wenn das Objekt "last picture" sich ändert (weil ein neues Bild mit neuem Dateinamen gemacht wurde)
dann kopiere /"last picture" nach /lastpic.jpg (hole Dateiname aus Objekt "last picture" und kopiere das Bild nach "lastpic.jpg") `
Ah okay also motion ist ein Adapter und da kannst du den Trigger raus verwenden, also wahrscheinlich
motion.0.thread0.events.last picture ````oder wie er eben korrekt heißt. Dann musst du nicht schedulen sondern kannst das als Auslöser nehmen. Um auf die Änderung eines Datenpunktes zu reagieren kann man ihn abonnieren mittels "on". Zum Verständnis, das Skript sollte mittels "ls" das Bild in dem gegebenen Pfad, mit dem neusten Änderungsdatum in die stdout geben. Sprich in stdout sollte der Name der neusten Datei stehen. Dann tust du das bild mittels "mv" dahin bewegen wo du es hin haben möchtest. Der "mv" Befehl überschreibt auch vorhandene Dateien, also wenn du "mv /opt/iobroker/node_modules/motion/data/lastpic /home/pi/lastpic.jpg" vornimmst würde er die Datei "/opt/iobroker/node_modules/motion/data/lastpic" nach "/home/pi/lastpic.jpg" verschieben + den Dateinamen ändern und falls dort schon eine lastpic.jpg existiert wird diese überschrieben.
on('motion.0.thread0.events.last picture', err => { // bei Änderung auslösen
exec('ls -Art /PFAD aller Bilder/ | tail -n 1', (error, stdout, stderr) => { // hole letztes file in PFAD
if(!error) {
// let imageName = stdout;
exec('mv /PFAD aller Bilder/' + stdout + '/PFAD wo das Zielbild liegen soll/ lastpic.jpg', (error, stdout, stderr) => {
if(error) log('error moving: ' + stderr, 'error'); // Wenn Fehler beim umbennenen --> logge ihn auf error
});
} else {
log('error listing: ' + stderr, 'error'); // Wenn Fehler dann logge auf error-level
} // endElse
});
});Die Kommentare in /* */ musst du entsprechend durch deine Pfade ersetzen.
-
Hallo,
statt "mv" nehmen ich "cp", ich möchte ja eine Kopie anlegen und das Original mit dem eindeutigen Namen behalten. Das Script braucht auch nicht nach der letzten Datei suchen ("exec ('ls…"), um den Namen vom Bild zu kennen. Der Dateiname inkl. .jpg steht im Objekt "motion.0.thread0.events.lastpicture".
Ich habe das Script jetzt drin, es liefert allerdings komischerweise einen Fehler (passiert auch mit mv):
javascript.0 script.js.IPCam.letzes_Bild_kopieren: error copying: cp: Fehlender Zieldatei‐Operand hinter '/mnt/hgfs/nuc_HDD/ipcam/862-05_2018-09-15_15-46-31_Snapshot.jpg' „cp --help“ liefert weitere Informationen. /bin/sh: 2: /mnt/hgfs/nuc_HDD/ipcam/lastpic.jpg: not found
sieht so aus, als wenn "/mnt/hgfs/nuc_HDD/ipcam/lastpic.jpg" nicht als Ziel, sondern als zweite Quelle genommen wird - irgendeine Idee?
Das Script mit meinen Pfadnamen sieht so aus:
on('motion.0.thread0.events.lastpicture', err => { // bei Änderung auslösen exec('ls -Art /mnt/hgfs/nuc_HDD/ipcam/ | tail -n 1', (error, stdout, stderr) => { // hole letztes file in PFAD if(!error) { // let imageName = stdout; exec('cp /mnt/hgfs/nuc_HDD/ipcam/' + stdout + '/mnt/hgfs/nuc_HDD/ipcam/lastpic.jpg', (error, stdout, stderr) => { if(error) log('error copying: ' + stderr, 'error'); // Wenn Fehler beim kopieren --> logge ihn auf error }); } else { log('error listing: ' + stderr, 'error'); // Wenn Fehler dann logge auf error-level } // endElse }); });
"exec('ls -Art…" könnte vielleicht noch wegoptimiert uns stdout dann durch "motion.0.thread0.events.lastpicture.val" oder wie die Syntax wäre ersetzt werden.
Um das Bild per Telegram aufs Telefon zu schicken, ist mir auch schon einmal geholfen worden, vielleicht noch als Input:
on("motion.0.thread0.events.lastpicture", function(obj) { sendTo('telegram.0', "/mnt/hgfs/nuc_HDD/ipcam/" + getState("motion.0.thread0.events.lastpicture").val); });
Schon einmal vielen Dank vorab!
-
on('motion.0.thread0.events.lastpicture', () => { // bei Änderung auslösen let fileName = getState('motion.0.thread0.events.lastpicture').val; // Name des neusten Bildes zuweisen exec('cp /mnt/hgfs/nuc_HDD/ipcam/' + fileName + ' /mnt/hgfs/nuc_HDD/ipcam/lastpic.jpg', (error, stdout, stderr) => { if(error) log('error copying: ' + stderr, 'error'); // Wenn Fehler beim kopieren --> logge ihn auf error }); });
Das sollte reichen.
Das mit dem cp lag daran, dass es wichtig ist "cam/' + fileName + ' /mnt/hgfs/nuc_HDD/ipcam/lastpic.jpg'" zwischen den beiden Pfaden ein Leerzeichen zu haben sonst ist es für ihn ein Pfad da Quelle und Ziel nicht getrennt waren.
-
Super, das funktioniert jetzt, vielen, vielen Dank!!!!
Trotzdem findet der proxy Adapter das Bild nicht, da muss ich wohl noch einmal unter Adapter nach Hilfe suchen…