Merge branch 'storageareas' into work_on_zms
This commit is contained in:
commit
ed6ff23c2f
|
@ -626,6 +626,7 @@ INSERT INTO `Controls` VALUES (NULL,'Vivotek ePTZ','Remote','Vivotek_ePTZ',0,0,1
|
||||||
INSERT INTO `Controls` VALUES (NULL,'Netcat ONVIF','Ffmpeg','Netcat',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,100,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,100,5,5,0,0,0,1,255,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
|
INSERT INTO `Controls` VALUES (NULL,'Netcat ONVIF','Ffmpeg','Netcat',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,100,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,100,5,5,0,0,0,1,255,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
|
||||||
INSERT INTO `Controls` VALUES (NULL,'Keekoon','Remote','Keekoon', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
INSERT INTO `Controls` VALUES (NULL,'Keekoon','Remote','Keekoon', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
INSERT INTO `Controls` VALUES (NULL,'HikVision','Local','',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,100,0,0,1,0,0,0,0,1,1,100,1,0,0,0);
|
INSERT INTO `Controls` VALUES (NULL,'HikVision','Local','',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,100,0,0,1,0,0,0,0,1,1,100,1,0,0,0);
|
||||||
|
INSERT INTO `Controls` VALUES (NULL,'Maginon Supra IPC','cURL','MaginonIPC',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,0,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Add some monitor preset values
|
-- Add some monitor preset values
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
--
|
||||||
|
-- This adds StorageAreas
|
||||||
|
--
|
||||||
|
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.TABLES
|
||||||
|
WHERE table_name = 'Storage'
|
||||||
|
AND table_schema = DATABASE()
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Storage table exists'",
|
||||||
|
"CREATE TABLE `Storage` (
|
||||||
|
`Id` smallint(5) unsigned NOT NULL auto_increment,
|
||||||
|
`Path` varchar(64) NOT NULL default '',
|
||||||
|
`Name` varchar(64) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`Id`)
|
||||||
|
)"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Add StorageId column to Monitors
|
||||||
|
--
|
||||||
|
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE table_name = 'Monitors'
|
||||||
|
AND table_schema = DATABASE()
|
||||||
|
AND column_name = 'StorageId'
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Column StorageId exists in Monitors'",
|
||||||
|
"ALTER TABLE Monitors ADD `StorageId` smallint(5) unsigned NOT NULL default 0 AFTER `ServerId`"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Add StorageId column to Eventss
|
||||||
|
--
|
||||||
|
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE table_name = 'Events'
|
||||||
|
AND table_schema = DATABASE()
|
||||||
|
AND column_name = 'StorageId'
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Column StorageId exists in Events'",
|
||||||
|
"ALTER TABLE Events ADD `StorageId` smallint(5) unsigned NOT NULL default 0 AFTER `MonitorId`"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
UPDATE Monitors SET StorageId = 0 WHERE StorageId IS NULL;
|
||||||
|
ALTER TABLE Monitors MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0;
|
||||||
|
UPDATE Events SET StorageId = 0 WHERE StorageId IS NULL;
|
||||||
|
ALTER TABLE Events MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0;
|
||||||
|
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE table_name = 'Events'
|
||||||
|
AND table_schema = DATABASE()
|
||||||
|
AND column_name = 'Orientation'
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Column Orientation exists in Events'",
|
||||||
|
"ALTER TABLE `Events` ADD `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0' AFTER `Notes`"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Update Monitors table to have an Index on ServerId
|
||||||
|
--
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE table_name = 'Monitors'
|
||||||
|
AND table_schema = DATABASE()
|
||||||
|
AND index_name = 'Monitors_ServerId_idx'
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Monitors_ServerId Index already exists on Monitors table'",
|
||||||
|
"CREATE INDEX `Monitors_ServerId_idx` ON `Monitors` (`ServerId`)"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Update Server table to have an Index on Name
|
||||||
|
--
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE table_name = 'Servers'
|
||||||
|
AND table_schema = DATABASE()
|
||||||
|
AND index_name = 'Servers_Name_idx'
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Servers_Name Index already exists on Servers table'",
|
||||||
|
"CREATE INDEX `Servers_Name_idx` ON `Servers` (`Name`)"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
|
||||||
|
-- ALTER TABLE Logs ALTER Message DROP DEFAULT;
|
||||||
|
ALTER TABLE Logs MODIFY Message TEXT NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE Config MODIFY DefaultValue TEXT;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Add an Id column and make it the primary key of the Filters table
|
||||||
|
--
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE table_name = 'Filters'
|
||||||
|
AND table_schema = DATABASE()
|
||||||
|
AND column_name = 'Id'
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Column Id exists in Filters'",
|
||||||
|
"ALTER TABLE `Filters` DROP PRIMARY KEY, ADD `Id` int(10) unsigned NOT NULL auto_increment PRIMARY KEY FIRST, ADD KEY `Name` (`Name`);"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
|
@ -16,7 +16,7 @@ Alias /zm "@ZM_WEBDIR@"
|
||||||
DirectoryIndex index.php
|
DirectoryIndex index.php
|
||||||
SSLRequireSSL
|
SSLRequireSSL
|
||||||
Options -Indexes +MultiViews +FollowSymLinks
|
Options -Indexes +MultiViews +FollowSymLinks
|
||||||
AllowOverride All
|
AllowOverride None
|
||||||
<IfModule mod_authz_core.c>
|
<IfModule mod_authz_core.c>
|
||||||
# Apache 2.4
|
# Apache 2.4
|
||||||
Require all granted
|
Require all granted
|
||||||
|
@ -31,7 +31,7 @@ Alias /zm "@ZM_WEBDIR@"
|
||||||
ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@"
|
ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@"
|
||||||
<Directory "@ZM_CGIDIR@">
|
<Directory "@ZM_CGIDIR@">
|
||||||
SSLRequireSSL
|
SSLRequireSSL
|
||||||
AllowOverride All
|
AllowOverride None
|
||||||
Options +ExecCGI +FollowSymLinks
|
Options +ExecCGI +FollowSymLinks
|
||||||
<IfModule mod_authz_core.c>
|
<IfModule mod_authz_core.c>
|
||||||
# Apache 2.4
|
# Apache 2.4
|
||||||
|
@ -44,3 +44,28 @@ ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@"
|
||||||
</IfModule>
|
</IfModule>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
|
# For better visibility, the following directives have been migrated from the
|
||||||
|
# default .htaccess files included with the CakePHP project.
|
||||||
|
# Parameters not set here are inherited from the parent directive above.
|
||||||
|
<Directory "@ZM_WEBDIR@/api">
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteRule ^$ app/webroot/ [L]
|
||||||
|
RewriteRule (.*) app/webroot/$1 [L]
|
||||||
|
RewriteBase /zm/api
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory "@ZM_WEBDIR@/api/app">
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteRule ^$ webroot/ [L]
|
||||||
|
RewriteRule (.*) webroot/$1 [L]
|
||||||
|
RewriteBase /zm/api
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory "@ZM_WEBDIR@/api/app/webroot">
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^ index.php [L]
|
||||||
|
RewriteBase /zm/api
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
|
|
@ -11,18 +11,61 @@ RewriteRule ^/?(zm)(.*) https://%{SERVER_NAME}/$1$2 [R,L]
|
||||||
|
|
||||||
Alias /zm "@ZM_WEBDIR@"
|
Alias /zm "@ZM_WEBDIR@"
|
||||||
<Directory "@ZM_WEBDIR@">
|
<Directory "@ZM_WEBDIR@">
|
||||||
|
# explicitly set index.php as the only directoryindex
|
||||||
|
DirectoryIndex disabled
|
||||||
|
DirectoryIndex index.php
|
||||||
SSLRequireSSL
|
SSLRequireSSL
|
||||||
Options -Indexes MultiViews FollowSymLinks
|
Options -Indexes +MultiViews +FollowSymLinks
|
||||||
AllowOverride All
|
AllowOverride None
|
||||||
Order allow,deny
|
<IfModule mod_authz_core.c>
|
||||||
Allow from all
|
# Apache 2.4
|
||||||
|
Require all granted
|
||||||
|
</IfModule>
|
||||||
|
<IfModule !mod_authz_core.c>
|
||||||
|
# Apache 2.2
|
||||||
|
Order deny,allow
|
||||||
|
Allow from all
|
||||||
|
</IfModule>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@"
|
ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@"
|
||||||
<Directory "@ZM_CGIDIR@">
|
<Directory "@ZM_CGIDIR@">
|
||||||
SSLRequireSSL
|
SSLRequireSSL
|
||||||
AllowOverride All
|
AllowOverride None
|
||||||
Options ExecCGI FollowSymLinks
|
Options +ExecCGI +FollowSymLinks
|
||||||
Order allow,deny
|
<IfModule mod_authz_core.c>
|
||||||
Allow from all
|
# Apache 2.4
|
||||||
|
Require all granted
|
||||||
|
</IfModule>
|
||||||
|
<IfModule !mod_authz_core.c>
|
||||||
|
# Apache 2.2
|
||||||
|
Order deny,allow
|
||||||
|
Allow from all
|
||||||
|
</IfModule>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
|
# For better visibility, the following directives have been migrated from the
|
||||||
|
# default .htaccess files included with the CakePHP project.
|
||||||
|
# Parameters not set here are inherited from the parent directive above.
|
||||||
|
<Directory "@ZM_WEBDIR@/api">
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteRule ^$ app/webroot/ [L]
|
||||||
|
RewriteRule (.*) app/webroot/$1 [L]
|
||||||
|
RewriteBase /zm/api
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory "@ZM_WEBDIR@/api/app">
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteRule ^$ webroot/ [L]
|
||||||
|
RewriteRule (.*) webroot/$1 [L]
|
||||||
|
RewriteBase /zm/api
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory "@ZM_WEBDIR@/api/app/webroot">
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^ index.php [L]
|
||||||
|
RewriteBase /zm/api
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,7 @@ Requires: perl(MIME::Lite)
|
||||||
Requires: perl(Net::SMTP)
|
Requires: perl(Net::SMTP)
|
||||||
Requires: perl(Net::FTP)
|
Requires: perl(Net::FTP)
|
||||||
Requires: perl(LWP::Protocol::https)
|
Requires: perl(LWP::Protocol::https)
|
||||||
|
Requires: ca-certificates
|
||||||
|
|
||||||
%{?with_init_systemd:Requires(post): systemd}
|
%{?with_init_systemd:Requires(post): systemd}
|
||||||
%{?with_init_systemd:Requires(post): systemd-sysv}
|
%{?with_init_systemd:Requires(post): systemd-sysv}
|
||||||
|
@ -162,7 +163,14 @@ too much degradation of performance.
|
||||||
%make_install
|
%make_install
|
||||||
|
|
||||||
# Remove unwanted files and folders
|
# Remove unwanted files and folders
|
||||||
find %{buildroot} \( -name .packlist -or -name .git -or -name .gitignore -or -name .gitattributes -or -name .travis.yml \) -type f -delete > /dev/null 2>&1 || :
|
find %{buildroot} \( -name .htaccess -or -name .editorconfig -or -name .packlist -or -name .git -or -name .gitignore -or -name .gitattributes -or -name .travis.yml \) -type f -delete > /dev/null 2>&1 || :
|
||||||
|
|
||||||
|
# Recursively change shebang in all relevant scripts and set execute permission
|
||||||
|
find %{buildroot}%{_datadir}/zoneminder/www/api \( -name cake -or -name cake.php \) -type f -exec sed -i 's\^#!/usr/bin/env bash$\#!/usr/bin/bash\' {} \; -exec %{__chmod} 755 {} \;
|
||||||
|
|
||||||
|
# Use the system cacert file rather then the one bundled with CakePHP
|
||||||
|
%{__rm} -f %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem
|
||||||
|
%{__ln_s} ../../../../../../../..%{_sysconfdir}/pki/tls/certs/ca-bundle.crt %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem
|
||||||
|
|
||||||
%post
|
%post
|
||||||
%if 0%{?with_init_sysv}
|
%if 0%{?with_init_sysv}
|
||||||
|
@ -297,6 +305,7 @@ rm -rf %{_docdir}/%{name}-%{version}
|
||||||
%{_unitdir}/zoneminder.service
|
%{_unitdir}/zoneminder.service
|
||||||
%{_datadir}/polkit-1/actions/com.zoneminder.systemctl.policy
|
%{_datadir}/polkit-1/actions/com.zoneminder.systemctl.policy
|
||||||
%{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules
|
%{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules
|
||||||
|
%{_bindir}/zmsystemctl.pl
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if 0%{?with_init_sysv}
|
%if 0%{?with_init_sysv}
|
||||||
|
@ -318,7 +327,6 @@ rm -rf %{_docdir}/%{name}-%{version}
|
||||||
%{_bindir}/zmvideo.pl
|
%{_bindir}/zmvideo.pl
|
||||||
%{_bindir}/zmwatch.pl
|
%{_bindir}/zmwatch.pl
|
||||||
%{_bindir}/zmcamtool.pl
|
%{_bindir}/zmcamtool.pl
|
||||||
%{_bindir}/zmsystemctl.pl
|
|
||||||
%{_bindir}/zmtelemetry.pl
|
%{_bindir}/zmtelemetry.pl
|
||||||
%{_bindir}/zmx10.pl
|
%{_bindir}/zmx10.pl
|
||||||
%{_bindir}/zmonvif-probe.pl
|
%{_bindir}/zmonvif-probe.pl
|
||||||
|
|
|
@ -101,7 +101,7 @@ How filters actually work
|
||||||
--------------------------
|
--------------------------
|
||||||
It is useful to know how filters actually work behind the scenes in ZoneMinder, in the event you find your filter not functioning as intended:
|
It is useful to know how filters actually work behind the scenes in ZoneMinder, in the event you find your filter not functioning as intended:
|
||||||
|
|
||||||
* the primary filter processing process in ZoneMinder is a perl file called ``zmfilter.pl``
|
* the primary filter processing process in ZoneMinder is a perl file called ``zmfilter.pl`` which retrieves filters from the Filters database table
|
||||||
* zmfilter.pl runs every FILTER_EXECUTE_INTERVAL seconds (default is 20s, can be changed in Options->System)
|
* zmfilter.pl runs every FILTER_EXECUTE_INTERVAL seconds (default is 20s, can be changed in Options->System)
|
||||||
* in each run, it goes through all the filters which are marked as "Run in Background" and if the conditions match performs the specified action
|
* in each run, it goes through all the filters which are marked as "Run in Background" and if the conditions match performs the specified action
|
||||||
* zmfilter.pl also reloads all the filters every FILTER_RELOAD_DELAY seconds (default is 300s/5mins, can be changed in Options->System)
|
* zmfilter.pl also reloads all the filters every FILTER_RELOAD_DELAY seconds (default is 300s/5mins, can be changed in Options->System)
|
||||||
|
|
|
@ -250,16 +250,9 @@ sub profiles
|
||||||
|
|
||||||
my $profiles = $result->get_Profiles();
|
my $profiles = $result->get_Profiles();
|
||||||
|
|
||||||
foreach my $profile ( @{ $profiles } ) {
|
foreach my $profile ( @{ $profiles } ) {
|
||||||
|
|
||||||
my $token = $profile->attr()->get_token() ;
|
my $token = $profile->attr()->get_token() ;
|
||||||
print $token . ", " .
|
|
||||||
$profile->get_Name() . ", " .
|
|
||||||
$profile->get_VideoEncoderConfiguration()->get_Encoding() . ", " .
|
|
||||||
$profile->get_VideoEncoderConfiguration()->get_Resolution()->get_Width() . ", " .
|
|
||||||
$profile->get_VideoEncoderConfiguration()->get_Resolution()->get_Height() . ", " .
|
|
||||||
$profile->get_VideoEncoderConfiguration()->get_RateControl()->get_FrameRateLimit() .
|
|
||||||
", ";
|
|
||||||
|
|
||||||
# Specification gives conflicting values for unicast stream types, try both.
|
# Specification gives conflicting values for unicast stream types, try both.
|
||||||
# http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl#op.GetStreamUri
|
# http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl#op.GetStreamUri
|
||||||
|
@ -278,9 +271,18 @@ sub profiles
|
||||||
die $result if not $result;
|
die $result if not $result;
|
||||||
# print $result . "\n";
|
# print $result . "\n";
|
||||||
|
|
||||||
print $result->get_MediaUri()->get_Uri() .
|
my $VideoEncoderConfiguration = $profile->get_VideoEncoderConfiguration();
|
||||||
"\n";
|
print join(', ', $token,
|
||||||
}
|
$profile->get_Name(),
|
||||||
|
( $VideoEncoderConfiguration ? (
|
||||||
|
$VideoEncoderConfiguration->get_Encoding(),
|
||||||
|
$VideoEncoderConfiguration->get_Resolution()->get_Width(),
|
||||||
|
$VideoEncoderConfiguration->get_Resolution()->get_Height(),
|
||||||
|
$VideoEncoderConfiguration->get_RateControl()->get_FrameRateLimit(),
|
||||||
|
) : () ),
|
||||||
|
$result->get_MediaUri()->get_Uri() ,
|
||||||
|
). "\n";
|
||||||
|
} # end foreach profile
|
||||||
|
|
||||||
#
|
#
|
||||||
# use message parser without schema validation ???
|
# use message parser without schema validation ???
|
||||||
|
|
|
@ -0,0 +1,333 @@
|
||||||
|
# ==========================================================================
|
||||||
|
#
|
||||||
|
# ZoneMinder Maginon Supra IPC Camera Control Protocol Module,
|
||||||
|
# Copyright (C) 2017 Martin Gutenbrunner (martin.gutenbrunner@SPAMsonic.net)
|
||||||
|
#
|
||||||
|
# This program 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 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
# ==========================================================================
|
||||||
|
#
|
||||||
|
# This module contains the implementation of the Maginon Supra IPC camera
|
||||||
|
# procotol version.
|
||||||
|
#
|
||||||
|
package ZoneMinder::Control::MaginonIPC;
|
||||||
|
|
||||||
|
use 5.006;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
require ZoneMinder::Base;
|
||||||
|
require ZoneMinder::Control;
|
||||||
|
|
||||||
|
our @ISA = qw(ZoneMinder::Control);
|
||||||
|
|
||||||
|
# ==========================================================================
|
||||||
|
#
|
||||||
|
# Maginon Supra IPC IP Camera Control Protocol
|
||||||
|
#
|
||||||
|
# ==========================================================================
|
||||||
|
|
||||||
|
use ZoneMinder::Logger qw(:all);
|
||||||
|
use ZoneMinder::Config qw(:all);
|
||||||
|
|
||||||
|
use Time::HiRes qw( usleep );
|
||||||
|
|
||||||
|
sub new
|
||||||
|
{
|
||||||
|
my $class = shift;
|
||||||
|
my $id = shift;
|
||||||
|
my $self = ZoneMinder::Control->new( $id );
|
||||||
|
bless( $self, $class );
|
||||||
|
srand( time() );
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
our $AUTOLOAD;
|
||||||
|
|
||||||
|
sub AUTOLOAD
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
my $class = ref($self) || croak( "$self not object" );
|
||||||
|
my $name = $AUTOLOAD;
|
||||||
|
$name =~ s/.*://;
|
||||||
|
if ( exists($self->{$name}) )
|
||||||
|
{
|
||||||
|
return( $self->{$name} );
|
||||||
|
}
|
||||||
|
Fatal( "Can't access $name member of object of class $class" );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub open
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
$self->loadMonitor();
|
||||||
|
|
||||||
|
use LWP::UserAgent;
|
||||||
|
$self->{ua} = LWP::UserAgent->new;
|
||||||
|
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
|
||||||
|
|
||||||
|
$self->{state} = 'open';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub close
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
$self->{state} = 'closed';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub printMsg
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
my $msg = shift;
|
||||||
|
my $msg_len = length($msg);
|
||||||
|
|
||||||
|
Debug( $msg."[".$msg_len."]" );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub sendCmd
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
my $cmd = shift;
|
||||||
|
|
||||||
|
#my $result = undef;
|
||||||
|
|
||||||
|
printMsg( $cmd, "Tx" );
|
||||||
|
|
||||||
|
my $url = "http://".$self->{Monitor}->{ControlAddress}."$cmd";
|
||||||
|
# Info($url);
|
||||||
|
my $req = HTTP::Request->new( GET=>$url );
|
||||||
|
my $res = $self->{ua}->request($req);
|
||||||
|
return( !undef );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveStop
|
||||||
|
{
|
||||||
|
Debug("moveStop");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=1";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConUp
|
||||||
|
{
|
||||||
|
Debug("moveConUp");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=0";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
my $autostop = $self->getParam( $params, 'autostop', 0 );
|
||||||
|
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
|
||||||
|
{
|
||||||
|
usleep( $self->{Monitor}->{AutoStopTimeout} );
|
||||||
|
$self->moveStop( $params );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConDown
|
||||||
|
{
|
||||||
|
Debug("moveConDown");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=2";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
my $autostop = $self->getParam( $params, 'autostop', 0 );
|
||||||
|
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
|
||||||
|
{
|
||||||
|
usleep( $self->{Monitor}->{AutoStopTimeout} );
|
||||||
|
$self->moveStop( $params );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConLeft
|
||||||
|
{
|
||||||
|
Debug("moveConLeft");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=4";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
my $autostop = $self->getParam( $params, 'autostop', 0 );
|
||||||
|
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
|
||||||
|
{
|
||||||
|
usleep( $self->{Monitor}->{AutoStopTimeout} );
|
||||||
|
$self->moveStop( $params );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConRight
|
||||||
|
{
|
||||||
|
Debug("moveConRight");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=6";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
my $autostop = $self->getParam( $params, 'autostop', 0 );
|
||||||
|
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
|
||||||
|
{
|
||||||
|
usleep( $self->{Monitor}->{AutoStopTimeout} );
|
||||||
|
$self->moveStop( $params );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConUpRight
|
||||||
|
{
|
||||||
|
Debug("moveConUpRight");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=91";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
my $autostop = $self->getParam( $params, 'autostop', 0 );
|
||||||
|
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
|
||||||
|
{
|
||||||
|
usleep( $self->{Monitor}->{AutoStopTimeout} );
|
||||||
|
$self->moveStop( $params );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConUpLeft
|
||||||
|
{
|
||||||
|
Debug("moveConUpLeft");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=90";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
my $autostop = $self->getParam( $params, 'autostop', 0 );
|
||||||
|
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
|
||||||
|
{
|
||||||
|
usleep( $self->{Monitor}->{AutoStopTimeout} );
|
||||||
|
$self->moveStop( $params );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConDownRight
|
||||||
|
{
|
||||||
|
Debug("moveConDownRight");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=93";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
my $autostop = $self->getParam( $params, 'autostop', 0 );
|
||||||
|
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
|
||||||
|
{
|
||||||
|
usleep( $self->{Monitor}->{AutoStopTimeout} );
|
||||||
|
$self->moveStop( $params );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConDownLeft
|
||||||
|
{
|
||||||
|
Debug("moveConDownLeft");
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $cmd = "/decoder_control.cgi?command=92";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
my $autostop = $self->getParam( $params, 'autostop', 0 );
|
||||||
|
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
|
||||||
|
{
|
||||||
|
usleep( $self->{Monitor}->{AutoStopTimeout} );
|
||||||
|
$self->moveStop( $params );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub presetSet
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $preset = $self->getParam( $params, 'preset' );
|
||||||
|
Info( "Set Preset $preset" );
|
||||||
|
|
||||||
|
my $cmdNum;
|
||||||
|
if ($preset == 1) {
|
||||||
|
$cmdNum = 30;
|
||||||
|
} elsif ($preset == 2) {
|
||||||
|
$cmdNum = 32;
|
||||||
|
} elsif ($preset == 3) {
|
||||||
|
$cmdNum = 34;
|
||||||
|
} elsif ($preset == 4) {
|
||||||
|
$cmdNum = 36;
|
||||||
|
} else {
|
||||||
|
$cmdNum = 36;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $cmd = "/decoder_control.cgi?command=$cmdNum";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub presetGoto
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $preset = $self->getParam( $params, 'preset' );
|
||||||
|
Info( "Goto Preset $preset" );
|
||||||
|
|
||||||
|
my $cmdNum;
|
||||||
|
if ($preset == 1) {
|
||||||
|
$cmdNum = 31;
|
||||||
|
} elsif ($preset == 2) {
|
||||||
|
$cmdNum = 33;
|
||||||
|
} elsif ($preset == 3) {
|
||||||
|
$cmdNum = 35;
|
||||||
|
} elsif ($preset == 4) {
|
||||||
|
$cmdNum = 37;
|
||||||
|
} else {
|
||||||
|
$cmdNum = 37;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $cmd = "/decoder_control.cgi?command=$cmdNum";
|
||||||
|
$self->sendCmd( $cmd );
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
|
__END__
|
||||||
|
# Below is stub documentation for your module. You'd better edit it!
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
ZoneMinder::Control::MaginonIPC - Zoneminder PTZ control module for the Maginon Supra-IPC 40 IP Camera
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use ZoneMinder::Control::MaginonIPC;
|
||||||
|
blah blah blah
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This is for Zoneminder PTZ control module for the Maginon Supra-IPC 40 camera. It probably also works with other models.
|
||||||
|
|
||||||
|
=head2 EXPORT
|
||||||
|
|
||||||
|
None by default.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
www.zoneminder.com
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
Martin Gutenbrunner, E<lt>martin.gutenbrunner@gmx.atE<gt>
|
||||||
|
|
||||||
|
=head1 COPYRIGHT AND LICENSE
|
||||||
|
|
||||||
|
Copyright (C) 2017 by Martin Gutenbrunner
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or modify
|
||||||
|
it under the same terms as Perl itself, either Perl version 5.8.3 or,
|
||||||
|
at your option, any later version of Perl 5 you may have available.
|
||||||
|
|
||||||
|
|
||||||
|
=cut
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
#
|
||||||
# ZoneMinder External Trigger Script, $Date: 2008-07-25 10:48:16 +0100 (Fri, 25 Jul 2008) $, $Revision: 2612 $
|
# ZoneMinder External Trigger Script
|
||||||
# Copyright (C) 2001-2008 Philip Coombes
|
# Copyright (C) 2001-2008 Philip Coombes
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
|
@ -21,92 +21,6 @@
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
zmtrigger.pl - ZoneMinder External Trigger Script
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
This script is used to trigger and cancel alarms from external connections
|
|
||||||
using an arbitrary text based format.
|
|
||||||
|
|
||||||
This script offers generic solution to external triggering of alarms. It
|
|
||||||
can handle external connections via either internet socket, unix socket or
|
|
||||||
file/device interfaces. You can either use it 'as is' if you can interface
|
|
||||||
with the existing format, or override connections and channels to customise
|
|
||||||
it to your needs.
|
|
||||||
|
|
||||||
If enabled by the OPT_TRIGGERS option, Zoneminder service start
|
|
||||||
zmtrigger.pl which listens for control messages on TCP port 6802.
|
|
||||||
|
|
||||||
=head1 TRIGGER MESSAGE FORMAT
|
|
||||||
|
|
||||||
B<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext>
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item B<id>
|
|
||||||
|
|
||||||
is the id number or name of the ZM monitor.
|
|
||||||
|
|
||||||
=item B<action>
|
|
||||||
|
|
||||||
Valid actions are 'on', 'off', 'cancel' or 'show' where
|
|
||||||
'on' forces an alarm condition on;
|
|
||||||
'off' forces an alarm condition off;
|
|
||||||
'cancel' negates the previous 'on' or 'off';
|
|
||||||
'show' updates the auxiliary text represented by the %Q
|
|
||||||
placeholder, which can optionally be added to the affected monitor's
|
|
||||||
timestamp label format.
|
|
||||||
|
|
||||||
Ordinarily you would use 'on' and 'cancel', 'off' would tend to be
|
|
||||||
used to suppress motion based events. Additionally 'on' and 'off' can
|
|
||||||
take an additional time offset, e.g. on+20 which automatically
|
|
||||||
cancel's the previous action after that number of seconds.
|
|
||||||
|
|
||||||
=item B<score>
|
|
||||||
|
|
||||||
is the score given to the alarm, usually to indicate it's
|
|
||||||
importance. For 'on' triggers it should be non-zero, otherwise it should
|
|
||||||
be zero.
|
|
||||||
|
|
||||||
=item B<cause>
|
|
||||||
|
|
||||||
is a 32 char max string indicating the reason for, or source of
|
|
||||||
the alarm e.g. 'Relay 1 open'. This is saved in the 'Cause' field of the
|
|
||||||
event. Ignored for 'off' or 'cancel' messages.
|
|
||||||
|
|
||||||
=item B<text>
|
|
||||||
|
|
||||||
is a 256 char max additional info field, which is saved in the
|
|
||||||
'Description' field of an event. Ignored for 'off' or 'cancel' messages.
|
|
||||||
|
|
||||||
=item B<showtext>
|
|
||||||
|
|
||||||
is up to 32 characters of text that can be displayed in the
|
|
||||||
timestamp that is added to images. The 'show' action is designed to
|
|
||||||
update this text without affecting alarms but the text is updated, if
|
|
||||||
present, for any of the actions. This is designed to allow external input
|
|
||||||
to appear on the images captured, for instance temperature or personnel
|
|
||||||
identity etc.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
Note that multiple messages can be sent at once and should be LF or CRLF
|
|
||||||
delimited. This script is not necessarily intended to be a solution in
|
|
||||||
itself, but is intended to be used as 'glue' to help ZoneMinder interface
|
|
||||||
with other systems. It will almost certainly require some customisation
|
|
||||||
before you can make any use of it. If all you want to do is generate alarms
|
|
||||||
from external sources then using the ZoneMinder::SharedMem perl module is
|
|
||||||
likely to be easier.
|
|
||||||
|
|
||||||
=head1 EXAMPLES
|
|
||||||
|
|
||||||
3|on+10|1|motion|text|showtext
|
|
||||||
|
|
||||||
Triggers 'alarm' on camera #3 for 10 seconds with score=1, cause='motion'.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
use strict;
|
use strict;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
|
||||||
|
@ -198,7 +112,6 @@ my $monitor_reload_time = 0;
|
||||||
my $needsReload = 0;
|
my $needsReload = 0;
|
||||||
loadMonitors();
|
loadMonitors();
|
||||||
|
|
||||||
|
|
||||||
$! = undef;
|
$! = undef;
|
||||||
my $rin = '';
|
my $rin = '';
|
||||||
my $win = $rin;
|
my $win = $rin;
|
||||||
|
@ -216,20 +129,19 @@ while( 1 ) {
|
||||||
if ( $nfound > 0 ) {
|
if ( $nfound > 0 ) {
|
||||||
Debug( "Got input from $nfound connections\n" );
|
Debug( "Got input from $nfound connections\n" );
|
||||||
foreach my $connection ( @in_select_connections ) {
|
foreach my $connection ( @in_select_connections ) {
|
||||||
|
|
||||||
if ( vec( $rout, $connection->fileno(), 1 ) ) {
|
if ( vec( $rout, $connection->fileno(), 1 ) ) {
|
||||||
Debug( 'Got input from connection '
|
Debug( 'Got input from connection '
|
||||||
.$connection->name()
|
.$connection->name()
|
||||||
." ("
|
.' ('
|
||||||
.$connection->fileno()
|
.$connection->fileno()
|
||||||
.")\n"
|
.")\n"
|
||||||
);
|
);
|
||||||
if ( $connection->spawns() ) {
|
if ( $connection->spawns() ) {
|
||||||
my $new_connection = $connection->accept();
|
my $new_connection = $connection->accept();
|
||||||
$spawned_connections{$new_connection->fileno()} = $new_connection;
|
$spawned_connections{$new_connection->fileno()} = $new_connection;
|
||||||
Debug( "Added new spawned connection ("
|
Debug( 'Added new spawned connection ('
|
||||||
.$new_connection->fileno()
|
.$new_connection->fileno()
|
||||||
."), "
|
.'), '
|
||||||
.int(keys(%spawned_connections))
|
.int(keys(%spawned_connections))
|
||||||
." spawned connections\n"
|
." spawned connections\n"
|
||||||
);
|
);
|
||||||
|
@ -248,7 +160,7 @@ while( 1 ) {
|
||||||
if ( vec( $rout, $connection->fileno(), 1 ) ) {
|
if ( vec( $rout, $connection->fileno(), 1 ) ) {
|
||||||
Debug( 'Got input from spawned connection '
|
Debug( 'Got input from spawned connection '
|
||||||
.$connection->name()
|
.$connection->name()
|
||||||
." ("
|
.' ('
|
||||||
.$connection->fileno()
|
.$connection->fileno()
|
||||||
.")\n"
|
.")\n"
|
||||||
);
|
);
|
||||||
|
@ -259,16 +171,16 @@ while( 1 ) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
delete( $spawned_connections{$connection->fileno()} );
|
delete( $spawned_connections{$connection->fileno()} );
|
||||||
Debug( "Removed spawned connection ("
|
Debug( 'Removed spawned connection ('
|
||||||
.$connection->fileno()
|
.$connection->fileno()
|
||||||
."), "
|
.'), '
|
||||||
.int(keys(%spawned_connections))
|
.int(keys(%spawned_connections))
|
||||||
." spawned connections\n"
|
." spawned connections\n"
|
||||||
);
|
);
|
||||||
$connection->close();
|
$connection->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} # end foreach connection
|
} # end foreach spawned connection
|
||||||
} elsif ( $nfound < 0 ) {
|
} elsif ( $nfound < 0 ) {
|
||||||
if ( $! == EINTR ) {
|
if ( $! == EINTR ) {
|
||||||
# Do nothing
|
# Do nothing
|
||||||
|
@ -299,33 +211,44 @@ while( 1 ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
my ( $state, $last_event ) = zmMemRead( $monitor,
|
my ( $state, $last_event ) = zmMemRead( $monitor,
|
||||||
[ 'shared_data:state', 'shared_data:last_event' ]
|
[
|
||||||
);
|
'shared_data:state',
|
||||||
|
'shared_data:last_event'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
#print( "$monitor->{Id}: S:$state, LE:$last_event\n" );
|
#print( "$monitor->{Id}: S:$state, LE:$last_event\n" );
|
||||||
#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" );
|
#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" );
|
||||||
if ( $state == STATE_ALARM || $state == STATE_ALERT ) { # In alarm state
|
if ( $state == STATE_ALARM || $state == STATE_ALERT ) {
|
||||||
|
# In alarm state
|
||||||
if ( !defined($monitor->{LastEvent})
|
if ( !defined($monitor->{LastEvent})
|
||||||
|| ($last_event != $monitor->{LastEvent})
|
|| ($last_event != $monitor->{LastEvent})
|
||||||
) { # A new event
|
) {
|
||||||
push( @out_messages, $monitor->{Id}.'|on|'.time().'|'.$last_event );
|
# A new event
|
||||||
} else { # The same one as last time, so ignore it
|
push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event );
|
||||||
|
} else {
|
||||||
|
# The same one as last time, so ignore it
|
||||||
# Do nothing
|
# Do nothing
|
||||||
}
|
}
|
||||||
} elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE)
|
} elsif (
|
||||||
|| ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE
|
($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE)
|
||||||
)) { # Out of alarm state
|
||
|
||||||
|
($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE)
|
||||||
|
) {
|
||||||
|
# Out of alarm state
|
||||||
push( @out_messages, $monitor->{Id}.'|off|'.time().'|'.$last_event );
|
push( @out_messages, $monitor->{Id}.'|off|'.time().'|'.$last_event );
|
||||||
} elsif ( defined($monitor->{LastEvent})
|
} elsif (
|
||||||
&& ($last_event != $monitor->{LastEvent})
|
defined($monitor->{LastEvent})
|
||||||
) { # We've missed a whole event
|
&&
|
||||||
|
($last_event != $monitor->{LastEvent})
|
||||||
|
) {
|
||||||
|
# We've missed a whole event
|
||||||
push( @out_messages, $monitor->{Id}.'|on|'.time().'|'.$last_event );
|
push( @out_messages, $monitor->{Id}.'|on|'.time().'|'.$last_event );
|
||||||
push( @out_messages, $monitor->{Id}.'|off|'.time().'|'.$last_event );
|
push( @out_messages, $monitor->{Id}.'|off|'.time().'|'.$last_event );
|
||||||
}
|
}
|
||||||
$monitor->{LastState} = $state;
|
$monitor->{LastState} = $state;
|
||||||
$monitor->{LastEvent} = $last_event;
|
$monitor->{LastEvent} = $last_event;
|
||||||
} # end foreach monitor
|
} # end foreach monitor
|
||||||
|
|
||||||
foreach my $connection ( @out_connections ) {
|
foreach my $connection ( @out_connections ) {
|
||||||
if ( $connection->canWrite() ) {
|
if ( $connection->canWrite() ) {
|
||||||
$connection->putMessages( \@out_messages );
|
$connection->putMessages( \@out_messages );
|
||||||
|
@ -379,7 +302,9 @@ while( 1 ) {
|
||||||
loadMonitors();
|
loadMonitors();
|
||||||
$needsReload = 0;
|
$needsReload = 0;
|
||||||
}
|
}
|
||||||
}
|
# zmDbConnect will ping and reconnect if neccessary
|
||||||
|
$dbh = zmDbConnect();
|
||||||
|
} # end while ( 1 )
|
||||||
Info( "Trigger daemon exiting\n" );
|
Info( "Trigger daemon exiting\n" );
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
@ -389,9 +314,9 @@ sub loadMonitors {
|
||||||
|
|
||||||
my %new_monitors = ();
|
my %new_monitors = ();
|
||||||
|
|
||||||
my $sql = "SELECT * FROM Monitors WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )".
|
my $sql = "SELECT * FROM Monitors
|
||||||
( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' ).
|
WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )".
|
||||||
'ORDER BY Id DESC'
|
( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' )
|
||||||
;
|
;
|
||||||
my $sth = $dbh->prepare_cached( $sql )
|
my $sth = $dbh->prepare_cached( $sql )
|
||||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
|
@ -450,7 +375,7 @@ sub handleMessage {
|
||||||
handleDelay($delay, $connection, $action_text);
|
handleDelay($delay, $connection, $action_text);
|
||||||
}
|
}
|
||||||
} elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) {
|
} elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) {
|
||||||
next if ( !$monitor->{Enabled} );
|
next if !$monitor->{Enabled};
|
||||||
|
|
||||||
my $trigger = $1;
|
my $trigger = $1;
|
||||||
my $delay = $2;
|
my $delay = $2;
|
||||||
|
@ -473,7 +398,9 @@ sub handleMessage {
|
||||||
zmTriggerShowtext( $monitor, $showtext ) if defined($showtext);
|
zmTriggerShowtext( $monitor, $showtext ) if defined($showtext);
|
||||||
Info( "Trigger '$trigger'\n" );
|
Info( "Trigger '$trigger'\n" );
|
||||||
# Wait til it's finished
|
# Wait til it's finished
|
||||||
while( zmInAlarm( $monitor ) && ($last_event == zmGetLastEvent( $monitor ))) {
|
while( zmInAlarm( $monitor )
|
||||||
|
&& ($last_event == zmGetLastEvent( $monitor ))
|
||||||
|
) {
|
||||||
# Tenth of a second
|
# Tenth of a second
|
||||||
usleep( 100000 );
|
usleep( 100000 );
|
||||||
}
|
}
|
||||||
|
@ -507,3 +434,90 @@ sub handleDelay {
|
||||||
}
|
}
|
||||||
1;
|
1;
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
zmtrigger.pl - ZoneMinder External Trigger Script
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This script is used to trigger and cancel alarms from external connections
|
||||||
|
using an arbitrary text based format.
|
||||||
|
|
||||||
|
This script offers generic solution to external triggering of alarms. It
|
||||||
|
can handle external connections via either internet socket, unix socket or
|
||||||
|
file/device interfaces. You can either use it 'as is' if you can interface
|
||||||
|
with the existing format, or override connections and channels to customise
|
||||||
|
it to your needs.
|
||||||
|
|
||||||
|
If enabled by the OPT_TRIGGERS option, Zoneminder service start
|
||||||
|
zmtrigger.pl which listens for control messages on TCP port 6802.
|
||||||
|
|
||||||
|
=head1 TRIGGER MESSAGE FORMAT
|
||||||
|
|
||||||
|
B<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext>
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item B<id>
|
||||||
|
|
||||||
|
is the id number or name of the ZM monitor.
|
||||||
|
|
||||||
|
=item B<action>
|
||||||
|
|
||||||
|
Valid actions are 'on', 'off', 'cancel' or 'show' where
|
||||||
|
'on' forces an alarm condition on;
|
||||||
|
'off' forces an alarm condition off;
|
||||||
|
'cancel' negates the previous 'on' or 'off';
|
||||||
|
'show' updates the auxiliary text represented by the %Q
|
||||||
|
placeholder, which can optionally be added to the affected monitor's
|
||||||
|
timestamp label format.
|
||||||
|
|
||||||
|
Ordinarily you would use 'on' and 'cancel', 'off' would tend to be
|
||||||
|
used to suppress motion based events. Additionally 'on' and 'off' can
|
||||||
|
take an additional time offset, e.g. on+20 which automatically
|
||||||
|
cancel's the previous action after that number of seconds.
|
||||||
|
|
||||||
|
=item B<score>
|
||||||
|
|
||||||
|
is the score given to the alarm, usually to indicate it's
|
||||||
|
importance. For 'on' triggers it should be non-zero, otherwise it should
|
||||||
|
be zero.
|
||||||
|
|
||||||
|
=item B<cause>
|
||||||
|
|
||||||
|
is a 32 char max string indicating the reason for, or source of
|
||||||
|
the alarm e.g. 'Relay 1 open'. This is saved in the 'Cause' field of the
|
||||||
|
event. Ignored for 'off' or 'cancel' messages.
|
||||||
|
|
||||||
|
=item B<text>
|
||||||
|
|
||||||
|
is a 256 char max additional info field, which is saved in the
|
||||||
|
'Description' field of an event. Ignored for 'off' or 'cancel' messages.
|
||||||
|
|
||||||
|
=item B<showtext>
|
||||||
|
|
||||||
|
is up to 32 characters of text that can be displayed in the
|
||||||
|
timestamp that is added to images. The 'show' action is designed to
|
||||||
|
update this text without affecting alarms but the text is updated, if
|
||||||
|
present, for any of the actions. This is designed to allow external input
|
||||||
|
to appear on the images captured, for instance temperature or personnel
|
||||||
|
identity etc.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
Note that multiple messages can be sent at once and should be LF or CRLF
|
||||||
|
delimited. This script is not necessarily intended to be a solution in
|
||||||
|
itself, but is intended to be used as 'glue' to help ZoneMinder interface
|
||||||
|
with other systems. It will almost certainly require some customisation
|
||||||
|
before you can make any use of it. If all you want to do is generate alarms
|
||||||
|
from external sources then using the ZoneMinder::SharedMem perl module is
|
||||||
|
likely to be easier.
|
||||||
|
|
||||||
|
=head1 EXAMPLES
|
||||||
|
|
||||||
|
3|on+10|1|motion|text|showtext
|
||||||
|
|
||||||
|
Triggers 'alarm' on camera #3 for 10 seconds with score=1, cause='motion'.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
|
@ -237,7 +237,7 @@ if ( $concat_name ) {
|
||||||
}
|
}
|
||||||
close $fd;
|
close $fd;
|
||||||
my $command = $Config{ZM_PATH_FFMPEG}
|
my $command = $Config{ZM_PATH_FFMPEG}
|
||||||
. " -f concat -i $concat_list_file -c copy "
|
. " -f concat -safe 0 -i $concat_list_file -c copy "
|
||||||
.$Config{ZM_FFMPEG_OUTPUT_OPTIONS}
|
.$Config{ZM_FFMPEG_OUTPUT_OPTIONS}
|
||||||
." '$video_file' > $Config{ZM_PATH_LOGS}/ffmpeg_${concat_name}.log 2>&1"
|
." '$video_file' > $Config{ZM_PATH_LOGS}/ffmpeg_${concat_name}.log 2>&1"
|
||||||
;
|
;
|
||||||
|
|
|
@ -27,10 +27,11 @@ MYSQL dbconn;
|
||||||
|
|
||||||
int zmDbConnected = false;
|
int zmDbConnected = false;
|
||||||
|
|
||||||
void zmDbConnect()
|
void zmDbConnect() {
|
||||||
{
|
if ( zmDbConnected )
|
||||||
if ( !mysql_init( &dbconn ) )
|
return;
|
||||||
{
|
|
||||||
|
if ( !mysql_init( &dbconn ) ) {
|
||||||
Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) );
|
Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
|
@ -38,48 +39,35 @@ void zmDbConnect()
|
||||||
if ( mysql_options( &dbconn, MYSQL_OPT_RECONNECT, &reconnect ) )
|
if ( mysql_options( &dbconn, MYSQL_OPT_RECONNECT, &reconnect ) )
|
||||||
Fatal( "Can't set database auto reconnect option: %s", mysql_error( &dbconn ) );
|
Fatal( "Can't set database auto reconnect option: %s", mysql_error( &dbconn ) );
|
||||||
std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":" );
|
std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":" );
|
||||||
if ( colonIndex == std::string::npos )
|
if ( colonIndex == std::string::npos ) {
|
||||||
{
|
if ( !mysql_real_connect( &dbconn, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, NULL, 0 ) ) {
|
||||||
if ( !mysql_real_connect( &dbconn, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, NULL, 0 ) )
|
|
||||||
{
|
|
||||||
Error( "Can't connect to server: %s", mysql_error( &dbconn ) );
|
Error( "Can't connect to server: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex );
|
std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex );
|
||||||
std::string dbPortOrSocket = staticConfig.DB_HOST.substr( colonIndex+1 );
|
std::string dbPortOrSocket = staticConfig.DB_HOST.substr( colonIndex+1 );
|
||||||
if ( dbPortOrSocket[0] == '/' )
|
if ( dbPortOrSocket[0] == '/' ) {
|
||||||
{
|
if ( !mysql_real_connect( &dbconn, NULL, staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, dbPortOrSocket.c_str(), 0 ) ) {
|
||||||
if ( !mysql_real_connect( &dbconn, NULL, staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, dbPortOrSocket.c_str(), 0 ) )
|
|
||||||
{
|
|
||||||
Error( "Can't connect to server: %s", mysql_error( &dbconn ) );
|
Error( "Can't connect to server: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
}
|
if ( !mysql_real_connect( &dbconn, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, atoi(dbPortOrSocket.c_str()), NULL, 0 ) ) {
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( !mysql_real_connect( &dbconn, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, atoi(dbPortOrSocket.c_str()), NULL, 0 ) )
|
|
||||||
{
|
|
||||||
Error( "Can't connect to server: %s", mysql_error( &dbconn ) );
|
Error( "Can't connect to server: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( mysql_select_db( &dbconn, staticConfig.DB_NAME.c_str() ) )
|
if ( mysql_select_db( &dbconn, staticConfig.DB_NAME.c_str() ) ) {
|
||||||
{
|
|
||||||
Error( "Can't select database: %s", mysql_error( &dbconn ) );
|
Error( "Can't select database: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
zmDbConnected = true;
|
zmDbConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmDbClose()
|
void zmDbClose() {
|
||||||
{
|
if ( zmDbConnected ) {
|
||||||
if ( zmDbConnected )
|
|
||||||
{
|
|
||||||
mysql_close( &dbconn );
|
mysql_close( &dbconn );
|
||||||
// mysql_init() call implicitly mysql_library_init() but
|
// mysql_init() call implicitly mysql_library_init() but
|
||||||
// mysql_close() does not call mysql_library_end()
|
// mysql_close() does not call mysql_library_end()
|
||||||
|
|
|
@ -155,6 +155,7 @@ bool EventStream::loadEventData( int event_id ) {
|
||||||
else
|
else
|
||||||
snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_data->event_id );
|
snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_data->event_id );
|
||||||
}
|
}
|
||||||
|
delete storage; storage = NULL;
|
||||||
|
|
||||||
updateFrameRate( (double)event_data->frame_count/event_data->duration );
|
updateFrameRate( (double)event_data->frame_count/event_data->duration );
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
|
||||||
mRawFrame = NULL;
|
mRawFrame = NULL;
|
||||||
mFrame = NULL;
|
mFrame = NULL;
|
||||||
frameCount = 0;
|
frameCount = 0;
|
||||||
startTime=0;
|
startTime = 0;
|
||||||
mIsOpening = false;
|
mIsOpening = false;
|
||||||
mCanCapture = false;
|
mCanCapture = false;
|
||||||
mOpenStart = 0;
|
mOpenStart = 0;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "zm_config.h"
|
#include "zm_config.h"
|
||||||
#include "zm_utils.h"
|
#include "zm_utils.h"
|
||||||
|
#include "zm_db.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -333,45 +334,7 @@ Logger::Level Logger::databaseLevel( Logger::Level databaseLevel ) {
|
||||||
databaseLevel = limit(databaseLevel);
|
databaseLevel = limit(databaseLevel);
|
||||||
if ( mDatabaseLevel != databaseLevel ) {
|
if ( mDatabaseLevel != databaseLevel ) {
|
||||||
if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) {
|
if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) {
|
||||||
if ( !mDbConnected ) {
|
zmDbConnect();
|
||||||
if ( !mysql_init( &mDbConnection ) ) {
|
|
||||||
Fatal( "Can't initialise database connection: %s", mysql_error( &mDbConnection ) );
|
|
||||||
exit( mysql_errno( &mDbConnection ) );
|
|
||||||
}
|
|
||||||
my_bool reconnect = 1;
|
|
||||||
if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) )
|
|
||||||
Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) );
|
|
||||||
std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":" );
|
|
||||||
if ( colonIndex == std::string::npos ) {
|
|
||||||
if ( !mysql_real_connect( &mDbConnection, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, NULL, 0 ) ) {
|
|
||||||
Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) );
|
|
||||||
exit( mysql_errno( &mDbConnection ) );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex );
|
|
||||||
std::string dbPortOrSocket = staticConfig.DB_HOST.substr( colonIndex+1 );
|
|
||||||
if ( dbPortOrSocket[0] == '/' ) {
|
|
||||||
if ( !mysql_real_connect( &mDbConnection, NULL, staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, dbPortOrSocket.c_str(), 0 ) ) {
|
|
||||||
Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) );
|
|
||||||
exit( mysql_errno( &mDbConnection ) );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ( !mysql_real_connect( &mDbConnection, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, atoi(dbPortOrSocket.c_str()), NULL, 0 ) ) {
|
|
||||||
Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) );
|
|
||||||
exit( mysql_errno( &mDbConnection ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // end if has colon
|
|
||||||
unsigned long mysqlVersion = mysql_get_server_version( &mDbConnection );
|
|
||||||
if ( mysqlVersion < 50019 )
|
|
||||||
if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) )
|
|
||||||
Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) );
|
|
||||||
if ( mysql_select_db( &mDbConnection, staticConfig.DB_NAME.c_str() ) ) {
|
|
||||||
Fatal( "Can't select database: %s", mysql_error( &mDbConnection ) );
|
|
||||||
exit( mysql_errno( &mDbConnection ) );
|
|
||||||
}
|
|
||||||
mDbConnected = true;
|
|
||||||
} // end if ! mDbConnected
|
|
||||||
} // end if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG )
|
} // end if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG )
|
||||||
mDatabaseLevel = databaseLevel;
|
mDatabaseLevel = databaseLevel;
|
||||||
} // end if ( mDatabaseLevel != databaseLevel )
|
} // end if ( mDatabaseLevel != databaseLevel )
|
||||||
|
@ -439,10 +402,7 @@ void Logger::closeFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::closeDatabase() {
|
void Logger::closeDatabase() {
|
||||||
if ( mDbConnected ) {
|
|
||||||
mysql_close( &mDbConnection );
|
|
||||||
mDbConnected = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::openSyslog() {
|
void Logger::openSyslog() {
|
||||||
|
@ -548,13 +508,13 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
||||||
char sql[ZM_SQL_MED_BUFSIZ];
|
char sql[ZM_SQL_MED_BUFSIZ];
|
||||||
char escapedString[(strlen(syslogStart)*2)+1];
|
char escapedString[(strlen(syslogStart)*2)+1];
|
||||||
|
|
||||||
mysql_real_escape_string( &mDbConnection, escapedString, syslogStart, strlen(syslogStart) );
|
mysql_real_escape_string( &dbconn, escapedString, syslogStart, strlen(syslogStart) );
|
||||||
|
|
||||||
snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line );
|
snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line );
|
||||||
if ( mysql_query( &mDbConnection, sql ) ) {
|
if ( mysql_query( &dbconn, sql ) ) {
|
||||||
Level tempDatabaseLevel = mDatabaseLevel;
|
Level tempDatabaseLevel = mDatabaseLevel;
|
||||||
databaseLevel( NOLOG );
|
databaseLevel( NOLOG );
|
||||||
Error( "Can't insert log entry: sql(%s) error(%s)", sql, mysql_error( &mDbConnection ) );
|
Error( "Can't insert log entry: sql(%s) error(%s)", sql, mysql_error( &dbconn ) );
|
||||||
databaseLevel(tempDatabaseLevel);
|
databaseLevel(tempDatabaseLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,6 +526,8 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
||||||
|
|
||||||
free(filecopy);
|
free(filecopy);
|
||||||
if ( level <= FATAL ) {
|
if ( level <= FATAL ) {
|
||||||
|
logTerm();
|
||||||
|
zmDbClose();
|
||||||
if ( level <= PANIC )
|
if ( level <= PANIC )
|
||||||
abort();
|
abort();
|
||||||
exit( -1 );
|
exit( -1 );
|
||||||
|
|
|
@ -27,16 +27,14 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
User::User()
|
User::User() {
|
||||||
{
|
|
||||||
username[0] = password[0] = 0;
|
username[0] = password[0] = 0;
|
||||||
enabled = false;
|
enabled = false;
|
||||||
stream = events = control = monitors = system = PERM_NONE;
|
stream = events = control = monitors = system = PERM_NONE;
|
||||||
monitor_ids = 0;
|
monitor_ids = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
User::User( MYSQL_ROW &dbrow )
|
User::User( MYSQL_ROW &dbrow ) {
|
||||||
{
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
strncpy( username, dbrow[index++], sizeof(username) );
|
strncpy( username, dbrow[index++], sizeof(username) );
|
||||||
strncpy( password, dbrow[index++], sizeof(password) );
|
strncpy( password, dbrow[index++], sizeof(password) );
|
||||||
|
@ -48,22 +46,18 @@ User::User( MYSQL_ROW &dbrow )
|
||||||
system = (Permission)atoi( dbrow[index++] );
|
system = (Permission)atoi( dbrow[index++] );
|
||||||
monitor_ids = 0;
|
monitor_ids = 0;
|
||||||
char *monitor_ids_str = dbrow[index++];
|
char *monitor_ids_str = dbrow[index++];
|
||||||
if ( monitor_ids_str && *monitor_ids_str )
|
if ( monitor_ids_str && *monitor_ids_str ) {
|
||||||
{
|
|
||||||
monitor_ids = new int[strlen(monitor_ids_str)];
|
monitor_ids = new int[strlen(monitor_ids_str)];
|
||||||
int n_monitor_ids = 0;
|
int n_monitor_ids = 0;
|
||||||
const char *ptr = monitor_ids_str;
|
const char *ptr = monitor_ids_str;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
int id = 0;
|
int id = 0;
|
||||||
while( isdigit( *ptr ) )
|
while( isdigit( *ptr ) ) {
|
||||||
{
|
|
||||||
id *= 10;
|
id *= 10;
|
||||||
id += *ptr-'0';
|
id += *ptr-'0';
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
if ( id )
|
if ( id ) {
|
||||||
{
|
|
||||||
monitor_ids[n_monitor_ids++] = id;
|
monitor_ids[n_monitor_ids++] = id;
|
||||||
if ( !*ptr )
|
if ( !*ptr )
|
||||||
break;
|
break;
|
||||||
|
@ -75,21 +69,16 @@ User::User( MYSQL_ROW &dbrow )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
User::~User()
|
User::~User() {
|
||||||
{
|
|
||||||
delete monitor_ids;
|
delete monitor_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool User::canAccess( int monitor_id )
|
bool User::canAccess( int monitor_id ) {
|
||||||
{
|
if ( !monitor_ids ) {
|
||||||
if ( !monitor_ids )
|
|
||||||
{
|
|
||||||
return( true );
|
return( true );
|
||||||
}
|
}
|
||||||
for ( int i = 0; monitor_ids[i]; i++ )
|
for ( int i = 0; monitor_ids[i]; i++ ) {
|
||||||
{
|
if ( monitor_ids[i] == monitor_id ) {
|
||||||
if ( monitor_ids[i] == monitor_id )
|
|
||||||
{
|
|
||||||
return( true );
|
return( true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,8 +87,7 @@ bool User::canAccess( int monitor_id )
|
||||||
|
|
||||||
// Function to load a user from username and password
|
// Function to load a user from username and password
|
||||||
// Please note that in auth relay mode = none, password is NULL
|
// Please note that in auth relay mode = none, password is NULL
|
||||||
User *zmLoadUser( const char *username, const char *password )
|
User *zmLoadUser( const char *username, const char *password ) {
|
||||||
{
|
|
||||||
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
||||||
char safer_username[65]; // current db username size is 32
|
char safer_username[65]; // current db username size is 32
|
||||||
char safer_password[129]; // current db password size is 64
|
char safer_password[129]; // current db password size is 64
|
||||||
|
@ -114,22 +102,20 @@ User *zmLoadUser( const char *username, const char *password )
|
||||||
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Enabled = 1", safer_username );
|
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Enabled = 1", safer_username );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mysql_query( &dbconn, sql ) )
|
if ( mysql_query( &dbconn, sql ) ) {
|
||||||
{
|
|
||||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
MYSQL_RES *result = mysql_store_result( &dbconn );
|
MYSQL_RES *result = mysql_store_result( &dbconn );
|
||||||
if ( !result )
|
if ( !result ) {
|
||||||
{
|
|
||||||
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
int n_users = mysql_num_rows( result );
|
int n_users = mysql_num_rows( result );
|
||||||
|
|
||||||
if ( n_users != 1 )
|
if ( n_users != 1 ) {
|
||||||
{
|
mysql_free_result( result );
|
||||||
Warning( "Unable to authenticate user %s", username );
|
Warning( "Unable to authenticate user %s", username );
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
@ -145,13 +131,11 @@ User *zmLoadUser( const char *username, const char *password )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to validate an authentication string
|
// Function to validate an authentication string
|
||||||
User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
|
User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||||
{
|
|
||||||
#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
||||||
#ifdef HAVE_GCRYPT_H
|
#ifdef HAVE_GCRYPT_H
|
||||||
// Special initialisation for libgcrypt
|
// Special initialisation for libgcrypt
|
||||||
if ( !gcry_check_version( GCRYPT_VERSION ) )
|
if ( !gcry_check_version( GCRYPT_VERSION ) ) {
|
||||||
{
|
|
||||||
Fatal( "Unable to initialise libgcrypt" );
|
Fatal( "Unable to initialise libgcrypt" );
|
||||||
}
|
}
|
||||||
gcry_control( GCRYCTL_DISABLE_SECMEM, 0 );
|
gcry_control( GCRYCTL_DISABLE_SECMEM, 0 );
|
||||||
|
@ -159,11 +143,9 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
|
||||||
#endif // HAVE_GCRYPT_H
|
#endif // HAVE_GCRYPT_H
|
||||||
|
|
||||||
const char *remote_addr = "";
|
const char *remote_addr = "";
|
||||||
if ( use_remote_addr )
|
if ( use_remote_addr ) {
|
||||||
{
|
|
||||||
remote_addr = getenv( "REMOTE_ADDR" );
|
remote_addr = getenv( "REMOTE_ADDR" );
|
||||||
if ( !remote_addr )
|
if ( !remote_addr ) {
|
||||||
{
|
|
||||||
Warning( "Can't determine remote address, using null" );
|
Warning( "Can't determine remote address, using null" );
|
||||||
remote_addr = "";
|
remote_addr = "";
|
||||||
}
|
}
|
||||||
|
@ -173,28 +155,25 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
|
||||||
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
||||||
snprintf( sql, sizeof(sql), "SELECT Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds FROM Users WHERE Enabled = 1" );
|
snprintf( sql, sizeof(sql), "SELECT Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds FROM Users WHERE Enabled = 1" );
|
||||||
|
|
||||||
if ( mysql_query( &dbconn, sql ) )
|
if ( mysql_query( &dbconn, sql ) ) {
|
||||||
{
|
|
||||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
MYSQL_RES *result = mysql_store_result( &dbconn );
|
MYSQL_RES *result = mysql_store_result( &dbconn );
|
||||||
if ( !result )
|
if ( !result ) {
|
||||||
{
|
|
||||||
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit( mysql_errno( &dbconn ) );
|
||||||
}
|
}
|
||||||
int n_users = mysql_num_rows( result );
|
int n_users = mysql_num_rows( result );
|
||||||
|
|
||||||
if ( n_users < 1 )
|
if ( n_users < 1 ) {
|
||||||
{
|
mysql_free_result( result );
|
||||||
Warning( "Unable to authenticate user" );
|
Warning( "Unable to authenticate user" );
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
while( MYSQL_ROW dbrow = mysql_fetch_row( result ) )
|
while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) {
|
||||||
{
|
|
||||||
const char *user = dbrow[0];
|
const char *user = dbrow[0];
|
||||||
const char *pass = dbrow[1];
|
const char *pass = dbrow[1];
|
||||||
|
|
||||||
|
@ -204,7 +183,7 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
|
||||||
unsigned char md5sum[md5len];
|
unsigned char md5sum[md5len];
|
||||||
|
|
||||||
time_t now = time( 0 );
|
time_t now = time( 0 );
|
||||||
unsigned int hours =config.auth_hash_ttl;
|
unsigned int hours = config.auth_hash_ttl;
|
||||||
|
|
||||||
if ( ! hours ) {
|
if ( ! hours ) {
|
||||||
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2.");
|
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2.");
|
||||||
|
@ -234,23 +213,23 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
|
||||||
gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len );
|
gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len );
|
||||||
#endif
|
#endif
|
||||||
auth_md5[0] = '\0';
|
auth_md5[0] = '\0';
|
||||||
for ( unsigned int j = 0; j < md5len; j++ )
|
for ( unsigned int j = 0; j < md5len; j++ ) {
|
||||||
{
|
|
||||||
sprintf( &auth_md5[2*j], "%02x", md5sum[j] );
|
sprintf( &auth_md5[2*j], "%02x", md5sum[j] );
|
||||||
}
|
}
|
||||||
Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", auth_key, auth_md5, auth );
|
Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", auth_key, auth_md5, auth );
|
||||||
|
|
||||||
if ( !strcmp( auth, auth_md5 ) )
|
if ( !strcmp( auth, auth_md5 ) ) {
|
||||||
{
|
|
||||||
// We have a match
|
// We have a match
|
||||||
User *user = new User( dbrow );
|
User *user = new User( dbrow );
|
||||||
Debug(1, "Authenticated user '%s'", user->getUsername() );
|
Debug(1, "Authenticated user '%s'", user->getUsername() );
|
||||||
|
mysql_free_result( result );
|
||||||
return( user );
|
return( user );
|
||||||
} else {
|
} else {
|
||||||
Debug(1, "No match for %s", auth );
|
Debug(1, "No match for %s", auth );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mysql_free_result( result );
|
||||||
#else // HAVE_DECL_MD5
|
#else // HAVE_DECL_MD5
|
||||||
Error( "You need to build with gnutls or openssl installed to use hash based authentication" );
|
Error( "You need to build with gnutls or openssl installed to use hash based authentication" );
|
||||||
#endif // HAVE_DECL_MD5
|
#endif // HAVE_DECL_MD5
|
||||||
|
|
|
@ -259,23 +259,19 @@ fi
|
||||||
|
|
||||||
if [ $TYPE == "binary" ]; then
|
if [ $TYPE == "binary" ]; then
|
||||||
if [ "$INTERACTIVE" != "no" ]; then
|
if [ "$INTERACTIVE" != "no" ]; then
|
||||||
read -p "Not doing dput since it's a binary release. Do you want to install it? (Y/N)"
|
read -p "Not doing dput since it's a binary release. Do you want to install it? (y/N)"
|
||||||
if [[ $REPLY == [yY] ]]; then
|
if [[ $REPLY == [yY] ]]; then
|
||||||
sudo dpkg -i $DIRECTORY*.deb
|
sudo dpkg -i $DIRECTORY*.deb
|
||||||
else
|
|
||||||
echo $REPLY;
|
|
||||||
fi;
|
fi;
|
||||||
if [ "$DISTRO" == "jessie" ]; then
|
read -p "Do you want to upload this binary to zmrepo? (y/N)"
|
||||||
read -p "Do you want to upload this binary to zmrepo? (y/N)"
|
if [[ $REPLY == [yY] ]]; then
|
||||||
if [[ $REPLY == [yY] ]]; then
|
if [ "$RELEASE" != "" ]; then
|
||||||
if [ "$RELEASE" != "" ]; then
|
scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/"
|
||||||
scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/"
|
else
|
||||||
|
if [ "$BRANCH" == "" ]; then
|
||||||
|
scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/"
|
||||||
else
|
else
|
||||||
if [ "$BRANCH" == "" ]; then
|
scp "$DIRECTORY-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/"
|
||||||
scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/"
|
|
||||||
else
|
|
||||||
scp "$DIRECTORY-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/"
|
|
||||||
fi;
|
|
||||||
fi;
|
fi;
|
||||||
fi;
|
fi;
|
||||||
fi;
|
fi;
|
||||||
|
|
|
@ -94,9 +94,8 @@ switch ( $_REQUEST['task'] )
|
||||||
$sql .= " order by ".$sortField." ".$sortOrder." limit ".$limit;
|
$sql .= " order by ".$sortField." ".$sortOrder." limit ".$limit;
|
||||||
$logs = array();
|
$logs = array();
|
||||||
foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) {
|
foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) {
|
||||||
$log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] );
|
$log['DateTime'] = preg_replace( '/^\d+/', strftime( '%Y-%m-%d %H:%M:%S', intval($log['TimeKey']) ), $log['TimeKey'] );
|
||||||
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
|
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
|
||||||
#$log['Message'] = preg_replace('/[\x00-\x1F\x7F]/u', '', $log['Message'] );
|
|
||||||
$log['Message'] = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $log['Message'] );
|
$log['Message'] = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $log['Message'] );
|
||||||
$logs[] = $log;
|
$logs[] = $log;
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,49 +101,66 @@ CakeLog::config('debug', array(
|
||||||
'engine' => 'File',
|
'engine' => 'File',
|
||||||
'types' => array('notice', 'info', 'debug'),
|
'types' => array('notice', 'info', 'debug'),
|
||||||
'file' => 'cake_debug',
|
'file' => 'cake_debug',
|
||||||
|
'path' => '@ZM_LOGDIR@/'
|
||||||
));
|
));
|
||||||
CakeLog::config('error', array(
|
CakeLog::config('error', array(
|
||||||
'engine' => 'File',
|
'engine' => 'File',
|
||||||
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
|
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
|
||||||
'file' => 'cake_error',
|
'file' => 'cake_error',
|
||||||
|
'path' => '@ZM_LOGDIR@/'
|
||||||
));
|
));
|
||||||
CakeLog::config('custom_path', array(
|
CakeLog::config('custom_path', array(
|
||||||
'engine' => 'File',
|
'engine' => 'File',
|
||||||
'path' => '@ZM_LOGDIR@'
|
'path' => '@ZM_LOGDIR@/'
|
||||||
));
|
));
|
||||||
|
|
||||||
Configure::write('ZM_CONFIG', '@ZM_CONFIG@');
|
Configure::write('ZM_CONFIG', '@ZM_CONFIG@');
|
||||||
|
Configure::write('ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@');
|
||||||
Configure::write('ZM_VERSION', '@VERSION@');
|
Configure::write('ZM_VERSION', '@VERSION@');
|
||||||
Configure::write('ZM_API_VERSION', '@API_VERSION@');
|
Configure::write('ZM_API_VERSION', '@API_VERSION@');
|
||||||
|
|
||||||
loadConfigFile();
|
# Process name, value pairs from the main config file first
|
||||||
|
$configvals = process_configfile(Configure::read('ZM_CONFIG'));
|
||||||
|
|
||||||
function loadConfigFile() {
|
# Search for user created config files. If one or more are found then
|
||||||
$configFile = Configure::read('ZM_CONFIG');
|
# update our config value array with those values
|
||||||
$localConfigFile = basename($configFile);
|
$configSubFolder = Configure::read('ZM_CONFIG_SUBDIR');
|
||||||
if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 )
|
if ( is_dir($configSubFolder) ) {
|
||||||
{
|
if ( is_readable($configSubFolder) ) {
|
||||||
if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) )
|
foreach ( glob("$configSubFolder/*.conf") as $filename ) {
|
||||||
print( "Warning, overriding installed $localConfigFile file with local copy\n" );
|
$configvals = array_replace($configvals, process_configfile($filename) );
|
||||||
else
|
}
|
||||||
error_log( "Warning, overriding installed $localConfigFile file with local copy" );
|
} else {
|
||||||
$configFile = $localConfigFile;
|
error_log( "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder." );
|
||||||
}
|
}
|
||||||
|
|
||||||
$cfg = fopen( $configFile, "r") or die("Could not open config file.");
|
|
||||||
while ( !feof($cfg) )
|
|
||||||
{
|
|
||||||
$str = fgets( $cfg, 256 );
|
|
||||||
if ( preg_match( '/^\s*$/', $str ))
|
|
||||||
continue;
|
|
||||||
elseif ( preg_match( '/^\s*#/', $str ))
|
|
||||||
continue;
|
|
||||||
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches )) {
|
|
||||||
Configure::write( $matches[1], $matches[2] );
|
|
||||||
define( $matches[1], $matches[2] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose( $cfg );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Now that our array our finalized, define each key => value
|
||||||
|
# pair in the array as a constant
|
||||||
|
foreach( $configvals as $key => $value) {
|
||||||
|
define( $key, $value );
|
||||||
|
Configure::write( $matches[1], $matches[2] );
|
||||||
|
}
|
||||||
|
|
||||||
|
function process_configfile($configFile) {
|
||||||
|
if ( is_readable( $configFile ) ) {
|
||||||
|
$configvals = array();
|
||||||
|
|
||||||
|
$cfg = fopen( $configFile, "r") or die("Could not open config file.");
|
||||||
|
while ( !feof($cfg) ) {
|
||||||
|
$str = fgets( $cfg, 256 );
|
||||||
|
if ( preg_match( '/^\s*$/', $str ))
|
||||||
|
continue;
|
||||||
|
elseif ( preg_match( '/^\s*#/', $str ))
|
||||||
|
continue;
|
||||||
|
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches ))
|
||||||
|
$configvals[$matches[1]] = $matches[2];
|
||||||
|
}
|
||||||
|
fclose( $cfg );
|
||||||
|
return( $configvals );
|
||||||
|
} else {
|
||||||
|
error_log( "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile." );
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1146,7 +1146,7 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
||||||
|
|
||||||
$StorageArea = NULL;
|
$StorageArea = NULL;
|
||||||
|
|
||||||
$terms = $filter['Query']['terms'];
|
$terms = isset($filter['Query']) ? $filter['Query']['terms'] : NULL;
|
||||||
|
|
||||||
if ( isset($terms) && count($terms) ) {
|
if ( isset($terms) && count($terms) ) {
|
||||||
for ( $i = 0; $i < count($terms); $i++ ) {
|
for ( $i = 0; $i < count($terms); $i++ ) {
|
||||||
|
@ -2133,18 +2133,14 @@ function getStreamHTML( $monitor, $options = array() ) {
|
||||||
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
|
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
|
||||||
} else {
|
} else {
|
||||||
if ( ! isset( $options['width'] ) ) {
|
if ( ! isset( $options['width'] ) ) {
|
||||||
if ( $options['width'] == 100 ) {
|
|
||||||
$options['width'] = $monitor->Width();
|
|
||||||
} else {
|
|
||||||
$options['width'] = NULL;
|
$options['width'] = NULL;
|
||||||
}
|
} else if ( $options['width'] == 100 ) {
|
||||||
|
$options['width'] = $monitor->Width();
|
||||||
}
|
}
|
||||||
if ( ! isset( $options['height'] ) ) {
|
if ( ! isset( $options['height'] ) ) {
|
||||||
if ( $options['height'] == 100 ) {
|
|
||||||
$options['height'] = $monitor->Height();
|
|
||||||
} else {
|
|
||||||
$options['height'] = NULL;
|
$options['height'] = NULL;
|
||||||
}
|
} else if ( $options['height'] == 100 ) {
|
||||||
|
$options['height'] = $monitor->Height();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( ! isset($options['mode'] ) ) {
|
if ( ! isset($options['mode'] ) ) {
|
||||||
|
|
|
@ -194,7 +194,7 @@ isset($view) || $view = NULL;
|
||||||
isset($request) || $request = NULL;
|
isset($request) || $request = NULL;
|
||||||
isset($action) || $action = NULL;
|
isset($action) || $action = NULL;
|
||||||
|
|
||||||
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' ) {
|
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $request != 'control' ) {
|
||||||
require_once( 'includes/csrf/csrf-magic.php' );
|
require_once( 'includes/csrf/csrf-magic.php' );
|
||||||
Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
|
Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
|
||||||
csrf_check();
|
csrf_check();
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#monitors .imageFeed img ,
|
#monitors .imageFeed img ,
|
||||||
#monitors .imageFeed svg {
|
#monitors .imageFeed svg {
|
||||||
border: 2px solid #ffffff;
|
border: 2px solid #ffffff;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#monitors .imageFeed img.idle {
|
#monitors .imageFeed img.idle {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#monitors .imageFeed img ,
|
#monitors .imageFeed img ,
|
||||||
#monitors .imageFeed svg {
|
#monitors .imageFeed svg {
|
||||||
border: 2px solid #999999;
|
border: 2px solid #999999;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#monitors .imageFeed img.idle {
|
#monitors .imageFeed img.idle {
|
||||||
|
|
|
@ -69,7 +69,6 @@
|
||||||
#topPanel #textPanel {
|
#topPanel #textPanel {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 140px;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
color: #dddddd;
|
color: #dddddd;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#monitors .imageFeed img.idle {
|
#monitors .imageFeed img.idle {
|
||||||
|
|
|
@ -69,7 +69,6 @@
|
||||||
#topPanel #textPanel {
|
#topPanel #textPanel {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 140px;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
color: #016A9D;
|
color: #016A9D;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
|
|
@ -211,10 +211,10 @@ function getNavBarHTML() {
|
||||||
<li><?php if ( logToDatabase() > Logger::NOLOG ) { ?> <?php echo makePopupLink( '?view=log', 'zmLog', 'log', '<span class="'.logState().'">'.translate('Log').'</span>' ) ?><?php } ?></li>
|
<li><?php if ( logToDatabase() > Logger::NOLOG ) { ?> <?php echo makePopupLink( '?view=log', 'zmLog', 'log', '<span class="'.logState().'">'.translate('Log').'</span>' ) ?><?php } ?></li>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<?php if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
|
<?php if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
|
||||||
<li><a href="/?view=devices">Devices</a></li>
|
<li><a href="?view=devices">Devices</a></li>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<li><?php echo makePopupLink( '?view=groups', 'zmGroups', 'groups', sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ).($group?' ('.$group['Name'].')':''), canView( 'Groups' ) ); ?></li>
|
<li><?php echo makePopupLink( '?view=groups', 'zmGroups', 'groups', sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ).($group?' ('.$group['Name'].')':''), canView( 'Groups' ) ); ?></li>
|
||||||
<li><a href="/?view=filter">Filters</a></li>
|
<li><a href="?view=filter">Filters</a></li>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0;
|
$cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0;
|
||||||
|
@ -285,4 +285,19 @@ function getNavBarHTML() {
|
||||||
<?php
|
<?php
|
||||||
return( ob_get_clean() );
|
return( ob_get_clean() );
|
||||||
} // end function getNavBarHTML()
|
} // end function getNavBarHTML()
|
||||||
|
|
||||||
|
function xhtmlFooter() {
|
||||||
|
global $view;
|
||||||
|
global $skin;
|
||||||
|
global $running;
|
||||||
|
if ( canEdit('System') ) {
|
||||||
|
include("skins/$skin/views/state.php");
|
||||||
|
?>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</body></html>
|
||||||
|
<?php
|
||||||
|
} // end xhtmlFooter
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -79,8 +79,8 @@ function getPopupSize( tag, width, height ) {
|
||||||
popupSize.height = height;
|
popupSize.height = height;
|
||||||
Error( "Got passed height but no addHeight when getting popup size for tag '"+tag+"'" );
|
Error( "Got passed height but no addHeight when getting popup size for tag '"+tag+"'" );
|
||||||
}
|
}
|
||||||
if ( popupSize.minHeight && popupSize.height < popupSize.minHeight ) {
|
if ( popupSize.minHeight && ( popupSize.height < popupSize.minHeight ) ) {
|
||||||
Warning( "Adjusting to minimum height when getting popup size for tag '"+tag+"'" );
|
Warning( "Adjusting to minimum height ("+popupSize.minHeight+") when getting popup size for tag '"+tag+"' because calculated height is " + popupSize.height );
|
||||||
popupSize.height = popupSize.minHeight;
|
popupSize.height = popupSize.minHeight;
|
||||||
}
|
}
|
||||||
Debug( popupSize );
|
Debug( popupSize );
|
||||||
|
@ -293,4 +293,3 @@ function addVideoTimingTrack(video, LabelFormat, monitorName, duration, startTim
|
||||||
track.src = 'data:plain/text;charset=utf-8,'+encodeURIComponent(webvttdata);
|
track.src = 'data:plain/text;charset=utf-8,'+encodeURIComponent(webvttdata);
|
||||||
video.appendChild(track);
|
video.appendChild(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -290,11 +290,5 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<?php
|
<?php xhtmlFooter() ?>
|
||||||
if ( canEdit('System') ) {
|
|
||||||
include("skins/$skin/views/state.php");
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ if ( isset( $_REQUEST['streamMode'] ) )
|
||||||
else
|
else
|
||||||
$streamMode = 'video';
|
$streamMode = 'video';
|
||||||
|
|
||||||
|
$replayMode = '';
|
||||||
if ( isset( $_REQUEST['replayMode'] ) )
|
if ( isset( $_REQUEST['replayMode'] ) )
|
||||||
$replayMode = validHtmlStr($_REQUEST['replayMode']);
|
$replayMode = validHtmlStr($_REQUEST['replayMode']);
|
||||||
if ( isset( $_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) )
|
if ( isset( $_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) )
|
||||||
|
|
|
@ -405,5 +405,4 @@ if ( canEdit( 'Events' ) ) {
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
<?php xhtmlFooter() ?>
|
||||||
</html>
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
var logParms = "view=request&request=log&task=query";
|
var logParms = "view=request&request=log&task=query";
|
||||||
var logReq = new Request.JSON( { url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: logResponse } );
|
var logReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: logResponse } );
|
||||||
var logTimer = undefined;
|
var logTimer = undefined;
|
||||||
var logTable = undefined;
|
var logTable = undefined;
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ function selectLayout( element ) {
|
||||||
} else if ( streamImg.nodeName == 'APPLET' || streamImg.nodeName == 'OBJECT' ) {
|
} else if ( streamImg.nodeName == 'APPLET' || streamImg.nodeName == 'OBJECT' ) {
|
||||||
// APPLET's and OBJECTS need to be re-initialized
|
// APPLET's and OBJECTS need to be re-initialized
|
||||||
}
|
}
|
||||||
streamImg.style.width = '';
|
streamImg.style.width = '100%';
|
||||||
}
|
}
|
||||||
var zonesSVG = $('zones'+monitor.id);
|
var zonesSVG = $('zones'+monitor.id);
|
||||||
if ( zonesSVG ) {
|
if ( zonesSVG ) {
|
||||||
|
@ -140,37 +140,8 @@ function selectLayout( element ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeWidth() {
|
function changeSize() {
|
||||||
var width = $('width').get('value');
|
var width = $('width').get('value');
|
||||||
|
|
||||||
for ( var x = 0; x < monitors.length; x++ ) {
|
|
||||||
var monitor = monitors[x];
|
|
||||||
/*Stream could be an applet so can't use moo tools*/
|
|
||||||
var streamImg = $( 'liveStream'+monitor.id );
|
|
||||||
if ( streamImg ) {
|
|
||||||
if ( streamImg.nodeName == 'IMG' ) {
|
|
||||||
var src = streamImg.src;
|
|
||||||
streamImg.src='';
|
|
||||||
src = src.replace(/width=[\.\d]+/i,'width='+width );
|
|
||||||
src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
|
||||||
streamImg.src = src;
|
|
||||||
|
|
||||||
}
|
|
||||||
streamImg.style.width = width? width + "px" : null;
|
|
||||||
//streamImg.style.height = '';
|
|
||||||
}
|
|
||||||
var zonesSVG = $('zones'+monitor.id);
|
|
||||||
if ( zonesSVG ) {
|
|
||||||
|
|
||||||
zonesSVG.style.width = width ? width + "px" : '100%';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$('scale').set('value', '' );
|
|
||||||
Cookie.write( 'zmMontageScale', '', { duration: 10*365 } );
|
|
||||||
Cookie.write( 'zmMontageWidth', width, { duration: 10*365 } );
|
|
||||||
} // end function changeWidth()
|
|
||||||
|
|
||||||
function changeHeight() {
|
|
||||||
var height = $('height').get('value');
|
var height = $('height').get('value');
|
||||||
|
|
||||||
for ( var x = 0; x < monitors.length; x++ ) {
|
for ( var x = 0; x < monitors.length; x++ ) {
|
||||||
|
@ -181,21 +152,27 @@ function changeHeight() {
|
||||||
if ( streamImg.nodeName == 'IMG' ) {
|
if ( streamImg.nodeName == 'IMG' ) {
|
||||||
var src = streamImg.src;
|
var src = streamImg.src;
|
||||||
streamImg.src='';
|
streamImg.src='';
|
||||||
|
src = src.replace(/width=[\.\d]+/i,'width='+width );
|
||||||
src = src.replace(/height=[\.\d]+/i,'height='+height );
|
src = src.replace(/height=[\.\d]+/i,'height='+height );
|
||||||
src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
||||||
streamImg.src = src;
|
streamImg.src = src;
|
||||||
streamImg.style.height = height ? height + "px" : null;
|
|
||||||
}
|
}
|
||||||
|
streamImg.style.width = width? width + "px" : null;
|
||||||
|
streamImg.style.height = height ? height + "px" : null;
|
||||||
|
//streamImg.style.height = '';
|
||||||
}
|
}
|
||||||
var zonesSVG = $('zones'+monitor.id);
|
var zonesSVG = $('zones'+monitor.id);
|
||||||
if ( zonesSVG ) {
|
if ( zonesSVG ) {
|
||||||
|
zonesSVG.style.width = width ? width + "px" : '100%';
|
||||||
zonesSVG.style.height = height + "px";
|
zonesSVG.style.height = height + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$('scale').set('value', '' );
|
$('scale').set('value', '' );
|
||||||
Cookie.write( 'zmMontageHeight', height, { duration: 10*365 } );
|
|
||||||
Cookie.write( 'zmMontageScale', '', { duration: 10*365 } );
|
Cookie.write( 'zmMontageScale', '', { duration: 10*365 } );
|
||||||
} // end function changeHeight()
|
Cookie.write( 'zmMontageWidth', width, { duration: 10*365 } );
|
||||||
|
Cookie.write( 'zmMontageHeight', height, { duration: 10*365 } );
|
||||||
|
} // end function changeSize()
|
||||||
|
|
||||||
function changeScale() {
|
function changeScale() {
|
||||||
var scale = $('scale').get('value');
|
var scale = $('scale').get('value');
|
||||||
|
|
|
@ -32,7 +32,14 @@ $maxTimeSecs = strtotime('1950-01-01 01:01:01');
|
||||||
$index=0;
|
$index=0;
|
||||||
$anyAlarms=false;
|
$anyAlarms=false;
|
||||||
|
|
||||||
foreach( dbFetchAll( $eventsSql ) as $event ) {
|
$result = dbQuery( $eventsSql );
|
||||||
|
if ( ! $result ) {
|
||||||
|
Fatal( "SQL-ERR");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( $event = $result->fetch( PDO::FETCH_ASSOC ) ) {
|
||||||
|
|
||||||
if ( $minTimeSecs > $event['StartTimeSecs'] ) $minTimeSecs = $event['StartTimeSecs'];
|
if ( $minTimeSecs > $event['StartTimeSecs'] ) $minTimeSecs = $event['StartTimeSecs'];
|
||||||
if ( $maxTimeSecs < $event['CalcEndTimeSecs'] ) $maxTimeSecs = $event['CalcEndTimeSecs'];
|
if ( $maxTimeSecs < $event['CalcEndTimeSecs'] ) $maxTimeSecs = $event['CalcEndTimeSecs'];
|
||||||
echo "
|
echo "
|
||||||
|
@ -84,8 +91,9 @@ $fromSecs=-1;
|
||||||
$toSecs=-1;
|
$toSecs=-1;
|
||||||
$maxScore=-1;
|
$maxScore=-1;
|
||||||
|
|
||||||
if ( $anyAlarms ) {
|
if ( $anyAlarms && $result = dbQuery( $frameSql ) ) {
|
||||||
foreach( dbFetchAll ($frameSql) as $frame ) {
|
|
||||||
|
while( $frame = $result->fetch( PDO::FETCH_ASSOC ) ) {
|
||||||
if ( $mId < 0 ) {
|
if ( $mId < 0 ) {
|
||||||
$mId = $frame['MonitorId'];
|
$mId = $frame['MonitorId'];
|
||||||
$fromSecs = $frame['TimeStampSecs'];
|
$fromSecs = $frame['TimeStampSecs'];
|
||||||
|
|
|
@ -3,17 +3,14 @@ var filterQuery = '<?php echo validJsStr($filterQuery) ?>';
|
||||||
<?php
|
<?php
|
||||||
$jsMonitors = array();
|
$jsMonitors = array();
|
||||||
$fields = array('Name', 'LabelFormat', 'SaveJPEGs', 'VideoWriter');
|
$fields = array('Name', 'LabelFormat', 'SaveJPEGs', 'VideoWriter');
|
||||||
foreach ( $monitors as $monitor )
|
foreach ( $monitors as $monitor ) {
|
||||||
{
|
if ( !empty($monitorIds[$monitor['Id']]) ) {
|
||||||
if ( !empty($monitorIds[$monitor['Id']]) )
|
$jsMonitor = array();
|
||||||
{
|
foreach ($fields as $field) {
|
||||||
$jsMonitor = array();
|
$jsMonitor[$field] = $monitor[$field];
|
||||||
foreach ($fields as $field)
|
|
||||||
{
|
|
||||||
$jsMonitor[$field] = $monitor[$field];
|
|
||||||
}
|
|
||||||
$jsMonitors[$monitor['Id']] = $jsMonitor;
|
|
||||||
}
|
}
|
||||||
|
$jsMonitors[$monitor['Id']] = $jsMonitor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
var monitors = <?php echo json_encode($jsMonitors) ?>;
|
var monitors = <?php echo json_encode($jsMonitors) ?>;
|
||||||
|
|
|
@ -58,7 +58,7 @@ if ( ! empty($_REQUEST['mid']) ) {
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$nextId = getTableAutoInc( 'Monitors' );
|
$nextId = getTableAutoInc( 'Monitors' );
|
||||||
if ( ! empty( $_REQUEST['dupId'] ) ) {
|
if ( isset( $_REQUEST['dupId'] ) ) {
|
||||||
$monitor = new Monitor( $_REQUEST['dupId'] );
|
$monitor = new Monitor( $_REQUEST['dupId'] );
|
||||||
if ( ZM_OPT_X10 )
|
if ( ZM_OPT_X10 )
|
||||||
$x10Monitor = dbFetchOne( 'SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['dupId']) );
|
$x10Monitor = dbFetchOne( 'SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['dupId']) );
|
||||||
|
@ -566,7 +566,7 @@ if ( $tab != 'source' || $monitor->Type()!= 'Remote' ) {
|
||||||
}
|
}
|
||||||
if ( $tab != 'source' || ($monitor->Type()!= 'Local' && $monitor->Type()!= 'Remote' && $monitor->Type()!= 'Ffmpeg' && $monitor->Type()!= 'Libvlc') ) {
|
if ( $tab != 'source' || ($monitor->Type()!= 'Local' && $monitor->Type()!= 'Remote' && $monitor->Type()!= 'Ffmpeg' && $monitor->Type()!= 'Libvlc') ) {
|
||||||
?>
|
?>
|
||||||
<input type="hidden" name="newMonitor[Method]" value="<?php echo validHtmlStr($monitor->Method()) ?>"/>
|
<input type="hidden" name="newMonitor[Method]" value="<?php echo validHtmlStr(null !== $monitor->Method() ? $monitor->Method() : 'rtpRtsp' ) ?>"/>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
if ( $tab != 'source' || ($monitor->Type()!= 'Ffmpeg' && $monitor->Type()!= 'Libvlc' )) {
|
if ( $tab != 'source' || ($monitor->Type()!= 'Ffmpeg' && $monitor->Type()!= 'Libvlc' )) {
|
||||||
|
|
|
@ -41,7 +41,6 @@ if ( isset( $_REQUEST['showZones'] ) ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$monitors = array();
|
$monitors = array();
|
||||||
<<<<<<< HEAD
|
|
||||||
$widths = array(
|
$widths = array(
|
||||||
'' => 'auto',
|
'' => 'auto',
|
||||||
160 => 160,
|
160 => 160,
|
||||||
|
@ -68,7 +67,6 @@ if ( isset( $_REQUEST['scale'] ) ) {
|
||||||
|
|
||||||
if ( ! $scale )
|
if ( ! $scale )
|
||||||
$scale = 100;
|
$scale = 100;
|
||||||
}
|
|
||||||
|
|
||||||
foreach( dbFetchAll( $sql ) as $row ) {
|
foreach( dbFetchAll( $sql ) as $row ) {
|
||||||
if ( !visibleMonitor( $row['Id'] ) ) {
|
if ( !visibleMonitor( $row['Id'] ) ) {
|
||||||
|
@ -142,8 +140,8 @@ if ( $showZones ) {
|
||||||
</div>
|
</div>
|
||||||
<h2><?php echo translate('Montage') ?></h2>
|
<h2><?php echo translate('Montage') ?></h2>
|
||||||
<div id="headerControl">
|
<div id="headerControl">
|
||||||
<span id="widthControl"><label><?php echo translate('Width') ?>:</label><?php echo htmlSelect( 'width', $widths, $options['width'], 'changeWidth(this);' ); ?></span>
|
<span id="widthControl"><label><?php echo translate('Width') ?>:</label><?php echo htmlSelect( 'width', $widths, $options['width'], 'changeSize(this);' ); ?></span>
|
||||||
<span id="heightControl"><label><?php echo translate('Height') ?>:</label><?php echo htmlSelect( 'height', $heights, $options['height'], 'changeHeight(this);' ); ?></span>
|
<span id="heightControl"><label><?php echo translate('Height') ?>:</label><?php echo htmlSelect( 'height', $heights, $options['height'], 'changeSize(this);' ); ?></span>
|
||||||
<span id="scaleControl"><label><?php echo translate('Scale') ?>:</label><?php echo htmlSelect( 'scale', $scales, $scale, 'changeScale(this);' ); ?></span>
|
<span id="scaleControl"><label><?php echo translate('Scale') ?>:</label><?php echo htmlSelect( 'scale', $scales, $scale, 'changeScale(this);' ); ?></span>
|
||||||
<span id="layoutControl"><label for="layout"><?php echo translate('Layout') ?>:</label><?php echo htmlSelect( 'layout', $layouts, $layout, 'selectLayout(this);' )?></span>
|
<span id="layoutControl"><label for="layout"><?php echo translate('Layout') ?>:</label><?php echo htmlSelect( 'layout', $layouts, $layout, 'selectLayout(this);' )?></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -116,7 +116,7 @@ if ( !empty($_REQUEST['group']) ) {
|
||||||
// Note we round up just a bit on the end time as otherwise you get gaps, like 59.78 to 00 in the next second, which can give blank frames when moved through slowly.
|
// Note we round up just a bit on the end time as otherwise you get gaps, like 59.78 to 00 in the next second, which can give blank frames when moved through slowly.
|
||||||
|
|
||||||
$eventsSql = '
|
$eventsSql = '
|
||||||
SELECT E.Id,E.Name,E.StorageId,UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs,
|
SELECT E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs,
|
||||||
CASE WHEN E.EndTime IS NULL THEN (SELECT UNIX_TIMESTAMP(DATE_ADD(E.StartTime, Interval max(Delta)+0.5 Second)) FROM Frames F WHERE F.EventId=E.Id)
|
CASE WHEN E.EndTime IS NULL THEN (SELECT UNIX_TIMESTAMP(DATE_ADD(E.StartTime, Interval max(Delta)+0.5 Second)) FROM Frames F WHERE F.EventId=E.Id)
|
||||||
ELSE UNIX_TIMESTAMP(E.EndTime)
|
ELSE UNIX_TIMESTAMP(E.EndTime)
|
||||||
END AS CalcEndTimeSecs, E.Length,
|
END AS CalcEndTimeSecs, E.Length,
|
||||||
|
|
|
@ -34,8 +34,7 @@ require_once( $skinJsPhpFile );
|
||||||
<script type="text/javascript" src="<?php echo $skinJsFile ?>"></script>
|
<script type="text/javascript" src="<?php echo $skinJsFile ?>"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
<?php
|
<?php
|
||||||
if ( !$debug )
|
if ( !$debug ) {
|
||||||
{
|
|
||||||
?>
|
?>
|
||||||
closeWindow();
|
closeWindow();
|
||||||
<?php
|
<?php
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
if ( !canEdit( 'Monitors' ) ) {
|
if ( !canEdit( 'Monitors' ) ) {
|
||||||
$view = 'error';
|
$view = 'error';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$cameras = array();
|
$cameras = array();
|
||||||
|
@ -40,78 +40,81 @@ function execONVIF( $cmd ) {
|
||||||
$html_output<br/><br/>
|
$html_output<br/><br/>
|
||||||
Please the following command from a command line for more information:<br/><br/>$shell_command"
|
Please the following command from a command line for more information:<br/><br/>$shell_command"
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
Logger::Debug( "Results from probe: " . implode( '<br/>', $output ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
function probeCameras( $localIp ) {
|
function probeCameras( $localIp ) {
|
||||||
$cameras = array();
|
$cameras = array();
|
||||||
$count = 0;
|
if ( $lines = @execONVIF( 'probe' ) ) {
|
||||||
if ( $lines = @execONVIF( 'probe' ) ) {
|
foreach ( $lines as $line ) {
|
||||||
foreach ( $lines as $line ) {
|
$line = rtrim( $line );
|
||||||
$line = rtrim( $line );
|
if ( preg_match( '|^(.+),(.+),\s\((.*)\)$|', $line, $matches ) ) {
|
||||||
if ( preg_match( '|^(.+),(.+),\s\((.*)\)$|', $line, $matches ) ) {
|
$device_ep = $matches[1];
|
||||||
$device_ep = $matches[1];
|
$soapversion = $matches[2];
|
||||||
$soapversion = $matches[2];
|
$camera = array(
|
||||||
$camera = array(
|
'model' => 'Unknown ONVIF Camera',
|
||||||
'model' => "Unknown ONVIF Camera",
|
'monitor' => array(
|
||||||
'monitor' => array(
|
'Function' => 'Monitor',
|
||||||
'Function' => "Monitor",
|
'Type' => 'Ffmpeg',
|
||||||
'Type' => 'Ffmpeg',
|
'Host' => $device_ep,
|
||||||
'Host' => $device_ep,
|
'SOAP' => $soapversion,
|
||||||
'SOAP' => $soapversion,
|
),
|
||||||
),
|
);
|
||||||
);
|
foreach ( preg_split('|,\s*|', $matches[3]) as $attr_val ) {
|
||||||
foreach ( preg_split('|,\s*|', $matches[3]) as $attr_val ) {
|
if ( preg_match( '|(.+)=\'(.*)\'|', $attr_val, $tokens ) ) {
|
||||||
if( preg_match( '|(.+)=\'(.*)\'|', $attr_val, $tokens ) ) {
|
if ( $tokens[1] == 'hardware' ) {
|
||||||
if($tokens[1] == "hardware") {
|
$camera['model'] = $tokens[2];
|
||||||
$camera['model'] = $tokens[2];
|
} elseif ( $tokens[1] == 'name' ) {
|
||||||
} elseif($tokens[1] == "name") {
|
$camera['monitor']['Name'] = $tokens[2];
|
||||||
$camera['monitor']['Name'] = $tokens[2];
|
} elseif ( $tokens[1] == 'location' ) {
|
||||||
} elseif($tokens[1] == "location") {
|
// $camera['location'] = $tokens[2];
|
||||||
// $camera['location'] = $tokens[2];
|
} else {
|
||||||
}
|
Logger::Debug('Unknown token ' . $tokens[1] );
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$cameras[$count ++] = $camera;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // end foreach token
|
||||||
return( $cameras );
|
$cameras[] = $camera;
|
||||||
|
}
|
||||||
|
} // end foreach line
|
||||||
|
}
|
||||||
|
return( $cameras );
|
||||||
}
|
}
|
||||||
|
|
||||||
function probeProfiles( $device_ep, $soapversion, $username, $password ) {
|
function probeProfiles( $device_ep, $soapversion, $username, $password ) {
|
||||||
$profiles = array();
|
$profiles = array();
|
||||||
$count = 0;
|
if ( $lines = @execONVIF( "profiles $device_ep $soapversion $username $password" ) ) {
|
||||||
if ( $lines = @execONVIF( "profiles $device_ep $soapversion $username $password" ) ) {
|
foreach ( $lines as $line ) {
|
||||||
foreach ( $lines as $line ) {
|
$line = rtrim( $line );
|
||||||
$line = rtrim( $line );
|
if ( preg_match( '|^(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+)\s*$|', $line, $matches ) ) {
|
||||||
if ( preg_match( '|^(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+)\s*$|', $line, $matches ) ) {
|
$stream_uri = $matches[7];
|
||||||
$stream_uri = $matches[7];
|
// add user@pass to URI
|
||||||
// add user@pass to URI
|
if ( preg_match( '|^(\S+://)(.+)$|', $stream_uri, $tokens ) ) {
|
||||||
if( preg_match( '|^(\S+://)(.+)$|', $stream_uri, $tokens ) ) {
|
$stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2];
|
||||||
$stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$profile = array( # 'monitor' part of camera
|
$profile = array( # 'monitor' part of camera
|
||||||
'Type' => 'Ffmpeg',
|
'Type' => 'Ffmpeg',
|
||||||
'Width' => $matches[4],
|
'Width' => $matches[4],
|
||||||
'Height' => $matches[5],
|
'Height' => $matches[5],
|
||||||
'MaxFPS' => $matches[6],
|
'MaxFPS' => $matches[6],
|
||||||
'Path' => $stream_uri,
|
'Path' => $stream_uri,
|
||||||
// local-only:
|
// local-only:
|
||||||
'Profile' => $matches[1],
|
'Profile' => $matches[1],
|
||||||
'Name' => $matches[2],
|
'Name' => $matches[2],
|
||||||
'Encoding' => $matches[3],
|
'Encoding' => $matches[3],
|
||||||
|
|
||||||
);
|
);
|
||||||
$profiles[$count ++] = $profile;
|
$profiles[] = $profile;
|
||||||
}
|
} else {
|
||||||
}
|
Logger::Debug("Line did not match preg: $line");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return( $profiles );
|
}
|
||||||
|
return( $profiles );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
if ( !canEdit( 'System' ) ) {
|
if ( !canEdit( 'System' ) ) {
|
||||||
$view = "error";
|
$view = 'error';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -40,18 +40,24 @@ if ( !canEdit( 'System' ) ) {
|
||||||
<label for="runState" class="col-sm-3 control-label">Change State</label>
|
<label for="runState" class="col-sm-3 control-label">Change State</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="runState" name="runState" class="form-control">
|
<select id="runState" name="runState" class="form-control">
|
||||||
<?php if ( daemonCheck() ) { ?>
|
<?php
|
||||||
|
if ( $running ) {
|
||||||
|
?>
|
||||||
<option value="stop" selected="selected"><?php echo translate('Stop') ?></option>
|
<option value="stop" selected="selected"><?php echo translate('Stop') ?></option>
|
||||||
<option value="restart"><?php echo translate('Restart') ?></option>
|
<option value="restart"><?php echo translate('Restart') ?></option>
|
||||||
<?php } else { ?>
|
|
||||||
<option value="start" selected="selected"><?php echo translate('Start') ?></option>
|
|
||||||
<?php }
|
|
||||||
?>
|
|
||||||
<?php
|
<?php
|
||||||
|
} else {
|
||||||
|
?>
|
||||||
|
<option value="start" selected="selected"><?php echo translate('Start') ?></option>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
$states = dbFetchAll( 'SELECT * FROM States' );
|
$states = dbFetchAll( 'SELECT * FROM States' );
|
||||||
foreach ( $states as $state ) { ?>
|
foreach ( $states as $state ) {
|
||||||
|
?>
|
||||||
<option value="<?php echo $state['Name'] ?>"><?php echo $state['Name'] ?></option>
|
<option value="<?php echo $state['Name'] ?>"><?php echo $state['Name'] ?></option>
|
||||||
<?php } ?>
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
</select>
|
</select>
|
||||||
</div><!--col-sm-9-->
|
</div><!--col-sm-9-->
|
||||||
</div><!--form-group-->
|
</div><!--form-group-->
|
||||||
|
|
|
@ -37,16 +37,16 @@ define( 'STRF_TL_AXIS_RANGE_YEAR1', '%b %Y' );
|
||||||
define( 'STRF_TL_AXIS_RANGE_YEAR2', STRF_TL_AXIS_RANGE_YEAR1 );
|
define( 'STRF_TL_AXIS_RANGE_YEAR2', STRF_TL_AXIS_RANGE_YEAR1 );
|
||||||
|
|
||||||
// When the chart range is months
|
// When the chart range is months
|
||||||
define( "STRF_TL_AXIS_RANGE_MONTH1", "%b" );
|
define( 'STRF_TL_AXIS_RANGE_MONTH1', '%b' );
|
||||||
define( "STRF_TL_AXIS_RANGE_MONTH2", STRF_TL_AXIS_RANGE_MONTH1." %Y" );
|
define( 'STRF_TL_AXIS_RANGE_MONTH2', STRF_TL_AXIS_RANGE_MONTH1.' %Y' );
|
||||||
|
|
||||||
// When the chart range is days
|
// When the chart range is days
|
||||||
define( "STRF_TL_AXIS_RANGE_DAY1", "%d" );
|
define( 'STRF_TL_AXIS_RANGE_DAY1', '%d' );
|
||||||
define( "STRF_TL_AXIS_RANGE_DAY2", STRF_TL_AXIS_RANGE_DAY1." %b %Y" );
|
define( 'STRF_TL_AXIS_RANGE_DAY2', STRF_TL_AXIS_RANGE_DAY1.' %b %Y' );
|
||||||
|
|
||||||
// When the chart range is less than a day
|
// When the chart range is less than a day
|
||||||
define( "STRF_TL_AXIS_RANGE_TIME1", "%H:%M" );
|
define( 'STRF_TL_AXIS_RANGE_TIME1', '%H:%M' );
|
||||||
define( "STRF_TL_AXIS_RANGE_TIME2", STRF_TL_AXIS_RANGE_TIME1.", %d %b %Y" );
|
define( 'STRF_TL_AXIS_RANGE_TIME2', STRF_TL_AXIS_RANGE_TIME1.', %d %b %Y' );
|
||||||
|
|
||||||
//
|
//
|
||||||
// These are the time axis tick labels
|
// These are the time axis tick labels
|
||||||
|
@ -74,56 +74,56 @@ $minEventWidth = 3;
|
||||||
$maxEventWidth = 6;
|
$maxEventWidth = 6;
|
||||||
|
|
||||||
$chart = array(
|
$chart = array(
|
||||||
"width"=>700,
|
'width'=>700,
|
||||||
"height"=>460,
|
'height'=>460,
|
||||||
"image" => array(
|
'image' => array(
|
||||||
"width"=>264,
|
'width'=>264,
|
||||||
"height"=>220,
|
'height'=>220,
|
||||||
"topOffset"=>20,
|
'topOffset'=>20,
|
||||||
),
|
),
|
||||||
"imageText" => array(
|
'imageText' => array(
|
||||||
"width"=>400,
|
'width'=>400,
|
||||||
"height"=>30,
|
'height'=>30,
|
||||||
"topOffset"=>20,
|
'topOffset'=>20,
|
||||||
),
|
),
|
||||||
"graph" => array(
|
'graph' => array(
|
||||||
"width"=>600,
|
'width'=>600,
|
||||||
"height"=>160,
|
'height'=>160,
|
||||||
"topOffset"=>30,
|
'topOffset'=>30,
|
||||||
),
|
),
|
||||||
"title" => array(
|
'title' => array(
|
||||||
"topOffset"=>50
|
'topOffset'=>50
|
||||||
),
|
),
|
||||||
"key" => array(
|
'key' => array(
|
||||||
"topOffset"=>50
|
'topOffset'=>50
|
||||||
),
|
),
|
||||||
"axes" => array(
|
'axes' => array(
|
||||||
"x" => array(
|
'x' => array(
|
||||||
"height" => 20,
|
'height' => 20,
|
||||||
),
|
),
|
||||||
"y" => array(
|
'y' => array(
|
||||||
"width" => 30,
|
'width' => 30,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
"grid" => array(
|
'grid' => array(
|
||||||
"x" => array(
|
'x' => array(
|
||||||
"major" => array(
|
'major' => array(
|
||||||
"max" => 12,
|
'max' => 12,
|
||||||
"min" => 4,
|
'min' => 4,
|
||||||
),
|
),
|
||||||
"minor" => array(
|
'minor' => array(
|
||||||
"max" => 48,
|
'max' => 48,
|
||||||
"min" => 12,
|
'min' => 12,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
"y" => array(
|
'y' => array(
|
||||||
"major" => array(
|
'major' => array(
|
||||||
"max" => 8,
|
'max' => 8,
|
||||||
"min" => 1,
|
'min' => 1,
|
||||||
),
|
),
|
||||||
"minor" => array(
|
'minor' => array(
|
||||||
"max" => 0,
|
'max' => 0,
|
||||||
"min" => 0,
|
'min' => 0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -152,7 +152,7 @@ if ( !empty($user['MonitorIds']) ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isset($_REQUEST['filter']) )
|
if ( isset($_REQUEST['filter']) )
|
||||||
$tree = parseFilterToTree( $_REQUEST['filter'] );
|
$tree = parseFilterToTree( $_REQUEST['filter']['Query'] );
|
||||||
else
|
else
|
||||||
$tree = false;
|
$tree = false;
|
||||||
|
|
||||||
|
@ -253,16 +253,16 @@ if ( $tree ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$scales = array(
|
$scales = array(
|
||||||
array( "name"=>"year", "factor"=>60*60*24*365, "align"=>1, "zoomout"=>2, "label"=>STRF_TL_AXIS_LABEL_YEAR ),
|
array( 'name'=>"year", 'factor'=>60*60*24*365, 'align'=>1, 'zoomout'=>2, 'label'=>STRF_TL_AXIS_LABEL_YEAR ),
|
||||||
array( "name"=>"month", "factor"=>60*60*24*30, "align"=>1, "zoomout"=>12, "label"=>STRF_TL_AXIS_LABEL_MONTH ),
|
array( 'name'=>"month", 'factor'=>60*60*24*30, 'align'=>1, 'zoomout'=>12, 'label'=>STRF_TL_AXIS_LABEL_MONTH ),
|
||||||
array( "name"=>"week", "factor"=>60*60*24*7, "align"=>1, "zoomout"=>4.25, "label"=>STRF_TL_AXIS_LABEL_WEEK, "labelCheck"=>"%W" ),
|
array( 'name'=>"week", 'factor'=>60*60*24*7, 'align'=>1, 'zoomout'=>4.25, 'label'=>STRF_TL_AXIS_LABEL_WEEK, 'labelCheck'=>"%W" ),
|
||||||
array( "name"=>"day", "factor"=>60*60*24, "align"=>1, "zoomout"=>7, "label"=>STRF_TL_AXIS_LABEL_DAY ),
|
array( 'name'=>"day", 'factor'=>60*60*24, 'align'=>1, 'zoomout'=>7, 'label'=>STRF_TL_AXIS_LABEL_DAY ),
|
||||||
array( "name"=>"hour4", "factor"=>60*60, "align"=>4, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_4HOUR, "labelCheck"=>"%H" ),
|
array( 'name'=>"hour4", 'factor'=>60*60, 'align'=>4, 'zoomout'=>6, 'label'=>STRF_TL_AXIS_LABEL_4HOUR, 'labelCheck'=>"%H" ),
|
||||||
array( "name"=>"hour", "factor"=>60*60, "align"=>1, "zoomout"=>4, "label"=>STRF_TL_AXIS_LABEL_HOUR, "labelCheck"=>"%H" ),
|
array( 'name'=>"hour", 'factor'=>60*60, 'align'=>1, 'zoomout'=>4, 'label'=>STRF_TL_AXIS_LABEL_HOUR, 'labelCheck'=>"%H" ),
|
||||||
array( "name"=>"minute10", "factor"=>60, "align"=>10, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_10MINUTE, "labelCheck"=>"%M" ),
|
array( 'name'=>"minute10", 'factor'=>60, 'align'=>10, 'zoomout'=>6, 'label'=>STRF_TL_AXIS_LABEL_10MINUTE, 'labelCheck'=>"%M" ),
|
||||||
array( "name"=>"minute", "factor"=>60, "align"=>1, "zoomout"=>10, "label"=>STRF_TL_AXIS_LABEL_MINUTE, "labelCheck"=>"%M" ),
|
array( 'name'=>"minute", 'factor'=>60, 'align'=>1, 'zoomout'=>10, 'label'=>STRF_TL_AXIS_LABEL_MINUTE, 'labelCheck'=>"%M" ),
|
||||||
array( "name"=>"second10", "factor"=>1, "align"=>10, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_10SECOND ),
|
array( 'name'=>"second10", 'factor'=>1, 'align'=>10, 'zoomout'=>6, 'label'=>STRF_TL_AXIS_LABEL_10SECOND ),
|
||||||
array( "name"=>"second", "factor"=>1, "align"=>1, "zoomout"=>10, "label"=>STRF_TL_AXIS_LABEL_SECOND ),
|
array( 'name'=>"second", 'factor'=>1, 'align'=>1, 'zoomout'=>10, 'label'=>STRF_TL_AXIS_LABEL_SECOND ),
|
||||||
);
|
);
|
||||||
|
|
||||||
$majXScale = getDateScale( $scales, $range, $chart['grid']['x']['major']['min'], $chart['grid']['x']['major']['max'] );
|
$majXScale = getDateScale( $scales, $range, $chart['grid']['x']['major']['min'], $chart['grid']['x']['major']['max'] );
|
||||||
|
@ -291,17 +291,17 @@ if ( isset($minTime) && isset($maxTime) ) {
|
||||||
$eventsSql .= " and EndTime >= '$minTime' and StartTime <= '$maxTime'";
|
$eventsSql .= " and EndTime >= '$minTime' and StartTime <= '$maxTime'";
|
||||||
}
|
}
|
||||||
|
|
||||||
$eventsSql .= " order by Id asc";
|
$eventsSql .= ' order by Id asc';
|
||||||
//echo "ESQL: $eventsSql<br>";
|
//echo "ESQL: $eventsSql<br>";
|
||||||
|
|
||||||
$chart['data'] = array(
|
$chart['data'] = array(
|
||||||
"x" => array(
|
'x' => array(
|
||||||
"lo" => strtotime( $minTime ),
|
'lo' => strtotime( $minTime ),
|
||||||
"hi" => strtotime( $maxTime ),
|
'hi' => strtotime( $maxTime ),
|
||||||
),
|
),
|
||||||
"y" => array(
|
'y' => array(
|
||||||
"lo" => 0,
|
'lo' => 0,
|
||||||
"hi" => 0,
|
'hi' => 0,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -311,95 +311,105 @@ $chart['data']['x']['density'] = $chart['data']['x']['range']/$chart['graph']['w
|
||||||
$monEventSlots = array();
|
$monEventSlots = array();
|
||||||
$monFrameSlots = array();
|
$monFrameSlots = array();
|
||||||
$monitorIds = array();
|
$monitorIds = array();
|
||||||
foreach( dbFetchAll( $eventsSql ) as $event ) {
|
$events_result = dbQuery( $eventsSql );
|
||||||
if ( !isset($monitorIds[$event['MonitorId']]) )
|
if ( ! $events_result ) {
|
||||||
$monitorIds[$event['MonitorId']] = true;
|
Fatal( "SQL-ERR");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !isset($monEventSlots[$event['MonitorId']]) )
|
$first_event = $event = $events_result->fetch( PDO::FETCH_ASSOC );
|
||||||
$monEventSlots[$event['MonitorId']] = array();
|
if ( $event ) {
|
||||||
|
do {
|
||||||
|
|
||||||
if ( !isset($monFrameSlots[$event['MonitorId']]) )
|
if ( !isset($monitorIds[$event['MonitorId']]) )
|
||||||
$monFrameSlots[$event['MonitorId']] = array();
|
$monitorIds[$event['MonitorId']] = true;
|
||||||
|
|
||||||
$currEventSlots = &$monEventSlots[$event['MonitorId']];
|
if ( !isset($monEventSlots[$event['MonitorId']]) )
|
||||||
$currFrameSlots = &$monFrameSlots[$event['MonitorId']];
|
$monEventSlots[$event['MonitorId']] = array();
|
||||||
|
|
||||||
$startTimeT = strtotime($event['StartTime']);
|
if ( !isset($monFrameSlots[$event['MonitorId']]) )
|
||||||
$startIndex = $rawStartIndex = (int)(($startTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
$monFrameSlots[$event['MonitorId']] = array();
|
||||||
if ( $startIndex < 0 )
|
|
||||||
$startIndex = 0;
|
|
||||||
|
|
||||||
if ( isset($event['EndTime']) )
|
$currEventSlots = &$monEventSlots[$event['MonitorId']];
|
||||||
$endTimeT = strtotime($event['EndTime']);
|
$currFrameSlots = &$monFrameSlots[$event['MonitorId']];
|
||||||
else
|
|
||||||
$endTimeT = time();
|
|
||||||
$endIndex = $rawEndIndex = (int)(($endTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
|
||||||
|
|
||||||
if ( $endIndex >= $chart['graph']['width'] )
|
$startTimeT = strtotime($event['StartTime']);
|
||||||
$endIndex = $chart['graph']['width'] - 1;
|
$startIndex = $rawStartIndex = (int)(($startTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
||||||
|
if ( $startIndex < 0 )
|
||||||
|
$startIndex = 0;
|
||||||
|
|
||||||
for ( $i = $startIndex; $i <= $endIndex; $i++ ) {
|
if ( isset($event['EndTime']) )
|
||||||
if ( !isset($currEventSlots[$i]) ) {
|
$endTimeT = strtotime($event['EndTime']);
|
||||||
if ( $rawStartIndex == $rawEndIndex ) {
|
else
|
||||||
$offset = 1;
|
$endTimeT = time();
|
||||||
} else {
|
$endIndex = $rawEndIndex = (int)(($endTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
||||||
$offset = 1 + ($event['Frames']?((int)(($event['Frames']-1)*(($i-$rawStartIndex)/($rawEndIndex-$rawStartIndex)))):0);
|
|
||||||
}
|
|
||||||
$currEventSlots[$i] = array( "count"=>0, "width"=>1, "offset"=>$offset, "event"=>$event );
|
|
||||||
} else {
|
|
||||||
$currEventSlots[$i]['count']++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( $event['MaxScore'] > 0 ) {
|
|
||||||
if ( $startIndex == $endIndex ) {
|
|
||||||
$framesSql = 'SELECT FrameId,Score FROM Frames WHERE EventId = ? AND Score > 0 ORDER BY Score DESC LIMIT 1';
|
|
||||||
$frame = dbFetchOne( $framesSql, NULL, array($event['Id']) );
|
|
||||||
|
|
||||||
$i = $startIndex;
|
if ( $endIndex >= $chart['graph']['width'] )
|
||||||
if ( !isset($currFrameSlots[$i]) ) {
|
$endIndex = $chart['graph']['width'] - 1;
|
||||||
$currFrameSlots[$i] = array( 'count'=>1, 'value'=>$event['MaxScore'], 'event'=>$event, 'frame'=>$frame );
|
|
||||||
} else {
|
|
||||||
$currFrameSlots[$i]['count']++;
|
|
||||||
if ( $event['MaxScore'] > $currFrameSlots[$i]['value'] ) {
|
|
||||||
$currFrameSlots[$i]['value'] = $event['MaxScore'];
|
|
||||||
$currFrameSlots[$i]['event'] = $event;
|
|
||||||
$currFrameSlots[$i]['frame'] = $frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( $event['MaxScore'] > $chart['data']['y']['hi'] ) {
|
|
||||||
$chart['data']['y']['hi'] = $event['MaxScore'];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$framesSql = 'SELECT FrameId,Delta,unix_timestamp(TimeStamp) AS TimeT,Score FROM Frames WHERE EventId = ? AND Score > 0';
|
|
||||||
$result = dbQuery( $framesSql, array( $event['Id'] ) );
|
|
||||||
while( $frame = dbFetchNext( $result ) ) {
|
|
||||||
if ( $frame['Score'] == 0 )
|
|
||||||
continue;
|
|
||||||
$frameTimeT = $frame['TimeT'];
|
|
||||||
$frameTimeT = $startTimeT + $frame['Delta'];
|
|
||||||
$frameIndex = (int)(($frameTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
|
||||||
if ( $frameIndex < 0 )
|
|
||||||
continue;
|
|
||||||
if ( $frameIndex >= $chart['graph']['width'] )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( !isset($currFrameSlots[$frameIndex]) ) {
|
for ( $i = $startIndex; $i <= $endIndex; $i++ ) {
|
||||||
$currFrameSlots[$frameIndex] = array( 'count'=>1, 'value'=>$frame['Score'], 'event'=>$event, 'frame'=>$frame );
|
if ( !isset($currEventSlots[$i]) ) {
|
||||||
|
if ( $rawStartIndex == $rawEndIndex ) {
|
||||||
|
$offset = 1;
|
||||||
} else {
|
} else {
|
||||||
$currFrameSlots[$frameIndex]['count']++;
|
$offset = 1 + ($event['Frames']?((int)(($event['Frames']-1)*(($i-$rawStartIndex)/($rawEndIndex-$rawStartIndex)))):0);
|
||||||
if ( $frame['Score'] > $currFrameSlots[$frameIndex]['value'] ) {
|
}
|
||||||
$currFrameSlots[$frameIndex]['value'] = $frame['Score'];
|
$currEventSlots[$i] = array( 'count'=>0, 'width'=>1, 'offset'=>$offset, 'event'=>$event );
|
||||||
$currFrameSlots[$frameIndex]['event'] = $event;
|
} else {
|
||||||
$currFrameSlots[$frameIndex]['frame'] = $frame;
|
$currEventSlots[$i]['count']++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( $event['MaxScore'] > 0 ) {
|
||||||
|
if ( $startIndex == $endIndex ) {
|
||||||
|
$framesSql = 'SELECT FrameId,Score FROM Frames WHERE EventId = ? AND Score > 0 ORDER BY Score DESC LIMIT 1';
|
||||||
|
$frame = dbFetchOne( $framesSql, NULL, array($event['Id']) );
|
||||||
|
|
||||||
|
$i = $startIndex;
|
||||||
|
if ( !isset($currFrameSlots[$i]) ) {
|
||||||
|
$currFrameSlots[$i] = array( 'count'=>1, 'value'=>$event['MaxScore'], 'event'=>$event, 'frame'=>$frame );
|
||||||
|
} else {
|
||||||
|
$currFrameSlots[$i]['count']++;
|
||||||
|
if ( $event['MaxScore'] > $currFrameSlots[$i]['value'] ) {
|
||||||
|
$currFrameSlots[$i]['value'] = $event['MaxScore'];
|
||||||
|
$currFrameSlots[$i]['event'] = $event;
|
||||||
|
$currFrameSlots[$i]['frame'] = $frame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( $frame['Score'] > $chart['data']['y']['hi'] ) {
|
if ( $event['MaxScore'] > $chart['data']['y']['hi'] ) {
|
||||||
$chart['data']['y']['hi'] = $frame['Score'];
|
$chart['data']['y']['hi'] = $event['MaxScore'];
|
||||||
}
|
}
|
||||||
} // end foreach frame
|
} else {
|
||||||
}
|
$framesSql = 'SELECT FrameId,Delta,unix_timestamp(TimeStamp) AS TimeT,Score FROM Frames WHERE EventId = ? AND Score > 0';
|
||||||
} // end if MaxScore > 0
|
$result = dbQuery( $framesSql, array( $event['Id'] ) );
|
||||||
} // end foreach event
|
while( $frame = dbFetchNext( $result ) ) {
|
||||||
|
if ( $frame['Score'] == 0 )
|
||||||
|
continue;
|
||||||
|
$frameTimeT = $frame['TimeT'];
|
||||||
|
$frameTimeT = $startTimeT + $frame['Delta'];
|
||||||
|
$frameIndex = (int)(($frameTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
||||||
|
if ( $frameIndex < 0 )
|
||||||
|
continue;
|
||||||
|
if ( $frameIndex >= $chart['graph']['width'] )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( !isset($currFrameSlots[$frameIndex]) ) {
|
||||||
|
$currFrameSlots[$frameIndex] = array( 'count'=>1, 'value'=>$frame['Score'], 'event'=>$event, 'frame'=>$frame );
|
||||||
|
} else {
|
||||||
|
$currFrameSlots[$frameIndex]['count']++;
|
||||||
|
if ( $frame['Score'] > $currFrameSlots[$frameIndex]['value'] ) {
|
||||||
|
$currFrameSlots[$frameIndex]['value'] = $frame['Score'];
|
||||||
|
$currFrameSlots[$frameIndex]['event'] = $event;
|
||||||
|
$currFrameSlots[$frameIndex]['frame'] = $frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( $frame['Score'] > $chart['data']['y']['hi'] ) {
|
||||||
|
$chart['data']['y']['hi'] = $frame['Score'];
|
||||||
|
}
|
||||||
|
} // end foreach frame
|
||||||
|
}
|
||||||
|
} // end if MaxScore > 0
|
||||||
|
} while( $event = $events_result->fetch( PDO::FETCH_ASSOC ) );
|
||||||
|
} # end if have first event
|
||||||
|
|
||||||
ksort( $monitorIds, SORT_NUMERIC );
|
ksort( $monitorIds, SORT_NUMERIC );
|
||||||
ksort( $monEventSlots, SORT_NUMERIC );
|
ksort( $monEventSlots, SORT_NUMERIC );
|
||||||
|
@ -702,15 +712,17 @@ xhtmlHeaders(__FILE__, translate('Timeline') );
|
||||||
<div id="image" class="imageHeight">
|
<div id="image" class="imageHeight">
|
||||||
<img id="imageSrc" class="imageWidth" src="graphics/transparent.gif" alt="<?php echo translate('ViewEvent') ?>" title="<?php echo translate('ViewEvent') ?>"/>
|
<img id="imageSrc" class="imageWidth" src="graphics/transparent.gif" alt="<?php echo translate('ViewEvent') ?>" title="<?php echo translate('ViewEvent') ?>"/>
|
||||||
<?php
|
<?php
|
||||||
|
if ( 0 ) {
|
||||||
//due to chrome bug, has to enable https://code.google.com/p/chromium/issues/detail?id=472300
|
//due to chrome bug, has to enable https://code.google.com/p/chromium/issues/detail?id=472300
|
||||||
//crossorigin has to be added below to make caption work in chrome
|
//crossorigin has to be added below to make caption work in chrome
|
||||||
?>
|
?>
|
||||||
<!--
|
<!--
|
||||||
<video id="preview" width="100%" controls crossorigin="anonymous">
|
<video id="preview" width="100%" controls crossorigin="anonymous">
|
||||||
<source src="<?php echo getEventDefaultVideoPath($event); ?>" type="video/mp4">
|
<source src="<?php echo getEventDefaultVideoPath($first_event); ?>" type="video/mp4">
|
||||||
Your browser does not support the video tag.
|
Your browser does not support the video tag.
|
||||||
</video>
|
</video>
|
||||||
o-->
|
o-->
|
||||||
|
<?php } ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -807,16 +819,12 @@ foreach( array_keys($monEventSlots) as $monitorId ) {
|
||||||
<?php
|
<?php
|
||||||
unset( $currEventSlots );
|
unset( $currEventSlots );
|
||||||
$currEventSlots = &$monEventSlots[$monitorId];
|
$currEventSlots = &$monEventSlots[$monitorId];
|
||||||
$monitorMouseover = $mouseover;
|
|
||||||
if ($monitors[$monitorId]['SaveJPEGs'] == 2) {
|
|
||||||
$monitorMouseover = false;
|
|
||||||
}
|
|
||||||
for ( $i = 0; $i < $chart['graph']['width']; $i++ ) {
|
for ( $i = 0; $i < $chart['graph']['width']; $i++ ) {
|
||||||
if ( isset($currEventSlots[$i]) ) {
|
if ( isset($currEventSlots[$i]) ) {
|
||||||
unset( $slot );
|
unset( $slot );
|
||||||
$slot = &$currEventSlots[$i];
|
$slot = &$currEventSlots[$i];
|
||||||
|
|
||||||
if ( $monitorMouseover ) {
|
if ( $mouseover ) {
|
||||||
$behaviours = array(
|
$behaviours = array(
|
||||||
'onclick="'.getSlotShowEventBehaviour( $slot ).'"',
|
'onclick="'.getSlotShowEventBehaviour( $slot ).'"',
|
||||||
'onmouseover="'.getSlotPreviewEventBehaviour( $slot ).'"'
|
'onmouseover="'.getSlotPreviewEventBehaviour( $slot ).'"'
|
||||||
|
@ -854,6 +862,6 @@ foreach( array_keys($monEventSlots) as $monitorId ) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
|
<script src="skins/<?php echo $skin ?>/js/moment.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue