v1.1
-added 'null' key word to img_comp_cmd parameter so motion detection can be turned off if desired -fixed footage directory max_events_bytes by having it loop through the directory at least 100 times
This commit is contained in:
parent
7c72d26e46
commit
c0f167e5b1
26
README.md
26
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
JustMotion is a simple, lightweight video surveillance application utilizing
|
JustMotion is a simple, lightweight video surveillance application utilizing
|
||||||
the server-client model that doesn't try to re-invent the wheel. The source
|
the server-client model that doesn't try to re-invent the wheel. The source
|
||||||
code for both server and client are available this repository and can be
|
code for both server and client are available in this repository and can be
|
||||||
compliled and/or installed separately.
|
compliled and/or installed separately.
|
||||||
|
|
||||||
# JustMotion-Server #
|
# JustMotion-Server #
|
||||||
|
@ -13,10 +13,10 @@ motion to permanent storage. The main advantage of this is reduced storage
|
||||||
requirements as opposed to continuous recording because only video footage
|
requirements as opposed to continuous recording because only video footage
|
||||||
of interest is kept in storage.
|
of interest is kept in storage.
|
||||||
|
|
||||||
The server implements the principle of doing the least as needed, as a result
|
The server implements the principle of doing the least as needed. As a result
|
||||||
it extremely lightweight with the fact it doesn't attempt to re-implement much
|
it is extremely lightweight with the fact it doesn't attempt to re-implement
|
||||||
of it's functions internally but will instead rely on external applications
|
much of it's functions internally but will instead rely on external
|
||||||
that already implement the functions very well.
|
applications that already implement the functions very well.
|
||||||
|
|
||||||
It doesn't have a builtin user interface so instead external applications are
|
It doesn't have a builtin user interface so instead external applications are
|
||||||
more than welcome to interface with the buffer/footage directories to
|
more than welcome to interface with the buffer/footage directories to
|
||||||
|
@ -26,14 +26,14 @@ implement a user interface of any flavor.
|
||||||
|
|
||||||
JustMotion-Client is the client portion of this application that actually
|
JustMotion-Client is the client portion of this application that actually
|
||||||
implement a user interface. Utilizing the same principle of doing the least as
|
implement a user interface. Utilizing the same principle of doing the least as
|
||||||
needed, it uses an external video player to play m3u8 playlist files mounted
|
needed, it uses an external video player to play m3u8 playlist files located
|
||||||
as an ssh filesystem to play live or recorded footage from the server.
|
at the server's buffer/footage directories. It mounts the server as an ssh
|
||||||
|
filesystem to access such directories so no need to open any addtional ports
|
||||||
|
if your server already has working ssh access.
|
||||||
|
|
||||||
### Usage (server) ###
|
### Usage (server) ###
|
||||||
|
|
||||||
```
|
```
|
||||||
JustMotion 1.0
|
|
||||||
|
|
||||||
Usage: jmotion <argument>
|
Usage: jmotion <argument>
|
||||||
|
|
||||||
-h : display usage information about this application.
|
-h : display usage information about this application.
|
||||||
|
@ -53,9 +53,6 @@ Usage: jmotion <argument>
|
||||||
|
|
||||||
The config file is a simple text file that contain parameters that dictate the
|
The config file is a simple text file that contain parameters that dictate the
|
||||||
behavior of the server for each camera located in the /etc/jmotion directory.
|
behavior of the server for each camera located in the /etc/jmotion directory.
|
||||||
The config for each camera can have any unique name within that directory.
|
|
||||||
Below is an example of a config file with all parameters supported and
|
|
||||||
descriptions.
|
|
||||||
```
|
```
|
||||||
# Motion Watch config file
|
# Motion Watch config file
|
||||||
#
|
#
|
||||||
|
@ -106,9 +103,8 @@ img_comp_cmd = compare -metric FUZZ &prev& &next& /dev/null
|
||||||
# formatted so the app will be required to support this format. also avoid
|
# formatted so the app will be required to support this format. also avoid
|
||||||
# outputting any special chars, only numeric chars with a single '.' if
|
# outputting any special chars, only numeric chars with a single '.' if
|
||||||
# outputting a decimal value. magick is the default if not defined in the
|
# outputting a decimal value. magick is the default if not defined in the
|
||||||
# config file. the special string &prev& will be substituted with the path
|
# config file. this parameter can also be set to 'null' as a means to turn
|
||||||
# to the "previous" bitmap image, behind in time stamp to the image path
|
# off motion detection.
|
||||||
# subtituted in &next&.
|
|
||||||
#
|
#
|
||||||
img_comp_out = stderr
|
img_comp_out = stderr
|
||||||
# this is the standard output stream the app defined in img_comp_cmd will
|
# this is the standard output stream the app defined in img_comp_cmd will
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define APP_VERSION "1.0"
|
#define APP_VERSION "1.1"
|
||||||
#define APP_NAME "JustMotion"
|
#define APP_NAME "JustMotion"
|
||||||
#define APP_TARGET "jmotion"
|
#define APP_TARGET "jmotion"
|
||||||
#define DATETIME_FMT "yyyyMMddhhmmss"
|
#define DATETIME_FMT "yyyyMMddhhmmss"
|
||||||
|
|
|
@ -29,21 +29,36 @@ void DetectLoop::init()
|
||||||
pcTimer = new QTimer(this);
|
pcTimer = new QTimer(this);
|
||||||
evtTimer = new QTimer(this);
|
evtTimer = new QTimer(this);
|
||||||
|
|
||||||
connect(pcTimer, &QTimer::timeout, this, &DetectLoop::pcBreak);
|
setupBuffDir(shared->buffPath);
|
||||||
connect(evtTimer, &QTimer::timeout, this, &DetectLoop::reset);
|
|
||||||
|
connect(pcTimer, &QTimer::timeout, this, &DetectLoop::pcBreak);
|
||||||
|
|
||||||
connect(this, &QFileSystemWatcher::directoryChanged, this, &DetectLoop::updated);
|
connect(this, &QFileSystemWatcher::directoryChanged, this, &DetectLoop::updated);
|
||||||
|
|
||||||
pcTimer->start(shared->postSecs * 1000);
|
pcTimer->start(shared->postSecs * 1000);
|
||||||
evtTimer->setSingleShot(true);
|
|
||||||
|
|
||||||
setupBuffDir(shared->buffPath);
|
if (shared->compCmd.toLower() != "null")
|
||||||
|
{
|
||||||
|
connect(evtTimer, &QTimer::timeout, this, &DetectLoop::reset);
|
||||||
|
|
||||||
|
evtTimer->setSingleShot(true);
|
||||||
|
|
||||||
|
eTimer.start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eTimer.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
addPath(shared->buffPath + "/vid");
|
addPath(shared->buffPath + "/vid");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DetectLoop::updated(const QString &path)
|
void DetectLoop::updated(const QString &path)
|
||||||
{
|
{
|
||||||
eTimer.start();
|
if (shared->compCmd.toLower() != "null")
|
||||||
|
{
|
||||||
|
eTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
auto clips = lsFilesInDir(path, shared->streamExt);
|
auto clips = lsFilesInDir(path, shared->streamExt);
|
||||||
auto index = clips.indexOf(vidBName);
|
auto index = clips.indexOf(vidBName);
|
||||||
|
@ -153,7 +168,11 @@ QStringList DetectLoop::buildSnapArgs(const QString &vidSrc, const QString &imgP
|
||||||
|
|
||||||
QString DetectLoop::statusLine()
|
QString DetectLoop::statusLine()
|
||||||
{
|
{
|
||||||
if (eTimer.elapsed() >= 5000)
|
if (!eTimer.isValid())
|
||||||
|
{
|
||||||
|
return "OFF ";
|
||||||
|
}
|
||||||
|
else if (eTimer.elapsed() >= 5000)
|
||||||
{
|
{
|
||||||
emit starving();
|
emit starving();
|
||||||
|
|
||||||
|
@ -187,7 +206,7 @@ void DetectLoop::exec()
|
||||||
QProcess::execute("ffmpeg", snapArgsA);
|
QProcess::execute("ffmpeg", snapArgsA);
|
||||||
QProcess::execute("ffmpeg", snapArgsB);
|
QProcess::execute("ffmpeg", snapArgsB);
|
||||||
|
|
||||||
if (QFile::exists(imgAPath) && QFile::exists(imgBPath))
|
if (QFile::exists(imgAPath) && QFile::exists(imgBPath) && (shared->compCmd.toLower() != "null"))
|
||||||
{
|
{
|
||||||
QProcess extComp;
|
QProcess extComp;
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ void EventLoop::exec()
|
||||||
|
|
||||||
auto names = lsFilesInDir(shared->recPath + "/vid", shared->recExt);
|
auto names = lsFilesInDir(shared->recPath + "/vid", shared->recExt);
|
||||||
|
|
||||||
if (byteSize(shared->recPath) > shared->evtMaxBytes)
|
for (auto i = 0; (byteSize(shared->recPath) >= shared->evtMaxBytes); ++i)
|
||||||
{
|
{
|
||||||
auto nameOnly = QFileInfo(shared->recPath + "/vid/" + names[0]).baseName();
|
auto nameOnly = QFileInfo(shared->recPath + "/vid/" + names[0]).baseName();
|
||||||
|
|
||||||
|
@ -163,6 +163,15 @@ void EventLoop::exec()
|
||||||
names.removeFirst();
|
names.removeFirst();
|
||||||
|
|
||||||
dirUpdated = true;
|
dirUpdated = true;
|
||||||
|
|
||||||
|
if (i > 100)
|
||||||
|
{
|
||||||
|
// loop through 100 times before breaking the for loop, prevents infinte looping
|
||||||
|
// if bytes size of the dir is not being read correctly or there is a lot to
|
||||||
|
// delete (don't want to keep EventLoop busy doing this for too long).
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirUpdated)
|
if (dirUpdated)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user