// This file is part of Motion Watch. // Motion Watch is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Motion Watch is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. #include "mo_detect.h" #include "logger.h" void detectLoop(shared_t *share) { detLog("detectLoop() -- start", share); wrOutLogs(share); vector bufFiles; do { bufFiles = lsFilesInDir(share->buffDir, "." + share->vidExt); // this loop will not process the last buffile while recLoop is still actively // pulling footage from ffmpeg. it is assumed the last file is not finished. // share->recLoopWait is used to detect if the recloop is still pulling. if not // then the last file is finally processed. if ((bufFiles.size() >= 2) || (share->recLoopWait && !bufFiles.empty())) { auto fullPath = cleanDir(share->buffDir) + "/" + bufFiles[0]; Mat thumbNail; if (moDetect(fullPath, thumbNail, share)) { share->skipCmd = true; detLog("motion detected in file: " + fullPath, share); wrOut(fullPath, thumbNail, share); } else { detLog("no motion detected in file: " + fullPath + " removing it.", share); remove(fullPath.c_str()); } } else { sleep(1); } } while (!bufFiles.empty() && !share->recLoopWait); detLog("detectLoop() -- finished", share); wrOutLogs(share); } void recLoop(shared_t *share) { while (rdConf(share)) { recLog("recLoop() -- start", share); wrOutLogs(share); if (!fileExists("/tmp/mow-lock")) { recLog("/tmp/mow-lock not found, assuming it is safe to update the webroot page.", share); recLog("webroot page = " + cleanDir(share->webRoot) + "/index.html", share); system("touch /tmp/mow-lock"); genCSS(share); genHTMLul(share->webRoot, string(APP_NAME) + " " + string(APP_VER), share); system("rm /tmp/mow-lock"); } else { recLog("/tmp/mow-lock pesent, skipping update of the webroot page.", share); } genHTMLul(share->outDir, share->camName, share); recLog("camera specific webroot page updated. page = " + share->outDir + "/index.html", share); auto bufPath = cleanDir(share->buffDir) + "/%03d." + share->vidExt; auto secs = to_string(share->secs); auto limSecs = to_string(share->secs + 3); auto cmd = "timeout -k 1 " + limSecs + " ffmpeg -hide_banner -i " + share->recordUrl + " -y -vcodec copy -map 0 -segment_time 00:00:10 -f segment -t " + secs + " " + bufPath; thread th2(detectLoop, share); recLog("detect_loop started in a seperate thread.", share); recLog("ffmpeg = " + cmd, share); system(cmd.c_str()); share->recLoopWait = true; th2.join(); wrOutLogs(share); if (!share->skipCmd) { recLog("motion not detected by detect loop.", share); recLog("running post command = " + share->postCmd, share); system(share->postCmd.c_str()); } else { recLog("motion detected by detect loop, skpping the post command.", share); } recLog("recLoop() -- finished", share); wrOutLogs(share); } share->logRun = false; } int main(int argc, char** argv) { struct shared_t sharedRes; sharedRes.conf = parseForParam("-c", argc, argv, false); if (parseForParam("-h", argc, argv, true) == "true") { cout << "Motion Watch " << APP_VER << endl << endl; cout << "Usage: mow " << endl << endl; cout << "-h : display usage information about this application." << endl; cout << "-c : path to the config file." << endl; cout << "-v : display the current version." << endl; } else if (parseForParam("-v", argc, argv, true) == "true") { cout << APP_VER << endl; } else if (sharedRes.conf.empty()) { cerr << "err: A config file was not given in -c" << endl; } else { sharedRes.retCode = 0; sharedRes.recLoopWait = false; sharedRes.skipCmd = false; sharedRes.init = true; sharedRes.logRun = true; recLoop(&sharedRes); return sharedRes.retCode; } return EINVAL; }