Merge branch 'master' of github.com:ZoneMinder/ZoneMinder

This commit is contained in:
Isaac Connor 2019-11-30 12:52:15 -05:00
commit ee6e732ef1
421 changed files with 25476 additions and 11055 deletions

View File

@ -21,8 +21,8 @@ In order to submit a bug report, please populate the fields below this line. Thi
**If the issue concerns a camera**
- Make and Model
- frame rate
- resolution
- Frame rate
- Resolution
- ZoneMinder Source Type:
**Describe the bug**

1
.github/stale.yml vendored
View File

@ -11,6 +11,7 @@ exemptLabels:
- "Under Review"
- "Bounty"
- "bug"
- "Feature"
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true

1
.gitignore vendored
View File

@ -157,3 +157,4 @@ web/undef.log
zm.conf
zmconfgen.pl
zmlinkcontent.sh
**/.DS_Store

View File

@ -1,6 +1,6 @@
language: cpp
sudo: required
dist: trusty
dist: xenial
git:
depth: 9999999
notifications:
@ -33,13 +33,23 @@ install:
env:
- SMPFLAGS=-j4 OS=el DIST=7
- SMPFLAGS=-j4 OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=fedora DIST=28 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=el DIST=8
- SMPFLAGS=-j4 OS=fedora DIST=29 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial
- SMPFLAGS=-j4 OS=fedora DIST=30
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=debian DIST=buster DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=disco ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=buster ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=stretch ARCH=i386
- SMPFLAGS=-j4 OS=raspbian DIST=stretch ARCH=armhf DOCKER_REPO=knnniggett/packpack
compiler:

View File

@ -166,6 +166,8 @@ set(ZM_DIR_SOUNDS "sounds" CACHE PATH
"Location to look for optional sound files, default: sounds")
set(ZM_PATH_ZMS "/cgi-bin/nph-zms" CACHE PATH
"Web url to zms streaming server, default: /cgi-bin/nph-zms")
set(ZM_PATH_SHUTDOWN "/sbin/shutdown" CACHE PATH
"Path to shutdown binary, default: /sbin/shutdown")
# Advanced
set(ZM_PATH_MAP "/dev/shm" CACHE PATH
@ -870,6 +872,13 @@ include(Pod2Man)
ADD_MANPAGE_TARGET()
# Process subdirectories
# build a bcrypt static library
set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(src/libbcrypt EXCLUDE_FROM_ALL)
set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
add_subdirectory(src)
add_subdirectory(scripts)
add_subdirectory(db)

View File

@ -3,7 +3,7 @@ ZoneMinder
[![Build Status](https://travis-ci.org/ZoneMinder/zoneminder.png)](https://travis-ci.org/ZoneMinder/zoneminder) [![Bountysource](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received)
[![Join Slack](https://github.com/ozonesecurity/ozonebase/blob/master/img/slacksm.png?raw=true)](https://join.slack.com/t/zoneminder-chat/shared_invite/enQtNTU0NDkxMDM5NDQwLTlhZDU2MGU4MmZmN2MxOTg1MmNmNmZjZGRmY2EzMThhNGQ0MWNmZTg1ZmYzNDQ4YjliMzVmYTQ3MDc5MTkzODE)
[![Join Slack](https://github.com/ozonesecurity/ozonebase/blob/master/img/slacksm.png?raw=true)](https://join.slack.com/t/zoneminder-chat/shared_invite/enQtNTU0NDkxMDM5NDQwLTdhZmQ5Y2M2NWQyN2JkYTBiN2ZkMzIzZGQ0MDliMTRmM2FjZWRlYzUwYTQ2MjMwMTVjMzQ1NjYxOTdmMjE2MTE)
All documentation for ZoneMinder is now online at https://zoneminder.readthedocs.org
@ -31,7 +31,7 @@ Better methods exist today that do much of this for you. The current development
This is the recommended method to install ZoneMinder onto your system. ZoneMinder packages are maintained for the following distros:
- Ubuntu via [Iconnor's PPA](https://launchpad.net/~iconnor/+archive/ubuntu/zoneminder)
- Ubuntu via [Iconnor's PPA](https://launchpad.net/~iconnor)
- Debian from their [default repository](https://packages.debian.org/search?searchon=names&keywords=zoneminder)
- RHEL/CentOS and clones via [RPM Fusion](http://rpmfusion.org)
- Fedora via [RPM Fusion](http://rpmfusion.org)

View File

@ -4,8 +4,8 @@ DROP TRIGGER IF EXISTS Events_Hour_delete_trigger//
CREATE TRIGGER Events_Hour_delete_trigger BEFORE DELETE ON Events_Hour
FOR EACH ROW BEGIN
UPDATE Monitors SET
HourEvents = COALESCE(HourEvents,1)-1,
HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0)
HourEvents = GREATEST(COALESCE(HourEvents,1)-1,0),
HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
@ -20,23 +20,21 @@ FOR EACH ROW
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)-COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
UPDATE Monitors SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
DELIMITER ;
delimiter //
DROP TRIGGER IF EXISTS Events_Day_delete_trigger//
CREATE TRIGGER Events_Day_delete_trigger BEFORE DELETE ON Events_Day
FOR EACH ROW BEGIN
UPDATE Monitors SET
DayEvents = COALESCE(DayEvents,1)-1,
DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0)
DayEvents = GREATEST(COALESCE(DayEvents,1)-1,0),
DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
@ -50,10 +48,10 @@ FOR EACH ROW
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId;
UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
@ -64,8 +62,8 @@ DROP TRIGGER IF EXISTS Events_Week_delete_trigger//
CREATE TRIGGER Events_Week_delete_trigger BEFORE DELETE ON Events_Week
FOR EACH ROW BEGIN
UPDATE Monitors SET
WeekEvents = COALESCE(WeekEvents,1)-1,
WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0)
WeekEvents = GREATEST(COALESCE(WeekEvents,1)-1,0),
WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
@ -79,10 +77,10 @@ FOR EACH ROW
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId;
UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
@ -92,8 +90,8 @@ DROP TRIGGER IF EXISTS Events_Month_delete_trigger//
CREATE TRIGGER Events_Month_delete_trigger BEFORE DELETE ON Events_Month
FOR EACH ROW BEGIN
UPDATE Monitors SET
MonthEvents = COALESCE(MonthEvents,1)-1,
MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0)
MonthEvents = GREATEST(COALESCE(MonthEvents,1)-1,0),
MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
@ -107,10 +105,10 @@ FOR EACH ROW
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId;
UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
@ -128,14 +126,14 @@ BEGIN
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( NEW.StorageId = OLD.StorageID ) THEN
IF ( diff ) THEN
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + diff WHERE Id = OLD.StorageId;
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Id = OLD.StorageId;
END IF;
ELSE
IF ( NEW.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Id = NEW.StorageId;
END IF;
IF ( OLD.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) - OLD.DiskSpace WHERE Id = OLD.StorageId;
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Id = OLD.StorageId;
END IF;
END IF;
@ -150,12 +148,16 @@ BEGIN
UPDATE Monitors SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Id=NEW.MonitorId;
ELSEIF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitors SET ArchivedEvents = COALESCE(ArchivedEvents,0)-1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) WHERE Id=OLD.MonitorId;
UPDATE Monitors
SET
ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0),
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
ELSE
IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Monitors SET
ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0)
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END IF;
@ -164,18 +166,18 @@ BEGIN
END IF;
IF ( diff ) THEN
UPDATE Monitors SET TotalEventDiskSpace = COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Id=OLD.MonitorId;
UPDATE Monitors
SET
TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END;
//
delimiter ;
DROP TRIGGER IF EXISTS event_insert_trigger//
DROP TRIGGER IF EXISTS event_insert_trigger;
delimiter //
/* The assumption is that when an Event is inserted, it has no size yet, so don't bother updating the DiskSpace, just the count.
* The DiskSpace will get update in the Event Update Trigger
*/
@ -203,7 +205,7 @@ CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events
FOR EACH ROW
BEGIN
IF ( OLD.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) - CAST(OLD.DiskSpace AS SIGNED) WHERE Id = OLD.StorageId;
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Id = OLD.StorageId;
END IF;
DELETE FROM Events_Hour WHERE EventId=OLD.Id;
DELETE FROM Events_Day WHERE EventId=OLD.Id;
@ -212,15 +214,15 @@ BEGIN
IF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitors SET
ArchivedEvents = COALESCE(ArchivedEvents,1) - 1,
ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),
TotalEvents = COALESCE(TotalEvents,1) - 1,
TotalEventDiskSpace = COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0)
ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,1) - 1,0),
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0),
TotalEvents = GREATEST(COALESCE(TotalEvents,1) - 1,0),
TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
ELSE
UPDATE Monitors SET
TotalEvents = COALESCE(TotalEvents,1)-1,
TotalEventDiskSpace=COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0)
TotalEvents = GREATEST(COALESCE(TotalEvents,1)-1,0),
TotalEventDiskSpace=GREATEST(COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END;

View File

@ -186,6 +186,7 @@ CREATE TABLE `Events` (
`Id` bigint unsigned NOT NULL auto_increment,
`MonitorId` int(10) unsigned NOT NULL default '0',
`StorageId` smallint(5) unsigned default 0,
`SecondaryStorageId` smallint(5) unsigned default 0,
`Name` varchar(64) NOT NULL default '',
`Cause` varchar(32) NOT NULL default '',
`StartTime` datetime default NULL,
@ -208,7 +209,7 @@ CREATE TABLE `Events` (
`Executed` tinyint(3) unsigned NOT NULL default '0',
`Notes` text,
`StateId` int(10) unsigned NOT NULL,
`Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0',
`Orientation` enum('ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT') NOT NULL default 'ROTATE_0',
`DiskSpace` bigint unsigned default NULL,
`Scheme` enum('Deep','Medium','Shallow') NOT NULL default 'Medium',
`Locked` BOOLEAN NOT NULL DEFAULT False,
@ -281,7 +282,7 @@ DROP TABLE IF EXISTS `Filters`;
CREATE TABLE `Filters` (
`Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '',
`Query` text NOT NULL,
`Query_json` text NOT NULL,
`AutoArchive` tinyint(3) unsigned NOT NULL default '0',
`AutoVideo` tinyint(3) unsigned NOT NULL default '0',
`AutoUpload` tinyint(3) unsigned NOT NULL default '0',
@ -292,6 +293,8 @@ CREATE TABLE `Filters` (
`AutoDelete` tinyint(3) unsigned NOT NULL default '0',
`AutoMove` tinyint(3) unsigned NOT NULL default '0',
`AutoMoveTo` smallint(5) unsigned NOT NULL default 0,
`AutoCopy` tinyint(3) unsigned NOT NULL default '0',
`AutoCopyTo` smallint(5) unsigned NOT NULL default 0,
`UpdateDiskSpace` tinyint(3) unsigned NOT NULL default '0',
`Background` tinyint(1) unsigned NOT NULL default '0',
`Concurrent` tinyint(1) unsigned NOT NULL default '0',
@ -351,6 +354,7 @@ CREATE INDEX `Groups_Monitors_MonitorId_idx` ON `Groups_Monitors` (`MonitorId`);
DROP TABLE IF EXISTS `Logs`;
CREATE TABLE `Logs` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`TimeKey` decimal(16,6) NOT NULL,
`Component` varchar(32) NOT NULL,
`ServerId` int(10) unsigned,
@ -360,6 +364,7 @@ CREATE TABLE `Logs` (
`Message` text NOT NULL,
`File` varchar(255) DEFAULT NULL,
`Line` smallint(5) unsigned DEFAULT NULL,
PRIMARY KEY (`Id`),
KEY `TimeKey` (`TimeKey`)
) ENGINE=@ZM_MYSQL_ENGINE@;
@ -411,7 +416,7 @@ CREATE TABLE `MonitorPresets` (
`Width` smallint(5) unsigned default NULL,
`Height` smallint(5) unsigned default NULL,
`Palette` int(10) unsigned default NULL,
`MaxFPS` decimal(5,2) default NULL,
`MaxFPS` decimal(5,3) default NULL,
`Controllable` tinyint(3) unsigned NOT NULL default '0',
`ControlId` varchar(16) default NULL,
`ControlDevice` varchar(255) default NULL,
@ -454,8 +459,10 @@ CREATE TABLE `Monitors` (
`Height` smallint(5) unsigned NOT NULL default '0',
`Colours` tinyint(3) unsigned NOT NULL default '1',
`Palette` int(10) unsigned NOT NULL default '0',
`Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0',
`Orientation` enum('ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT') NOT NULL default 'ROTATE_0',
`Deinterlacing` int(10) unsigned NOT NULL default '0',
`DecoderHWAccelName` varchar(64),
`DecoderHWAccelDevice` varchar(255),
`SaveJPEGs` TINYINT NOT NULL DEFAULT '3' ,
`VideoWriter` TINYINT NOT NULL DEFAULT '0',
`OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2'),
@ -479,6 +486,7 @@ CREATE TABLE `Monitors` (
`StreamReplayBuffer` int(10) unsigned NOT NULL default '1000',
`AlarmFrameCount` smallint(5) unsigned NOT NULL default '1',
`SectionLength` int(10) unsigned NOT NULL default '600',
`MinSectionLength` int(10) unsigned NOT NULL default '10',
`FrameSkip` smallint(5) unsigned NOT NULL default '0',
`MotionFrameSkip` smallint(5) unsigned NOT NULL default '0',
`AnalysisFPSLimit` decimal(5,2) default NULL,
@ -586,6 +594,7 @@ CREATE INDEX `Servers_Name_idx` ON `Servers` (`Name`);
DROP TABLE IF EXISTS `Stats`;
CREATE TABLE `Stats` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`MonitorId` int(10) unsigned NOT NULL default '0',
`ZoneId` int(10) unsigned NOT NULL default '0',
`EventId` BIGINT UNSIGNED NOT NULL,
@ -602,6 +611,7 @@ CREATE TABLE `Stats` (
`MinY` smallint(5) unsigned NOT NULL default '0',
`MaxY` smallint(5) unsigned NOT NULL default '0',
`Score` smallint(5) unsigned NOT NULL default '0',
PRIMARY KEY (`Id`),
KEY `EventId` (`EventId`),
KEY `MonitorId` (`MonitorId`),
KEY `ZoneId` (`ZoneId`)
@ -640,6 +650,8 @@ CREATE TABLE `Users` (
`System` enum('None','View','Edit') NOT NULL default 'None',
`MaxBandwidth` varchar(16),
`MonitorIds` text,
`TokenMinExpiry` BIGINT UNSIGNED NOT NULL DEFAULT 0,
`APIEnabled` tinyint(3) UNSIGNED NOT NULL default 1,
PRIMARY KEY (`Id`),
UNIQUE KEY `UC_Username` (`Username`)
) ENGINE=@ZM_MYSQL_ENGINE@;
@ -740,14 +752,24 @@ insert into Storage VALUES (NULL, '@ZM_DIR_EVENTS@', 'Default', 'local', NULL, N
--
-- Create a default admin user.
--
insert into Users VALUES (NULL,'admin',password('admin'),'',1,'View','Edit','Edit','Edit','Edit','Edit','Edit','','');
insert into Users VALUES (NULL,'admin','$2b$12$NHZsm6AM2f2LQVROriz79ul3D6DnmFiZC.ZK5eqbF.ZWfwH9bqUJ6','',1,'View','Edit','Edit','Edit','Edit','Edit','Edit','','',0,1);
--
-- Add a sample filter to purge the oldest 100 events when the disk is 95% full
--
insert into Filters values (NULL,'PurgeWhenFull','{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}',0/*AutoArchive*/,0/*AutoVideo*/,0/*AutoUpload*/,0/*AutoEmail*/,0/*AutoMessage*/,0/*AutoExecute*/,'',1/*AutoDelete*/,0/*AutoMove*/,0/*MoveTo*/,0/*UpdateDiskSpace*/,1/*Background*/,0/*Concurrent*/);
insert into Filters values (NULL,'Update DiskSpace','{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"}]}',0,0,0,0,0,0,'',0,0,0,1,1,0);
insert into Filters values (NULL,'PurgeWhenFull','{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}',
0/*AutoArchive*/,
0/*AutoVideo*/,
0/*AutoUpload*/,
0/*AutoEmail*/,
0/*AutoMessage*/,
0/*AutoExecute*/,'',
1/*AutoDelete*/,
0/*AutoMove*/,0/*MoveTo*/,
0/*AutoCopy*/,0/*CopyTo*/,
0/*UpdateDiskSpace*/,1/*Background*/,0/*Concurrent*/);
insert into Filters values (NULL,'Update DiskSpace','{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"}]}',0,0,0,0,0,0,'',0,0,0,0,0,1,1,0);
--
-- Add in some sample control protocol definitions
@ -789,7 +811,7 @@ INSERT INTO `Controls` VALUES (NULL,'IOS Camera','Ffmpeg','IPCAMIOS',0,0,0,0,0,0
INSERT INTO `Controls` VALUES (NULL,'Dericam P2','Ffmpeg','DericamP2',0,1,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,0,1,10,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,45,0,0,1,0,0,0,0,1,1,45,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Trendnet','Remote','Trendnet',1,1,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,0,0,0,0,0,1,1,1,0,1,0,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,'PSIA','Remote','PSIA',0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,100,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,0,1,1,1,0,0,1,0,1,0,0,0,0,1,-100,100,0,0,1,0,0,0,0,1,-100,100,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Dahua','Remote','Dahua',0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,8,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,0,1,1,1,0,0,1,0,1,0,0,0,0,1,1,8,0,0,1,0,0,0,0,1,1,8,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Dahua','Ffmpeg','Dahua',0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,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,1,20,1,1,1,1,0,0,1,0,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,'FOSCAMR2C','Libvlc','FOSCAMR2C',1,1,1,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,12,0,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,4,0,NULL,1,NULL,NULL,NULL,NULL,1,0,4,0,NULL,0,0);
INSERT INTO `Controls` VALUES (NULL,'Amcrest HTTP API','Ffmpeg','Amcrest_HTTP',0,0,1,0,1,0,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,1,5,0,0,1,0,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,5);

12
db/zm_update-1.33.10.sql Normal file
View File

@ -0,0 +1,12 @@
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'MinSectionLength'
) > 0,
"SELECT 'Column MinSectionLength already exists in Monitors'",
"ALTER TABLE Monitors ADD `MinSectionLength` int(10) unsigned NOT NULL default '10' AFTER SectionLength"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

24
db/zm_update-1.33.11.sql Normal file
View File

@ -0,0 +1,24 @@
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'DecoderHWAccelName'
) > 0,
"SELECT 'Column DecoderHWAccelName already exists in Monitors'",
"ALTER TABLE Monitors ADD `DecoderHWAccelName` varchar(64) AFTER `Deinterlacing`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'DecoderHWAccelDevice'
) > 0,
"SELECT 'Column DecoderHWAccelDevice already exists in Monitors'",
"ALTER TABLE Monitors ADD `DecoderHWAccelDevice` varchar(255) AFTER `DecoderHWAccelName`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

27
db/zm_update-1.33.12.sql Normal file
View File

@ -0,0 +1,27 @@
--
-- Add primary keys for Logs and Stats tables
--
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Logs'
AND column_name = 'Id'
) > 0,
"SELECT 'Column Id already exists in Logs'",
"ALTER TABLE `Logs` ADD COLUMN `Id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`Id`)"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Stats'
AND column_name = 'Id'
) > 0,
"SELECT 'Column Id already exists in Stats'",
"ALTER TABLE `Stats` ADD COLUMN `Id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`Id`)"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

6
db/zm_update-1.33.13.sql Normal file
View File

@ -0,0 +1,6 @@
--
-- Add primary keys for Logs and Stats tables
--
SELECT "Modifying Monitors MaxFPS to DECIMAL(5,3)";
ALTER TABLE `Monitors` MODIFY `MaxFPS` decimal(5,3) default NULL;

51
db/zm_update-1.33.14.sql Normal file
View File

@ -0,0 +1,51 @@
--
-- Add CopyTo action to Filters
--
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Filters'
AND column_name = 'AutoCopy'
) > 0,
"SELECT 'Column AutoCopy already exists in Filters'",
"ALTER TABLE Filters ADD `AutoCopy` tinyint(3) unsigned NOT NULL default '0' AFTER `AutoMove`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Filters'
AND column_name = 'AutoCopyTo'
) > 0,
"SELECT 'Column AutoCopyTo already exists in Filters'",
"ALTER TABLE Filters ADD `AutoCopyTo` smallint(5) unsigned NOT NULL default '0' AFTER `AutoCopy`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Filters'
AND column_name = 'Query_json'
) > 0,
"SELECT 'Column Query_json already exists in Filters'",
"ALTER TABLE `Filters` Change `Query` `Query_json` text NOT NULL"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Events'
AND column_name = 'SecondaryStorageId'
) > 0,
"SELECT 'Column SecondaryStorageId already exists in Events'",
"ALTER TABLE `Events` ADD `SecondaryStorageId` smallint(5) unsigned default 0 AFTER `StorageId`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

19
db/zm_update-1.33.15.sql Normal file
View File

@ -0,0 +1,19 @@
ALTER TABLE Events MODIFY `Orientation` enum('0','90','180','270','hori','vert','ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT') NOT NULL default 'ROTATE_0';
UPDATE Events SET Orientation='ROTATE_0' WHERE Orientation='0';
UPDATE Events SET Orientation='ROTATE_90' WHERE Orientation='90';
UPDATE Events SET Orientation='ROTATE_180' WHERE Orientation='180';
UPDATE Events SET Orientation='ROTATE_270' WHERE Orientation='270';
UPDATE Events SET Orientation='FLIP_HORI' WHERE Orientation='hori';
UPDATE Events SET Orientation='FLIP_VERT' WHERE Orientation='vert';
ALTER TABLE Events MODIFY `Orientation` enum('ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT') NOT NULL default 'ROTATE_0';
ALTER TABLE Monitors MODIFY `Orientation` enum('0','90','180','270','hori','vert','ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT') NOT NULL default 'ROTATE_0';
UPDATE Monitors SET Orientation='ROTATE_0' WHERE Orientation='0';
UPDATE Monitors SET Orientation='ROTATE_90' WHERE Orientation='90';
UPDATE Monitors SET Orientation='ROTATE_180' WHERE Orientation='180';
UPDATE Monitors SET Orientation='ROTATE_270' WHERE Orientation='270';
UPDATE Monitors SET Orientation='FLIP_HORI' WHERE Orientation='hori';
UPDATE Monitors SET Orientation='FLIP_VERT' WHERE Orientation='vert';
ALTER TABLE Monitors MODIFY `Orientation` enum('ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT') NOT NULL default 'ROTATE_0';

283
db/zm_update-1.33.7.sql Normal file
View File

@ -0,0 +1,283 @@
delimiter //
DROP TRIGGER IF EXISTS Events_Hour_delete_trigger//
CREATE TRIGGER Events_Hour_delete_trigger BEFORE DELETE ON Events_Hour
FOR EACH ROW BEGIN
UPDATE Monitors SET
HourEvents = COALESCE(HourEvents,1)-1,
HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
DROP TRIGGER IF EXISTS Events_Hour_update_trigger//
CREATE TRIGGER Events_Hour_update_trigger AFTER UPDATE ON Events_Hour
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
DROP TRIGGER IF EXISTS Events_Day_delete_trigger//
CREATE TRIGGER Events_Day_delete_trigger BEFORE DELETE ON Events_Day
FOR EACH ROW BEGIN
UPDATE Monitors SET
DayEvents = GREATEST(COALESCE(DayEvents,1)-1,0),
DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
DROP TRIGGER IF EXISTS Events_Day_update_trigger;
CREATE TRIGGER Events_Day_update_trigger AFTER UPDATE ON Events_Day
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
DROP TRIGGER IF EXISTS Events_Week_delete_trigger//
CREATE TRIGGER Events_Week_delete_trigger BEFORE DELETE ON Events_Week
FOR EACH ROW BEGIN
UPDATE Monitors SET
WeekEvents = COALESCE(WeekEvents,1)-1,
WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
DROP TRIGGER IF EXISTS Events_Week_update_trigger;
CREATE TRIGGER Events_Week_update_trigger AFTER UPDATE ON Events_Week
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
DROP TRIGGER IF EXISTS Events_Month_delete_trigger//
CREATE TRIGGER Events_Month_delete_trigger BEFORE DELETE ON Events_Month
FOR EACH ROW BEGIN
UPDATE Monitors SET
MonthEvents = COALESCE(MonthEvents,1)-1,
MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
DROP TRIGGER IF EXISTS Events_Month_update_trigger;
CREATE TRIGGER Events_Month_update_trigger AFTER UPDATE ON Events_Month
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
drop procedure if exists update_storage_stats//
drop trigger if exists event_update_trigger//
CREATE TRIGGER event_update_trigger AFTER UPDATE ON Events
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( NEW.StorageId = OLD.StorageID ) THEN
IF ( diff ) THEN
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Id = OLD.StorageId;
END IF;
ELSE
IF ( NEW.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Id = NEW.StorageId;
END IF;
IF ( OLD.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Id = OLD.StorageId;
END IF;
END IF;
UPDATE Events_Hour SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Events_Day SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Events_Week SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Events_Month SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
IF ( NEW.Archived != OLD.Archived ) THEN
IF ( NEW.Archived ) THEN
INSERT INTO Events_Archived (EventId,MonitorId,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.DiskSpace);
UPDATE Monitors SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Id=NEW.MonitorId;
ELSEIF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitors
SET
ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0),
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
ELSE
IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Monitors SET
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END IF;
ELSEIF ( NEW.Archived AND diff ) THEN
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
END IF;
IF ( diff ) THEN
UPDATE Monitors
SET
TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END;
//
DROP TRIGGER IF EXISTS event_insert_trigger//
/* The assumption is that when an Event is inserted, it has no size yet, so don't bother updating the DiskSpace, just the count.
* The DiskSpace will get update in the Event Update Trigger
*/
CREATE TRIGGER event_insert_trigger AFTER INSERT ON Events
FOR EACH ROW
BEGIN
INSERT INTO Events_Hour (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0);
INSERT INTO Events_Day (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0);
INSERT INTO Events_Week (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0);
INSERT INTO Events_Month (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0);
UPDATE Monitors SET
HourEvents = COALESCE(HourEvents,0)+1,
DayEvents = COALESCE(DayEvents,0)+1,
WeekEvents = COALESCE(WeekEvents,0)+1,
MonthEvents = COALESCE(MonthEvents,0)+1,
TotalEvents = COALESCE(TotalEvents,0)+1
WHERE Id=NEW.MonitorId;
END;
//
DROP TRIGGER IF EXISTS event_delete_trigger//
CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events
FOR EACH ROW
BEGIN
IF ( OLD.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Id = OLD.StorageId;
END IF;
DELETE FROM Events_Hour WHERE EventId=OLD.Id;
DELETE FROM Events_Day WHERE EventId=OLD.Id;
DELETE FROM Events_Week WHERE EventId=OLD.Id;
DELETE FROM Events_Month WHERE EventId=OLD.Id;
IF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitors SET
ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,1) - 1,0),
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0),
TotalEvents = GREATEST(COALESCE(TotalEvents,1) - 1,0),
TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
ELSE
UPDATE Monitors SET
TotalEvents = GREATEST(COALESCE(TotalEvents,1)-1,0),
TotalEventDiskSpace=GREATEST(COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END;
//
DROP TRIGGER IF EXISTS Zone_Insert_Trigger//
CREATE TRIGGER Zone_Insert_Trigger AFTER INSERT ON Zones
FOR EACH ROW
BEGIN
UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Id=NEW.MonitorID;
END
//
DROP TRIGGER IF EXISTS Zone_Delete_Trigger//
CREATE TRIGGER Zone_Delete_Trigger AFTER DELETE ON Zones
FOR EACH ROW
BEGIN
UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Id=OLD.MonitorID;
END
//
DELIMITER ;
REPLACE INTO Events_Hour SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 hour);
REPLACE INTO Events_Day SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 day);
REPLACE INTO Events_Week SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 week);
REPLACE INTO Events_Month SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 month);
REPLACE INTO Events_Archived SELECT Id,MonitorId,DiskSpace FROM Events WHERE Archived=1;
UPDATE Monitors INNER JOIN (
SELECT MonitorId,
COUNT(Id) AS TotalEvents,
SUM(DiskSpace) AS TotalEventDiskSpace,
SUM(IF(Archived,1,0)) AS ArchivedEvents,
SUM(IF(Archived,DiskSpace,0)) AS ArchivedEventDiskSpace,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 hour),1,0)) AS HourEvents,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 hour),DiskSpace,0)) AS HourEventDiskSpace,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 day),1,0)) AS DayEvents,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 day),DiskSpace,0)) AS DayEventDiskSpace,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 week),1,0)) AS WeekEvents,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 week),DiskSpace,0)) AS WeekEventDiskSpace,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 month),1,0)) AS MonthEvents,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 month),DiskSpace,0)) AS MonthEventDiskSpace
FROM Events GROUP BY MonitorId
) AS E ON E.MonitorId=Monitors.Id SET
Monitors.TotalEvents = E.TotalEvents,
Monitors.TotalEventDiskSpace = E.TotalEventDiskSpace,
Monitors.ArchivedEvents = E.ArchivedEvents,
Monitors.ArchivedEventDiskSpace = E.ArchivedEventDiskSpace,
Monitors.HourEvents = E.HourEvents,
Monitors.HourEventDiskSpace = E.HourEventDiskSpace,
Monitors.DayEvents = E.DayEvents,
Monitors.DayEventDiskSpace = E.DayEventDiskSpace,
Monitors.WeekEvents = E.WeekEvents,
Monitors.WeekEventDiskSpace = E.WeekEventDiskSpace,
Monitors.MonthEvents = E.MonthEvents,
Monitors.MonthEventDiskSpace = E.MonthEventDiskSpace;

283
db/zm_update-1.33.8.sql Normal file
View File

@ -0,0 +1,283 @@
delimiter //
DROP TRIGGER IF EXISTS Events_Hour_delete_trigger//
CREATE TRIGGER Events_Hour_delete_trigger BEFORE DELETE ON Events_Hour
FOR EACH ROW BEGIN
UPDATE Monitors SET
HourEvents = GREATEST(COALESCE(HourEvents,1)-1,0),
HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
DROP TRIGGER IF EXISTS Events_Hour_update_trigger//
CREATE TRIGGER Events_Hour_update_trigger AFTER UPDATE ON Events_Hour
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
DROP TRIGGER IF EXISTS Events_Day_delete_trigger//
CREATE TRIGGER Events_Day_delete_trigger BEFORE DELETE ON Events_Day
FOR EACH ROW BEGIN
UPDATE Monitors SET
DayEvents = GREATEST(COALESCE(DayEvents,1)-1,0),
DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
DROP TRIGGER IF EXISTS Events_Day_update_trigger;
CREATE TRIGGER Events_Day_update_trigger AFTER UPDATE ON Events_Day
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
DROP TRIGGER IF EXISTS Events_Week_delete_trigger//
CREATE TRIGGER Events_Week_delete_trigger BEFORE DELETE ON Events_Week
FOR EACH ROW BEGIN
UPDATE Monitors SET
WeekEvents = GREATEST(COALESCE(WeekEvents,1)-1,0),
WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
DROP TRIGGER IF EXISTS Events_Week_update_trigger;
CREATE TRIGGER Events_Week_update_trigger AFTER UPDATE ON Events_Week
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
DROP TRIGGER IF EXISTS Events_Month_delete_trigger//
CREATE TRIGGER Events_Month_delete_trigger BEFORE DELETE ON Events_Month
FOR EACH ROW BEGIN
UPDATE Monitors SET
MonthEvents = GREATEST(COALESCE(MonthEvents,1)-1,0),
MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END;
//
DROP TRIGGER IF EXISTS Events_Month_update_trigger;
CREATE TRIGGER Events_Month_update_trigger AFTER UPDATE ON Events_Month
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( diff ) THEN
IF ( NEW.MonitorID != OLD.MonitorID ) THEN
UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitors.Id=OLD.MonitorId;
UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitors.Id=NEW.MonitorId;
ELSE
UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
END IF;
END IF;
END;
//
drop procedure if exists update_storage_stats//
drop trigger if exists event_update_trigger//
CREATE TRIGGER event_update_trigger AFTER UPDATE ON Events
FOR EACH ROW
BEGIN
declare diff BIGINT default 0;
set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0);
IF ( NEW.StorageId = OLD.StorageID ) THEN
IF ( diff ) THEN
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Id = OLD.StorageId;
END IF;
ELSE
IF ( NEW.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Id = NEW.StorageId;
END IF;
IF ( OLD.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Id = OLD.StorageId;
END IF;
END IF;
UPDATE Events_Hour SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Events_Day SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Events_Week SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Events_Month SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
IF ( NEW.Archived != OLD.Archived ) THEN
IF ( NEW.Archived ) THEN
INSERT INTO Events_Archived (EventId,MonitorId,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.DiskSpace);
UPDATE Monitors SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Id=NEW.MonitorId;
ELSEIF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitors
SET
ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0),
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
ELSE
IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Monitors SET
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END IF;
ELSEIF ( NEW.Archived AND diff ) THEN
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
END IF;
IF ( diff ) THEN
UPDATE Monitors
SET
TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END;
//
DROP TRIGGER IF EXISTS event_insert_trigger//
/* The assumption is that when an Event is inserted, it has no size yet, so don't bother updating the DiskSpace, just the count.
* The DiskSpace will get update in the Event Update Trigger
*/
CREATE TRIGGER event_insert_trigger AFTER INSERT ON Events
FOR EACH ROW
BEGIN
INSERT INTO Events_Hour (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0);
INSERT INTO Events_Day (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0);
INSERT INTO Events_Week (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0);
INSERT INTO Events_Month (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0);
UPDATE Monitors SET
HourEvents = COALESCE(HourEvents,0)+1,
DayEvents = COALESCE(DayEvents,0)+1,
WeekEvents = COALESCE(WeekEvents,0)+1,
MonthEvents = COALESCE(MonthEvents,0)+1,
TotalEvents = COALESCE(TotalEvents,0)+1
WHERE Id=NEW.MonitorId;
END;
//
DROP TRIGGER IF EXISTS event_delete_trigger//
CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events
FOR EACH ROW
BEGIN
IF ( OLD.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Id = OLD.StorageId;
END IF;
DELETE FROM Events_Hour WHERE EventId=OLD.Id;
DELETE FROM Events_Day WHERE EventId=OLD.Id;
DELETE FROM Events_Week WHERE EventId=OLD.Id;
DELETE FROM Events_Month WHERE EventId=OLD.Id;
IF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitors SET
ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,1) - 1,0),
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0),
TotalEvents = GREATEST(COALESCE(TotalEvents,1) - 1,0),
TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
ELSE
UPDATE Monitors SET
TotalEvents = GREATEST(COALESCE(TotalEvents,1)-1,0),
TotalEventDiskSpace=GREATEST(COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
END IF;
END;
//
DROP TRIGGER IF EXISTS Zone_Insert_Trigger//
CREATE TRIGGER Zone_Insert_Trigger AFTER INSERT ON Zones
FOR EACH ROW
BEGIN
UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Id=NEW.MonitorID;
END
//
DROP TRIGGER IF EXISTS Zone_Delete_Trigger//
CREATE TRIGGER Zone_Delete_Trigger AFTER DELETE ON Zones
FOR EACH ROW
BEGIN
UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Id=OLD.MonitorID;
END
//
DELIMITER ;
REPLACE INTO Events_Hour SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 hour);
REPLACE INTO Events_Day SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 day);
REPLACE INTO Events_Week SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 week);
REPLACE INTO Events_Month SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 month);
REPLACE INTO Events_Archived SELECT Id,MonitorId,DiskSpace FROM Events WHERE Archived=1;
UPDATE Monitors INNER JOIN (
SELECT MonitorId,
COUNT(Id) AS TotalEvents,
SUM(DiskSpace) AS TotalEventDiskSpace,
SUM(IF(Archived,1,0)) AS ArchivedEvents,
SUM(IF(Archived,DiskSpace,0)) AS ArchivedEventDiskSpace,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 hour),1,0)) AS HourEvents,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 hour),DiskSpace,0)) AS HourEventDiskSpace,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 day),1,0)) AS DayEvents,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 day),DiskSpace,0)) AS DayEventDiskSpace,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 week),1,0)) AS WeekEvents,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 week),DiskSpace,0)) AS WeekEventDiskSpace,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 month),1,0)) AS MonthEvents,
SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 month),DiskSpace,0)) AS MonthEventDiskSpace
FROM Events GROUP BY MonitorId
) AS E ON E.MonitorId=Monitors.Id SET
Monitors.TotalEvents = E.TotalEvents,
Monitors.TotalEventDiskSpace = E.TotalEventDiskSpace,
Monitors.ArchivedEvents = E.ArchivedEvents,
Monitors.ArchivedEventDiskSpace = E.ArchivedEventDiskSpace,
Monitors.HourEvents = E.HourEvents,
Monitors.HourEventDiskSpace = E.HourEventDiskSpace,
Monitors.DayEvents = E.DayEvents,
Monitors.DayEventDiskSpace = E.DayEventDiskSpace,
Monitors.WeekEvents = E.WeekEvents,
Monitors.WeekEventDiskSpace = E.WeekEventDiskSpace,
Monitors.MonthEvents = E.MonthEvents,
Monitors.MonthEventDiskSpace = E.MonthEventDiskSpace;

27
db/zm_update-1.33.9.sql Normal file
View File

@ -0,0 +1,27 @@
--
-- Add per user API enable/disable and ability to set a minimum issued time for tokens
--
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Users'
AND column_name = 'TokenMinExpiry'
) > 0,
"SELECT 'Column TokenMinExpiry already exists in Users'",
"ALTER TABLE Users ADD `TokenMinExpiry` BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER `MonitorIds`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Users'
AND column_name = 'APIEnabled'
) > 0,
"SELECT 'Column APIEnabled already exists in Users'",
"ALTER TABLE Users ADD `APIEnabled` tinyint(3) UNSIGNED NOT NULL default 1 AFTER `TokenMinExpiry`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -21,11 +21,13 @@ Build-Depends: debhelper (>= 9), cmake
, libphp-serialization-perl
, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, libdbd-mysql-perl
, libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl
, libmodule-load-perl, libsys-mmap-perl, libjson-any-perl
, libmodule-load-perl, libsys-mmap-perl, libjson-maybexs-perl
, libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl
, libdata-dump-perl, libclass-std-fast-perl, libsoap-wsdl-perl, libio-socket-multicast-perl, libdigest-sha-perl
, libsys-cpu-perl, libsys-meminfo-perl
, libdata-uuid-perl
, libssl-dev
, libcrypt-eksblowfish-perl, libdata-entropy-perl
Standards-Version: 3.9.4
Package: zoneminder
@ -37,7 +39,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
, libphp-serialization-perl
, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, libdbd-mysql-perl
, libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl
, libmodule-load-perl, libsys-mmap-perl, libjson-any-perl, libjson-maybexs-perl
, libmodule-load-perl, libsys-mmap-perl, libjson-maybexs-perl
, libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl
, libdata-dump-perl, libclass-std-fast-perl, libsoap-wsdl-perl, libio-socket-multicast-perl, libdigest-sha-perl
, libsys-cpu-perl, libsys-meminfo-perl
@ -51,6 +53,9 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
, zip
, libvlccore5 | libvlccore7 | libvlccore8, libvlc5
, libpolkit-gobject-1-0, php5-gd
, libssl
,libcrypt-eksblowfish-perl, libdata-entropy-perl
Recommends: mysql-server | mariadb-server
Description: Video camera security and surveillance solution
ZoneMinder is intended for use in single or multi-camera video security

View File

@ -31,6 +31,10 @@ if [ "$1" = "configure" ]; then
# test if database if already present...
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
if [ $? -ne 0 ]; then
echo "Error creating db."
exit 1;
fi
# This creates the user.
echo "grant lock tables, alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else

View File

@ -24,6 +24,7 @@ override_dh_auto_configure:
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_CONFIG_DIR="/etc/zm" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_PATH_SHUTDOWN="/sbin/shutdown" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
override_dh_auto_install:

View File

@ -23,7 +23,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.33.6
Version: 1.33.14
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@ -73,6 +73,7 @@ BuildRequires: libcurl-devel
BuildRequires: libv4l-devel
BuildRequires: desktop-file-utils
BuildRequires: gzip
BuildRequires: zlib-devel
# ZoneMinder looks for and records the location of the ffmpeg binary during build
BuildRequires: ffmpeg
@ -410,6 +411,18 @@ EOF
%dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload
%changelog
* Sun Aug 11 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.14-1
- Bump to 1.33.13 Development
* Sun Jul 07 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.12-1
- Bump to 1.33.12 Development
* Sun Jun 23 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.9-1
- Bump to 1.33.9 Development
* Tue Apr 30 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.8-1
- Bump to 1.33.8 Development
* Sun Apr 07 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.6-1
- Bump to 1.33.6 Development

View File

@ -1,12 +1,13 @@
Source: zoneminder
Section: net
Priority: optional
Maintainer: Dmitry Smirnov <onlyjob@debian.org>
Uploaders: Vagrant Cascadian <vagrant@debian.org>
Maintainer: Isaac Connor <isaac@zoneminder.com>
Uploaders: Isaac Connor <isaac@zoneminder.com>
Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh-linktree
,cmake
,libx264-dev, libmp4v2-dev
,libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libavdevice-dev
,libavresample-dev
,libbz2-dev
,libgcrypt-dev
,libcurl4-gnutls-dev
@ -23,6 +24,9 @@ Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh
,libsys-mmap-perl [!hurd-any]
,libwww-perl
,libdata-uuid-perl
,libssl-dev
,libcrypt-eksblowfish-perl
,libdata-entropy-perl
# Unbundled (dh_linktree):
,libjs-jquery
,libjs-mootools
@ -49,11 +53,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libdbd-mysql-perl
,libdevice-serialport-perl
,libimage-info-perl
,libjson-any-perl
,libjson-maybexs-perl
,libsys-mmap-perl [!hurd-any]
,liburi-encode-perl
,libwww-perl
,libdatetime-perl
,libdata-uuid-perl
,libnumber-bytes-human-perl
,libfile-slurp-perl
@ -63,8 +67,12 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,policykit-1
,rsyslog | system-log-daemon
,zip
,libdata-dump-perl, libclass-std-fast-perl, libsoap-wsdl-perl, libio-socket-multicast-perl, libdigest-sha-perl
,libdata-dump-perl, libclass-std-fast-perl, libsoap-wsdl-perl
,libio-socket-multicast-perl, libdigest-sha-perl
,libsys-cpu-perl, libsys-meminfo-perl
,libssl | libssl1.0.0
,libcrypt-eksblowfish-perl
,libdata-entropy-perl
Recommends: ${misc:Recommends}
,libapache2-mod-php5 | php5-fpm
,mysql-server | virtual-mysql-server
@ -91,7 +99,7 @@ Description: video camera security and surveillance solution
# ,libdbd-mysql-perl
# ,libdevice-serialport-perl
# ,libimage-info-perl
# ,libjson-any-perl
# ,libjson-maybexs-perl
# ,libsys-mmap-perl [!hurd-any]
# ,liburi-encode-perl
# ,libwww-perl

View File

@ -27,6 +27,7 @@ override_dh_auto_configure:
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_CACHEDIR="/var/cache/zoneminder/cache" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_PATH_SHUTDOWN="/sbin/shutdown" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
override_dh_clean:

View File

@ -9,4 +9,5 @@
endscript
daily
rotate 7
maxage 7
}

View File

@ -34,6 +34,10 @@ if [ "$1" = "configure" ]; then
# test if database if already present...
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
if [ $? -ne 0 ]; then
echo "Error creating db."
exit 1;
fi
# This creates the user.
echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else

View File

@ -1,8 +1,8 @@
Source: zoneminder
Section: net
Priority: optional
Maintainer: Dmitry Smirnov <onlyjob@debian.org>
Uploaders: Vagrant Cascadian <vagrant@debian.org>
Maintainer: Isaac Connor <isaac@zoneminder.com>
Uploaders: Isaac Connor <isaac@zoneminder.com>
Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree, dh-systemd, dh-apache2
,cmake
,libx264-dev, libmp4v2-dev
@ -10,7 +10,7 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
,libavcodec-dev (>= 6:10~)
,libavformat-dev (>= 6:10~)
,libavutil-dev (>= 6:10~)
,libswresample-dev
,libswresample-dev | libavresample-dev
,libswscale-dev (>= 6:10~)
,ffmpeg | libav-tools
,net-tools
@ -30,6 +30,9 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
,libsys-mmap-perl [!hurd-any]
,libwww-perl
,libdata-uuid-perl
,libssl-dev
,libcrypt-eksblowfish-perl
,libdata-entropy-perl
# Unbundled (dh_linktree):
,libjs-jquery
,libjs-mootools
@ -42,7 +45,7 @@ Package: zoneminder
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,javascript-common
,libmp4v2-2, libx264-142|libx264-148|libx264-152
,libmp4v2-2, libx264-142|libx264-148|libx264-152|libx264-155
,libswscale-ffmpeg3|libswscale4|libswscale3|libswscale5
,libswresample2|libswresample3|libswresample24|libswresample-ffmpeg1
,ffmpeg | libav-tools
@ -55,12 +58,12 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libdbd-mysql-perl
,libdevice-serialport-perl
,libimage-info-perl
,libjson-any-perl
,libjson-maybexs-perl
,libsys-mmap-perl [!hurd-any]
,liburi-encode-perl
,libwww-perl
,libdata-dump-perl
,libdatetime-perl
,libclass-std-fast-perl
,libsoap-wsdl-perl
,libio-socket-multicast-perl
@ -76,6 +79,9 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,rsyslog | system-log-daemon
,zip
,libpcre3
,libssl | libssl1.0.0 | libssl1.1
,libcrypt-eksblowfish-perl
,libdata-entropy-perl
Recommends: ${misc:Recommends}
,libapache2-mod-php5 | libapache2-mod-php | php5-fpm | php-fpm
,mysql-server | mariadb-server | virtual-mysql-server
@ -103,7 +109,7 @@ Description: video camera security and surveillance solution
# ,libdbd-mysql-perl
# ,libdevice-serialport-perl
# ,libimage-info-perl
# ,libjson-any-perl
# ,libjson-maybexs-perl
# ,libsys-mmap-perl [!hurd-any]
# ,liburi-encode-perl
# ,libwww-perl

View File

@ -27,6 +27,7 @@ override_dh_auto_configure:
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_CACHEDIR="/var/cache/zoneminder/cache" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_PATH_SHUTDOWN="/sbin/shutdown" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
override_dh_clean:

View File

@ -9,4 +9,5 @@
endscript
daily
rotate 7
maxage 7
}

View File

@ -56,6 +56,10 @@ if [ "$1" = "configure" ]; then
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
echo "Creating zm db"
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
if [ $? -ne 0 ]; then
echo "Error creating db."
exit 1;
fi
# This creates the user.
echo "grant lock tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else

View File

@ -13,7 +13,7 @@ Type=forking
ExecStart=/usr/bin/zmpkg.pl start
ExecReload=/usr/bin/zmpkg.pl restart
ExecStop=/usr/bin/zmpkg.pl stop
PIDFile=/var/run/zm/zm.pid
PIDFile=/run/zm/zm.pid
Restart=always
RestartSec=10
Environment=TZ=:/etc/localtime

View File

@ -1,4 +1,4 @@
d /var/run/zm 0755 www-data www-data
d /run/zm 0755 www-data www-data
d /tmp/zm 0755 www-data www-data
d /var/tmp/zm 0755 www-data www-data
d /var/cache/zoneminder/cache 0755 www-data www-data

BIN
docs/_static/Icon_External_Link.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

2
docs/_static/README.txt vendored Normal file
View File

@ -0,0 +1,2 @@
The external link icon is GPL licensed. Original license link:
https://commons.wikimedia.org/wiki/Category:External_link_icons#/media/File:Icon_External_Link.png

View File

@ -1,3 +1,18 @@
img {
border: 1px solid black !important;
}
.admonition-todo {
border-top: 2px solid red;
border-bottom: 2px solid red;
border-left: 2px solid red;
border-right: 2px solid red;
background-color: #ff6347;
}
a.reference.external:link,
a.reference.external:visited{
background: url('./Icon_External_Link.png') center right no-repeat;
padding-right: 13px;
}

View File

@ -1,10 +1,12 @@
API
====
This document will provide an overview of ZoneMinder's API. This is work in progress.
This document will provide an overview of ZoneMinder's API.
Overview
^^^^^^^^
In an effort to further 'open up' ZoneMinder, an API was needed. This will
allow quick integration with and development of ZoneMinder.
@ -12,178 +14,187 @@ The API is built in CakePHP and lives under the ``/api`` directory. It
provides a RESTful service and supports CRUD (create, retrieve, update, delete)
functions for Monitors, Events, Frames, Zones and Config.
Streaming Interface
^^^^^^^^^^^^^^^^^^^
Developers working on their application often ask if there is an "API" to receive live streams, or recorded event streams.
It is possible to stream both live and recorded streams. This isn't strictly an "API" per-se (that is, it is not integrated
into the Cake PHP based API layer discussed here) and also why we've used the term "Interface" instead of an "API".
API Wrappers
^^^^^^^^^^^^^
- pyzm is a python wrapper for the ZoneMinder APIs. It supports both the legacy and new token based API, as well as ZM logs/ZM shared memory support. See `its project site <https://github.com/pliablepixels/pyzm/>`__ for more details. Documentation is `here <https://pyzm.readthedocs.io/en/latest/>`__.
Live Streams
~~~~~~~~~~~~~~
What you need to know is that if you want to display "live streams", ZoneMinder sends you streaming JPEG images (MJPEG)
which can easily be rendered in a browser using an ``img src`` tag.
API evolution
^^^^^^^^^^^^^^^
For example:
The ZoneMinder API has evolved over time. Broadly speaking the iterations were as follows:
::
* Prior to version 1.29, there really was no API layer. Users had to use the same URLs that the web console used to 'mimic' operations, or use an XML skin
* Starting version 1.29, a v1.0 CakePHP based API was released which continues to evolve over time. From a security perspective, it still tied into ZM auth and required client cookies for many operations. Primarily, two authentication modes were offered:
<img src="https://yourserver/zm/cgi-bin/nph-zms?scale=50&width=640p&height=480px&mode=jpeg&maxfps=5&buffer=1000&&monitor=1&auth=b54a589e09f330498f4ae2203&connkey=36139" />
* You use cookies to maintain session state (``ZM_SESS_ID``)
* You use an authentication hash to validate yourself, which included encoding personal information and time stamps which at times caused timing validation issues, especially for mobile consumers
will display a live feed from monitor id 1, scaled down by 50% in quality and resized to 640x480px.
* Starting version 1.34, ZoneMinder has introduced a new "token" based system which is based JWT. We have given it a '2.0' version ID. These tokens don't encode any personal data and can be statelessly passed around per request. It introduces concepts like access tokens, refresh tokens and per user level API revocation to manage security better. The internal components of ZoneMinder all support this new scheme now and if you are using the APIs we strongly recommend you migrate to 1.34 and use this new token system (as a side note, 1.34 also moves from MYSQL PASSWORD to Bcrypt for passwords, which is also a good reason why you should migate).
* Note that as of 1.34, both versions of API access will work (tokens and the older auth hash mechanism), however we no longer use sessions by default. You will have to add a ``stateful=1`` query parameter during login to tell ZM to set a COOKIE and store the required info in the session. This option is only available if ``OPT_USE_LEGACY_API_AUTH`` is set to ON.
* This assumes ``/zm/cgi-bin`` is your CGI_BIN path. Change it to what is correct in your system
* The "auth" token you see above is required if you use ZoneMinder authentication. To understand how to get the auth token, please read the "Login, Logout & API security" section below.
* The "connkey" parameter is essentially a random number which uniquely identifies a stream. If you don't specify a connkey, ZM will generate its own. It is recommended to generate a connkey because you can then use it to "control" the stream (pause/resume etc.)
* Instead of dealing with the "auth" token, you can also use ``&user=username&pass=password`` where "username" and "password" are your ZoneMinder username and password respectively. Note that this is not recommended because you are transmitting them in a URL and even if you use HTTPS, they may show up in web server logs.
.. note::
For the rest of the document, we will specifically highlight v2.0 only features. If you don't see a special mention, assume it applies for both API versions.
PTZ on live streams
-------------------
PTZ commands are pretty cryptic in ZoneMinder. This is not meant to be an exhaustive guide, but just something to whet your appetite:
Lets assume you have a monitor, with ID=6. Let's further assume you want to pan it left.
You'd need to send a:
``POST`` command to ``https://yourserver/zm/index.php`` with the following data payload in the command (NOT in the URL)
``view=request&request=control&id=6&control=moveConLeft&xge=30&yge=30``
Obviously, if you are using authentication, you need to be logged in for this to work.
Like I said, at this stage, this is only meant to get you started. Explore the ZoneMinder code and use "Inspect source" as you use PTZ commands in the ZoneMinder source code.
`control_functions.php <https://github.com/ZoneMinder/zoneminder/blob/10531df54312f52f0f32adec3d4720c063897b62/web/skins/classic/includes/control_functions.php>`__ is a great place to start.
Pre-recorded (past event) streams
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similar to live playback, if you have chosen to store events in JPEG mode, you can play it back using:
::
<img src="https://yourserver/zm/cgi-bin/nph-zms?mode=jpeg&frame=1&replay=none&source=event&event=293820&connkey=77493&auth=b54a58f5f4ae2203" />
* This assumes ``/zm/cgi-bin`` is your CGI_BIN path. Change it to what is correct in your system
* This will playback event 293820, starting from frame 1 as an MJPEG stream
* Like before, you can add more parameters like ``scale`` etc.
* auth and connkey have the same meaning as before, and yes, you can replace auth by ``&user=usename&pass=password`` as before and the same security concerns cited above apply.
If instead, you have chosen to use the MP4 (Video) storage mode for events, you can directly play back the saved video file:
::
<video src="https://yourserver/zm/index.php?view=view_video&eid=294690&auth=33f3d558af84cf08" type="video/mp4"></video>
* This will play back the video recording for event 294690
What other parameters are supported?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The best way to answer this question is to play with ZoneMinder console. Open a browser, play back live or recorded feed, and do an "Inspect Source" to see what parameters
are generated. Change and observe.
Enabling API
^^^^^^^^^^^^
A default ZoneMinder installs with APIs enabled. You can explictly enable/disable the APIs
via the Options->System menu by enabling/disabling ``OPT_USE_API``. Note that if you intend
to use APIs with 3rd party apps, such as zmNinja or others that use APIs, you should also
enable ``AUTH_HASH_LOGINS``.
^^^^^^^^^^^^^
Login, Logout & API Security
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The APIs tie into ZoneMinder's existing security model. This means if you have
OPT_AUTH enabled, you need to log into ZoneMinder using the same browser you plan to
use the APIs from. If you are developing an app that relies on the API, you need
to do a POST login from the app into ZoneMinder before you can access the API.
ZoneMinder comes with APIs enabled. To check if APIs are enabled, visit ``Options->System``. If ``OPT_USE_API`` is enabled, your APIs are active.
For v2.0 APIs, you have an additional option right below it:
Then, you need to re-use the authentication information of the login (returned as cookie states)
with subsequent APIs for the authentication information to flow through to the APIs.
* ``OPT_USE_LEGACY_API_AUTH`` which is enabled by default. When enabled, the `login.json` API (discussed later) will return both the old style (``auth=``) and new style (``token=``) credentials. The reason this is enabled by default is because any existing apps that use the API would break if they were not updated to use v2.0. (Note that zmNinja 1.3.057 and beyond will support tokens)
This means if you plan to use cuRL to experiment with these APIs, you first need to login:
Enabling secret key
^^^^^^^^^^^^^^^^^^^
**Login process for ZoneMinder v1.32.0 and above**
* It is **important** that you create a "Secret Key". This needs to be a set of hard to guess characters, that only you know. ZoneMinder does not create a key for you. It is your responsibility to create it. If you haven't created one already, please do so by going to ``Options->Systems`` and populating ``AUTH_HASH_SECRET``. Don't forget to save.
* If you plan on using V2.0 token based security, **it is mandatory to populate this secret key**, as it is used to sign the token. If you don't, token authentication will fail. V1.0 did not mandate this requirement.
Getting an API key
^^^^^^^^^^^^^^^^^^^^^^^
To get an API key:
::
curl -XPOST -d "user=XXXX&pass=YYYY" -c cookies.txt http://yourzmip/zm/api/host/login.json
curl -XPOST -d "user=yourusername&pass=yourpassword" https://yourserver/zm/api/host/login.json
Staring ZM 1.32.0, you also have a `logout` API that basically clears your session. It looks like this:
If you want to use a stateful connection, so you don't have to pass auth credentials with each query, you can use the following:
::
curl -b cookies.txt http://yourzmip/zm/api/host/logout.json
curl -XPOST -c cookies.txt -d "user=yourusername&pass=yourpassword&stateful=1" https://yourserver/zm/api/host/login.json
**Login process for older versions of ZoneMinder**
::
curl -d "username=XXXX&password=YYYY&action=login&view=console" -c cookies.txt http://yourzmip/zm/index.php
The equivalent logout process for older versions of ZoneMinder is:
::
curl -XPOST -d "username=XXXX&password=YYYY&action=logout&view=console" -b cookies.txt http://yourzmip/zm/index.php
replacing *XXXX* and *YYYY* with your username and password, respectively.
Please make sure you do this in a directory where you have write permissions, otherwise cookies.txt will not be created
and the command will silently fail.
What the "-c cookies.txt" does is store a cookie state reflecting that you have logged into ZM. You now need
to apply that cookie state to all subsequent APIs. You do that by using a '-b cookies.txt' to subsequent APIs if you are
using CuRL like so:
::
curl -b cookies.txt http://yourzmip/zm/api/monitors.json
This would return a list of monitors and pass on the authentication information to the ZM API layer.
A deeper dive into the login process
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As you might have seen above, there are two ways to login, one that uses the `login.json` API and the other that logs in using the ZM portal. If you are running ZoneMinder 1.32.0 and above, it is *strongly* recommended you use the `login.json` approach. The "old" approach will still work but is not as powerful as the API based login. Here are the reasons why:
* The "old" approach basically uses the same login webpage (`index.php`) that a user would log into when viewing the ZM console. This is not really using an API and more importantly, if you have additional components like reCAPTCHA enabled, this will not work. Using the API approach is much cleaner and will work irrespective of reCAPTCHA
* The new login API returns important information that you can use to stream videos as well, right after login. Consider for example, a typical response to the login API (`/login.json`):
This returns a payload like this for API v1.0:
::
{
"credentials": "auth=f5b9cf48693fe8552503c8ABCD5",
"credentials": "auth=05f3a50e8f7<deleted>063",
"append_password": 0,
"version": "1.31.44",
"version": "1.33.9",
"apiversion": "1.0"
}
In this example I have `OPT_AUTH` enabled in ZoneMinder and it returns my credential key. You can then use this key to stream images like so:
Or for API 2.0:
::
<img src="https://server/zm/cgi-bin/nph-zms?monitor=1&auth=<authval>" />
{
"access_token": "eyJ0eXAiOiJK<deleted>HE",
"access_token_expires": 3600,
"refresh_token": "eyJ0eXAiOi<deleted>mPs",
"refresh_token_expires": 86400,
"credentials": "auth=05f3a50e8f7<deleted>063", # only if OPT_USE_LEGACY_API_AUTH is enabled
"append_password": 0, # only if OPT_USE_LEGACY_API_AUTH is enabled
"version": "1.33.9",
"apiversion": "2.0"
}
Where `authval` is the credentials returned to start streaming videos.
Using these keys with subsequent requests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The `append_password` field will contain 1 when it is necessary for you to append your ZM password. This is the case when you set `AUTH_RELAY` in ZM options to "plain", for example. In that case, the `credentials` field may contain something like `&user=admin&pass=` and you have to add your password to that string.
Once you have the keys (a.k.a credentials (v1.0, v2.0) or token (v2.0)) you should now supply that key to subsequent API calls like this:
::
# v1.0 or 2.0 based API access (will only work if AUTH_HASH_LOGINS is enabled
# RECOMMENDED: v2.0 token based
curl -XGET https://yourserver/zm/api/monitors.json?token=<access_token>
# or, for legacy mode:
curl -XGET https://yourserver/zm/api/monitors.json?auth=<hex digits from 'credentials'>
# or, if you specified -c cookies.txt in the original login request
curl -b cookies.txt -XGET https://yourserver/zm/api/monitors.json
.. NOTE:: It is recommended you invoke the `login` API once every 60 minutes to make sure the session stays alive. The same is true if you use the old login method too.
.. NOTE::
If you are using an ``HTTP GET`` request, the token/auth needs to be passed as a query parameter in the URL. If you are using an ``HTTP POST`` (like when you use the API to modify a monitor, for example), you can choose to pass the token as a data payload instead. The API layer discards data payloads for ``HTTP GET``. Finally, If you don't pass keys, you could also use cookies (not recommended as a general approach).
Key lifetime (v1.0)
^^^^^^^^^^^^^^^^^^^^^
If you are using the old credentials mechanism present in v1.0, then the credentials will time out based on PHP session timeout (if you are using cookies), or the value of ``AUTH_HASH_TTL`` (if you are using ``auth=`` and have enabled ``AUTH_HASH_LOGINS``) which defaults to 2 hours. Note that there is no way to look at the hash and decipher how much time is remaining. So it is your responsibility to record the time you got the hash and assume it was generated at the time you got it and re-login before that time expires.
Key lifetime (v2.0)
^^^^^^^^^^^^^^^^^^^^^^
In version 2.0, it is easy to know when a key will expire before you use it. You can find that out from the ``access_token_expires`` and ``refresh_token_exipres`` values (in seconds) after you decode the JWT key (there are JWT decode libraries for every language you want). You should refresh the keys before the timeout occurs, or you will not be able to use the APIs.
Understanding access/refresh tokens (v2.0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you are using V2.0, then you need to know how to use these tokens effectively:
* Access tokens are short lived. ZoneMinder issues access tokens that live for 3600 seconds (1 hour).
* Access tokens should be used for all subsequent API accesses.
* Refresh tokens should ONLY be used to generate new access tokens. For example, if an access token lives for 1 hour, before the hour completes, invoke the ``login.json`` API above with the refresh token to get a new access token. ZoneMinder issues refresh tokens that live for 24 hours.
* To generate a new refresh token before 24 hours are up, you will need to pass your user login and password to ``login.json``
**To Summarize:**
* Pass your ``username`` and ``password`` to ``login.json`` only once in 24 hours to renew your tokens
* Pass your "refresh token" to ``login.json`` once in two hours (or whatever you have set the value of ``AUTH_HASH_TTL`` to) to renew your ``access token``
* Use your ``access token`` for all API invocations.
In fact, V2.0 will reject your request (if it is not to ``login.json``) if it comes with a refresh token instead of an access token to discourage usage of this token when it should not be used.
This minimizes the amount of sensitive data that is sent over the wire and the lifetime durations are made so that if they get compromised, you can regenerate or invalidate them (more on this later)
Understanding key security
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Version 1.0 uses an MD5 hash to generate the credentials. The hash is computed over your secret key (if available), username, password and some time parameters (along with remote IP if enabled). This is not a secure/recommended hashing mechanism. If your auth hash is compromised, an attacker will be able to use your hash till it expires. To avoid this, you could disable the user in ZoneMinder. Furthermore, enabling remote IP (``AUTH_HASH_REMOTE_IP``) requires that you issue future requests from the same IP that generated the tokens. While this may be considered an additional layer for security, this can cause issues with mobile devices.
* Version 2.0 uses a different approach. The hash is a simple base64 encoded form of "claims", but signed with your secret key. Consider for example, the following access key:
::
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJab25lTWluZGVyIiwiaWF0IjoxNTU3OTQwNzUyLCJleHAiOjE1NTc5NDQzNTIsInVzZXIiOiJhZG1pbiIsInR5cGUiOiJhY2Nlc3MifQ.-5VOcpw3cFHiSTN5zfGDSrrPyVya1M8_2Anh5u6eNlI
If you were to use any `JWT token verifier <https://jwt.io>`__ it can easily decode that token and will show:
::
{
"iss": "ZoneMinder",
"iat": 1557940752,
"exp": 1557944352,
"user": "admin",
"type": "access"
}
Invalid Signature
Don't be surprised. JWT tokens, by default, are `not meant to be encrypted <https://softwareengineering.stackexchange.com/questions/280257/json-web-token-why-is-the-payload-public>`__. It is just an assertion of a claim. It states that the issuer of this token was ZoneMinder,
It was issued at (iat) Wednesday, 2019-05-15 17:19:12 UTC and will expire on (exp) Wednesday, 2019-05-15 18:19:12 UTC. This token claims to be owned by an admin and is an access token. If your token were to be stolen, this information is available to the person who stole it. Note that there are no sensitive details like passwords in this claim.
Examples (please read security notice above)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
However, that person will **not** have your secret key as part of this token and therefore, will NOT be able to create a new JWT token to get, say, a refresh token. They will however, be able to use your access token to access resources just like the auth hash above, till the access token expires (2 hrs). To revoke this token, you don't need to disable the user. Go to ``Options->API`` and tap on "Revoke All Access Tokens". This will invalidate the token immediately (this option will invalidate all tokens for all users, and new ones will need to be generated).
Please remember, if you are using authentication, please add a ``-b cookies.txt`` to each of the commands below if you are using
CuRL. If you are not using CuRL and writing your own app, you need to make sure you pass on cookies to subsequent requests
in your app.
Over time, we will provide you with more fine grained access to these options.
**Summarizing good practices:**
* Use HTTPS, not HTTP
* If possible, use free services like `LetsEncrypt <https://letsencrypt.org>`__ instead of self-signed certificates (sometimes this is not possible)
* Keep your tokens as private as possible, and use them as recommended above
* If you believe your tokens are compromised, revoke them, but also check if your attacker has compromised more than you think (example, they may also have your username/password or access to your system via other exploits, in which case they can regenerate as many tokens/credentials as they want).
.. NOTE::
Subsequent sections don't explicitly callout the key addition to APIs. We assume that you will append the correct keys as per our explanation above.
Examples
^^^^^^^^^
(In all examples, replace 'server' with IP or hostname & port where ZoneMinder is running)
@ -410,6 +421,15 @@ This returns number of events per monitor that were recorded in the last day whe
Return sorted events
^^^^^^^^^^^^^^^^^^^^^^
This returns a list of events within a time range and also sorts it by descending order
::
curl -XGET "http://server/zm/api/events/index/StartTime%20>=:2015-05-15%2018:43:56/EndTime%20<=:208:43:56.json?sort=StartTime&direction=desc"
Configuration Apis
^^^^^^^^^^^^^^^^^^^
@ -584,9 +604,104 @@ Returns:
This only works if you have a multiserver setup in place. If you don't it will return an empty array.
Other APIs
^^^^^^^^^^
This is not a complete list. ZM supports more parameters/APIs. A good way to dive in is to look at the `API code <https://github.com/ZoneMinder/zoneminder/tree/master/web/api/app/Controller>`__ directly.
Streaming Interface
^^^^^^^^^^^^^^^^^^^
Developers working on their application often ask if there is an "API" to receive live streams, or recorded event streams.
It is possible to stream both live and recorded streams. This isn't strictly an "API" per-se (that is, it is not integrated
into the Cake PHP based API layer discussed here) and also why we've used the term "Interface" instead of an "API".
Live Streams
~~~~~~~~~~~~~~
What you need to know is that if you want to display "live streams", ZoneMinder sends you streaming JPEG images (MJPEG)
which can easily be rendered in a browser using an ``img src`` tag.
For example:
::
<img src="https://yourserver/zm/cgi-bin/nph-zms?scale=50&width=640p&height=480px&mode=jpeg&maxfps=5&buffer=1000&&monitor=1&token=eW<deleted>03&connkey=36139" />
# or
<img src="https://yourserver/zm/cgi-bin/nph-zms?scale=50&width=640p&height=480px&mode=jpeg&maxfps=5&buffer=1000&&monitor=1&auth=b5<deleted>03&connkey=36139" />
will display a live feed from monitor id 1, scaled down by 50% in quality and resized to 640x480px.
* This assumes ``/zm/cgi-bin`` is your CGI_BIN path. Change it to what is correct in your system
* The "auth" token you see above is required if you use ZoneMinder authentication. To understand how to get the auth token, please read the "Login, Logout & API security" section below.
* The "connkey" parameter is essentially a random number which uniquely identifies a stream. If you don't specify a connkey, ZM will generate its own. It is recommended to generate a connkey because you can then use it to "control" the stream (pause/resume etc.)
* Instead of dealing with the "auth" token, you can also use ``&user=username&pass=password`` where "username" and "password" are your ZoneMinder username and password respectively. Note that this is not recommended because you are transmitting them in a URL and even if you use HTTPS, they may show up in web server logs.
PTZ on live streams
-------------------
PTZ commands are pretty cryptic in ZoneMinder. This is not meant to be an exhaustive guide, but just something to whet your appetite:
Lets assume you have a monitor, with ID=6. Let's further assume you want to pan it left.
You'd need to send a:
``POST`` command to ``https://yourserver/zm/index.php`` with the following data payload in the command (NOT in the URL)
``view=request&request=control&id=6&control=moveConLeft&xge=30&yge=30``
Obviously, if you are using authentication, you need to be logged in for this to work.
Like I said, at this stage, this is only meant to get you started. Explore the ZoneMinder code and use "Inspect source" as you use PTZ commands in the ZoneMinder source code.
`control_functions.php <https://github.com/ZoneMinder/zoneminder/blob/10531df54312f52f0f32adec3d4720c063897b62/web/skins/classic/includes/control_functions.php>`__ is a great place to start.
Pre-recorded (past event) streams
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similar to live playback, if you have chosen to store events in JPEG mode, you can play it back using:
::
<img src="https://yourserver/zm/cgi-bin/nph-zms?mode=jpeg&frame=1&replay=none&source=event&event=293820&connkey=77493&token=ew<deleted>" />
# or
<img src="https://yourserver/zm/cgi-bin/nph-zms?mode=jpeg&frame=1&replay=none&source=event&event=293820&connkey=77493&auth=b5<deleted>" />
* This assumes ``/zm/cgi-bin`` is your CGI_BIN path. Change it to what is correct in your system
* This will playback event 293820, starting from frame 1 as an MJPEG stream
* Like before, you can add more parameters like ``scale`` etc.
* auth and connkey have the same meaning as before, and yes, you can replace auth by ``&user=usename&pass=password`` as before and the same security concerns cited above apply.
If instead, you have chosen to use the MP4 (Video) storage mode for events, you can directly play back the saved video file:
::
<video src="https://yourserver/zm/index.php?view=view_video&eid=294690&token=eW<deleted>" type="video/mp4"></video>
# or
<video src="https://yourserver/zm/index.php?view=view_video&eid=294690&auth=33<deleted>" type="video/mp4"></video>
This above will play back the video recording for event 294690
What other parameters are supported?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The best way to answer this question is to play with ZoneMinder console. Open a browser, play back live or recorded feed, and do an "Inspect Source" to see what parameters
are generated. Change and observe.
Further Reading
^^^^^^^^^^^^^^^^
As described earlier, treat this document as an "introduction" to the important parts of the API and streaming interfaces.
There are several details that haven't yet been documented. Till they are, here are some resources:

View File

@ -31,7 +31,7 @@ def setup(app):
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
extensions = ['sphinx.ext.todo']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -265,3 +265,6 @@ texinfo_documents = [
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# Display todos by setting to True
todo_include_todos = True

View File

@ -1,8 +1,11 @@
FAQ
=====
.. todo:: needs to be reviewed - some entries may be old/invalid. I've done one round, but icOn needs to review.
This is the FAQ page. Feel free to contribute any FAQs that you think are missing.
.. note:: It is always a good idea to refer to the `ZoneMinder forums <https://forums.zoneminder.com/viewforum.php?f=26&sid=fc93f65726d3a29fbf6f610b21f52b16>`__ for tips and tricks. While we try and make sure this FAQ is pruned/adjusted to align with the latest stable release, some of the entries may no longer be accurate (or there may be better suggestions in the forums).
How can I stop ZoneMinder filling up my disk?
---------------------------------------------
@ -29,23 +32,22 @@ To delete events that are older than 7 days, create a new filter with "Date" set
Save with 'Run Filter In Background' enabled to have it run automatically.
Optional skip archived events: click on the plus sign next to -7 days to add another condition. "and" "archive status" equal to "unarchived only".
Optional slow delete: limit the number of results to 3. If you have a large backlog of events that would be deleted, this can hard spike the CPU usage for a long time. Limiting the number of results to only the first three each time the filter is run spreads out the delete processes over time, dramatically lessening the CPU load.
Optional slow delete: limit the number of results to a number, say ``10`` in the filter. If you have a large backlog of events that would be deleted, this can hard spike the CPU usage for a long time. Limiting the number of results to only the first three each time the filter is run spreads out the delete processes over time, dramatically lessening the CPU load.
.. warning:: We no longer recommend use enable ``OPT_FAST_DELETE`` or ``RUN_AUDIT`` anymore, unless you are using an old or low powered system to run Zoneminder. Please consider the remaining tips in this answer to be 'generally deprecated, use only if you must'.
There are two methods for ZM to remove files when they are deleted that can be found in Options under the System tab ZM_OPT_FAST_DELETE and ZM_RUN_AUDIT.
ZM_OPT_FAST_DELETE:
Normally an event created as the result of an alarm consists of entries in one or more database tables plus the various files associated with it. When deleting events in the browser it can take a long time to remove all of this if you are trying to do a lot of events at once. If you are running on an older or under-powered system, you may want to set this option which means that the browser client only deletes the key entries in the events table, which means the events will no longer appear in the listing, and leaves the zmaudit daemon to clear up the rest later. If you do so, disk space will not be freed immediately so you will need to run zmaudit more frequently. On modern systems, we recommend that you leave this off.
Normally an event created as the result of an alarm consists of entries in one or more database tables plus the various files associated with it. When deleting events in the browser it can take a long time to remove all of this if you are trying to do a lot of events at once. If you are running on an older or under-powered system, you may want to set this option which means that the browser client only deletes the key entries in the events table, which means the events will no longer appear in the listing, and leaves the zmaudit daemon to clear up the rest later. If you do so, disk space will not be freed immediately so you will need to run zmaudit more frequently. On modern systems, we recommend that you leave this **off**.
ZM_RUN_AUDIT:
The zmaudit daemon exists to check that the saved information in the database and on the file system match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronize the two data stores. This option controls whether zmaudit is run in the background and performs these checks and fixes continuously. This is recommended for most systems however if you have a very large number of events the process of scanning the database and file system may take a long time and impact performance. In this case you may prefer to not have zmaudit running unconditionally and schedule occasional checks at other, more convenient, times.
ZM_AUDIT_CHECK_INTERVAL:
The zmaudit daemon exists to check that the saved information in the database and on the files system match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronize the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and file system may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.
@ -64,12 +66,15 @@ In *general* a good estimate of memory required would be:
Min Bits of Memory = 20% overhead * (image-width*image-height*image buffer size*target color space*number of cameras)
Where:
* image-width and image-height are the width and height of images that your camera is configured for (in my case, 1280x960). This value is in the Source tab for each monitor
* image buffer size is the # of images ZM will keep in memory (this is used by ZM to make sure it has pre and post images before detecting an alarm - very useful because by the time an alarm is detected, the reason for the alarm may move out of view and a buffer is really useful for this, including for analyzing stats/scores). This value is in the buffers tab for each monitor
* target color space is the color depth - 8bit, 24bit or 32bit. It's again in the source tab of each monitor
The 1.2 at the start is basically adding 20% on top of the calculation to account for image/stream overheads (this is an estimate)
The 20% overhead on top of the calculation to account for image/stream overheads (this is an estimate)
The math breakdown for 4 cameras running at 1280x960 capture, 50 frame buffer, 24 bit color space:
::
1280*960 = 1,228,800 (bytes)
@ -96,8 +101,6 @@ So a good rule of thumb is to make sure you have twice the memory as the calcula
As it turns out, ZM uses mapped memory and by default, 50% of your physical memory is what this will grow to. When you reach that limit , ZM breaks down with various errors.
(**Note**: Mapped memory is applicable when you install ZoneMinder with mapped memory support, which is the default mode. If you have specifically disabled mapped memory then please see the next FAQ enty on how to increase shared memory)
A good way to know how much memory is allocated to ZM for its operation is to do a ``df -h``
A sample output on Ubuntu:
@ -116,140 +119,43 @@ For example, if you want to increase this limit to 70% of your memory, add the f
where SHMPATH is the ``Mounted on`` path. Here, that would be ``/run/shm``. Other systems may be ``/dev/shm``.
What does a 'Can't shmget: Invalid argument' error in my logs mean? (and my camera does not display at higher resolutions)
--------------------------------------------------------------------------------------------------------------------------------------
(*Note*: This is applicable for systems that have mapped memory disabled in ZoneMinder. By default, Mapped memory is enabled and unless you have disabled it manually, please refer to the "Math for Memory" question above and how to increase mapped memory limits)
This error is discussed in the README in the following excerpt:-
''...this is caused by an attempt to allocate an amount of shared memory greater than your system can handle. The size it requests is based on the following formula, ``ring buffer size x image width x image height x 3 (for 24 bit images) + a bit of overhead``.
So, for example:
::
384x288 capture resolution, that makes: 110 592 pixels
in 24 bit color that's x 3 = 331,776 bytes per frame
by 80 frames ring buffer x80 = 26,542,080 bytes per camera
by 4 cameras x4 = 106,168,320 bytes.
Plus 10% overhead = 116,785,152 bytes
Thats 114,048 kB, respectively 111.38 MB.
If my shared memory is set to 134,217,728, which is exactly 128MB,
that means I shouldn't have any problem.
(Note that 1kbyte = 1024bytes, 1MB = 1024 kB)
If for instance you were using 24bit 640x480 then this would come to about 92Mb if you are using the default buffer size of 100. If this is too large then you can either reduce the image or buffer sizes or increase the maximum amount of shared memory available. If you are using RedHat then you can get details on how to change these settings `here <http://www.redhat.com/docs/manuals/database/RHDB-2.1-Manual/admin_user/kernel-resources.html>`__
You should be able to use a similar procedure with other distributions to modify the shared memory pool without kernel recompilations though in some cases this may be necessary. Note, this error also sometimes occurs if you have an old shared memory segment lying around from a previous run that is too small. Use the ipcs and ipcrm system commands to check and remove it if necessary.'"
You can often find out how many 4KB shared memory pages are available by typing the following :-
::
# cat /proc/sys/kernel/shmall
2097152
In recent kernels the shmall is set to 2097152 memory pages multiplied by 4096 bytes per page for a total of 8 GB of shared memory available. You only need to increase the shmall value if you have a computer with more than 8GB of memory and wish to use more of it for shared memory usage, such as large databases.
The most shared memory bytes you can allocate in one go :-
::
# cat /proc/sys/kernel/shmmax
33554432
In recent kernels the shmmax is set to 33554432 bytes for only 32 MB of maximum shared memory allocatable at a time, hardly enough for ZoneMinder to go above 320 x 240 x 24-bit resolution at 40 frames in the buffer if it is using the /dev/shm shared memory device, so this value needs to be increased. If you are using ZoneMinder with the memory mapped (mmap) compile time option then this doesn't affect you.
To change the value to 128 MB temporarily during this kernel execution type (for example) :-
``echo 536870912 >/proc/sys/kernel/shmmax``
*Be sure to restart ZoneMinder after this.*
However be aware that sometimes you will only need to change the shmmax value as shmall is often large enough. Also changing these values in this way is only effective until your machine is rebooted.
To change them permanently you will need to edit ``/etc/sysctl.conf`` and add the following lines (for example) :-
``kernel.shmmax = 536870912``
Or if your distribution has the ``/etc/sysctl.d/`` folder you can create a file in this folder without modifying the ``/etc/sysctl.d`` so you won't lose the changes during distro upgrades :-
```echo kernel.shmmax = 536870912 >/etc/sysctl.d/60-kernel-shm.conf```
To load these settings in the sysctl.conf file type:
``sysctl -p``
To check your shared memory settings type:
``ipcs -l``
Note that with Megapixel cameras like the Axis 207mw becoming cheaper and more attractive, the above memory settings are not adequate. To get Zoneminder working with a full 1280x1024 resolution camera in full color, increase ``134217728`` (128 MB) to, for example, ``268435456`` (256 MB) and multiple this value by each camera.
These changes will now also be set the next time your machine is restarted.
Versions 1.24.x of ZoneMinder also allows you to use an alternate method of shared memory allocation, `Mmap mapped memory <http://en.wikipedia.org/wiki/Mmap>`__ . This requires less configuration and can be simpler to use. Mapped memory allows you to use a special type of file as the placeholder for your memory and this file is 'mapped' into memory space for easy and fast access.
To enable mapped memory in ZoneMinder you need add add the --enable--mmap=yes switch to your configure line. By default mapped memory files are created in /dev/shm which on most distributions is a dedicated pseudo-partition containing memory formatted as a filesystem. If your system uses a different path then this can be changed in ZoneMinder in Options->paths->PATH_MAP. It uses a filesystem type called `tmpfs <http://en.wikipedia.org/wiki/Tmpfs>`__. If you type ``df -h`` you should see this area and the size of memory it currently allows. To increase size for tmpfs you need to edit /etc/default/tmpfs. Search for:
``SHM_SIZE=128M``
and change to something like
``SHM_SIZE=1G``
then reboot the system. You could possibly need to change RUN_SIZE, too.
It is important that you do not use a disk based filesystem for your memory mapped files as this will cause memory access to be extremely slow. ZoneMinder creates files called .zm.mmap.<monitor id> in the mapped memory filesystem.
Mapped memory is subject to the same limitations in terms of total memory as using more traditional shared memory but does not require any configuration per allocation or chunk. In future versions of ZoneMinder this will be the default shared memory storage method.
Another good article about shared memory settings can be found `here <http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.uprun.doc/doc/t0008238.htm>`__ .
The essential difference was that the kernel.shmall setting is NOT in a direct memory setting in KB but in pages of memory. it is Max Pages of memory
*For example:* If you want to allocate a maximum memory setting to 8GB you have to convert it to the number of pages (or segments).
with a page size of 4096.
kernel.shmall = 8000x1024x1024/4096
``kernel.shmall = 2097152``
NOT 8388608000 as would be suggested in the RedHat article linked above.
shmmax is the max amount to allocate in one request -
this is is an actual memory size (as opposed to pages) set to 4GB
``kernel.shmmax = 4294967296``
The ``/etc/sysctl.conf`` would have these lines
::
kernel.shmall = 2097152
kernel.shmmax = 4294967296</pre>
As above, reload your sysctl.conf with ``sysctl -p`` and check that the settings are correct with ``ipcs -l``.
I have enabled motion detection but it is not always being triggered when things happen in the camera view
---------------------------------------------------------------------------------------------------------------
ZoneMinder uses zones to examine images for motion detection. When you create the initial zones you can choose from a number of preset values for sensitivity etc. Whilst these are usually a good starting point they are not always suitable for all situations and you will probably need to tweak the values for your specific circumstances. The meanings of the various settings are described in the documentation (`here <http://www.zoneminder.com/wiki/index.php/Documentation#Defining_Zones>`__) however if you believe you have sensible settings configured then there are two diagnostic approaches you can use.
ZoneMinder uses zones to examine images for motion detection. When you create the initial zones you can choose from a number of preset values for sensitivity etc. Whilst these are usually a good starting point they are not always suitable for all situations and you will probably need to tweak the values for your specific circumstances. The meanings of the various settings are described in the documentation (`here <https://zoneminder.readthedocs.io/en/latest/userguide/definezone.html>`__). Another user contributed illustrated Zone definition guide can be found here: `An illustrated guide to Zones <https://wiki.zoneminder.com/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__
However if you believe you have sensible settings configured then there are diagnostic approaches you can use.
Another user contributed illustrated Zone definition guide can be found here: `An illustrated guide to Zones <http://www.zoneminder.com/wiki/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__
Event Statistics
^^^^^^^^^^^^^^^^^
The first technique is to use event statistics. Firstly you should ensure they are switched on in Options->Logging->RECORD_EVENT_STATS. This will then cause the raw motion detection statistics for any subsequently generated events to be written to the DB. These can then be accessed by first clicking on the Frames or Alarm Frames values of the event from any event list view in the web gui. Then click on the score value to see the actual values that caused the event. Alternatively the stats can be accessed by clicking on the 'Stats' link when viewing any individual frame. The values displayed there correspond with the values that are used in the zone configuration and give you an idea of what 'real world' values are being generated.
The first technique is to use event statistics. Firstly you should ensure they are switched on in ``Options->Logging->RECORD_EVENT_STATS``. This will then cause the raw motion detection statistics for any subsequently generated events to be written to the DB. These can then be accessed by first clicking on the Frames or Alarm Frames values of the event from any event list view in the web gui. Then click on the score value to see the actual values that caused the event. Alternatively the stats can be accessed by clicking on the 'Stats' link when viewing any individual frame. The values displayed there correspond with the values that are used in the zone configuration and give you an idea of what 'real world' values are being generated.
Note that if you are investigating why events 'do not' happen then these will not be saved and so won't be accessible. The best thing to do in that circumstance is to make your zone more sensitive so that it captures all events (perhap even ones you don't want) so you can get an idea of what values are being generated and then start to adjust back to less sensitive settings if necessary. You should make sure you test your settings under a variety of lighting conditions (e.g. day and night, sunny or dull) to get the best feel for that works and what doesn't.
Using statistics will slow your system down to a small degree and use a little extra disk space in the DB so once you are happy you can switch them off again. However it is perfectly feasible to keep them permanently on if your system is able to cope which will allow you to review your setting periodically.
Diagnostic Images
^^^^^^^^^^^^^^^^^^^^
The second approach is to use diagnostic images which are saved copies of the intermediate images that ZM uses when determining motion detection. These are switched on and off using Options->Logging->RECORD_DIAG_IMAGES.
Diagnostic Images along with FIFO
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The second approach is to use diagnostic images which are saved copies of the intermediate images that ZM uses when determining motion detection. These are switched on and off using ``Options->Logging->RECORD_DIAG_IMAGES``.
.. note:: In addition to the detailed explanation below, a recently added ``RECORD_DIAG_IMAGES_FIFO`` option, also available in ``Options->Logging`` can be an invaluable tool to see how your current motion settings are affecting motion detection. The ``delta`` stream along with the ``raw`` (json output) stream can be invaluable to see the effect in real time. Please refer to the explanation of this feature in :doc:`/userguide/options/options_logging`
There are two kinds of diagnostic images which are and are written (and continuously overwritten) to the top level monitor event directory. If an event occurs then the files are additionally copied to the event directory and renamed with the appropriate frame number as a prefix.
The first set are produced by the monitor on the image as a whole. The diag-r.jpg image is the current reference image against which all individual frames are compared and the diag-d.jpg image is the delta image highlighting the difference between the reference image and the last analysed image. In this images identical pixels will be black and the more different a pixel is the whiter it will be. Viewing this image and determining the colour of the pixels is a good way of getting a feel for the pixel differences you might expect (often more than you think).
The first set are produced by the monitor on the image as a whole. The ``diag-r.jpg`` image is the current reference image against which all individual frames are compared and the ``diag-d.jpg`` image is the delta image highlighting the difference between the reference image and the last analysed image. In this images identical pixels will be black and the more different a pixel is the whiter it will be. Viewing this image and determining the colour of the pixels is a good way of getting a feel for the pixel differences you might expect (often more than you think).
The second set of diag images are labelled as diag-<zoneid>-<stage>.jpg where zoneid is the id of the zone in question (Smile) and the stage is where in the alarm check process the image is generated from. So if you have several zones you can expect to see multiple files. Also these files are only interested in what is happening in their zone only and will ignore anything else outside of the zone. The stages that each number represents are as follows,
The second set of diag images are labelled as ``diag-<zoneid>-<stage>.jpg`` where zoneid is the id of the zone in question (Smile) and the stage is where in the alarm check process the image is generated from. So if you have several zones you can expect to see multiple files. Also these files are only interested in what is happening in their zone only and will ignore anything else outside of the zone. The stages that each number represents are as follows,
# Alarmed Pixels - This image shows all pixels in the zone that are considered to be alarmed as white pixels and all other pixels as black.
# Filtered Pixels - This is as stage one except that all pixels removed by the filters are now black. The white pixels represent the pixels that are candidates to generate an event.
# Raw Blobs - This image contains all alarmed pixels from stage 2 but aggrageted into blobs. Each blob will have a different greyscale value (between 1 and 254) so they can be difficult to spot with the naked eye but using a colour picker or photoshop will make it easier to see what blob is what.
# Filtered Blobs - This image is as stage 3 but under (or over) sized blobs have been removed. This is the final step before determining if an event has occurred, just prior to the number of blobs being counted. Thus this image forms the basis for determining whether an event is generated and outlining on alarmed images is done from the blobs in this image.
* Alarmed Pixels - This image shows all pixels in the zone that are considered to be alarmed as white pixels and all other pixels as black.
* Filtered Pixels - This is as stage one except that all pixels removed by the filters are now black. The white pixels represent the pixels that are candidates to generate an event.
* Raw Blobs - This image contains all alarmed pixels from stage 2 but aggrageted into blobs. Each blob will have a different greyscale value (between 1 and 254) so they can be difficult to spot with the naked eye but using a colour picker or photoshop will make it easier to see what blob is what.
* Filtered Blobs - This image is as stage 3 but under (or over) sized blobs have been removed. This is the final step before determining if an event has occurred, just prior to the number of blobs being counted. Thus this image forms the basis for determining whether an event is generated and outlining on alarmed images is done from the blobs in this image.
Using the above images you should be able to tell at all stages what ZM is doing to determine if an event should happen or not. They are useful diagnostic tools but as is mentioned elsewhere they will massively slow your system down and take up a great deal more space. You should never leave ZM running for any length of time with diagnostic images on.
Why can't ZoneMinder capture images (either at all or just particularly fast) when I can see my camera just fine in xawtv or similar?
----------------------------------------------------------------------------------------------------------------------------------------------
@ -259,14 +165,14 @@ On average a card that can capture at 25fps per chip PAL for one input will do m
When using xawtv etc to view the stream you are not looking at an image captured using the frame grabber but the card's video memory mapped onto your screen. This requires no capture or processing unless you do an explicit capture via the J or ctrl-J keys for instance. Some cards or drivers do not support the frame grabber interface at all so may not work with ZoneMinder even though you can view the stream in xawtv. If you can grab a still using the grab functionality of xawtv then in general your card will work with ZoneMinder.
Why can't I see streamed images when I can see stills in the Zone window etc?
Why can't I see streamed images when I can see stills in the zone window etc?
-------------------------------------------------------------------------------------
This issue is normally down to one of two causes
1) You are using Internet Explorer and are trying to view multi-part jpeg streams. IE does not support these streams directly, unlike most other browsers. You will need to install Cambozola or another multi-part jpeg aware plugin to view them. To do this you will need to obtain the applet from the Downloads page and install the cambozola.jar file in the same directory as the ZoneMinder php files. Then find the ZoneMinder Options->Images page and enable ZM_OPT_CAMBOZOLA and enter the web path to the .jar file in ZM_PATH_CAMBOZOLA. This will ordinarily just be cambozola.jar. Provided (Options / B/W tabs) WEB_H_CAN_STREAM is set to auto and WEB_H_STREAM_METHOD is set to jpeg then Cambozola should be loaded next time you try and view a stream.
1) You are using Internet Explorer and are trying to view multi-part jpeg streams. IE does not support these streams directly, unlike most other browsers. You will need to install Cambozola or another multi-part jpeg aware plugin to view them. To do this you will need to obtain the applet from the Downloads page and install the cambozola.jar file in the same directory as the ZoneMinder php files. Then find the ZoneMinder Options->Images page and enable ``OPT_CAMBOZOLA`` and enter the web path to the .jar file in ``PATH_CAMBOZOLA``. This will ordinarily just be cambozola.jar. Provided (Options / B/W tabs) ``WEB_H_CAN_STREAM`` is set to auto and ``WEB_H_STREAM_METHOD`` is set to jpeg then Cambozola should be loaded next time you try and view a stream.
'''NOTE''': If you find that the Cambozola applet loads in IE but the applet just displays the version # of Cambozola and the author's name (as opposed to seeing the streaming images), you may need to chmod (''-rwxrwxr-x'') your (''usr/share/zoneminder/'') cambozola.jar:
**NOTE**: If you find that the Cambozola applet loads in IE but the applet just displays the version of Cambozola and the author's name (as opposed to seeing the streaming images), you may need to chmod (``-rwxrwxr-x``) your (``usr/share/zoneminder/``) cambozola.jar:
::
@ -274,9 +180,7 @@ This issue is normally down to one of two causes
Once I did this, images started to stream for me.
2) The other common cause for being unable to view streams is that you have installed the ZoneMinder cgi binaries (zms and nph-zms) in a different directory than your web server is expecting. Make sure that the --with-cgidir option you use to the ZoneMinder configure script is the same as the CGI directory configure for your web server. If you are using Apache, which is the most common one, then in your httpd.conf file there should be a line like ``ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"`` where the last directory in the quotes is the one you have specified. If not then change one or the other to match. Be warned that configuring apache can be complex so changing the one passed to the ZoneMinder configure (and then rebuilding and reinstalling) is recommended in the first instance. If you change the apache config you will need to restart apache for the changes to take effect. If you still cannot see stream reliably then try changing Options->Paths->ZM_PATH_ZMS to just use zms if nph-zms is specified, or vice versa. Also check in your apache error logs.
Also, please check the value of the ZM_PATH_ZMS setting under the Paths Options tab. It is where you configure the URL to the zms or nph-zms CGI executable. Under most Debian-based distros this value should be /zm/cgi-bin/nph-zms but in the past may have been /cgi-bin/nph-zms or you may have configured it to be something else.
2) The other common cause for being unable to view streams is that you have installed the ZoneMinder cgi binaries (zms and nph-zms) in a different directory than your web server is expecting. Make sure that the --with-cgidir option you use to the ZoneMinder configure script is the same as the CGI directory configure for your web server. If you are using Apache, which is the most common one, then in your httpd.conf file there should be a line like ``ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"`` where the last directory in the quotes is the one you have specified. If not then change one or the other to match. Be warned that configuring apache can be complex so changing the one passed to the ZoneMinder configure (and then rebuilding and reinstalling) is recommended in the first instance. If you change the apache config you will need to restart apache for the changes to take effect. If you still cannot see stream reliably then try changing ``ZM_PATH_ZMS`` in your ``/etc/zm/config`` directory to just use zms if nph-zms is specified, or vice versa. Also check in your apache error logs.
Lastly, please look for errors created by the zmc processes. If zmc isn't running, then zms will not be able to get an image from it and will exit.
@ -302,6 +206,11 @@ change the 3 to a 1
network.http.max-persistent-connections-per-proxy -> 100 again
network.http.max-persistent-connections-per-server -> 100 again
I can't see more than 6 monitors in montage on my browser
---------------------------------------------------------
Browsers such a Chrome and Safari only support upto 6 streams from the same domain. To work around that, take a look at the multi-port configuration discussed in the ``MIN_STREAMING_PORT`` configuration in :doc:`/userguide/options/options_network`
Why is ZoneMinder using so much CPU?
---------------------------------------
@ -315,8 +224,8 @@ The main causes are.
* Big image sizes. A image of 640x480 requires at least four times the processing of a 320x240 image. Experiment with different sizes to see what effect it may have. Sometimes a large image is just two interlaced smaller frames so has no real benefit anyway. This is especially true for analog cameras/cards as image height over 320 (NTSC) or 352 PAL) are invariably interlaced.
* Capture frame rates. Unless there's a compelling reason in your case there is often little benefit in running cameras at 25fps when 5-10fps would often get you results just as good. Try changing your monitor settings to limit your cameras to lower frame rates. You can still configure ZM to ignore these limits and capture as fast as possible when motion is detected.
* Run function. Obviously running in Record or Mocord modes or in Modect with lots of events generates a lot of DB and file activity and so CPU and load will increase.
* Basic default detection zones. By default when a camera is added one detection zone is added which covers the whole image with a default set of parameters. If your camera covers a view in which various regions are unlikely to generate a valid alarm (ie the sky) then I would experiment with reducing the zone sizes or adding inactive zones to blank out areas you don't want to monitor. Additionally the actual settings of the zone themselves may not be optimal. When doing motion detection the number of changed pixels above a threshold is examined, then this is filter, then contiguous regions are calculated to see if an alarm is generated. If any maximum or minimum threshold is exceeded according to your zone settings at any time the calculation stops. If your settings always result in the calculations going through to the last stage before being failed then additional CPU time is used unnecessarily. Make sure your maximum and minimumzone thresholds are set to sensible values and experiment by switching RECORD_EVENT_STATS on and seeing what the actual values of alarmed pixels etc are during sample events.
* Optimise your settings. After you've got some settings you're happy with then switching off RECORD_EVENT_STATS will prevent the statistics being written to the database which saves some time. Other settings which might make a difference are ZM_FAST_RGB_DIFFS and the JPEG_xxx_QUALITY ones.
* Basic default detection zones. By default when a camera is added one detection zone is added which covers the whole image with a default set of parameters. If your camera covers a view in which various regions are unlikely to generate a valid alarm (ie the sky) then I would experiment with reducing the zone sizes or adding inactive zones to blank out areas you don't want to monitor. Additionally the actual settings of the zone themselves may not be optimal. When doing motion detection the number of changed pixels above a threshold is examined, then this is filter, then contiguous regions are calculated to see if an alarm is generated. If any maximum or minimum threshold is exceeded according to your zone settings at any time the calculation stops. If your settings always result in the calculations going through to the last stage before being failed then additional CPU time is used unnecessarily. Make sure your maximum and minimumzone thresholds are set to sensible values and experiment by switching ``RECORD_EVENT_STATS`` on and seeing what the actual values of alarmed pixels etc are during sample events.
* Optimise your settings. After you've got some settings you're happy with then switching off ``RECORD_EVENT_STATS`` will prevent the statistics being written to the database which saves some time. Other settings which might make a difference are ``ZM_FAST_RGB_DIFFS`` and the ``JPEG_xxx_QUALITY`` ones.
I'm sure there are other things which might make a difference such as what else you have running on the box and memory sizes (make sure there's no swapping going on). Also speed of disk etc will make some difference during event capture and also if you are watching the whole time then you may have a bunch of zms processes running also.
@ -330,17 +239,19 @@ Using the timeline view is only recommended when using FireFox, however even the
This function has from time to time been corrupted in the SVN release or in the stable releases, try and reinstall from a fresh download.
.. _disk_bw_faq:
How much Hard Disk Space / Bandwidth do I need for ZM?
---------------------------------------------------------------
Please see `this excel sheet <http://www.jpwilson.eu/ZM_Utils/ZM%20storage%20calc%20sheet.xls>`__ or `this online excel sheet <https://docs.google.com/spreadsheets/d/1G2Er8fZ_lWQv9QV8qf9yGCMkiUG03a-UwgLLxzCL0OY/edit#gid=49279749>`__ (both are user contributed excel sheets)
Please see `this online excel sheet <https://docs.google.com/spreadsheets/d/1iPMCGwlXiW8WnQuewgFhUqBs7ZaPKqXDkBtCQVHR6H0/edit?usp=sharing>`__. Note that this is just an estimate
Or go to `this link <http://www.axis.com/products/video/design_tool/index.html>`__ for the Axis bandwidth calculator. Although this is aimed at Axis cameras it still produces valid results for any kind of IP camera.
Or go to `this link <http://www.axis.com/products/video/design_tool/v2/>`__ for the Axis bandwidth calculator. Although this is aimed at Axis cameras it still produces valid results for any kind of IP camera.
As a quick guide I have 4 cameras at 320x240 storing 1 fps except during alarm events. After 1 week 60GB of space in the volume where the events are stored (/var/www/html/zm) has been used.
When I try and run ZoneMinder I get lots of audit permission errors in the logs and it won't start
-------------------------------------------------------------------------------------------------------
Many Linux distributions nowadays are built with security in mind. One of the latest methods of achieving this is via SELinux (Secure Linux) which controls who is able to run what in a more precise way then traditional accounting and file based permissions (`link <http://en.wikipedia.org/wiki/Selinux>`__).
Many Linux distributions nowadays are built with security in mind. One of the latest methods of achieving this is via SELinux (Secure Linux) which controls who is able to run what in a more precise way then traditional accounting and file based permissions (`link <https://en.wikipedia.org/wiki/Selinux>`__).
If you are seeing entries in your system log like:
Jun 11 20:44:02 kernel: audit(1150033442.443:226): avc: denied { read } for pid=5068
@ -353,38 +264,13 @@ Note that SELinux may cause errors other than those listed above. If you are in
How do I enable ZoneMinder's security?
-------------------------------------------
In the console, click on Options. Check the box next to "ZM_OPT_USE_AUTH". You will immediately be asked to login. The default username is 'admin' and the password is 'admin'.
In the console, click on ``Options->System``. Check the box next to ``ZM_OPT_USE_AUTH``. You will immediately be asked to login. The default username is 'admin' and the password is 'admin'.
To Manage Users:
In main console, go to Options->Users.
In main console, go to ``Options->Users``.
You may also consider to use the web server security, for example, htaccess files under Apache scope; You may even use this as an additional/redundant security on top of Zoneminders built-in security features;
You may also consider to use the web server security, for example, htaccess files under Apache scope; You may even use this as an additional/redundant security on top of Zoneminders built-in security features. Note that if you choose to enable webserver auth, zmNinja may have issues. Please read the `zmNinja FAQ on basic authentication <https://zmninja.readthedocs.io/en/latest/guides/FAQ.html#i-can-t-see-streams-i-use-basic-auth>`__ for more information. Also please note that zmNinja does not support digest authentication.
Why does ZM stop recording once I have 32000 events for my monitor?
------------------------------------------------------------------------
Storing more than 32k files in a single folder is a limitation of some filesystems. To avoid this, enable USE_DEEP_STORAGE under Options.
USE_DEEP_STORAGE is now the default for new ZoneMinder systems so this limitation should only apply to users upgrading from a previous version of ZoneMinder.
Versions of ZM from 1.23.0 onwards allow you to have a deeper filesystem with fewer files per individual directory. As well as not being susceptible to the 32k limit, this is also somewhat faster.
If you have upgraded from a previous version of ZoneMinder and this option is not already enabled, it is very important to follow the steps below to enable it on an existing system. Failure to properly follow these steps **WILL RESULT IN LOSS OF YOUR DATA!**
::
# Stop ZoneMinder
# Backup your event data and the dB if you have the available storage
# Enable USE_DEEP_STORAGE under Options.
# From the command line, run "sudo zmupdate.pl --migrate-events"
# Monitor the output for any events that fail to convert.
# After the conversion completes, you can restart ZoneMinder
Note that you can re-run the migrate-events command if any error messages scroll off the screen.
You can read about the lack of a limit in the number of sub-directories in the ext4 filesystem at: `this link <http://kernelnewbies.org/Ext4>`__
and see what tools may assist in your use of this filesystem `here <http://ext4.wiki.kernel.org/index.php/Ext4_Howto>`__
If you search for ext3 or reiserfs on the forums you will find various threads on this issue with guidance on
how to convert.
Managing system load (with IP Cameras in mind)
----------------------------------------------------
@ -410,7 +296,7 @@ Zoneminder runs on Linux, Linux measures system load using "load", which is comp
A load of 1.0 means the processor has "just enough to do right now". Also worth noting that a load of 4.0 means exactly the same for a quad processor machine - each number equals a single processor's workload. A very high load can be fine on a computer that has a stacked workload - such as a machine sending out bulk emails, or working its way through a knotty problem; it'll just keep churning away until it's done. However - Zoneminder needs to process information in real time so it can't afford to stack its jobs, it needs to deal with them right away.
For a better and full explanation of Load: `Please read this <http://en.wikipedia.org/wiki/Load_%28computing%29>`__
For a better and full explanation of Load: `Please read this <https://en.wikipedia.org/wiki/Load_%28computing%29>`__
My load is too high, how can I reduce it?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -427,7 +313,7 @@ Zoneminder is *very* tweakable and it's possible to tune it to compromise. The f
* Experiment with using jpeg instead of mjpeg. Some users have reported it gives better performance, but YMMV.
* Tweak the zones. Keep them as small and as few as possible. Stick to one zone unless you really need more. Read `this <http://www.zoneminder.com/wiki/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__ for an easy to understand explanation along with the official Zone guide.
* Tweak the zones. Keep them as small and as few as possible. Stick to one zone unless you really need more. Read `this <https://wiki.zoneminder.com/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__ for an easy to understand explanation along with the official Zone guide.
* Schedule. If you are running a linux system at near capacity, you'll need to think carefully about things like backups and scheduled tasks. updatedb - the process which maintains a file database so that 'locate' works quickly, is normally scheduled to run once a day and if on a busy system can create a heavy increase on the load. The same is true for scheduled backups, especially those which compress the files. Re-schedule these tasks to a time when the cpu is less likely to be busy, if possible - and also use the "nice" command to reduce their priority. (crontab and /etc/cron.daily/ are good places to start)
@ -440,73 +326,16 @@ More expensive options:
* Faster CPU. Simple but effective. Zoneminder also works very well with multiple processor systems out of the box (if SMP is enabled in your kernel). The load of different cameras is spread across the processors.
* Try building Zoneminder with processor specific instructions that are optimised to the system it will be running on, also increasing the optimisation level of GCC beyond -O2 will help.
* Try building Zoneminder with processor specific instructions that are optimised to the system it will be running on, also increasing the optimisation level of GCC beyond -O2 will help. This topic is beyond the scope of this document.
::
./configure CFLAGS="-g -O3 -march=athlon-xp -mtune=athlon-xp" CXXFLAGS="-g -O3 -march=athlon-xp -mtune=athlon-xp"
The above command is optimised for an Athlon XP cpu so you will need to use the specific processor tag for your cpu, also the compiler optimisation has been increased to -O3.
You also need to put in your normal ./configure commands as if you were compiling with out this optimisation.
A further note is that the compile must be performed on the system that Zoneminder will be running on as this optimisation will make it hardware specific code.
Processor specific commands can be found in the GCC manual along with some more options that may increase performanc.
`<http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options>`__
The below command has been used to compile Zoneminder on a Athlon XP system running CentOS 5.5 and along with the libjpeg-turbo modification to reduce the CPU load in half, libjpeg-turbo reduced the load by 1/3 before the processor optimisation.
::
./configure --with-webdir=/var/www/html/zm --with-cgidir=/var/www/cgi-bin CFLAGS="-g -O3 -march=athlon-xp -mtune=athlon-xp" CXXFLAGS="-D__STDC_CONSTANT_MACROS -g -O3 -march=athlon-xp -mtune=athlon-xp" --enable-mmap --sysconfdir=/etc/zm
The following command has been used to compile Zoneminder 1.25 on a CentOS 6.0 system, the native command should choose the processor automatically during compile time, this needs to be performed on the actual system!!.
::
CFLAGS="-g -O3 -march=native -mtune=native" CXXFLAGS="-D__STDC_CONSTANT_MACROS -g -O3 -march=native -mtune=native" ./configure --with-webdir=/var/www/html/zm --with-cgidir=/var/www/cgi-bin --with-webuser=apache --with-webgroup=apache ZM_DB_HOST=localhost ZM_DB_NAME=zm ZM_DB_USER=your_zm_user ZM_DB_PASS=your_zm_password ZM_SSL_LIB=openssl
Processor specific commands can be found in the `GCC manual <https://gcc.gnu.org/onlinedocs/gcc/>`__ along with some more options that may increase performance.
What about disks and bandwidth?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A typical 100mbit LAN will cope with most setups easily. If you're feeding from cameras over smaller or internet links, obviously fps will be much lower.
Disk and Bandwidth calculators are referenced on the Zoneminder wiki here: http://www.zoneminder.com/wiki/index.php/FAQ#How_much_Hard_Disk_Space_.2F_Bandwidth_do_I_need_for_ZM.3F
Building ZoneMinder
--------------------
When running configure I am getting a lot of messages about not being able to compile the ffmpeg libraries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you see output from configure that looks like this
::
checking libavcodec/avcodec.h usability... no
checking libavcodec/avcodec.h presence... yes
configure: WARNING: libavcodec/avcodec.h: present but cannot be compiled
configure: WARNING: libavcodec/avcodec.h: check for missing
prerequisite headers?
configure: WARNING: libavcodec/avcodec.h: see the Autoconf documentation
configure: WARNING: libavcodec/avcodec.h: section "Present But
Cannot Be Compiled"
configure: WARNING: libavcodec/avcodec.h: proceeding with the compiler's
result
configure: WARNING: ## ------------------------------------- ##
configure: WARNING: ## Report this to support@zoneminder.com ##
configure: WARNING: ## ------------------------------------- ##</pre>
then it is caused not by the ZoneMinder build system but ffmpeg itself. However there is a workaround you can use which is to add ``CPPFLAGS=-D__STDC_CONSTANT_MACROS``
to the ZoneMinder ``./configure`` command which should solve the issue. However this is not a proper 'fix' as such, which can only come from the ffmpeg project itself.
I cannot build ZoneMinder and am getting lots of undefined C++ template errors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is almost certainly due to the 'ccache' package which attempts to speed up compilation by caching compiled objects. Unfortunately one of the side effects is that it breaks the GNU g++ template resolution method that ZoneMinder uses in building by prevent files getting recompiled. The simplest way around this is to remove the ccache package using your distros package manager.
Disk and Bandwidth calculators are referenced in :ref:`disk_bw_faq`.
How do I build for X10 support?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -530,7 +359,7 @@ To save a run state you should first configure your monitors for Modect, Record,
Now you can switch between these two states by selecting them from the same dialog you saved them, or from the command line from issue the command ''zmpkg.pl <run state>'', for example ''zmpkg.pl Daytime''.
The final step you need to take, is scheduling the time the changes take effect. For this you can use `cron <http://en.wikipedia.org/wiki/Cron>`__. A simple entry to change to the Daylight state at at 8am and to the nighttime state at 8pm would be as follows,
The final step you need to take, is scheduling the time the changes take effect. For this you can use `cron <https://en.wikipedia.org/wiki/Cron>`__. A simple entry to change to the Daylight state at at 8am and to the nighttime state at 8pm would be as follows,
::
@ -544,50 +373,10 @@ Although the example above describes changing states at different times of day,
How can I use ZoneMinder to trigger something else when there is an alarm?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ZoneMinder includes a perl API which means you can create a script to interact with the ZM shared memory data and use it in your own scripts to react to ZM alarms or to trigger ZM to generate new alarms. Full details are in the README or by doing ``perldoc ZoneMinder``, ``perldoc ZoneMinder::SharedMem`` etc.
Below is an example script that checks all monitors for alarms and when one occurs, prints a message to the screen. You can add in your own code to make this reaction a little more useful.
ZoneMinder includes a perl API which means you can create a script to interact with the ZM shared memory data and use it in your own scripts to react to ZM alarms or to trigger ZM to generate new alarms. Full details are in the README or by doing ``perldoc ZoneMinder`` etc.
::
ZoneMinder provides a sample alarm script called `zmalarm.pl <https://github.com/ZoneMinder/zoneminder/blob/master/utils/zm-alarm.pl>`__ that you can refer to as a starting point.
#!/usr/bin/perl -w
use strict;
use ZoneMinder;
$| = 1;
zmDbgInit( "myscript", level=>0, to_log=>0, to_syslog=>0, to_term=>1 );
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS );
my $sql = "select M.*, max(E.Id) as LastEventId from Monitors as M left join Events as E on M.Id = E.MonitorId where M.Function != 'None' group by (M.Id)";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
my @monitors;
while ( my $monitor = $sth->fetchrow_hashref() )
{
push( @monitors, $monitor );
}
while( 1 )
{
foreach my $monitor ( @monitors )
{
next if ( !zmMemVerify( $monitor ) );
if ( my $last_event_id = zmHasAlarmed( $monitor, $monitor->{LastEventId} ) )
{
$monitor->{LastEventId} = $last_event_id;
print( "Monitor ".$monitor->{Name}." has alarmed\n" );
#
# Do your stuff here
#
}
}
sleep( 1 );
}
Trouble Shooting
-------------------
@ -596,13 +385,9 @@ This is also how to obtain the info that we need to help you on the forums.
What logs should I check for errors?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ZoneMinder creates its own logs and are usually located in the ``/tmp`` directory.
ZoneMinder creates its own logs and are usually located in the ``/var/log/`` directory. Refer to the logging discussion in :doc:`/userguide/options/options_logging` for more details on where logs are stored and how to enable various log levels.
The ZoneMinder logs for the RPM packages are located in ``/var/log/zm``.
Depending on your problem errors can show up in any of these logs but, usually the logs of interest are ``zmdc.log`` and ``zmpkg.log`` if ZM is not able to start.
Now since ZM is dependent on other components to work, you might not find errors in ZM but in the other components.
Since ZM is dependent on other components to work, you might not find errors in ZM but in the other components.
::
@ -618,8 +403,6 @@ If ZM is not functioning, you should always be able to find an error in at least
This will append any data entered to any of these logs to your console screen (``-f``). To exit, hit [ctrl -c].
More verbose logging for the ZoneMinder binaries is available by enabling the debug option from the control panel and will be placed in the path you have configured for the debug logs. Output can be limited to a specific binary as described in the Debug options page under the "?" marks.
How can I trouble shoot the hardware and/or software?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -643,12 +426,33 @@ The apache web server needs to have the right permissions and configuration to b
Why am I getting broken images when trying to view events?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Zoneminder and the Apache web server need to have the right permissions. Check this forum topic and similar ones:
http://www.zoneminder.com/forums/viewtopic.php?p=48754#48754
Zoneminder and the Apache web server need to have the right permissions. Check `this forum topic <https://forums.zoneminder.com/viewtopic.php?p=48754>`__ and similar ones:
I can review events for the current day, but ones from yesterday and beyond error out
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you've checked that the ``www-data`` user has permissions to the storage folders, perhaps your php.ini's timezone setting is incorrect. They _must_ match for certain playback functions.
If you're using Linux, this can be found using the following command:
::
timedatectl | grep "Time zone"
If using FreeBSD, you can use this one-liner:
::
cd /usr/share/zoneinfo/ && find * -type f -exec cmp -s {} /etc/localtime \; -print;
Once you know what timezone your system is set to make sure you set the right time zone in ZM (Available in ``Options->System->TimeZone``)
Why is the image from my color camera appearing in black and white?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you recently upgraded to zoneminder 1.26, there is a per camera option that defaults to black and white and can be mis-set if your upgrade didn't happen right. See this thread: http://www.zoneminder.com/forums/viewtopic.php?f=30&t=21344
If you recently upgraded to zoneminder 1.26, there is a per camera option that defaults to black and white and can be mis-set if your upgrade didn't happen right. See this thread: https://forums.zoneminder.com/viewtopic.php?f=30&t=21344
This may occur if you have a NTSC analog camera but have configured the source in ZoneMinder as PAL for the Device Format under the source tab. You may also be mislead because zmu can report the video port as being PAL when the camera is actually NTSC. Confirm the format of your analog camera by checking it's technical specifications, possibly found with the packaging it came in, on the manufacturers website, or even on the retail website where you purchased the camera. Change the Device Format setting to NTSC and set it to the lowest resolution of 320 x 240. If you have confirmed that the camera itself is NTSC format, but don't get a picture using the NTSC setting, consider increasing the shared memory '''kernel.shmall''' and '''kernel.shmmax''' settings in /etc/sysctl.conf to a larger value such as 268435456. This is also the reason you should start with the 320x240 resolution, so as to minimize the potential of memory problems which would interfere with your attempts to troubleshoot the device format issue. Once you have obtained a picture in the monitor using the NTSC format, then you can experiment with raising the resolution.
@ -658,39 +462,17 @@ If this camera is attached to a capture card, then you may have selected the wro
Why do I only see black screens with a timestamp when monitoring my camera?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the monitor windows where you see the black screen with a timestamp, select settings and enter the Brightness, Contrast, Hue, and Color settings reported for the device by '''zmu -d <device_path> -q -v'''. 32768 may be appropriate values to try for these settings. After saving the settings, select Settings again to confirm they saved successfully.
In the monitor windows where you see the black screen with a timestamp, select settings and enter the Brightness, Contrast, Hue, and Color settings reported for the device by ``zmu -d <device_path> -q -v``. 32768 may be appropriate values to try for these settings. After saving the settings, select Settings again to confirm they saved successfully.
I am getting messages about a backtrace in my logs, what do I do?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you are seeing entries in your log like the following
::
Jan 11 20:25:22 localhost zma_m2[19051]: ERR [Backtrace: /lib64/libc.so.6 [0x3347230210]]
Jan 11 20:25:22 localhost zma_m2[19051]: ERR [Backtrace: /lib64/libc.so.6(memset+0xce) [0x334727684e]]
Jan 11 20:25:22 localhost zma_m2[19051]: ERR [Backtrace: /usr/local/bin/zma [0x40ee9a]]
Jan 11 20:25:22 localhost zma_m2[19051]: ERR [Backtrace: /usr/local/bin/zma [0x419946]]
Jan 11 20:25:22 localhost zma_m2[19051]: ERR [Backtrace: /usr/local/bin/zma [0x4213cf]]
Jan 11 20:25:22 localhost zma_m2[19051]: ERR [Backtrace: /usr/local/bin/zma(cos+0x35c) [0x404674]]
Jan 11 20:25:22 localhost zma_m2[19051]: ERR [Backtrace: /lib64/libc.so.6(__libc_start_main+0xf4) [0x334721da44]]
Jan 11 20:25:22 localhost zma_m2[19051]: ERR [Backtrace: /usr/local/bin/zma(cos+0xd1) [0x4043e9]]
Jan 11 20:25:22 localhost zma_m2[19051]: INF [Backtrace complete]</pre>
then you can help diagnose the problem by running a special command to translate the hex addresses into helpful information. This command is called addr2line and you can type 'man addr2line' for more information.
Basically addr2line takes two sets of parameters, the first is the name of the binary file, and the second is a list of addresses. Both of these pieces of information are displayed in the logs. The filename is the first part after the 'Backtrace:' tag, in this case /usr/local/bin/zma, though it may well be different in your case. Some of the lines refer to libraries rather than the zma executable but those can be ignored for now, the important part is noting which ZM binary is involved. The binary file is passed in following the -e flag. The addresses to pass to addr2line are those contained in the '[]' pairs. Again you can ignore those that are on a line that refers to a library but it will not hurt if you include them.
So in the example above, the command would be ``addr2line -e /usr/local/bin/zma 0x40ee9a 0x419946 0x4213cf 0x404674 0x4043e9``
This should then dump out a more symbolic list containing source file names and line numbers, and it is this information which will be helpful if posted to the forums. Sometimes addr2line fails to produce useful output. This is usually because either the problem is so severe that it has corrupted the stack and prevented useful information from being displayed, or that you have either compiled ZM without the -g flag for debug, or you have stripped the binaries of symbol information after installation. This this case you would need to rebuild temporarily with debug enabled for the information to be useful.
This error some times happens when a linked camera looses its link or it is corrupted by the user or some other system event, try deleting the affected cameras and recreating them in the Zoneminder console.
How do I repair the MySQL Database?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There is two ways to go about this. In most cases you can run from the command prompt ->
* mysqlcheck --all-databases --auto-repair -p'''your_database_password''' -u '''your_databse_user'''
``mysqlcheck --all-databases --auto-repair -p your_database_password -u your_databse_user``
If that does not work then you will have to make sure that ZoneMinder is stopped then run the following (nothing should be using the database while running this and you will have to adjust for your correct path if it is different). ->
* myisamchk --silent --force --fast --update-state -O key_buffer=64M -O sort_buffer=64M -O read_buffer=1M -O write_buffer=1M /var/lib/mysql/*/*.MYI
If that does not work then you will have to make sure that ZoneMinder is stopped then run the following (nothing should be using the database while running this and you will have to adjust for your correct path if it is different):
``myisamchk --silent --force --fast --update-state -O key_buffer=64M -O sort_buffer=64M -O read_buffer=1M -O write_buffer=1M /var/lib/mysql/*/*.MYI``
How do I repair the MySQL Database when the cli fails?
@ -698,7 +480,7 @@ How do I repair the MySQL Database when the cli fails?
In Ubuntu, the commands listed above do not seem to work. However, actually doing it by hand from within MySQL does. (But that is beyond the scope of this document) But that got me thinking... And phpmyadmin does work. Bring up a terminal.
``sudo apt-get install phpmyadmin``
Now go to http://zoneminder_IP/ and stop the ZM service. Continue to http://zoneminder_IP/phpmyadmin and select the zoneminder database. Select and tables marked 'in use' and pick the action 'repare' to fix. Restart the zoneminder service from the web browser. Remove or disable the phpmyadmin tool, as it is not always the most secure thing around, and opens your database wide to any skilled hacker.
Now go to ``http://zoneminder_IP/`` and stop the ZM service. Continue to ``http://zoneminder_IP/phpmyadmin`` and select the zoneminder database. Select and tables marked 'in use' and pick the action 'repare' to fix. Restart the zoneminder service from the web browser. Remove or disable the phpmyadmin tool, as it is not always the most secure thing around, and opens your database wide to any skilled hacker.
``sudo apt-get remove phpmyadmin``
I upgraded by distribution and ZM stopped working
@ -728,6 +510,8 @@ What causes "Invalid JPEG file structure: two SOI markers" from zmc (1.24.x)
Some settings that used to be global only are now per camera. On the Monitor Source tab, if you are using Remote Protocol "HTTP" and Remote Method "Simple", try changing Remote Method to "Regexp".
Miscellaneous
-------------------
I see ZoneMinder is licensed under the GPL. What does that allow or restrict me in doing with ZoneMinder?
@ -741,10 +525,13 @@ The ZoneMinder license is described at the end of the documentation and consists
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.
This means that ZoneMinder is licensed under the terms described `here <http://www.gnu.org/copyleft/gpl.html>`__. There is a comprehensive FAQ covering the GPL at http://www.gnu.org/licenses/gpl-faq.html but in essence you are allowed to redistribute or modify GPL licensed software provided that you release your distribution or modifications freely under the same terms. You are allowed to sell systems based on GPL software. You are not allowed to restrict or reduce the rights of GPL software in your distribution however. Of course if you are just making modifications for your system locally you are not releasing changes so you have no obligations in this case. I recommend reading the GPL FAQ for more in-depth coverage of this issue.
This means that ZoneMinder is licensed under the terms described `here <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>`__. There is a comprehensive FAQ covering the GPL at https://www.gnu.org/licenses/gpl-faq.html but in essence you are allowed to redistribute or modify GPL licensed software provided that you release your distribution or modifications freely under the same terms. You are allowed to sell systems based on GPL software. You are not allowed to restrict or reduce the rights of GPL software in your distribution however. Of course if you are just making modifications for your system locally you are not releasing changes so you have no obligations in this case. I recommend reading the GPL FAQ for more in-depth coverage of this issue.
Can I use ZoneMinder as part of my commercial product?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The GPL license allows you produce systems based on GPL software provided your systems also adhere to that license and any modifications you make are also released under the same terms. The GPL does not permit you to include ZoneMinder in proprietary systems (see http://www.gnu.org/licenses/gpl-faq.html#GPLInProprietarySystem for details). If you wish to include ZoneMinder in this kind of system then you will need to license ZoneMinder under different terms. This is sometimes possible and you will need to contact me for further details in these circumstances.
The GPL license allows you produce systems based on GPL software provided your systems also adhere to that license and any modifications you make are also released under the same terms. The GPL does not permit you to include ZoneMinder in proprietary systems (see https://www.gnu.org/licenses/gpl-faq.html#GPLInProprietarySystem for details). If you wish to include ZoneMinder in this kind of system then you will need to license ZoneMinder under different terms. This is sometimes possible and you will need to contact me for further details in these circumstances.
I am having issues with zmNinja and/or Event Notification Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
zmNinja and the Event Notification Server are 3rd party solutions. The developer maintains exhaustive `documentation and FAQs <https://zmninja.readthedocs.io/en/latest/>`__. Please direct your questions there.

View File

@ -10,7 +10,9 @@ ZoneMinder Documentation
faq
contributing
Welcome to ZoneMinder's documentation, the following resources are available
Welcome to ZoneMinder's documentation. Please navigate to one of the links below.
If you are facing issues that are not covered in the documentation, please feel free to check the `ZoneMinder Forums <https://forums.zoneminder.com/viewforum.php?f=26>`__ or join the `ZoneMinder-Chat Slack channel <https://join.slack.com/t/zoneminder-chat/shared_invite/enQtNTU0NDkxMDM5NDQwLTdhZmQ5Y2M2NWQyN2JkYTBiN2ZkMzIzZGQ0MDliMTRmM2FjZWRlYzUwYTQ2MjMwMTVjMzQ1NjYxOTdmMjE2MTE>`__ if you prefer real time interaction.
:doc:`installationguide/index`
Many distribution repos only hold older versions of ZoneMinder, current versions contain many bug fixes and updated functionality. Instructions here for installing updated packages or compiling from source.
@ -27,6 +29,9 @@ Welcome to ZoneMinder's documentation, the following resources are available
:doc:`contributing`
How to contribute to ZoneMinder. As a community project we always need help, you don't need to be a coder to test or update documentation.
`Event Notification Server and Machine Learning hooks <https://zmeventnotification.readthedocs.io/en/latest/index.html>`__
Documentation for the 3rd party Event Notification Server and Machine Learning for Object/People/Face detection.
Indices and tables

View File

@ -65,7 +65,7 @@ Because ZoneMinder's package repository provides a secure connection through HTT
Finally, download the GPG key for ZoneMinder's repository:
::
sudo wget -O - https://zmrepo.zoneminder.com/debian/archive-keyring.gpg | sudo apt-key add -
wget -O - https://zmrepo.zoneminder.com/debian/archive-keyring.gpg | sudo apt-key add -
**Step 5:** Install ZoneMinder
@ -82,8 +82,7 @@ a read.
::
gunzip /usr/share/doc/zoneminder/README.Debian.gz
cat /usr/share/doc/zoneminder/README.Debian
zcat /usr/share/doc/zoneminder/README.Debian.gz
**Step 7:** Enable ZoneMinder service
@ -190,11 +189,17 @@ Add the following to the bottom of the file
::
# Backports repository
deb http://httpredir.debian.org/debian jessie-backports main contrib non-free
deb http://archive.debian.org/debian/ jessie-backports main contrib non-free
CTRL+o and <Enter> to save
CTRL+x to exit
Run the following
::
echo 'Acquire::Check-Valid-Until no;' > /etc/apt/apt.conf.d/99no-check-valid-until
**Step 5:** Install ZoneMinder
::
@ -209,8 +214,7 @@ a read.
::
gunzip /usr/share/doc/zoneminder/README.Debian.gz
cat /usr/share/doc/zoneminder/README.Debian
zcat /usr/share/doc/zoneminder/README.Debian.gz
**Step 7:** Setup Database

View File

@ -0,0 +1,11 @@
An Easy To Use Docker Image
===========================
If you are interested in trying out ZoneMinder quickly, user Dan Landon maintains an easy to use docker image for ZoneMinder. With a few simple configuration changes, it also provides complete Event Notification Server and Machine Learning hook support. Please follow instructions in his repostory. He maintains two repositories:
* If you want to run the latest stable release, please use his `zoneminder repository <https://github.com/dlandon/zoneminder>`__.
* If you want to run the latest zoneminder master, please use his `zoneminder master repository <https://github.com/dlandon/zoneminder.master-docker>`__.
In both cases, instructions are provided in the repo README files.
If you are looking at building your own native (non docker) binary packages of ZoneMinder for your distro, please refer to the distro specific install guides or :doc:`packpack`.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -1,14 +1,18 @@
Installation Guide
======================================
.. todo:: This entire guide needs to be checked/updated as needed
Contents:
.. toctree::
:maxdepth: 2
easydocker
packpack
ubuntu
debian
redhat
windows_wsl
multiserver
dedicateddrive

View File

@ -1,6 +1,8 @@
All Distros - A Docker Way to Build ZoneMinder
===============================================
.. note:: If you are looking for an easy way to run ZoneMinder and not interested in building your own docker image, please refer to :doc:`easydocker`.
.. contents::
These instructions represent an alternative way to build ZoneMinder for any supported distro.
@ -124,4 +126,4 @@ More testing needs to be done for Redhat distros but it appears Fedora users can
sudo systemctl start systemd-binfmt
TO-DO: Verify the details behind enabling qemu emulation on redhat distros. Pull requests are welcome.
.. todo:: Verify the details behind enabling qemu emulation on redhat distros. Pull requests are welcome.

View File

@ -101,7 +101,7 @@ Certain commands in these instructions require root privileges while other comma
Set Up Your Environment
***********************
Before you begin, set up an rpmbuild environment by following `this guide <http://wiki.centos.org/HowTos/SetupRpmBuildEnvironment>`_ by the CentOS developers.
Before you begin, set up an rpmbuild environment by following `this guide <https://wiki.centos.org/HowTos/SetupRpmBuildEnvironment>`_ by the CentOS developers.
In addition, make sure RPM Fusion is enabled as described in the previous section `How to Install ZoneMinder`_.

View File

@ -3,8 +3,8 @@ Ubuntu
.. contents::
Easy Way: Ubuntu 18.04
----------------------
Easy Way: Ubuntu 18.04 (Bionic)
-------------------------------
These instructions are for a brand new ubuntu 18.04 system which does not have ZM
installed.
@ -15,6 +15,7 @@ achieve the same result by running:
::
sudo apt-get install tasksel
sudo tasksel install lamp-server
During installation it will ask you to set up a master/root password for the MySQL.
@ -39,19 +40,10 @@ guide you with a quick search.
following a new release of ZoneMinder. To use this repository instead of the
official Ubuntu repository, enter the following from the command line:
::
add-apt-repository ppa:iconnor/zoneminder
Please note that as of 1.32.0 We are creating a new PPA for each major version, as a means to prevent automatic upgrades from one major version to another. So instead of the above ppa line use the following:
::
add-apt-repository ppa:iconnor/zoneminder-1.32
If you are on Trusty or Xenial, you may want to add both, as there are some packages for dependencies included in the old ppa.
Update repo and upgrade.
::
@ -163,7 +155,7 @@ You may also want to enable to following modules to improve caching performance
nano /etc/php/7.2/apache2/php.ini
Search for [Date] (Ctrl + w then type Date and press Enter) and change
date.timezone for your time zone, see [this](http://php.net/manual/en/timezones.php).
date.timezone for your time zone, see [this](https://www.php.net/manual/en/timezones.php).
**Don't forget to remove the ; from in front of date.timezone**
::
@ -202,8 +194,8 @@ CTRL+x to exit
PPA install may need some tweaking of ZMS_PATH in ZoneMinder options. `Socket_sendto or no live streaming`_
Easy Way: Ubuntu 16.04
----------------------
Easy Way: Ubuntu 16.04 (Xenial)
-------------------------------
These instructions are for a brand new ubuntu 16.04 system which does not have ZM
installed.
@ -241,16 +233,8 @@ guide you with a quick search.
::
add-apt-repository ppa:iconnor/zoneminder
Please note that as of 1.32.0 We are creating a new PPA for each major version, as a means to prevent automatic upgrades from one major version to another. So instead of the above ppa line use the following:
::
add-apt-repository ppa:iconnor/zoneminder-1.32
If you are on Trusty or Xenial, you may want to add both, as there are some packages for dependencies included in the old ppa.
Update repo and upgrade.
::
@ -362,7 +346,7 @@ You may also want to enable to following modules to improve caching performance
nano /etc/php/7.0/apache2/php.ini
Search for [Date] (Ctrl + w then type Date and press Enter) and change
date.timezone for your time zone, see [this](http://php.net/manual/en/timezones.php).
date.timezone for your time zone, see [this](https://www.php.net/manual/en/timezones.php).
**Don't forget to remove the ; from in front of date.timezone**
::
@ -401,8 +385,8 @@ CTRL+x to exit
PPA install may need some tweaking of ZMS_PATH in ZoneMinder options. `Socket_sendto or no live streaming`_
Easy Way: Ubuntu 14.x
---------------------
Easy Way: Ubuntu 14.x (Trusty)
------------------------------
**These instructions are for a brand new ubuntu 14.x system which does not have ZM installed.**
**Step 1:** Either run commands in this install using sudo or use the below to become root
@ -450,7 +434,7 @@ Easy Way: Ubuntu 14.x
nano /etc/php5/apache2/php.ini
Search for [Date] (Ctrl + w then type Date and press Enter) and change
date.timezone for your time zone, see [this](http://php.net/manual/en/timezones.php).
date.timezone for your time zone, see [this](https://www.php.net/manual/en/timezones.php).
**Don't forget to remove the ; from in front of date.timezone**
::

View File

@ -0,0 +1,10 @@
Windows 10+ using WSL
=======================
With Windows 10, Microsoft released the `Window Subsystem for Linux (WSL) <https://docs.microsoft.com/en-us/windows/wsl/faq>`__ that enables you to run native Linux tools directly on Windows, alongside your traditional Windows desktop and modern store apps. To install WSL, please refer to the
`installation guide from Microsoft <https://docs.microsoft.com/en-us/windows/wsl/install-win10>`__.
ZoneMinder now runs on Windows 10+ systems which have WSL enabled. This guide will explain how to go about installing an Ubuntu ZM image on Windows 10+.
.. todo:: Isaac to add instructions.

View File

@ -17,8 +17,6 @@ Binaries
This is the ZoneMinder Capture daemon. This binary's job is to sit on a video device and suck frames off it as fast as possible, this should run at more or less constant speed.
**zma**
This is the ZoneMinder Analysis daemon. This is the component that goes through the captured frames and checks them for motion which might generate an alarm or event. It generally keeps up with the Capture daemon but if very busy may skip some frames to prevent it falling behind.
**zmf**
This is the ZoneMinder Frame daemon. This is an optional daemon that can run in concert with the Analysis daemon and whose function it is to actually write captured frames to disk. This frees up the Analysis daemon to do more analysis (!) and so keep up with the Capture daemon better. If it isnt running or dies then the Analysis daemon just writes them itself.
**zms**
This is the ZoneMinder Streaming server. The web interface connects with this to get real-time or historical streamed images. It runs only when a live monitor stream or event stream is actually being viewed and dies when the event finishes or the associate web page is closed. If you find you have several zms processes running when nothing is being viewed then it is likely you need a patch for apache (see the Troubleshooting section). A non-parsed header version of zms, called nph-zms, is also installed and may be used instead depending on your web server configuration.
**zmu**
@ -41,11 +39,11 @@ Finally some perl scripts in the scripts directory. These scripts all have some
**zmpkg.pl**
This is the ZoneMinder Package Control script. This is used by the web interface and service scripts to control the execution of the system as a whole.
**zmdc.pl**
This is the ZoneMinder Daemon Control script. This is used by the web interface and the zmpkg.pl script to control and maintain the execution of the capture and analysis daemons, amongst others. You should not need to run this script yourself.
This is the ZoneMinder Daemon Control script. This is used by the web interface and the zmpkg.pl script to control and maintain the execution of the capture and analysis daemons, amongst others. You should not need to run this script yourself, although you can use it to start/top individual ZM processes.
**zmfilter.pl**
This script controls the execution of saved filters and will be started and stopped by the web interface based on whether there are filters that have been defined to be autonomous. This script is also responsible for the automatic uploading of events to a 3rd party server.
This script controls the execution of saved filters and will be started and stopped by the web interface based on whether there are filters that have been defined to be autonomous(background). This script is also responsible for the automatic uploading of events to a 3rd party server. Prior to 1.32 there was one zmfilter.pl process. In 1.32 onwards we start a zmfilter.pl process for each background filter so that the processing time of one filter doesn't delay the processing of another filter.
**zmaudit.pl**
This script is used to check the consistency of the event file system and database. It can delete orphaned events, i.e. ones that appear in one location and not the other as well as checking that all the various event related tables are in line. It can be run interactively or in batch mode either from the command line or a cron job or similar. In the zmconfig.pl there is an option to specify fast event deletes where the web interface only deletes the event entry from the database itself. If this is set then it is this script that tidies up the rest.
This script is used to check the consistency of the event file system and database. It can delete orphaned events, i.e. ones that appear in one location and not the other as well as checking that all the various event related tables are in line. It can be run interactively or in batch mode either from the command line or a cron job or similar. In the zmconfig.pl there is an option to specify fast event deletes where the web interface only deletes the event entry from the database itself. If this is set then it is this script that tidies up the rest. We do not recommend fast event deletion and we do not recommend having zmaudit.pl run in the background. It is a very ram cpu and disk io intensive program, constantly scanning every event. Please run it manually or from a cron job on weekends or something.
**zmwatch.pl**
This is a simple script purely designed to keep an eye on the capture daemons and restart them if they lockup. It has been known for sync problems in the video drivers to cause this so this script makes sure that nothing important gets missed.
**zmupdate.pl**
@ -74,6 +72,9 @@ Finally some perl scripts in the scripts directory. These scripts all have some
**zm**
This is the (optional) ZoneMinder init script, see below for details.
**zmeventnotification.pl**
This is an optional 3rd party real time event notification server that also provides push notifications for zmNinja as well as machine learning powered object/face-detection. Please see `Event Notification Server Documentation <https://zmeventnotification.readthedocs.io/en/latest/index.html>`__ for more details (Note that the machine learning components are optional, and are developed in Python3)
Finally, there are also a number of ZoneMinder perl modules included. These are used by the scripts above, but can also be used by your own or 3rd party scripts. Full documentation for most modules is available in pod form via perldoc but the general purpose of each module is as follows.
**ZoneMinder.pm**
@ -86,9 +87,15 @@ Finally, there are also a number of ZoneMinder perl modules included. These are
This module contains the defined Debug and Error functions etc, that are used by scripts to produce diagnostic information in a standard format.
**ZoneMinder/Database.pm**
This module contains database access definitions and functions. Currently not a lot is in this module but it is included as a placeholder for future development.
**ZoneMinder/Event.pm**
This module contains functions to load, manipulate, delete, copy, move events.
**ZoneMinder/Filter.pm**
This module contains functions to load, execute etc filters.
**ZoneMinder/SharedMem.pm**
This module contains standard shared memory access functions. These can be used to access the current state of monitors etc as well as issuing commands to the monitors to switch things on and off. This module effectively provides a ZoneMinder API.
**ZoneMinder/ConfigAdmin.pm**
This module is a specialised module that contains the definition, and other information, about the various configuration options. It is not intended for use by 3rd parties.
**ZoneMinder/Control/\*.pm**
These modules contain implementations of the various PTZ protocols.
**ZoneMinder/Trigger/\*.pm**
These modules contain definitions of trigger channels and connections used by the zmtrigger.pl script. Although they can be used as is, they are really intended as examples that can be customised or specialised for different interfaces. Contributed modules for new channels or connections will be welcomed and included in future versions of ZoneMinder.

View File

@ -0,0 +1,47 @@
Configuration Files
--------------------
This section describes configuration files that ZoneMinder uses beyond the various Web UI options.
.. _replacement_for_options_path:
System Path Configurations
~~~~~~~~~~~~~~~~~~~~~~~~~~
At one point of time, ZoneMinder stored various system path configurations under the Web UI (``Options->Paths``). This was removed a few versions ago and now resides in a configuration file. The motivation for this change can be read in `this discussion <https://github.com/ZoneMinder/zoneminder/pull/1908>`__.
Typically, path configurations now reside in ``/etc/zm``.
Here is an example of the file hierarchy:
::
/etc/zm
├── conf.d
│   ├── 01-system-paths.conf
│   ├── 02-multiserver.conf
| ├── 03-custom.conf #optional
│   └── README
├── objectconfig.ini # optional
├── zm.conf
└── zmeventnotification.ini #optional
The roles of the files are as follows:
* ``zm.conf`` contains various base configuration entries. You should not edit this file as it may be overwritten on an upgrade.
* ``zmeventnotification.ini`` is only present if you have installed the ZoneMinder Event Notification Server.
* ``objectconfig.ini`` is only present if you have installed the machine learning hooks for the Event Notification Server.
* ``conf.d`` contains additional configuration items as follows:
* ``01-system-paths.conf`` contains all the paths that were once part of ``Options->Paths`` in the Web UI. You should not edit this file as it may be overwritten on an upgrade
* ``02-multiserver.conf`` file consists of custom variables if you are deploying ZoneMinder in a multi-server configuration (see :doc:`/installationguide/multiserver`)
* ``03-custom.conf`` is an custom config file that I created to override specific variables in the path files. **This is the recommended way to customize entries**. Anything that you want to change should be in a new file inside ``conf.d``. Note that ZoneMinder will sort all the files alphabetically and run their contents in ascending order. So it doesn't really matter what you name them, as long as you make sure your changes are not overwritten by another file in the sorting sequence. It is therefore good practice to prefix your file names by ``nn-`` where ``nn`` is a monotonically increasing numerical sequence ``01-`` ``02-`` ``03-`` and so forth, so you know the order they will be processed.
Timezone Configuration
~~~~~~~~~~~~~~~~~~~~~~~
Earlier versions of ZoneMinder relied on ``php.ini`` to set Date/Time Zone. This is no longer the case. You can (and must) set the Timezone via the Web UI, starting ZoneMinder version 1.34. See :ref:`here <timezone_config>`.
Database Specific Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. todo:: do we really need to have this section? Not sure if its generic and not specific to ZM
While the ZoneMinder specific database config entries reside in ``/etc/zm/zm.conf`` and related customizations discussed above, general database configuration items can be tweaked in ``/etc/mysql`` (or whichever path your DB server is installed)

View File

@ -46,6 +46,10 @@ Linked Monitors
This field allows you to select other monitors on your system that act as triggers for this monitor. So if you have a camera covering one aspect of your property you can force all cameras to record while that camera detects motion or other events. You can either directly enter a comma separated list of monitor ids or click on Select to choose a selection. Be very careful not to create circular dependencies with this feature however you will have infinitely persisting alarms which is almost certainly not what you want! To unlink monitors you can ctrl-click.
Maximum FPS
.. warning::
Unless you know what you are doing, please leave this field empty, especially if you are configuring a network camera. More often than not, putting a value here adversely affects recording.
On some occasions you may have one or more cameras capable of high capture rates but find that you generally do not require this performance at all times and would prefer to lighten the load on your server. This option permits you to limit the maximum capture rate to a specified value. This may allow you to have more cameras supported on your system by reducing the CPU load or to allocate video bandwidth unevenly between cameras sharing the same video device. This value is only a rough guide and the lower the value you set the less close the actual FPS may approach it especially on shared devices where it can be difficult to synchronise two or more different capture rates precisely. This option controls the maximum FPS in the circumstance where no alarm is occurring only.
This feature is limited and will only work under the following conditions:
@ -56,6 +60,11 @@ Maximum FPS
Using this field for video streams from IP cameras will cause undesirable results when the value is equal to or less than the frame rate from the camera. Note that placing a value higher than the camera's frame rate is allowed and can help prevent cpu spikes when communication from the camera is lost.
Alarm Maximum FPS
.. warning::
Unless you know what you are doing, please leave this field empty, especially if you are configuring a network camera. More often than not, putting a value here adversely affects recording.
If you have specified a Maximum FPS it may be that you dont want this limitation to apply when your monitor is recording motion or other event. This setting allows you to override the Maximum FPS value if this circumstance occurs. As with the Maximum FPS setting leaving this blank implies no limit so if you have set a maximum fps in the previous option then when an alarm occurs this limit would be ignored and ZoneMinder would capture as fast as possible for the duration of the alarm, returning to the limited value after the alarm has concluded. Equally you could set this to the same, or higher (or even lower) value than Maximum FPS for more precise control over the capture rate in the event of an alarm.
**IMPORTANT:** This field is subject to the same limitations as the Maximum FPS field. Ignoring these limitations will produce undesriable results.
@ -71,15 +80,15 @@ Source Tab
FFmpeg
^^^^^^
This is the recommended source type for most modern ip cameras.
This is the **recommended** source type for most modern ip cameras.
Source Path
Use this field to enter the full URL of the stream or file your camera supports. This is usually an RTSP url. There are several methods to learn this:
* Check the documentation that came with your camera
* Look for your camera in the hardware compatibilty list in the wiki http://wiki.zoneminder.com/Hardware_Compatibility_List
* Look for your camera in the hardware compatibilty list in the `hardware compatibility wiki <https://wiki.zoneminder.com/Hardware_Compatibility_List>`__
* Try ZoneMinder's new ONVIF probe feature
* Download and install the ONVIF Device Manager onto a Windows machine https://sourceforge.net/projects/onvifdm/
* Download and install the `ONVIF Device Manager <https://sourceforge.net/projects/onvifdm/>`__ onto a Windows machine
* Use Google to find third party sites, such as ispy, which document this information
Source Colours
Specify the amount of colours in the captured image. 32 bit is the preferred choice here. Unlike with local cameras changing this has no controlling effect on the remote camera itself so ensure that your camera is actually capturing to this palette beforehand.
@ -121,7 +130,7 @@ Remote Protocol
Remote Method
When HTTP is the Remote Protocol, your choices are Simple and Regexp. Most should choose Simple. When RTSP is the Remote Protocol, your choices are RTP/Unicast, RTP/Multicast, RTP/RTSP, RTP,RTSP,HTTP. Try each of these to determine which works with your camera. Most cameras will use either RTP/Unicast (UDP) or RTP/RTSP (TCP).
Remote Host/Port/Path
Use these fields to enter the full URL of the camera. Basically if your camera is at http://camserver.home.net:8192/cameras/camera1.jpg then these fields will be camserver.home.net, 8192 and /cameras/camera1.jpg respectively. Leave the port at 80 if there is no special port required. If you require authentication to access your camera then add this onto the host name in the form <username>:<password>@<hostname>.com. This will usually be 32 or 24 bit colour even if the image looks black and white. Look in Supported Hardware > Network Cameras section, how to obtain these strings that may apply to your camera.
Use these fields to enter the full URL of the camera. Basically if your camera is at ``http://camserver.home.net:8192/cameras/camera1.jpg`` then these fields will be camserver.home.net, 8192 and /cameras/camera1.jpg respectively. Leave the port at 80 if there is no special port required. If you require authentication to access your camera then add this onto the host name in the form <username>:<password>@<hostname>.com. This will usually be 32 or 24 bit colour even if the image looks black and white. Look in Supported Hardware > Network Cameras section, how to obtain these strings that may apply to your camera.
Remote Image Colours
Specify the amount of colours in the captured image. Unlike with local cameras changing this has no controlling effect on the remote camera itself so ensure that your camera is actually capturing to this palette beforehand.
Capture Width/Height
@ -271,3 +280,7 @@ Default Scale
If your monitor has been defined with a particularly large or small image size then you can choose a default scale here with which to view the monitor so it is easier or more visible from the web interface.
Web Colour
Some elements of ZoneMinder now use colours to identify monitors on certain views. You can select which colour is used for each monitor here. Any specification that is valid for HTML colours is valid here, e.g. red or #ff0000. A small swatch next to the input box displays the colour you have chosen.
Embed EXIF data into image:
Embeds EXIF data into each jpeg frame
.. todo:: what about mp4s?

View File

@ -40,7 +40,7 @@ Type
Preset
The preset chooser sets sensible default values based on computational needs (fast v. best) and sensitivity (low, medium, high.) It is not required that you select a preset, and you can alter any of the parameters after choosing a preset. For a small number of monitors with ZoneMinder running on modern equipment, Best, high sensitivity can be chosen as a good starting point.
It is important to understand that the available presets are intended merely as a starting point. Since every camera's view is unique, they are not guaranteed to work properly in every case. Presets tend to work acceptably for indoor cameras, where the objects of interest are relatively close and there typically are few or no unwanted objects moving within the cameras view. Presets, on the other hand, tend to not work acceptably for outdoor cameras, where the field of view is typically much wider, objects of interest are farther away, and changing weather patterns can cause false triggers. For outdoor cameras in particular, you will almost certainly have to tune your motion detection zone to get desired results. Please refer to `this guide <http://www.zoneminder.com/wiki/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__ to learn how to do this.
It is important to understand that the available presets are intended merely as a starting point. Since every camera's view is unique, they are not guaranteed to work properly in every case. Presets tend to work acceptably for indoor cameras, where the objects of interest are relatively close and there typically are few or no unwanted objects moving within the cameras view. Presets, on the other hand, tend to not work acceptably for outdoor cameras, where the field of view is typically much wider, objects of interest are farther away, and changing weather patterns can cause false triggers. For outdoor cameras in particular, you will almost certainly have to tune your motion detection zone to get desired results. Please refer to `this guide <https://wiki.zoneminder.com/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__ to learn how to do this.
Units
* Pixels - Selecting this option will allow many of the following values to be entered (or viewed) in units of pixels.
@ -109,5 +109,5 @@ Extend Alarm Frame Count
Other information
-----------------
Refer to `this <http://www.zoneminder.com/wiki/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__ user contributed Zone guide for additional information will illustrations if you are new to zones and need more help.
Refer to `this <https://wiki.zoneminder.com/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__ user contributed Zone guide for additional information will illustrations if you are new to zones and need more help.

View File

@ -8,10 +8,7 @@ Filters allow you to define complex conditions with associated actions in ZoneMi
And many more.
The filter window can be accessed from various views, one of which is to simply tap on the filter button in the main web view:
.. image:: images/filter-button.png
:width: 600px
The filter window can be accessed by tapping on the top level filter menu
You can use the filter window to create your own filters or to modify existing ones. You can even save your favourite filters to re-use at a future date. Filtering itself is fairly simple; you first choose how many expressions you'd like your filter to contain. Changing this value will cause the window to redraw with a corresponding row for each expression. You then select what you want to filter on and how the expressions relate by choosing whether they are 'and' or 'or' relationships. For filters comprised of many expressions you will also get the option to bracket parts of the filter to ensure you can express it as desired. Then if you like choose how you want your results sorted and whether you want to limit the amount of events displayed.
@ -22,25 +19,37 @@ Here is what the filter window looks like
:width: 800px
* *A*: This is a dropdown list where you can select pre-defined filters. You will notice that ZoneMinder comes with a PurgeWhenFull filter that is configured to delete events if you reach 95% of disk space.
* *B* and *C*: This is where you specify conditions that need to match before the filter is executed. You use the "+" and "-" buttons to add/delete conditions
* *D*: This is where you specify what needs to happen when the conditions match:
* *B*: If you are creating a new filter, you can type in a name for your filter here
* *C*: This is where you specify conditions that need to match before the filter is executed. You use the "+" and "-" buttons to add/delete conditions
* *D*: This allows you to perform sorting and limiting operations on the output before you take an action
* *E*: This is where you specify what needs to happen when the conditions match:
* Archive all matches: sets the archive field to 1 in the Database for the matched events.
Think of 'archiving' as grouping them under a special category - you can view archived
events later and also make sure archived events don't get deleted, for example
* Email details of all matches: Sends an email to the configured address with details about the event.
The email can be customized as per TBD
* Execute command on all matches: Allows you to execute any arbitrary command on the matched events. You can use replacement tokens as subsequent arguents to the command, the last argument will be the absolute path to the event, preceeded by replacement arguents. eg: /usr/bin/script.sh %MN% will excecute as /usr/bin/script.sh MonitorName /path/to/event.
* Delete all matches: Deletes all the matched events
* *E*: Use 'Submit' to 'test' your matching conditions. This will just match and show you what filters match. Use 'Execute' to actually execute the action after matching your conditions. Use 'Save' to save the filter for future use and 'Reset' to clear your settings
.. NOTE:: More details on filter conditions:
.. todo ::
fill in what update used disk space, copy all matches, move all matches do. For the "create video" filter, put in more details on how it works, any dependencies etc.
* Update used disk space:
* Create video for all matches: creates a video file of all the events that match
* Execute command on all matches: Allows you to execute any arbitrary command on the matched events. You can use replacement tokens as subsequent arguents to the command, the last argument will be the absolute path to the event, preceeded by replacement arguents. eg: /usr/bin/script.sh %MN% will excecute as /usr/bin/script.sh MonitorName /path/to/event.
* Delete all matches: Deletes all the matched events.
* Copy all matches:
* Move all matches:
* Run filter in background: When checked, ZoneMinder will make sure the filter is checked regularly. For example, if you want to be notified of new events by email, you should make sure this is checked. Filters that are configured to run in the background have a “*” next to it.
* Run filter concurrently: Allows this filter to run in its own thread thereby letting other filters run in parallel.
* *F*: Use 'List Matches' to 'test' your matching conditions. This will just match and show you what filters match. Use 'Execute' to actually execute the action after matching your conditions. Use 'Save' to save the filter for future use and 'Reset' to clear your settings
.. note:: More details on filter conditions:
There are several different elements to an event that you can filter on, some of which require further explanation. These are as follows,
* 'Date/Time' which must evaluate to a date and a time together,
* 'Date' and 'Time' which are variants which may only contain the relevant subsets of this,
* 'Weekday' which as expected is a day of the week.
All of the preceding elements take a very flexible free format of dates and time based on the PHP strtotime function (http://www.php.net/manual/en/function.strtotime.php). This allows values such as 'last Wednesday' etc to be entered. We recommend acquainting yourself with this function to see what the allowed formats are. However automated filters are run in perl and so are parsed by the Date::Manip package. Not all date formats are available in both so if you are saved your filter to do automatic deletions or other tasks you should make sure that the date and time format you use is compatible with both methods. The safest type of format to use is -3 day or similar with easily parseable numbers and units are in English.
All of the preceding elements take a very flexible free format of dates and time based on the PHP strtotime function (https://www.php.net/manual/en/function.strtotime.php). This allows values such as 'last Wednesday' etc to be entered. We recommend acquainting yourself with this function to see what the allowed formats are. However automated filters are run in perl and so are parsed by the Date::Manip package. Not all date formats are available in both so if you are saved your filter to do automatic deletions or other tasks you should make sure that the date and time format you use is compatible with both methods. The safest type of format to use is -3 day or similar with easily parseable numbers and units are in English.
The other things you can filter on are all fairly self explanatory, except perhaps for 'Archived' which you can use to include or exclude Archived events. In general you'll probably do most filtering on un-archived events. There are also two elements, Disk Blocks and Disk Percent which dont directly relate to the events themselves but to the disk partition on which the events are stored. These allow you to specify an amount of disk usage either in blocks or in percentage as returned by the df command. They relate to the amount of disk space used and not the amount left free. Once your filter is specified, clicking 'submit' will filter the events according to your specification. As the disk based elements are not event related directly if you create a filter and include the term DiskPercent > 95 then if your current disk usage is over that amount when you submit the filter then all events will be listed whereas if it is less then none at all will. As such the disk related terms will tend to be used mostly for automatic filters (see below). If you have created a filter you want to keep, you can name it and save it by clicking 'Save'.
@ -72,6 +81,7 @@ Here is what the filter window looks like
* %MEW% Number of events for the monitor in the last week
* %MEM% Number of events for the monitor in the last month
* %MEA% Number of archived events for the monitor
* %MOD% Path to image containing object detection
* %MP% Path to the monitor window
* %MPS% Path to the monitor stream
* %MPI% Path to the monitor recent image
@ -87,15 +97,8 @@ Here is what the filter window looks like
Saving filters
-----------------
.. image:: images/filter-save.png
:width: 400px
When saving filters, if you want the filter to run in the background make sure you select the "Run filter in background" option. When checked, ZoneMinder will make sure the filter is checked regularly. For example, if you want to be notified of new events by email, you should make sure this is checked. Filters that are configured to run in the background have a "*" next to it.
For example:
.. image:: images/filter-choosefilter.png
:width: 400px
How filters actually work
--------------------------

View File

@ -5,32 +5,144 @@ Having followed the :doc:`/installationguide/index` for your distribution you sh
.. image:: ../installationguide/images/zm_first_screen_post_install.png
.. _timezone_config:
Setting Timezone
^^^^^^^^^^^^^^^^^
Previous versions of ZoneMinder required the user to set up Timezone correctly in ``php.ini``. This is no longer the case. Starting 1.34, ZoneMinder allows you to specify the TimeZone in the UI. Please make sure it is set up correctly. The Timezone can be changed by selecting ``Options->System->Timezone``
.. image:: images/getting-started-timezone.png
Enabling Authentication
^^^^^^^^^^^^^^^^^^^^^^^
We strongly recommend enabling authentication right away. There are some situations where certain users don't enable authentication, such as instances where the server is in a LAN not directly exposed to the Internet, and is only accessible via VPN etc., but in most cases, authentication should be enabled. So let's do that right away.
* Click on the Options link on the top right corner of the web interface
* You will now be presented with a screen full of options. Click on the "System" tab
* Click on the Options link on the top bar of the web interface
* You will now be presented with a sidebar full of options. Click on the "System" link
.. image:: images/getting-started-enable-auth.png
* The relevant portions to change are marked in red above
* Enable OPT_USE_AUTH - this automatically switches to authentication mode with a default user (more on that later)
* Select a random string for AUTH_HASH_SECRET - this is used to make the authentication logic more secure, so
please generate your own string and please don't use the same value in the example.
please generate your own string and make sure it is sufficiently randomized and long. Note that if you plan to use APIs with ZoneMinder (needed by zmNinja/other apps), it is mandatory that you have this field populated
* The other options highlighed above should already be set, but if not, please make sure they are
* Note that if you are planning to use zmNinja and plan to use ZM authentication, you must also:
* set ``AUTH_RELAY`` to hashed
* Enable ``AUTH_HASH_LOGINS``
* Click on Save at the bottom and that's it! The next time you refresh that page, you will now be presented with a login screen. Job well done!
.. image:: images/getting-started-login.png
.. NOTE:: The default login/password is "admin/admin"
.. note:: The default login/password is "admin/admin"
Switching to flat theme
^^^^^^^^^^^^^^^^^^^^^^^
What you see is what is called a "classic" skin. Zoneminder has a host of configuration options that you can customize over time. This guide is meant to get you started the easiest possible way, so we will not go into all the details. However, it is worthwhile to note that Zoneminder also has a 'flat' theme that depending on your preferences may look more modern. So let's use that as an example of introducing you to the Options menu
Understanding the Web Console
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Before we proceed, lets spend a few minutes understanding the key functions of the web console.
For the sake of illustration, we are going to use a populated zoneminder configuration with several monitors and events.
.. image:: images/getting-started-understand-console.png
This screen is called the "console" screen in ZoneMinder and shows a summary of your monitors, associated events and more information.
* **A**: The options menu lets you configure many aspects of ZoneMinder. Refer to :doc:`options`.
* **B**: This brings up a color coded log window that shows various system and component level logs. This window is useful if you are trying to diagnose issues. Refer to :doc:`logging`.
* **C**: ZoneMinder allows you to group monitors gor logical separation. This option lets you create new groups, associate monitors to them and edit/delete existing groups.
* **D**: Filters are a powerful mechanism to perform actions when certain conditions are met. ZoneMinder comes with some preset filters that keep a tab of disk space and others. Many users create their own filters for more advanced actions like sending emails when certain events occur and more. Refer to :doc:`filterevents`.
* **E**: The Cycle option allows you to rotate between live views of each cofigured monitor.
* **F**: The Montage option shows a collage of your monitors. You can customize them including moving them around.
* **G**: Montage Review allows you to simultaneously view past events for different monitors. Note that this is a very resource intensive page and its performance will vary based on your system capabilities.
* **H**: Audit Events Report is more of a power user feature. This option looks for recording gaps in events and recording issues in mp4 files.
* **I**: This is the user you are currently logged in as.
* **J**: ZoneMinder allows you to maintain "run states". If you click on the "Running" text, ZoneMinder brings up a popup that allows you to define additional "states" (referred to as runstates). A runstate is essentially a snapshot that records the state of each monitor and you can switch between states easily. For example, you might have a run state defined that switches all monitors to "monitor" mode in which they are not recording anything while another state that sets some of the monitors to "modect". Why would you want this? A great example is to disable recording when you are at home and enable when you are away, based on time of day or other triggers. You can switch states by selecting an appropriate state manually, or do it automatically via cron jobs, for example. An example of using cron to automatically switch is provided in the :ref:`FAQ <runstate_cron_example>`. More esoteric examples of switching run states based on phone location can be found `here <https://forums.zoneminder.com/viewtopic.php?f=9&t=23026>`__.
Here is an example of multiple run states that I've defined. Each one of these runstates changes the mode of specific monitors depending on time of day and other conditions. Use your imagination to decide which conditions require state changes.
.. image:: images/runstates.png
* **K**: This line shows you system health information
* **L**: This defines how Zoneminder will record events. There are various modes. In brief Modect == record if a motion is detected,Record = always record 24x7, Mocord = always record PLUS detect motion, Monitor = just provide a live view but don't record anytime, Nodect = Don't record till an external entity via zmtrigger tells Zoneminder to (this is advanced usage).
* **M**: This is the "source" column that tells you the type of the camera - if its an IP camera, a USB camera or more. In this example, they are all IP cameras. Green means the monitor is running. Red means there is something wrong with that camera.
* **N**: This is the core of ZoneMinder - recording events. It gives you a count of how many events were recorded over the hour, day, week, month.
* **O**: These are the "Zones". Zones are areas within the camera that you mark as 'hotspots' for motion detection. Simply put, when you first configure your monitors (cameras), by default Zoneminder uses the entire field of view of the camera to detect motion. You may not want this. You may want to create "zones" specifically for detecting motion and ignore others. For example, lets consider a room with a fan that spins. You surely don't want to consider the fan moving continuously a reason for triggering a record? Probably not - in that case, you'd leave the fan out while making your zones.
* **P**: This is a "visual filter" which lets you 'filter' the console display based on text you enter. While this may not be particularly useful for small systems, ZoneMinder is also used in mega-installations will well over 200+ cameras and this visual filter helps reduce the monitors you are seeing at one time.
Adding Monitors
^^^^^^^^^^^^^^^
Now that we have a basic understanding of the web console, lets go about adding a new camera (monitor). For this example, lets assume we have an IP camera that streams RTSP at LAN IP address 192.168.1.33.
.. sidebar:: Note
This is meant to be a simple example. For a more detailed explanation of other options available when creating a monitor, please see :doc:`/userguide/definemonitor`
The first thing we will need to know is how to access that camera's video feed. You will need to consult your camera's manual or check their forum. Zoneminder community users also have a frequently updated list right `here <https://wiki.zoneminder.com/index.php/Hardware_Compatibility_List>`__ that lists information about many cameras. If you don't find your list there and can't seem to find it elsewhere, feel free to register and ask in the `user forums <https://forums.zoneminder.com/>`__.
The camera we are using as an example here is a Foscam 9831W which is a 1280x960 RTSP camera, and the URL to access it's feed is *username:password@IPADDRESS:PORT/videoMain*
Let's get started:
Click on the "Add" button below:
.. image:: images/getting-started-modern-look.png
:width: 600px
This brings up the new monitor window:
.. image:: images/getting-started-add-monitor-general.png
:width: 600px
* We've given it a name of 'Garage', because, well, its better than Monitor-1 and this is my Garage camera.
* There are various source types. As a brief introduction you'd want to use 'Local' if your camera is physically attached to your ZM server (like a USB camera, for example), and one of 'Remote', 'FFMpeg', 'Libvlc' or 'cURL' for a remote camera (not necessarily, but usually). For this example, let's go with 'FFMpeg'.
.. note::
As a thumb rule, if you have a camera accessible via IP and it does HTTP or RTSP,
start with FFMpeg first and libvlc if it doesn't work (:doc:`/userguide/definemonitor`
covers other modes in more details). If you are wondering what 'File' does, well, ZoneMinder was
built with compatibility in mind. Take a look at `this post
<https://wiki.zoneminder.com/index.php/How_to_use_ZoneMinder_with_cameras_it_may_not_directly_support>`__ to see how file can be used for leisure reading.
* In this example, the Function is 'Modect', which means it will start recording if motion is detected on that camera feed. The parameters for what constitutes motion detected is specific in :doc:`definezone`
* In Analytis FPS, we've put in 5FPS here. Note that you should not put an FPS that is greater than the camera FPS. In my case, 5FPS is sufficient for my needs
.. note::
Leave Maximum FPS and Alarm Maximum FPS **empty** if you are configuring an IP camera. In older versions of ZoneMinder, you were encouraged to put a value here, but that is no longer recommended. Infact, if you see your feed going much slower than the feed is supposed to go, or you get a lot of buffering/display issues, make sure this is empty. If you need to control camera FPS, please do it directly on the camera (via its own web interface, for example)
* We are done for the General tab. Let's move to the next tab
.. image:: images/getting-started-add-monitor-source.png
:width: 800px
* Let's select a protocol of RTSP and a remote method of RTP/RTSP (this is an RTSP camera)
* Note that starting ZM 1.34, GPUs are supported. In my case, I have an NVIDIA GeForce GTX1050i. These ``cuda`` and ``cuvid`` parameters are what my system supports to use the NVIDIA hardware decoder and GPU resources. If you don't have a GPU, or don't know how to configure your ffmpeg to support it, leave it empty for now. In future, we will add a section on how to set up a GPU
.. todo::
add GPU docs
That's pretty much it. Click on Save. We are not going to explore the other tabs in this simple guide.
You now have a configured monitor:
.. image:: images/getting-started-add-monitor-modect-ready.png
And then, finally, to see if everything works, if you click on the garage monitor you just added, you should be able to see its live feed. If you don't, inspect your webserver logs and your ZoneMinder logs to see what is going on.
Switching to another theme
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. todo::
Fix theme text after I clearly understand that System->CSS is doing
When you first install ZoneMinder, you see is what is called a "classic" skin. Zoneminder has a host of configuration options that you can customize over time. This guide is meant to get you started the easiest possible way, so we will not go into all the details. However, it is worthwhile to note that Zoneminder also has a 'flat' theme that depending on your preferences may look more modern. So let's use that as an example of introducing you to the Options menu
* Click on the Options link on the top right of the web interface in the image above
* This will bring you to the options window as shown below. Click on the "System" tab and then select the
@ -51,98 +163,6 @@ Congratulations! You now have a modern looking interface.
.. image:: images/getting-started-modern-look.png
Understanding the Web Console
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Before we proceed, lets spend a few minutes understanding the key functions of the web console.
For the sake of illustration, we are going to use a populated zoneminder configuration with several monitors and events.
Obviously, this does not reflect your current web console - which is essentially void of any useful information till now,
as we are yet to add things. Let's take a small break and understand what the various functions are before we configure our
own empty screen.
.. image:: images/getting-started-understand-console.png
* **A**: This is the username that is logged in. You are logged in as 'admin' here
* **B**: Click here to explore the various options of ZoneMinder and how to configure them. You already used this to enable authentication and change style above. Over time, you will find this to have many other things you will want to customize.
* **C**: This link, when clicked, opens up a color coded log window of what is going on in Zoneminder and often gives you good insight into what is going wrong or right. Note that the color here is red - that is an indication that some error occurred in ZoneMinder. You should click it and investigate.
* **D**: This is the core of ZoneMinder - recording events. It gives you a count of how many events were recorded over the hour, day, week, month.
* **E**: These are the "Zones". Zones are areas within the camera that you mark as 'hotspots' for motion detection. Simply put, when you first configure your monitors (cameras), by default Zoneminder uses the entire field of view of the camera to detect motion. You may not want this. You may want to create "zones" specifically for detecting motion and ignore others. For example, lets consider a room with a fan that spins. You surely don't want to consider the fan moving continuously a reason for triggering a record? Probably not - in that case, you'd leave the fan out while making your zones.
* **F**: This is the "source" column that tells you the type of the camera - if its an IP camera, a USB camera or more. In this example, they are all IP cameras. Note the color red on item F ? Well that means there is something wrong with that camera. No wonder the log also shows red. Good indication for you to tap on logs and investigate
* **G**: This defines how Zoneminder will record events. There are various modes. In brief Modect == record if a motion is detected,Record = always record 24x7, Mocord = always record PLUS detect motion, Monitor = just provide a live view but don't record anytime, Nodect = Don't record till an external entity via zmtrigger tells Zoneminder to (this is advanced usage).
* **H**: If you click on these links you can view a "Montage" of all your configured monitors or cycle through each one
* **I**: One of the most often missed features is the ability of ZoneMinder to maintain "run states". If you click on the "Running" text, ZoneMinder brings up a popup that allows you to define additional "states" (referred to as runstates). A runstate is essentially a snapshot that records the state of each monitor and you can switch between states easily. For example, you might have a run state defined that switches all monitors to "monitor" mode in which they are not recording anything while another state that sets some of the monitors to "modect". Why would you want this? A great example is to disable recording when you are at home and enable when you are away, based on time of day or other triggers. You can switch states by selecting an appropriate state manually, or do it automatically via cron jobs, for example. An example of using cron to automatically switch is provided in the :ref:`FAQ <runstate_cron_example>`. More esoteric examples of switching run states based on phone location can be found `here <https://forums.zoneminder.com/viewtopic.php?f=9&t=23026>`__.
Here is an example of multiple run states that I've defined. Each one of these runstates changes the mode of specific monitors depending on time of day and other conditions. Use your imagination to decide which conditions require state changes.
.. image:: images/runstates.png
Adding Monitors
^^^^^^^^^^^^^^^
Now that we have a basic understanding of the web console, lets go about adding a new camera (monitor). For this example, lets assume we have an IP camera that streams RTSP at LAN IP address 192.168.1.33.
The first thing we will need to know is how to access that camera's video feed. You will need to consult your camera's manual or check their forum. Zoneminder community users also have a frequently updated list right `here <http://www.zoneminder.com/wiki/index.php/Hardware_Compatibility_List>`__ that lists information about many cameras. If you don't find your list there and can't seem to find it elsewhere, feel free to register and ask in the `user foums <http://www.zoneminder.com/forums/>`__.
The camera we are using as an example here is a Foscam 9831W which is a 1280x960 RTSP camera, and the URL to access it's feed is *username:password@IPADDRESS:PORT/videoMain*
Let's get started:
Click on the "Add new monitor" button below:
.. image:: images/getting-started-modern-look.png
This brings up the new monitor window:
.. image:: images/getting-started-add-monitor-general.png
:width: 800px
* We've given it a name of 'Garage', because, well, its better than Monitor-1 and this is my Garage camera.
* There are various source types. As a brief introduction you'd want to use 'Local' if your camera is physically attached to your ZM server (like a USB camera, for example), and one of 'Remote', 'FFMpeg', 'Libvlc' or 'cURL' for a remote camera (not necessarily, but usually). For this example, let's go with 'Remote'.
.. NOTE::
As a thumb rule, if you have a camera accessible via IP and it does HTTP or RTSP,
start with Remote, then try FFMpeg and libvlc if it doesn't work (:doc:`/userguide/definemonitor`
covers other modes in more details). If you are wondering what 'File' does, well, ZoneMinder was
built with compatibility in mind. Take a look at `this post
<http://www.zoneminder.com/wiki/index.php/How_to_use_ZoneMinder_with_cameras_it_may_not_directly_support>`__ to see how file can be used for leisure reading.
* Let's leave the Function as 'Monitor' just so we can use this as an example to change it later another way. Practically, feel free to select your mode right now - Modect, Record etc depending on what you want ZoneMinder to do with this camera
* We've put in MaxFPS and AlarmFPS as 20 here. **You can leave this empty too**. Whatever you do here, *it's important to make sure these values are higher than the FPS of the camera*. The reason we've added a value here is that as of Aug 2015, if a camera goes offline, ZoneMinder eats up a lot of CPU trying to reach it and putting a larger value here than the actual FPS helps in that specific situation.
.. NOTE::
We strongly recommend not putting in a lower FPS here that the one configured inside your camera.
Zoneminder should not be used to manage camera frame rate. That always causes many problems. It's
much better you set the value directly in-camera and either leave this blank or specify a higher FPS
here. In this case, our actual camera FPS is 3 and we've set this value here to 10.
* We are done for the General tab. Let's move to the next tab
.. image:: images/getting-started-add-monitor-source.png
:width: 800px
* Let's select a protocol of RTSP and a remote method of RTP/RTSP (this is an RTSP camera)
* The other boxes are mostly self-explanatory
That's pretty much it. Click on Save. We are not going to explore the other tabs in this simple guide.
You now have a configured monitor:
.. image:: images/getting-started-add-monitor-orange.png
If you want to change its mode from Monitor to say, Modect (Motion Detect), later all you need to do is click on the Function column that says 'Monitor' and change it to 'Modect' like so:
.. image:: images/getting-started-add-monitor-modect.png
and we now have:
.. image:: images/getting-started-add-monitor-modect-ready.png
And then, finally, to see if everything works, lets click on the monitor name ('Garage' in this example) and that should bring up a live feed just like this:
.. image:: images/getting-started-add-monitor-live.png
Conclusion

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 517 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 KiB

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 83 KiB

File diff suppressed because one or more lines are too long

View File

@ -15,4 +15,5 @@ User Guide
cameracontrol
mobile
logging
configfiles

View File

@ -11,4 +11,4 @@ A fast video interface core, a user-friendly and comprehensive PHP based web int
The core of ZoneMinder is the capture and analysis of images and a highly configurable set of parameters that eliminate false positives whilst ensuring minimum loss of footage. For example, you can define a set of 'zones' for each camera of varying sensitivity and functionality. This eliminates zones that you don't wish to track or define areas that will alarm if various thresholds are exceeded in conjunction with other zones.
ZoneMinder is free under GPL License, but if you do find it useful, then please feel free to visit http://www.zoneminder.com/donate.html and help us fund our future improvements.
ZoneMinder is free under GPL License, but if you do find it useful, then please feel free to visit https://zoneminder.com/donate/ and help us fund our future improvements.

View File

@ -1,18 +1,33 @@
Logging
=======
Most components of ZoneMinder can emit informational, warning, error and debug messages in a standard format. These messages can be logged in one or more locations. By default all messages produced by scripts are logged in <script name>.log files which are placed in the directory defined by the ZM_PATH_LOGS configuration variable. This is initially defined as /tmp though it can be overridden (see the Options and Users section above). So for example, the zmpkg.pl script will output messages to /tmp/zmpkg.pl, an example of these messages is::
.. note::
Understanding how logging works in ZoneMinder is key to being able to isolate/pinpoint issues well. Please refer to :doc:`/userguide/options/options_logging` to read about how to customize logging.
03/01/06 13:46:00.166046 zmpkg[11148].INF [Command: start]
Most components of ZoneMinder can emit informational, warning, error and debug messages in a standard format. These messages can be logged in one or more locations. By default all messages produced by scripts are logged in <script name>.log files which are placed in the directory defined by the ``ZM_PATH_LOGS`` configuration variable. This is initially defined as ``/var/log/zm`` (on debian based systems) though it can be overridden to a custom path (the path is usually defined in ``/etc/zm/conf.d/01-system-paths.conf``, but to override it, you should create your own config file, not overwrite this file). So for example, the ``zmdc.pl`` script will output messages to ``/var/log/zmdc.log``, an example of these messages is::
10/24/2019 08:01:19.291513 zmdc[6414].INF [ZMServer:408] [Starting pending process, zma -m 2]
10/24/2019 08:01:19.296575 zmdc[6414].INF [ZMServer:408] ['zma -m 2' starting at 19/10/24 08:01:19, pid = 15740]
10/24/2019 08:01:19.296927 zmdc[15740].INF [ZMServer:408] ['zma -m 2' started at 19/10/24 08:01:19]
where the first part refers to the date and time of the entry, the next section is the name (or an abbreviated version) of the script, followed by the process id in square brackets, a severity code (INF, WAR, ERR or DBG) and the debug text. If you change the location of the log directory, ensure it refers to an existing directory which the web user has permissions to write to. Also ensure that no logs are present in that directory the web user does not have permission to open. This can happen if you run commands or scripts as the root user for testing at some point. If this occurs then subsequent non-privileged runs will fails due to being unable to open the log files.
As well as specific script logging above, information, warning and error messages are logged via the system syslog service. This is a standard component on Linux systems and allows logging of all sorts of messages in a standard way and using a standard format. On most systems, unless otherwise configured, messages produced by ZoneMinder will go to the /var/log/messages file. On some distributions they may end up in another file, but usually still in /var/log. Messages in this file are similar to those in the script log files but differ slightly. For example the above event in the system log file looks like::
As well as specific script logging above, information, warning and error messages are logged via the system syslog service. This is a standard component on Linux systems and allows logging of all sorts of messages in a standard way and using a standard format. On most systems, unless otherwise configured, messages produced by ZoneMinder will go to the ``/var/log/messages`` or ``/var/log/syslog`` file. On some distributions they may end up in another file, but usually still in /var/log. Messages in this file are similar to those in the script log files but differ slightly. For example the above event in the system log file looks like::
Jan 3 13:46:00 shuttle52 zmpkg[11148]: INF [Command: start]
where you can see that the date is formatted differently (and only to 1 second precision) and there is an additional field for the hostname (as syslog can operate over a network). As well as ZoneMinder entries in this file you may also see entries from various other system components. You should ensure that your syslogd daemon is running for syslog messages to be correctly handled.
Customizing logging properly in ZoneMinder
-------------------------------------------
.. todo:
Is this all valid anymore ?
Other Notes
-------------
A number of users have asked how to suppress or redirect ZoneMinder messages that are written to this file. This most often occurs due to not wanting other system messages to be overwhelmed and obscured by the ZoneMinder produced ones (which can be quite frequent by default). In order to control syslog messages you need to locate and edit the syslog.conf file on your system. This will often be in the /etc directory. This file allows configuration of syslog so that certain classes and categories of messages are routed to different files or highlighted to a console, or just ignored. Full details of the format of this file is outside the scope of this document (typing man syslog.conf will give you more information) but the most often requested changes are easy to implement.
The syslog service uses the concept of priorities and facilities where the former refers to the importance of the message and the latter refers to that part of the system from which it originated. Standard priorities include info, warning, err and debug and ZoneMinder uses these priorities when generating the corresponding class of message. Standard facilities include mail, cron and security etc but as well this, there are eight local facilities that can be used by machine specific message generators. ZoneMinder produces its messages via the local1 facility.

View File

@ -6,17 +6,15 @@ Here are some options for using ZoneMinder on Mobile devices:
Third party mobile clients
^^^^^^^^^^^^^^^^^^^^^^^^^^^
* zmNinja (`source code <https://github.com/pliablepixels/zmNinja>`__, needs APIs to be installed to work)
* Available in App Store and Play Store - `website <http://pliablepixels.github.io/zmNinja/>`__
* zmView (limited, free) and zmView Pro (more features, paid)
* Available in App Store and Play Store, relies on ZM skins `website <http://html5-clouds.com/?q=node/55>`__
* Available in App Store, Play Store and for Desktops - `website <http://pliablepixels.github.io/zmNinja/>`__
Using the existing web console
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* You can directly use the ZoneMinder interface by launching a browser and going to the ZoneMinder server just like you do on the Desktop
* ZoneMinder also has a "mobile skin" that offers limited functionality (not all views are present in this skin). You can point your mobile browser to ``http://yourzoneminderip/zm/index.php?skin=mobile`` and bookmark it. **Note however that 1.29 is the last release that will support the mobile skin. It's use is deprecated**
Discontinued clients
^^^^^^^^^^^^^^^^^^^^
The following are a list of clients that do not work and have not been updated:
* eyeZM
* zmView

View File

@ -5,13 +5,16 @@ The various options you can specify are displayed in a tabbed dialog with each g
If you have changed the value of an option you should then save it. A number of the option groups will then prompt you to let you know that the option(s) you have changed will require a system restart. This is not done automatically in case you will be changing many values in the same session, however once you have made all of your changes you should restart ZoneMinder as soon as possible. The reason for this is that web and some scripts will pick up the new changes immediately but some of the daemons will still be using the old values and this can lead to data inconsistency or loss.
.. note:: If you are looking for ``Options->Paths`` documentation, it was moved to a configuration file starting ZoneMinder 1.32. See :ref:`here <replacement_for_options_path>`.
.. toctree::
options/options_display
options/options_system
options/options_config
options/options_api
options/options_servers
options/options_paths
options/options_storage
options/options_web
options/options_images
options/options_logging

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -0,0 +1,13 @@
Options - API
---------------
.. note::
The ZoneMinder web interface does not use APIs and therefore, the tokens discussed here don't apply to the ZoneMinder UI. These only appy to apps that use the ZoneMinder API, like zmNinja.
The API option screen allows you enable/disable APIs on a per user basis. Furthermore, it also allows you to "revoke" tokens allotted to users. Starting ZoneMinder 1.34, the API ecosystem was overhauled and we now support JWT tokens with a concept of refresh tokens and access tokens. This allows for authentication without the need for sending passwords with each authentication request. For a more detailed understanding of how this works, please refer to :doc:`/api`. Over time, more control will be added to this screen.
.. image:: images/Options_API.png
The "Revoke All Tokens" button can be used to globally invalidate access tokens for all users. If tokens are revoked, the user(s) will need to re-authenticate with login and password.
As of today, refresh tokens last for 24 hours and access tokens for 1 hour.

View File

@ -1,9 +1,13 @@
Options - High, Medium and Low B/W
----------------------------------
There are a number of options that are grouped into bandwidth categories, this allows you to configure the ZoneMinder client to work optimally over the various access methods you might to access the client. You may want to use different modes depending on your network to preserve bandwidth.
A partial screenshot is shown below:
.. image:: images/Options_BW.png
There are now a number of options that are grouped into bandwidth categories, this allows you to configure the ZoneMinder client to work optimally over the various access methods you might to access the client. The following options are available in H, M and L options. These 3 groups control what happens when the client is running in 'high', 'medium' and 'low' bandwidth mode respectively. In most cases the default values will be suitable as a starting point.
The following options are available in H, M and L options. These 3 groups control what happens when the client is running in 'high', 'medium' and 'low' bandwidth mode respectively. In most cases the default values will be suitable as a starting point.
High - You should set these options for when accessing the ZoneMinder client over a local network or high speed link.

Some files were not shown because too many files have changed in this diff Show More