Merge branch 'master' into zma_to_thread

This commit is contained in:
Isaac Connor 2020-11-12 12:53:55 -05:00
commit df783f4835
98 changed files with 2043 additions and 1150 deletions

2
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "web/api/app/Plugin/Crud"]
path = web/api/app/Plugin/Crud
url = https://github.com/ZoneMinder/crud.git
url = https://github.com/FriendsOfCake/crud.git
branch = 3.0
[submodule "web/api/app/Plugin/CakePHP-Enum-Behavior"]
path = web/api/app/Plugin/CakePHP-Enum-Behavior

View File

@ -3,10 +3,10 @@ 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
UPDATE Monitor_Status SET
HourEvents = GREATEST(COALESCE(HourEvents,1)-1,0),
HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
END;
//
@ -20,10 +20,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 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;
UPDATE Monitor_Status SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId;
UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSE
UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId;
UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitor_Status.MonitorId=NEW.MonitorId;
END IF;
END IF;
END;
@ -32,10 +32,10 @@ FOR EACH ROW
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
UPDATE Monitor_Status SET
DayEvents = GREATEST(COALESCE(DayEvents,1)-1,0),
DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
END;
//
@ -48,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=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;
UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId;
UPDATE Monitor_Status SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSE
UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
END IF;
END IF;
END;
@ -61,10 +61,10 @@ FOR EACH ROW
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
UPDATE Monitor_Status SET
WeekEvents = GREATEST(COALESCE(WeekEvents,1)-1,0),
WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
END;
//
@ -77,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=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;
UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId;
UPDATE Monitor_Status SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSE
UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
END IF;
END IF;
END;
@ -89,10 +89,10 @@ FOR EACH ROW
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
UPDATE Monitor_Status SET
MonthEvents = GREATEST(COALESCE(MonthEvents,1)-1,0),
MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
END;
//
@ -105,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=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;
UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId;
UPDATE Monitor_Status SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSE
UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId;
UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
END IF;
END IF;
END;
@ -126,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 = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Id = OLD.StorageId;
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Storage.Id = OLD.StorageId;
END IF;
ELSE
IF ( NEW.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Id = NEW.StorageId;
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Storage.Id = NEW.StorageId;
END IF;
IF ( OLD.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Id = OLD.StorageId;
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Storage.Id = OLD.StorageId;
END IF;
END IF;
@ -145,20 +145,20 @@ BEGIN
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;
UPDATE Monitor_Status SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSEIF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitors
UPDATE Monitor_Status
SET
ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0),
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
ELSE
IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Monitors SET
UPDATE Monitor_Status SET
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
END IF;
END IF;
ELSEIF ( NEW.Archived AND diff ) THEN
@ -166,10 +166,10 @@ BEGIN
END IF;
IF ( diff ) THEN
UPDATE Monitors
UPDATE Monitor_Status
SET
TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
END IF;
END;
@ -185,17 +185,17 @@ 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
INSERT INTO Events_Hour (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Day (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Week (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Month (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
UPDATE Monitor_Status 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;
WHERE Monitor_Status.MonitorId=NEW.MonitorId;
END;
//
@ -205,7 +205,7 @@ 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;
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Storage.Id = OLD.StorageId;
END IF;
DELETE FROM Events_Hour WHERE EventId=OLD.Id;
DELETE FROM Events_Day WHERE EventId=OLD.Id;
@ -213,17 +213,17 @@ BEGIN
DELETE FROM Events_Month WHERE EventId=OLD.Id;
IF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitors SET
UPDATE Monitor_Status 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;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
ELSE
UPDATE Monitors SET
UPDATE Monitor_Status SET
TotalEvents = GREATEST(COALESCE(TotalEvents,1)-1,0),
TotalEventDiskSpace=GREATEST(COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Id=OLD.MonitorId;
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
END IF;
END;
@ -233,14 +233,14 @@ 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;
UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Monitors.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;
UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Monitors.Id=OLD.MonitorID;
END
//

View File

@ -189,8 +189,8 @@ CREATE TABLE `Events` (
`SecondaryStorageId` smallint(5) unsigned default 0,
`Name` varchar(64) NOT NULL default '',
`Cause` varchar(32) NOT NULL default '',
`StartTime` datetime default NULL,
`EndTime` datetime default NULL,
`StartDateTime` datetime default NULL,
`EndDateTime` datetime default NULL,
`Width` smallint(5) unsigned NOT NULL default '0',
`Height` smallint(5) unsigned NOT NULL default '0',
`Length` decimal(10,2) NOT NULL default '0.00',
@ -216,52 +216,52 @@ CREATE TABLE `Events` (
PRIMARY KEY (`Id`),
KEY `Events_MonitorId_idx` (`MonitorId`),
KEY `Events_StorageId_idx` (`StorageId`),
KEY `Events_StartTime_idx` (`StartTime`),
KEY `Events_EndTime_DiskSpace` (`EndTime`,`DiskSpace`)
KEY `Events_StartDateTime_idx` (`StartDateTime`),
KEY `Events_EndDateTime_DiskSpace` (`EndDateTime`,`DiskSpace`)
) ENGINE=@ZM_MYSQL_ENGINE@;
DROP TABLE IF EXISTS `Events_Hour`;
CREATE TABLE `Events_Hour` (
`EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL,
`StartTime` datetime default NULL,
`StartDateTime` datetime default NULL,
`DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`),
KEY `Events_Hour_MonitorId_idx` (`MonitorId`),
KEY `Events_Hour_StartTime_idx` (`StartTime`)
KEY `Events_Hour_StartDateTime_idx` (`StartDateTime`)
) ENGINE=@ZM_MYSQL_ENGINE@;
DROP TABLE IF EXISTS `Events_Day`;
CREATE TABLE `Events_Day` (
`EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL,
`StartTime` datetime default NULL,
`StartDateTime` datetime default NULL,
`DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`),
KEY `Events_Day_MonitorId_idx` (`MonitorId`),
KEY `Events_Day_StartTime_idx` (`StartTime`)
KEY `Events_Day_StartDateTime_idx` (`StartDateTime`)
) ENGINE=@ZM_MYSQL_ENGINE@;
DROP TABLE IF EXISTS `Events_Week`;
CREATE TABLE `Events_Week` (
`EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL,
`StartTime` datetime default NULL,
`StartDateTime` datetime default NULL,
`DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`),
KEY `Events_Week_MonitorId_idx` (`MonitorId`),
KEY `Events_Week_StartTime_idx` (`StartTime`)
KEY `Events_Week_StartDateTime_idx` (`StartDateTime`)
) ENGINE=@ZM_MYSQL_ENGINE@;
DROP TABLE IF EXISTS `Events_Month`;
CREATE TABLE `Events_Month` (
`EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL,
`StartTime` datetime default NULL,
`StartDateTime` datetime default NULL,
`DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`),
KEY `Events_Month_MonitorId_idx` (`MonitorId`),
KEY `Events_Month_StartTime_idx` (`StartTime`)
KEY `Events_Month_StartDateTime_idx` (`StartDateTime`)
) ENGINE=@ZM_MYSQL_ENGINE@;
@ -303,6 +303,7 @@ CREATE TABLE `Filters` (
`UpdateDiskSpace` tinyint(3) unsigned NOT NULL default '0',
`Background` tinyint(1) unsigned NOT NULL default '0',
`Concurrent` tinyint(1) unsigned NOT NULL default '0',
`LockRows` tinyint(1) unsigned NOT NULL default '0',
PRIMARY KEY (`Id`),
KEY `Name` (`Name`)
) ENGINE=@ZM_MYSQL_ENGINE@;
@ -315,6 +316,7 @@ DROP TABLE IF EXISTS `Frames`;
CREATE TABLE `Frames` (
`Id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`EventId` BIGINT UNSIGNED NOT NULL default '0',
FOREIGN KEY (`EventId`) REFERENCES `Events` (`Id`) ON DELETE CASCADE,
`FrameId` int(10) unsigned NOT NULL default '0',
`Type` enum('Normal','Bulk','Alarm') NOT NULL default 'Normal',
`TimeStamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
@ -524,18 +526,6 @@ CREATE TABLE `Monitors` (
`WebColour` varchar(32) NOT NULL default 'red',
`Exif` tinyint(1) unsigned NOT NULL default '0',
`Sequence` smallint(5) unsigned default NULL,
`TotalEvents` int(10) default NULL,
`TotalEventDiskSpace` bigint default NULL,
`HourEvents` int(10) default NULL,
`HourEventDiskSpace` bigint default NULL,
`DayEvents` int(10) default NULL,
`DayEventDiskSpace` bigint default NULL,
`WeekEvents` int(10) default NULL,
`WeekEventDiskSpace` bigint default NULL,
`MonthEvents` int(10) default NULL,
`MonthEventDiskSpace` bigint default NULL,
`ArchivedEvents` int(10) default NULL,
`ArchivedEventDiskSpace` bigint default NULL,
`ZoneCount` TINYINT NOT NULL DEFAULT 0,
`Refresh` int(10) unsigned default NULL,
`Latitude` DECIMAL(10,8),
@ -552,6 +542,18 @@ CREATE TABLE `Monitor_Status` (
`CaptureFPS` DECIMAL(10,2) NOT NULL default 0,
`AnalysisFPS` DECIMAL(5,2) NOT NULL default 0,
`CaptureBandwidth` INT NOT NULL default 0,
`TotalEvents` int(10) default NULL,
`TotalEventDiskSpace` bigint default NULL,
`HourEvents` int(10) default NULL,
`HourEventDiskSpace` bigint default NULL,
`DayEvents` int(10) default NULL,
`DayEventDiskSpace` bigint default NULL,
`WeekEvents` int(10) default NULL,
`WeekEventDiskSpace` bigint default NULL,
`MonthEvents` int(10) default NULL,
`MonthEventDiskSpace` bigint default NULL,
`ArchivedEvents` int(10) default NULL,
`ArchivedEventDiskSpace` bigint default NULL,
PRIMARY KEY (`MonitorId`)
) ENGINE=@ZM_MYSQL_ENGINE@;
--
@ -609,8 +611,11 @@ DROP TABLE IF EXISTS `Stats`;
CREATE TABLE `Stats` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`MonitorId` int(10) unsigned NOT NULL default '0',
FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE,
`ZoneId` int(10) unsigned NOT NULL default '0',
FOREIGN KEY (`ZoneId`) REFERENCES `Zones` (`Id`) ON DELETE CASCADE,
`EventId` BIGINT UNSIGNED NOT NULL,
FOREIGN KEY (`EventId`) REFERENCES `Events` (`Id`) ON DELETE CASCADE,
`FrameId` int(10) unsigned NOT NULL default '0',
`PixelDiff` tinyint(3) unsigned NOT NULL default '0',
`AlarmPixels` int(10) unsigned NOT NULL default '0',
@ -705,6 +710,7 @@ DROP TABLE IF EXISTS `Zones`;
CREATE TABLE `Zones` (
`Id` int(10) unsigned NOT NULL auto_increment,
`MonitorId` int(10) unsigned NOT NULL default '0',
FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE,
`Name` varchar(64) NOT NULL default '',
`Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive','Privacy') NOT NULL default 'Active',
`Units` enum('Pixels','Percent') NOT NULL default 'Pixels',
@ -799,7 +805,7 @@ INSERT INTO `Filters`
VALUES
(
'PurgeWhenFull',
'{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}',
'{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="},{"cnj":"and","obr":"0","attr":"EndDateTime","op":"IS NOT","val":"NULL","cbr":"0"}],"limit":100,"sort_asc":1}',
0/*AutoArchive*/,
0/*AutoVideo*/,
0/*AutoUpload*/,
@ -843,7 +849,7 @@ INSERT INTO `Filters`
)
VALUES (
'Update DiskSpace',
'{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"}]}',
'{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"},{"cnj":"and","obr":"0","attr":"EndDateTime","op":"IS NOT","val":"NULL","cbr":"0"}]}',
0/*AutoArchive*/,
0/*AutoVideo*/,
0/*AutoUpload*/,

92
db/zm_update-1.35.11.sql Normal file
View File

@ -0,0 +1,92 @@
/* Change Id type to BIGINT. */
set @exist := (SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'Events' AND COLUMN_NAME = 'Id' and DATA_TYPE='bigint');
set @sqlstmt := if( @exist = 0, "ALTER TABLE Events MODIFY Id bigint unsigned NOT NULL auto_increment", "SELECT 'Events.Id is already BIGINT'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
/* Add FOREIGN KEYS After deleting lost records */
set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Frames' and column_name='EventId' and referenced_table_name='Events' and referenced_column_name='Id');
set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'");
set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY EventId in Frames already exists'", @sqlstmt);
set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for EventId to Frames'", @sqlstmt);
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Frames'", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "DELETE FROM Frames WHERE EventId NOT IN (SELECT Id FROM Events)", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "ALTER TABLE Frames ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='EventId' and referenced_table_name='Events' and referenced_column_name='Id');
set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'");
set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY EventId in Stats already exists'", @sqlstmt);
set @sqlstmt := if( @exist = 0, "SELECT 'Adding FOREIGN KEY for EventId to Stats'", @sqlstmt);
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Stats'", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "DELETE FROM Stats WHERE EventId NOT IN (SELECT Id FROM Events);", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "ALTER TABLE Stats ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='MonitorId' and referenced_table_name='Monitors' and referenced_column_name='Id');
set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'");
set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY for MonitorId in Stats already exists'", @sql_stmt);
set @sqlstmt := if( @exist = 0, "SELECT 'Adding FOREIGN KEY for MonitorId to Stats'", @sqlstmt);
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Stats'", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "DELETE FROM Stats WHERE MonitorId NOT IN (SELECT Id FROM Monitors);", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "ALTER TABLE Stats ADD FOREIGN KEY (MonitorId) REFERENCES Monitors (Id) ON DELETE CASCADE", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='ZoneId' and referenced_table_name='Zones' and referenced_column_name='Id');
set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'");
set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY for ZoneId in Stats already exists'", @sqlstmt);
set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for ZoneId to Stats'", @sqlstmt);
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Stats'", "SELECT 'Ok'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "DELETE FROM Stats WHERE ZoneId NOT IN (SELECT Id FROM Zones);", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
set @sqlstmt := if( @exist = 0, "ALTER TABLE Stats ADD FOREIGN KEY (ZoneId) REFERENCES Zones (Id) ON DELETE CASCADE", "SELECT '.'");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
SELECT 'Adding foreign key for MonitorId to Zones';
set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Zones' and column_name='MonitorId' and referenced_table_name='Monitors' and referenced_column_name='Id');
set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'");
set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY for MonitorId in Zones already exists'", @sqlstmnt);
set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for MonitorId in Zones'", @sqlstmnt);
/*"SELECT 'FOREIGN KEY for MonitorId in Zones does not already exist'");*/
set @badzones := (select count(*) FROM Zones WHERE MonitorId NOT IN (SELECT Id FROM Monitors));
set @sqlstmt := if ( @badzones > 0, "SELECT 'You have Zones with no Monitor record in the Monitors table. Please delete them manually'", "ALTER TABLE Zones ADD FOREIGN KEY (MonitorId) REFERENCES Monitors (Id)");
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;

18
db/zm_update-1.35.12.sql Normal file
View File

@ -0,0 +1,18 @@
--
-- Update Filters table to have a LockRows Column
--
SELECT 'Checking for LockRows in Filters';
SET @s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Filters'
AND table_schema = DATABASE()
AND column_name = 'LockRows'
) > 0,
"SELECT 'Column LockRows already exists in Filters'",
"ALTER TABLE Filters ADD COLUMN `LockRows` tinyint(1) unsigned NOT NULL default '0' AFTER `Concurrent`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

101
db/zm_update-1.35.13.sql Normal file
View File

@ -0,0 +1,101 @@
/* DateTime is invalid and it being set here will cause warnings because it isn't in the dropdown set of values in Filter edit. */
UPDATE Config SET Value='StartDateTime' WHERE Name='ZM_WEB_EVENT_SORT_FIELD' AND Value='DateTime';
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Events'
AND column_name = 'StartDateTime'
) > 0,
"SELECT 'Column StartDateTime already exists in Events'",
"ALTER TABLE Events CHANGE StartTime StartDateTime datetime default 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 = 'EndDateTime'
) > 0,
"SELECT 'Column EndDateTime already exists in Events'",
"ALTER TABLE Events CHANGE EndTime EndDateTime datetime default 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_Hour'
AND column_name = 'StartDateTime'
) > 0,
"SELECT 'Column StartDateTime already exists in Events_Hour'",
"ALTER TABLE Events_Hour CHANGE StartTime StartDateTime datetime default 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_Day'
AND column_name = 'StartDateTime'
) > 0,
"SELECT 'Column StartDateTime already exists in Events_Day'",
"ALTER TABLE Events_Day CHANGE StartTime StartDateTime datetime default 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_Week'
AND column_name = 'StartDateTime'
) > 0,
"SELECT 'Column StartDateTime already exists in Events_Week'",
"ALTER TABLE Events_Week CHANGE StartTime StartDateTime datetime default 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_Month'
AND column_name = 'StartDateTime'
) > 0,
"SELECT 'Column StartDateTime already exists in Events_Month'",
"ALTER TABLE Events_Month CHANGE StartTime StartDateTime datetime default NULL"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
delimiter //
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,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Day (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Week (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Month (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,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;
//
delimiter ;

574
db/zm_update-1.35.14.sql Normal file
View File

@ -0,0 +1,574 @@
SELECT 'This update may make changes that require SUPER privileges. If you see an error message saying:
ERROR 1419 (HY000) at line 298: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
You will have to either run this update as root manually using something like (on ubuntu/debian)
sudo mysql --defaults-file=/etc/mysql/debian.cnf zm < /usr/share/zoneminder/db/zm_update-1.35.14.sql
OR
sudo mysql --defaults-file=/etc/mysql/debian.cnf "set global log_bin_trust_function_creators=1;"
sudo zmupdate.pl
';
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'TotalEvents'
) > 0,
"SELECT 'Column TotalEvents already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `TotalEvents` INT(10) AFTER `CaptureBandwidth`"
));
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 = 'TotalEvents'
) > 0,
"SELECT 'Column TotalEvents is already removed from Monitors'",
"ALTER TABLE `Monitors` DROP `TotalEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'TotalEventDiskSpace'
) > 0,
"SELECT 'Column TotalEventDiskSpace already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `TotalEventDiskSpace` BIGINT AFTER `TotalEvents`"
));
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 = 'TotalEventDiskSpace'
) > 0,
"SELECT 'Column TotalEventDiskSpace is already removed from Monitors'",
"ALTER TABLE `Monitors` DROP `TotalEventDiskSpace`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'HourEvents'
) > 0,
"SELECT 'Column HourEvents already exists in Monitors'",
"ALTER TABLE `Monitor_Status` ADD `HourEvents` INT(10) AFTER `TotalEventDiskSpace`"
));
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 = 'HourEvents'
) > 0,
"ALTER TABLE `Monitors` DROP `HourEvents`",
"SELECT 'Column HourEvents is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'HourEventDiskSpace'
) > 0,
"SELECT 'Column HourEventDiskSpace already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `HourEventDiskSpace` BIGINT AFTER `HourEvents`"
));
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 = 'HourEventDiskSpace'
) > 0,
"ALTER TABLE `Monitors` DROP `HourEventDiskSpace`",
"SELECT 'Column HourEventDiskSpace is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'DayEvents'
) > 0,
"SELECT 'Column DayEvents already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `DayEvents` INT(10) AFTER `HourEventDiskSpace`"
));
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 = 'DayEvents'
) > 0,
"ALTER TABLE `Monitors` DROP `DayEvents`",
"SELECT 'Column DayEvents is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'DayEventDiskSpace'
) > 0,
"SELECT 'Column DayEventDiskSpace already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `DayEventDiskSpace` BIGINT AFTER `DayEvents`"
));
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 = 'DayEventDiskSpace'
) > 0,
"ALTER TABLE `Monitors` DROP `DayEventDiskSpace`",
"SELECT 'Column DayEventDiskSpace is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'WeekEvents'
) > 0,
"SELECT 'Column WeekEvents already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `WeekEvents` INT(10) AFTER `DayEventDiskSpace`"
));
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 = 'WeekEvents'
) > 0,
"ALTER TABLE `Monitors` DROP `WeekEvents`",
"SELECT 'Column WeekEvents is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'WeekEventDiskSpace'
) > 0,
"SELECT 'Column WeekEventDiskSpace already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `WeekEventDiskSpace` BIGINT AFTER `WeekEvents`"
));
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 = 'WeekEventDiskSpace'
) > 0,
"ALTER TABLE `Monitors` DROP `WeekEventDiskSpace`",
"SELECT 'Column WeekEventDiskSpace is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'MonthEvents'
) > 0,
"SELECT 'Column MonthEvents already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `MonthEvents` INT(10) AFTER `WeekEventDiskSpace`"
));
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 = 'MonthEvents'
) > 0,
"ALTER TABLE `Monitors` DROP `MonthEvents`",
"SELECT 'Column MonthEvents is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'MonthEventDiskSpace'
) > 0,
"SELECT 'Column MonthEventDiskSpace already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `MonthEventDiskSpace` BIGINT AFTER `MonthEvents`"
));
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 = 'MonthEventDiskSpace'
) > 0,
"ALTER TABLE `Monitors` DROP `MonthEventDiskSpace`",
"SELECT 'Column MonthEventDiskSpace is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'ArchivedEvents'
) > 0,
"SELECT 'Column ArchivedEvents already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `ArchivedEvents` INT(10) AFTER `MonthEventDiskSpace`"
));
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 = 'ArchivedEvents'
) > 0,
"ALTER TABLE `Monitors` DROP `ArchivedEvents`",
"SELECT 'Column ArchivedEvents is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
AND column_name = 'ArchivedEventDiskSpace'
) > 0,
"SELECT 'Column ArchivedEventDiskSpace already exists in Monitor_Status'",
"ALTER TABLE `Monitor_Status` ADD `ArchivedEventDiskSpace` BIGINT AFTER `ArchivedEvents`"
));
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 = 'ArchivedEventDiskSpace'
) > 0,
"ALTER TABLE `Monitors` DROP `ArchivedEventDiskSpace`",
"SELECT 'Column ArchivedEventDiskSpace is already removed from Monitors'"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
UPDATE Monitor_Status 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(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour),1,0)) AS HourEvents,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour),DiskSpace,0)) AS HourEventDiskSpace,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day),1,0)) AS DayEvents,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day),DiskSpace,0)) AS DayEventDiskSpace,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week),1,0)) AS WeekEvents,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week),DiskSpace,0)) AS WeekEventDiskSpace,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month),1,0)) AS MonthEvents,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month),DiskSpace,0)) AS MonthEventDiskSpace
FROM Events GROUP BY MonitorId
) AS E ON E.MonitorId=Monitor_Status.MonitorId SET
Monitor_Status.TotalEvents = E.TotalEvents,
Monitor_Status.TotalEventDiskSpace = E.TotalEventDiskSpace,
Monitor_Status.ArchivedEvents = E.ArchivedEvents,
Monitor_Status.ArchivedEventDiskSpace = E.ArchivedEventDiskSpace,
Monitor_Status.HourEvents = E.HourEvents,
Monitor_Status.HourEventDiskSpace = E.HourEventDiskSpace,
Monitor_Status.DayEvents = E.DayEvents,
Monitor_Status.DayEventDiskSpace = E.DayEventDiskSpace,
Monitor_Status.WeekEvents = E.WeekEvents,
Monitor_Status.WeekEventDiskSpace = E.WeekEventDiskSpace,
Monitor_Status.MonthEvents = E.MonthEvents,
Monitor_Status.MonthEventDiskSpace = E.MonthEventDiskSpace;
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 Monitor_Status SET
HourEvents = GREATEST(COALESCE(HourEvents,1)-1,0),
HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Monitor_Status.MonitorId=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 Monitor_Status SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId;
UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSE
UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitor_Status.MonitorId=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 Monitor_Status SET
DayEvents = GREATEST(COALESCE(DayEvents,1)-1,0),
DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Monitor_Status.MonitorId=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 Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId;
UPDATE Monitor_Status SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSE
UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=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 Monitor_Status SET
WeekEvents = GREATEST(COALESCE(WeekEvents,1)-1,0),
WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Monitor_Status.MonitorId=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 Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId;
UPDATE Monitor_Status SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSE
UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=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 Monitor_Status SET
MonthEvents = GREATEST(COALESCE(MonthEvents,1)-1,0),
MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Monitor_Status.MonitorId=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 Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId;
UPDATE Monitor_Status SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSE
UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=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 Storage.Id = OLD.StorageId;
END IF;
ELSE
IF ( NEW.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Storage.Id = NEW.StorageId;
END IF;
IF ( OLD.DiskSpace ) THEN
UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Storage.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 Monitor_Status SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId;
ELSEIF ( OLD.Archived ) THEN
DELETE FROM Events_Archived WHERE EventId=OLD.Id;
UPDATE Monitor_Status
SET
ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0),
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0)
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
ELSE
IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
UPDATE Monitor_Status SET
ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Monitor_Status.MonitorId=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 Monitor_Status
SET
TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0)
WHERE Monitor_Status.MonitorId=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,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Day (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Week (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
INSERT INTO Events_Month (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0);
UPDATE Monitor_Status 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 Monitor_Status.MonitorId=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 Storage.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 Monitor_Status 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 Monitor_Status.MonitorId=OLD.MonitorId;
ELSE
UPDATE Monitor_Status SET
TotalEvents = GREATEST(COALESCE(TotalEvents,1)-1,0),
TotalEventDiskSpace=GREATEST(COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0)
WHERE Monitor_Status.MonitorId=OLD.MonitorId;
END IF;
END;
//
DELIMITER ;
REPLACE INTO Events_Hour SELECT Id,MonitorId,StartDateTime,DiskSpace FROM Events WHERE StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour);
REPLACE INTO Events_Day SELECT Id,MonitorId,StartDateTime,DiskSpace FROM Events WHERE StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day);
REPLACE INTO Events_Week SELECT Id,MonitorId,StartDateTime,DiskSpace FROM Events WHERE StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week);
REPLACE INTO Events_Month SELECT Id,MonitorId,StartDateTime,DiskSpace FROM Events WHERE StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month);
REPLACE INTO Events_Archived SELECT Id,MonitorId,DiskSpace FROM Events WHERE Archived=1;
UPDATE Monitor_Status 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(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour),1,0)) AS HourEvents,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour),DiskSpace,0)) AS HourEventDiskSpace,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day),1,0)) AS DayEvents,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day),DiskSpace,0)) AS DayEventDiskSpace,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week),1,0)) AS WeekEvents,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week),DiskSpace,0)) AS WeekEventDiskSpace,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month),1,0)) AS MonthEvents,
SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month),DiskSpace,0)) AS MonthEventDiskSpace
FROM Events GROUP BY MonitorId
) AS E ON E.MonitorId=Monitor_Status.MonitorId SET
Monitor_Status.TotalEvents = E.TotalEvents,
Monitor_Status.TotalEventDiskSpace = E.TotalEventDiskSpace,
Monitor_Status.ArchivedEvents = E.ArchivedEvents,
Monitor_Status.ArchivedEventDiskSpace = E.ArchivedEventDiskSpace,
Monitor_Status.HourEvents = E.HourEvents,
Monitor_Status.HourEventDiskSpace = E.HourEventDiskSpace,
Monitor_Status.DayEvents = E.DayEvents,
Monitor_Status.DayEventDiskSpace = E.DayEventDiskSpace,
Monitor_Status.WeekEvents = E.WeekEvents,
Monitor_Status.WeekEventDiskSpace = E.WeekEventDiskSpace,
Monitor_Status.MonthEvents = E.MonthEvents,
Monitor_Status.MonthEventDiskSpace = E.MonthEventDiskSpace;

View File

@ -39,9 +39,9 @@ if [ "$1" = "configure" ]; then
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
echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute, REFERENCES on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else
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;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute, REFERENCES on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
zmupdate.pl --nointeractive

View File

@ -3,7 +3,7 @@
%global zmgid_final apache
# Crud is configured as a git submodule
%global crud_version 3.1.0-zm
%global crud_version 3.2.0
# CakePHP-Enum-Behavior is configured as a git submodule
%global ceb_version 1.0-zm
@ -28,7 +28,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.35.10
Version: 1.35.14
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@ -44,7 +44,7 @@ License: GPLv2+ and LGPLv2+ and MIT
URL: http://www.zoneminder.com/
Source0: https://github.com/ZoneMinder/ZoneMinder/archive/%{version}.tar.gz#/zoneminder-%{version}.tar.gz
Source1: https://github.com/ZoneMinder/crud/archive/v%{crud_version}.tar.gz#/crud-%{crud_version}.tar.gz
Source1: https://github.com/FriendOfCake/crud/archive/v%{crud_version}.tar.gz#/crud-%{crud_version}.tar.gz
Source2: https://github.com/ZoneMinder/CakePHP-Enum-Behavior/archive/%{ceb_version}.tar.gz#/cakephp-enum-behavior-%{ceb_version}.tar.gz
%{?rhel:BuildRequires: epel-rpm-macros}

View File

@ -67,8 +67,8 @@ if [ "$1" = "configure" ]; then
# This creates the user.
echo "CREATE USER '${ZM_DB_USER}'@localhost IDENTIFIED BY '${ZM_DB_PASS}';" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
echo "Updating permissions"
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;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
echo "Updating permissions for user ${ZM_DB_USER}@localhost"
echo "GRANT LOCK TABLES,ALTER,DROP,SELECT,INSERT,UPDATE,DELETE,CREATE,INDEX,ALTER ROUTINE,CREATE ROUTINE, TRIGGER,EXECUTE,REFERENCES ON ${ZM_DB_NAME}.* TO '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
zmupdate.pl --nointeractive
zmupdate.pl --nointeractive -f

View File

@ -25,8 +25,8 @@ create_update_user () {
# This creates the user.
echo "CREATE USER '${ZM_DB_USER}'@${ZM_DB_HOST} IDENTIFIED BY '${ZM_DB_PASS}';" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
echo "Updating permissions"
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}'@${ZM_DB_HOST};" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
echo "Updating permissions for user ${ZM_DB_USER}@${ZM_DB_HOST}"
echo "GRANT LOCK tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine,trigger,execute,REFERENCES ON ${ZM_DB_NAME}.* TO '${ZM_DB_USER}'@${ZM_DB_HOST};" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
}
update_db () {

View File

@ -27,7 +27,7 @@ After you've done that, you changes will automatically be loaded into zmfilter w
Check the ``zmfilter.log`` file to make sure it is running as sometimes missing perl modules mean that it never runs but people don't always realize.
**Purge By Age**
To delete events that are older than 7 days, create a new filter with "Date" set to "less than" and a value of "-7 days", sort by "date/time" in "asc"ending order, then enable the checkbox "delete all matches". You can also use a value of week or week and days: "-2 week" or "-2 week 4 day"
To delete events that are older than 7 days, create a new filter with "End Date" set to "less than" and a value of "-7 days", sort by "date/time" in "asc"ending order, then enable the checkbox "delete all matches". You can also use a value of week or week and days: "-2 week" or "-2 week 4 day"
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".
@ -534,4 +534,4 @@ The GPL license allows you produce systems based on GPL software provided your s
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.
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

@ -2648,7 +2648,7 @@ our @options = (
},
{
name => 'ZM_WEB_EVENT_SORT_FIELD',
default => 'StartDateTime',
default => 'StartTime',
description => 'Default field the event lists are sorted by',
help => q`
Events in lists can be initially ordered in any way you want.
@ -2660,7 +2660,7 @@ our @options = (
`,
type => {
db_type =>'string',
hint =>'Id|Name|Cause|DiskSpace|MonitorName|StartDateTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore',
hint =>'Id|Name|Cause|DiskSpace|MonitorName|StartTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore',
pattern =>qr|.|,
format =>q( $1 )
},

View File

@ -68,8 +68,8 @@ $serial = $primary_key = 'Id';
SecondaryStorageId
Name
Cause
StartTime
EndTime
StartDateTime
EndDateTime
Width
Height
Length
@ -111,8 +111,8 @@ sub Time {
$_[0]{Time} = $_[1];
}
if ( ! defined $_[0]{Time} ) {
if ( $_[0]{StartTime} ) {
$_[0]{Time} = Date::Parse::str2time( $_[0]{StartTime} );
if ( $_[0]{StartDateTime} ) {
$_[0]{Time} = Date::Parse::str2time( $_[0]{StartDateTime} );
}
}
return $_[0]{Time};
@ -349,6 +349,10 @@ sub GenerateVideo {
return;
} # end sub GenerateVideo
# Note about transactions, this function may be called with rows locked and hence in a transaction.
# So we will detect if we are in a transaction, and if not, start one. We will NOT do rollback or
# commits unless we started the transaction.
sub delete {
my $event = $_[0];
@ -360,11 +364,11 @@ sub delete {
my $in_zmaudit = ( $0 =~ 'zmaudit.pl$');
if ( ! $in_zmaudit ) {
if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartTime} ) ) {
if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartDateTime} ) ) {
# zmfilter shouldn't delete anything in an odd situation. zmaudit will though.
my ( $caller, undef, $line ) = caller;
Warning("$0 Can't Delete event $event->{Id} from Monitor $event->{MonitorId} StartTime:".
(defined($event->{StartTime})?$event->{StartTime}:'undef')." from $caller:$line");
Warning("$0 Can't Delete event $event->{Id} from Monitor $event->{MonitorId} StartDateTime:".
(defined($event->{StartDateTime})?$event->{StartDateTime}:'undef')." from $caller:$line");
return;
}
if ( !($event->Storage()->Path() and -e $event->Storage()->Path()) ) {
@ -375,26 +379,28 @@ sub delete {
if ( $$event{Id} ) {
# Need to have an event Id if we are to delete from the db.
Info("Deleting event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime} from ".$event->Path());
Info("Deleting event $event->{Id} from Monitor $event->{MonitorId} StartDateTime:$event->{StartDateTime} from ".$event->Path());
$ZoneMinder::Database::dbh->ping();
$ZoneMinder::Database::dbh->begin_work();
#$event->lock_and_load();
my $in_transaction = $ZoneMinder::Database::dbh->{AutoCommit} ? 0 : 1;
ZoneMinder::Database::zmDbDo('DELETE FROM Frames WHERE EventId=?', $$event{Id});
if ( $ZoneMinder::Database::dbh->errstr() ) {
$ZoneMinder::Database::dbh->commit();
return;
}
$ZoneMinder::Database::dbh->begin_work() if ! $in_transaction;
# Going to delete in order of least value to greatest value. Stats is least and references Frames
ZoneMinder::Database::zmDbDo('DELETE FROM Stats WHERE EventId=?', $$event{Id});
if ( $ZoneMinder::Database::dbh->errstr() ) {
$ZoneMinder::Database::dbh->commit();
$ZoneMinder::Database::dbh->commit() if ! $in_transaction;
return;
}
ZoneMinder::Database::zmDbDo('DELETE FROM Frames WHERE EventId=?', $$event{Id});
if ( $ZoneMinder::Database::dbh->errstr() ) {
$ZoneMinder::Database::dbh->commit() if ! $in_transaction;
return;
}
# Do it individually to avoid locking up the table for new events
ZoneMinder::Database::zmDbDo('DELETE FROM Events WHERE Id=?', $$event{Id});
$ZoneMinder::Database::dbh->commit();
$ZoneMinder::Database::dbh->commit() if ! $in_transaction;
}
if ( ( $in_zmaudit or (!$Config{ZM_OPT_FAST_DELETE})) and $event->Storage()->DoDelete() ) {
@ -814,9 +820,9 @@ sub recover_timestamps {
my $duration = $last_timestamp - $first_timestamp;
$Event->Length($duration);
$Event->StartTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp) );
$Event->EndTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $last_timestamp) );
Debug("From capture Jpegs have duration $duration = $last_timestamp - $first_timestamp : $$Event{StartTime} to $$Event{EndTime}");
$Event->StartDateTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp) );
$Event->EndDateTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $last_timestamp) );
Debug("From capture Jpegs have duration $duration = $last_timestamp - $first_timestamp : $$Event{StartDateTime} to $$Event{EndDateTime}");
$ZoneMinder::Database::dbh->begin_work();
foreach my $jpg ( @capture_jpgs ) {
my ( $id ) = $jpg =~ /^(\d+)\-capture\.jpg$/;
@ -852,8 +858,8 @@ sub recover_timestamps {
}
my $seconds = ($h*60*60)+($m*60)+$s;
$Event->Length($seconds.'.'.$u);
$Event->StartTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp) );
$Event->EndTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp+$seconds) );
$Event->StartDateTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp) );
$Event->EndDateTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp+$seconds) );
}
if ( @mp4_files ) {
$Event->DefaultVideo($mp4_files[0]);

View File

@ -77,6 +77,7 @@ UpdateDiskSpace
UserId
Background
Concurrent
LockRows
);
sub Execute {
@ -103,6 +104,8 @@ sub Execute {
$sql =~ s/zmSystemLoad/$load/g;
}
$sql .= ' FOR UPDATE' if $$self{LockRows};
Debug("Filter::Execute SQL ($sql)");
my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr());
@ -146,7 +149,7 @@ sub Sql {
my $filter_expr = ZoneMinder::General::jsonDecode($self->{Query_json});
my $sql = 'SELECT E.*,
unix_timestamp(E.StartTime) as Time,
unix_timestamp(E.StartDateTime) as Time,
M.Name as MonitorName,
M.DefaultRate,
M.DefaultScale
@ -181,27 +184,25 @@ sub Sql {
$self->{Sql} .= $Config{ZM_SERVER_ID};
# StartTime options
} elsif ( $term->{attr} eq 'DateTime' ) {
$self->{Sql} .= 'E.StartTime';
} elsif ( $term->{attr} eq 'StartDateTime' ) {
$self->{Sql} .= 'E.StartTime';
$self->{Sql} .= 'E.StartDateTime';
} elsif ( $term->{attr} eq 'Date' ) {
$self->{Sql} .= 'to_days( E.StartTime )';
$self->{Sql} .= 'to_days( E.StartDateTime )';
} elsif ( $term->{attr} eq 'StartDate' ) {
$self->{Sql} .= 'to_days( E.StartTime )';
$self->{Sql} .= 'to_days( E.StartDateTime )';
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' ) {
$self->{Sql} .= 'extract( hour_second from E.StartTime )';
$self->{Sql} .= 'extract( hour_second from E.StartDateTime )';
} elsif ( $term->{attr} eq 'Weekday' or $term->{attr} eq 'StartWeekday' ) {
$self->{Sql} .= 'weekday( E.StartTime )';
$self->{Sql} .= 'weekday( E.StartDateTime )';
# EndTIme options
} elsif ( $term->{attr} eq 'EndDateTime' ) {
$self->{Sql} .= 'E.EndTime';
$self->{Sql} .= 'E.EndDateTime';
} elsif ( $term->{attr} eq 'EndDate' ) {
$self->{Sql} .= 'to_days( E.EndTime )';
} elsif ( $term->{attr} eq 'EndTime' ) {
$self->{Sql} .= 'extract( hour_second from E.EndTime )';
$self->{Sql} .= 'to_days( E.EndDateTime )';
} elsif ( $term->{attr} eq 'EndDateTime' ) {
$self->{Sql} .= 'extract( hour_second from E.EndDateTime )';
} elsif ( $term->{attr} eq 'EndWeekday' ) {
$self->{Sql} .= "weekday( E.EndTime )";
$self->{Sql} .= "weekday( E.EndDateTime )";
} elsif ( $term->{attr} eq 'ExistsInFileSystem' ) {
push @{$self->{PostSQLConditions}}, $term;
$self->{Sql} .= 'TRUE /* ExistsInFileSystem */';
@ -365,7 +366,7 @@ sub Sql {
$sql .= ' AND ( '.join(' or ', @auto_terms).' )';
}
if ( !$filter_expr->{sort_field} ) {
$filter_expr->{sort_field} = 'StartTime';
$filter_expr->{sort_field} = 'StartDateTime';
$filter_expr->{sort_asc} = 0;
}
my $sort_column = '';
@ -375,10 +376,14 @@ sub Sql {
$sort_column = 'M.Name';
} elsif ( $filter_expr->{sort_field} eq 'Name' ) {
$sort_column = 'E.Name';
} elsif ( $filter_expr->{sort_field} eq 'StartDateTime' ) {
$sort_column = 'E.StartDateTime';
} elsif ( $filter_expr->{sort_field} eq 'StartTime' ) {
$sort_column = 'E.StartTime';
$sort_column = 'E.StartDateTime';
} elsif ( $filter_expr->{sort_field} eq 'EndTime' ) {
$sort_column = 'E.EndTime';
$sort_column = 'E.EndDateTime';
} elsif ( $filter_expr->{sort_field} eq 'EndDateTime' ) {
$sort_column = 'E.EndDateTime';
} elsif ( $filter_expr->{sort_field} eq 'Secs' ) {
$sort_column = 'E.Length';
} elsif ( $filter_expr->{sort_field} eq 'Frames' ) {
@ -394,7 +399,7 @@ sub Sql {
} elsif ( $filter_expr->{sort_field} eq 'DiskSpace' ) {
$sort_column = 'E.DiskSpace';
} else {
$sort_column = 'E.StartTime';
$sort_column = 'E.StartDateTime';
}
my $sort_order = $filter_expr->{sort_asc} ? 'ASC' : 'DESC';
$sql .= ' ORDER BY '.$sort_column.' '.$sort_order;

View File

@ -262,21 +262,21 @@ sub createEvent {
}
$frame->{Type} = $frame->{Score}>0?'Alarm':'Normal' unless( $frame->{Type} );
$frame->{Delta} = $lastTimestamp?($frame->{TimeStamp}-$lastTimestamp):0.0;
$event->{StartTime} = $frame->{TimeStamp} unless ( $event->{StartTime} );
$event->{StartDateTime} = $frame->{TimeStamp} unless ( $event->{StartDateTime} );
$event->{TotScore} += $frame->{Score};
$event->{MaxScore} = $frame->{Score} if ( $frame->{Score} > $event->{MaxScore} );
$event->{AlarmFrames}++ if ( $frame->{Type} eq 'Alarm' );
$event->{EndTime} = $frame->{TimeStamp};
$event->{EndDateTime} = $frame->{TimeStamp};
$lastTimestamp = $frame->{TimeStamp};
}
$event->{Width} = $event->{monitor}->{Width} unless( $event->{Width} );
$event->{Height} = $event->{monitor}->{Height} unless( $event->{Height} );
$event->{AvgScore} = $event->{TotScore}/int($event->{AlarmFrames});
$event->{Length} = $event->{EndTime} - $event->{StartTime};
$event->{Length} = $event->{EndDateTime} - $event->{StartDateTime};
my %formats = (
StartTime => 'from_unixtime(?)',
EndTime => 'from_unixtime(?)',
StartDateTime => 'from_unixtime(?)',
EndDateTime => 'from_unixtime(?)',
);
my ( @fields, @formats, @values );
@ -297,7 +297,7 @@ sub createEvent {
$event->{Id} = $dbh->{mysql_insertid};
Info( "Created event ".$event->{Id} );
if ( $event->{EndTime} ) {
if ( $event->{EndDateTime} ) {
$event->{Name} = $event->{monitor}->{EventPrefix}.$event->{Id}
if ( $event->{Name} eq 'New Event' );
my $sql = "update Events set Name = ? where Id = ?";
@ -383,8 +383,8 @@ sub updateEvent {
if ( $event->{Name} eq 'New Event' );
my %formats = (
StartTime => 'from_unixtime(?)',
EndTime => 'from_unixtime(?)',
StartDateTime => 'from_unixtime(?)',
EndDateTime => 'from_unixtime(?)',
);
my ( @values, @sets );

View File

@ -159,7 +159,7 @@ sub new {
( $this->{fileName} = $0 ) =~ s|^.*/||;
$this->{logPath} = $ZoneMinder::Config::Config{ZM_PATH_LOGS};
$this->{logFile} = $this->{logPath}.'/'.$this->{id}.'.log';
($this->{logFile}) = $this->{logFile} =~ /^([\w\.\/]+)$/;
($this->{logFile}) = $this->{logFile} =~ /^([_\-\w\.\/]+)$/;
$this->{trace} = 0;
@ -504,9 +504,9 @@ sub openFile {
$LOGFILE->autoflush() if $this->{autoFlush};
my $webUid = (getpwnam($ZoneMinder::Config::Config{ZM_WEB_USER}))[2];
Error("Can't get uid for $ZoneMinder::Config::Config{ZM_WEB_USER}") if ! defined $webUid;
Error('Can\'t get uid for '.$ZoneMinder::Config::Config{ZM_WEB_USER}) if ! defined $webUid;
my $webGid = (getgrnam($ZoneMinder::Config::Config{ZM_WEB_GROUP}))[2];
Error("Can't get gid for $ZoneMinder::Config::Config{ZM_WEB_USER}") if ! defined $webGid;
Error('Can\'t get gid for '.$ZoneMinder::Config::Config{ZM_WEB_USER}) if ! defined $webGid;
if ( $> == 0 ) {
# If we are root, we want to make sure that www-data or whatever owns the file
chown($webUid, $webGid, $this->{logFile} ) or
@ -610,6 +610,7 @@ sub logInit( ;@ ) {
my %options = @_ ? @_ : ();
$logger = ZoneMinder::Logger->new() if !$logger;
$logger->initialise(%options);
logSetSignal();
}
sub logReinit {
@ -626,12 +627,26 @@ sub logHupHandler {
$do_log_rotate = 1;
}
sub logUSR1Handler {
$logger->level($logger->level()+1);
Info('Logger - Level changed to '. $logger->level() . '=>'.$codes{$logger->level()});
}
sub logUSR2Handler {
$logger->level($logger->level()-1);
Info('Logger - Level changed to '. $logger->level() . '=>'.$codes{$logger->level()});
}
sub logSetSignal {
$SIG{HUP} = \&logHupHandler;
$SIG{USR1} = \&logUSR1Handler;
$SIG{USR2} = \&logUSR2Handler;
}
sub logClearSignal {
$SIG{HUP} = 'DEFAULT';
$SIG{USR1} = 'DEFAULT';
$SIG{USR2} = 'DEFAULT';
}
sub logLevel {

View File

@ -121,18 +121,6 @@ $serial = $primary_key = 'Id';
WebColour
Exif
Sequence
TotalEvents
TotalEventDiskSpace
HourEvents
HourEventDiskSpace
DayEvents
DayEventDiskSpace
WeekEvents
WeekEventDiskSpace
MonthEvents
MonthEventDiskSpace
ArchivedEvents
ArchivedEventDiskSpace
ZoneCount
Refresh
DefaultCodec
@ -219,18 +207,6 @@ $serial = $primary_key = 'Id';
WebColour => '#ff0000',
Exif => 0,
Sequence => undef,
TotalEvents => undef,
TotalEventDiskSpace => undef,
HourEvents => undef,
HourEventDiskSpace => undef,
DayEvents => undef,
DayEventDiskSpace => undef,
WeekEvents => undef,
WeekEventDiskSpace => undef,
MonthEvents => undef,
MonthEventDiskSpace => undef,
ArchivedEvents => undef,
ArchivedEventDiskSpace => undef,
ZoneCount => 0,
Refresh => undef,
DefaultCodec => 'auto',

View File

@ -0,0 +1,99 @@
# ==========================================================================
#
# ZoneMinder Monitor_STatus Module
# Copyright (C) 2020 ZoneMinder
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ==========================================================================
#
# This module contains the common definitions and functions used by the rest
# of the ZoneMinder scripts
#
package ZoneMinder::Monitor_Status;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Object;
#our @ISA = qw(Exporter ZoneMinder::Base);
use parent qw(ZoneMinder::Object);
use vars qw/ $table $primary_key %fields $serial %defaults $debug/;
$table = 'Monitor_Status';
$serial = $primary_key = 'MonitorId';
%fields = map { $_ => $_ } qw(
MonitorId
TotalEvents
TotalEventDiskSpace
HourEvents
HourEventDiskSpace
DayEvents
DayEventDiskSpace
WeekEvents
WeekEventDiskSpace
MonthEvents
MonthEventDiskSpace
ArchivedEvents
ArchivedEventDiskSpace
);
%defaults = (
TotalEvents => undef,
TotalEventDiskSpace => undef,
HourEvents => undef,
HourEventDiskSpace => undef,
DayEvents => undef,
DayEventDiskSpace => undef,
WeekEvents => undef,
WeekEventDiskSpace => undef,
MonthEvents => undef,
MonthEventDiskSpace => undef,
ArchivedEvents => undef,
ArchivedEventDiskSpace => undef,
);
sub Monitor {
return new ZoneMinder::Monitor( $_[0]{MonitorId} );
} # end sub Monitor
1;
__END__
=head1 NAME
ZoneMinder::Monitor_Status - Perl Class for Monitor Status
=head1 SYNOPSIS
use ZoneMinder::Monitor_Status;
=head1 AUTHOR
Isaac Connor, E<lt>isaac@zoneminder.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2001-2017 ZoneMinder LLC
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -40,6 +40,10 @@ our @ISA = qw(ZoneMinder::Base);
#
# ==========================================================================
sub def_or_undef {
return defined($_[0]) ? $_[0] : 'undef';
}
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all);
@ -370,40 +374,29 @@ sub set {
$log->error("$type -> set called with non-hash params from $caller $line");
}
foreach my $field ( keys %fields ) {
if ( $params ) {
$log->debug("field: $field, param: ".$$params{$field}) if $debug;
if ( exists $$params{$field} ) {
$log->debug("field: $field, $$self{$field} =? param: ".$$params{$field}) if $debug;
if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) {
# Only make changes to fields that have changed
if ( defined $fields{$field} ) {
$$self{$field} = $$params{$field} if defined $fields{$field};
push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating
} # end if
$log->debug("Running $field with $$params{$field}") if $debug;
if ( my $func = $self->can( $field ) ) {
$func->( $self, $$params{$field} );
} # end if
} # end if
} # end if
} # end if $params
if ( defined $fields{$field} ) {
if ( $$self{$field} ) {
$$self{$field} = transform( $type, $field, $$self{$field} );
} # end if $$self{field}
}
} # end foreach field
if ( $params ) {
foreach my $field ( keys %{$params} ) {
$log->debug("field: $field, ".def_or_undef($$self{$field}).' =? param: '.def_or_undef($$params{$field})) if $debug;
if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) {
# Only make changes to fields that have changed
if ( defined $fields{$field} ) {
$$self{$field} = $$params{$field};
push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating
} # end if has a column
$log->debug("Running $field with $$params{$field}") if $debug;
if ( my $func = $self->can( $field ) ) {
$func->( $self, $$params{$field} );
} # end if has function
} # end if has change
} # end foreach field
} # end if $params
foreach my $field ( keys %defaults ) {
if ( ( ! exists $$self{$field} ) or (!defined $$self{$field}) or ( $$self{$field} eq '' ) ) {
$log->debug("Setting default ($field) ($$self{$field}) ($defaults{$field}) ") if $debug;
$log->debug("Setting default ($field) (".def_or_undef($$self{$field}).') ('.def_or_undef($defaults{$field}).') ') if $debug;
if ( defined $defaults{$field} ) {
$log->debug("Default $field is defined: $defaults{$field}") if $debug;
if ( $defaults{$field} eq 'NOW()' ) {
$$self{$field} = 'NOW()';
if ( $defaults{$field} eq '' or $defaults{$field} eq 'NOW()' ) {
$$self{$field} = $defaults{$field};
} else {
$$self{$field} = eval($defaults{$field});
$log->error( "Eval error of object default $field default ($defaults{$field}) Reason: " . $@ ) if $@;
@ -411,8 +404,9 @@ sub set {
} else {
$$self{$field} = $defaults{$field};
} # end if
#$$self{$field} = ( defined $defaults{$field} ) ? eval($defaults{$field}) : $defaults{$field};
$log->debug("Setting default for ($field) using ($defaults{$field}) to ($$self{$field}) ") if $debug;
$log->debug("Setting default for ($field) using (".def_or_undef($defaults{$field}).') to ('.def_or_undef($$self{$field}).') ') if $debug;
} elsif ( defined $fields{$field} and $$self{$field} ) {
$$self{$field} = transform( $type, $field, $$self{$field} );
} # end if
} # end foreach default
return @set_fields;

View File

@ -205,7 +205,7 @@ MAIN: while( $loop ) {
my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql )
or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() );
my $eventSelectSql = 'SELECT `Id`, (unix_timestamp() - unix_timestamp(`StartTime`)) AS Age
my $eventSelectSql = 'SELECT `Id`, (unix_timestamp() - unix_timestamp(`StartDateTime`)) AS Age
FROM `Events` WHERE `MonitorId` = ?'.(@Storage_Areas ? ' AND `StorageId` IN ('.join(',',map { '?'} @Storage_Areas).')' : '' ). ' ORDER BY `Id`';
my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql )
or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() );
@ -397,13 +397,13 @@ MAIN: while( $loop ) {
my ( undef, $year, $month, $day ) = split('/', $day_dir);
$year += 2000;
my ( $hour, $minute, $second ) = split('/', $event_dir);
my $StartTime =sprintf('%.4d-%.2d-%.2d %.2d:%.2d:%.2d', $year, $month, $day, $hour, $minute, $second);
my $StartDateTime =sprintf('%.4d-%.2d-%.2d %.2d:%.2d:%.2d', $year, $month, $day, $hour, $minute, $second);
my $Event = ZoneMinder::Event->find_one(
MonitorId=>$monitor_dir,
StartTime=>$StartTime,
StartDateTime=>$StartDateTime,
);
if ( $Event ) {
Debug("Found event matching starttime on monitor $monitor_dir at $StartTime: " . $Event->to_string());
Debug("Found event matching StartDateTime on monitor $monitor_dir at $StartDateTime: " . $Event->to_string());
next;
}
aud_print("Deleting event directories with no event id information at $day_dir/$event_dir");
@ -440,7 +440,7 @@ MAIN: while( $loop ) {
$Event->Path();
$Event->age();
Debug("Have event $$Event{Id} at $$Event{Path}");
$Event->StartTime(POSIX::strftime('%Y-%m-%d %H:%M:%S', gmtime(time_of_youngest_file($Event->Path()))));
$Event->StartDateTime(POSIX::strftime('%Y-%m-%d %H:%M:%S', gmtime(time_of_youngest_file($Event->Path()))));
} # end foreach event
}
@ -592,7 +592,7 @@ EVENT: while ( my ( $db_event, $age ) = each( %$db_events ) ) {
Warning("Event $$Event{Id} is Archived. Taking no further action on it.");
next;
}
if ( !$Event->StartTime() ) {
if ( !$Event->StartDateTime() ) {
aud_print("Event $$Event{Id} has no start time.");
if ( confirm() ) {
$Event->delete();
@ -600,7 +600,7 @@ EVENT: while ( my ( $db_event, $age ) = each( %$db_events ) ) {
}
next;
}
if ( ! $Event->EndTime() ) {
if ( ! $Event->EndDateTime() ) {
if ( $age > $Config{ZM_AUDIT_MIN_AGE} ) {
aud_print("Event $$Event{Id} has no end time and is $age seconds old. Deleting it.");
if ( confirm() ) {
@ -639,9 +639,9 @@ EVENT: while ( my ( $db_event, $age ) = each( %$db_events ) ) {
Info("Updating storage area on event $$Event{Id} from $$Event{StorageId} to $$fs_events{$db_event}{StorageId}");
$Event->StorageId($$fs_events{$db_event}->StorageId());
}
if ( ! $Event->StartTime() ) {
Info("Updating StartTime on event $$Event{Id} from $$Event{StartTime} to $$fs_events{$db_event}{StartTime}");
$Event->StartTime($$fs_events{$db_event}->StartTime());
if ( ! $Event->StartDateTime() ) {
Info("Updating StartDateTime on event $$Event{Id} from $$Event{StartDateTime} to $$fs_events{$db_event}{StartDateTime}");
$Event->StartDateTime($$fs_events{$db_event}->StartDateTime());
}
$Event->save();
@ -683,12 +683,12 @@ if ( $level > 1 ) {
# Remove empty events (with no frames)
$cleaned = 0;
Debug("Checking for Events with no Frames");
my $selectEmptyEventsSql = 'SELECT `E`.`Id` AS `Id`, `E`.`StartTime`, `F`.`EventId` FROM `Events` AS E LEFT JOIN `Frames` AS F ON (`E`.`Id` = `F`.`EventId`)
WHERE isnull(`F`.`EventId`) AND now() - interval '.$Config{ZM_AUDIT_MIN_AGE}.' second > `E`.`StartTime`';
my $selectEmptyEventsSql = 'SELECT `E`.`Id` AS `Id`, `E`.`StartDateTime`, `F`.`EventId` FROM `Events` AS E LEFT JOIN `Frames` AS F ON (`E`.`Id` = `F`.`EventId`)
WHERE isnull(`F`.`EventId`) AND now() - interval '.$Config{ZM_AUDIT_MIN_AGE}.' second > `E`.`StartDateTime`';
if ( my $selectEmptyEventsSth = $dbh->prepare_cached( $selectEmptyEventsSql ) ) {
if ( $res = $selectEmptyEventsSth->execute() ) {
while( my $event = $selectEmptyEventsSth->fetchrow_hashref() ) {
aud_print("Found empty event with no frame records '$event->{Id}' at $$event{StartTime}");
aud_print("Found empty event with no frame records '$event->{Id}' at $$event{StartDateTime}");
if ( confirm() ) {
if ( $res = $deleteEventSth->execute($event->{Id}) ) {
$cleaned = 1;
@ -750,7 +750,7 @@ if ( $level > 1 ) {
#"SELECT E.Id, ANY_VALUE(E.MonitorId),
#
#max(F.TimeStamp) as EndTime,
#unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length,
#unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartDateTime) as Length,
#max(F.FrameId) as Frames,
#count(if(F.Score>0,1,NULL)) as AlarmFrames,
#sum(F.Score) as TotScore,
@ -760,11 +760,11 @@ if ( $level > 1 ) {
#WHERE isnull(E.Frames) or isnull(E.EndTime)
#GROUP BY E.Id HAVING EndTime < (now() - interval ".$Config{ZM_AUDIT_MIN_AGE}.' second)'
#;
'SELECT *, unix_timestamp(`StartTime`) AS `TimeStamp` FROM `Events` WHERE `EndTime` IS NULL AND `StartTime` < (now() - interval '.$Config{ZM_AUDIT_MIN_AGE}.' second)'.($monitor_id?' AND MonitorId=?':'');
'SELECT *, unix_timestamp(`StartDateTime`) AS `TimeStamp` FROM `Events` WHERE `EndDateTime` IS NULL AND `StartDateTime` < (now() - interval '.$Config{ZM_AUDIT_MIN_AGE}.' second)'.($monitor_id?' AND MonitorId=?':'');
my $selectFrameDataSql = '
SELECT
max(`TimeStamp`) AS `EndTime`,
max(`TimeStamp`) AS `EndDateTime`,
unix_timestamp(max(`TimeStamp`)) AS `EndTimeStamp`,
max(`FrameId`) AS `Frames`,
count(if(`Score`>0,1,NULL)) AS `AlarmFrames`,
@ -779,7 +779,7 @@ FROM `Frames` WHERE `EventId`=?';
my $updateUnclosedEventsSql =
"UPDATE low_priority `Events`
SET `Name` = ?,
`EndTime` = ?,
`EndDateTime` = ?,
`Length` = ?,
`Frames` = ?,
`AlarmFrames` = ?,
@ -794,7 +794,7 @@ FROM `Frames` WHERE `EventId`=?';
$res = $selectUnclosedEventsSth->execute($monitor_id?$monitor_id:())
or Fatal("Can't execute: ".$selectUnclosedEventsSth->errstr());
while( my $event = $selectUnclosedEventsSth->fetchrow_hashref() ) {
aud_print("Found open event '$event->{Id}' on Monitor $event->{MonitorId} at $$event{StartTime}");
aud_print("Found open event '$event->{Id}' on Monitor $event->{MonitorId} at $$event{StartDateTime}");
if ( confirm('close', 'closing') ) {
if ( ! ( $res = $selectFrameDataSth->execute($event->{Id}) ) ) {
Error("Can't execute: $selectFrameDataSql:".$selectFrameDataSth->errstr());
@ -808,7 +808,7 @@ FROM `Frames` WHERE `EventId`=?';
$event->{Id},
RECOVER_TAG
),
$frame->{EndTime},
$frame->{EndDateTime},
$frame->{EndTimeStamp} - $event->{TimeStamp},
$frame->{Frames},
$frame->{AlarmFrames},
@ -885,11 +885,11 @@ FROM `Frames` WHERE `EventId`=?';
$loop = $continuous;
my $eventcounts_sql = '
UPDATE `Monitors` SET
`TotalEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id`),
`TotalEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id` AND `DiskSpace` IS NOT NULL),
`ArchivedEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id` AND `Archived`=1),
`ArchivedEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id` AND `Archived`=1 AND `DiskSpace` IS NOT NULL)
UPDATE `Monitor_Status` SET
`TotalEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitor_Status`.`MonitorId`),
`TotalEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitor_Status`.`MonitorId` AND `DiskSpace` IS NOT NULL),
`ArchivedEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitor_Status`.`MonitorId` AND `Archived`=1),
`ArchivedEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitor_Status`.`MonitorId` AND `Archived`=1 AND `DiskSpace` IS NOT NULL)
';
my $eventcounts_sth = $dbh->prepare_cached( $eventcounts_sql );
@ -897,40 +897,40 @@ FROM `Frames` WHERE `EventId`=?';
$eventcounts_sth->finish();
my $eventcounts_hour_sql = '
UPDATE `Monitors` INNER JOIN (
UPDATE `Monitor_Status` INNER JOIN (
SELECT `MonitorId`, COUNT(*) AS `HourEvents`, SUM(COALESCE(`DiskSpace`,0)) AS `HourEventDiskSpace`
FROM `Events_Hour` GROUP BY `MonitorId`
) AS `E` ON `E`.`MonitorId`=`Monitors`.`Id` SET
`Monitors`.`HourEvents` = `E`.`HourEvents`,
`Monitors`.`HourEventDiskSpace` = `E`.`HourEventDiskSpace`
) AS `E` ON `E`.`MonitorId`=`Monitor_Status`.`MonitorId` SET
`Monitor_Status`.`HourEvents` = `E`.`HourEvents`,
`Monitor_Status`.`HourEventDiskSpace` = `E`.`HourEventDiskSpace`
';
my $eventcounts_day_sql = '
UPDATE `Monitors` INNER JOIN (
UPDATE `Monitor_Status` INNER JOIN (
SELECT `MonitorId`, COUNT(*) AS `DayEvents`, SUM(COALESCE(`DiskSpace`,0)) AS `DayEventDiskSpace`
FROM `Events_Day` GROUP BY `MonitorId`
) AS `E` ON `E`.`MonitorId`=`Monitors`.`Id` SET
`Monitors`.`DayEvents` = `E`.`DayEvents`,
`Monitors`.`DayEventDiskSpace` = `E`.`DayEventDiskSpace`
) AS `E` ON `E`.`MonitorId`=`Monitor_Status`.`MonitorId` SET
`Monitor_Status`.`DayEvents` = `E`.`DayEvents`,
`Monitor_Status`.`DayEventDiskSpace` = `E`.`DayEventDiskSpace`
';
my $eventcounts_week_sql = '
UPDATE `Monitors` INNER JOIN (
UPDATE `Monitor_Status` INNER JOIN (
SELECT `MonitorId`, COUNT(*) AS `WeekEvents`, SUM(COALESCE(`DiskSpace`,0)) AS `WeekEventDiskSpace`
FROM `Events_Week` GROUP BY `MonitorId`
) AS `E` ON `E`.`MonitorId`=`Monitors`.`Id` SET
`Monitors`.`WeekEvents` = `E`.`WeekEvents`,
`Monitors`.`WeekEventDiskSpace` = `E`.`WeekEventDiskSpace`
) AS `E` ON `E`.`MonitorId`=`Monitor_Status`.`MonitorId` SET
`Monitor_Status`.`WeekEvents` = `E`.`WeekEvents`,
`Monitor_Status`.`WeekEventDiskSpace` = `E`.`WeekEventDiskSpace`
';
my $eventcounts_month_sql = '
UPDATE `Monitors` INNER JOIN (
UPDATE `Monitor_Status` INNER JOIN (
SELECT `MonitorId`, COUNT(*) AS `MonthEvents`, SUM(COALESCE(`DiskSpace`,0)) AS `MonthEventDiskSpace`
FROM `Events_Month` GROUP BY `MonitorId`
) AS `E` ON `E`.`MonitorId`=`Monitors`.`Id` SET
`Monitors`.`MonthEvents` = `E`.`MonthEvents`,
`Monitors`.`MonthEventDiskSpace` = `E`.`MonthEventDiskSpace`
) AS `E` ON `E`.`MonitorId`=`Monitor_Status`.`MonitorId` SET
`Monitor_Status`.`MonthEvents` = `E`.`MonthEvents`,
`Monitor_Status`.`MonthEventDiskSpace` = `E`.`MonthEventDiskSpace`
';
my $eventcounts_hour_sth = $dbh->prepare_cached($eventcounts_hour_sql);
my $eventcounts_day_sth = $dbh->prepare_cached($eventcounts_day_sql);

View File

@ -277,6 +277,7 @@ FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) {
sub checkFilter {
my $filter = shift;
my $in_transaction = ZoneMinder::Database::start_transaction($dbh) if $$filter{LockRows};
my @Events = $filter->Execute();
Debug(
join(' ',
@ -396,6 +397,7 @@ sub checkFilter {
$ZoneMinder::Database::dbh->commit();
} # end if UpdateDiskSpace
} # end foreach event
ZoneMinder::Database::end_transaction($dbh, $in_transaction) if $$filter{LockRows};
} # end sub checkFilter
sub generateVideo {
@ -702,7 +704,7 @@ sub substituteTags {
$text =~ s/%EN%/$Event->{Name}/g;
$text =~ s/%EC%/$Event->{Cause}/g;
$text =~ s/%ED%/$Event->{Notes}/g;
$text =~ s/%ET%/$Event->{StartTime}/g;
$text =~ s/%ET%/$Event->{StartDateTime}/g;
$text =~ s/%EVF%/$$Event{DefaultVideo}/g; # Event video filename
$text =~ s/%EL%/$Event->{Length}/g;
$text =~ s/%EF%/$Event->{Frames}/g;

View File

@ -231,7 +231,7 @@ Debug("@Monitors");
$Event->Height( $Monitor->Height() );
$Event->Orientation( $Monitor->Orientation() );
$Event->recover_timestamps();
if ( $$Event{StartTime} ) {
if ( $$Event{StartDateTime} ) {
$Event->save({}, 1);
Info("Event resurrected as " . $Event->to_string() );
} else {
@ -294,7 +294,7 @@ Debug("@Monitors");
$Event->StorageId( $Storage->Id() );
$Event->DiskSpace( undef );
$Event->recover_timestamps();
if ( $$Event{StartTime} ) {
if ( $$Event{StartDateTime} ) {
$Event->save({}, 1);
Info("Event resurrected as " . $Event->to_string() );
} else {
@ -309,13 +309,13 @@ Debug("@Monitors");
my ( undef, $year, $month, $day ) = split('/', $day_dir);
$year += 2000;
my ( $hour, $minute, $second ) = split('/', $event_dir);
my $StartTime =sprintf('%.4d-%.2d-%.2d %.2d:%.2d:%.2d', $year, $month, $day, $hour, $minute, $second);
my $StartDateTime =sprintf('%.4d-%.2d-%.2d %.2d:%.2d:%.2d', $year, $month, $day, $hour, $minute, $second);
my $Event = ZoneMinder::Event->find_one(
MonitorId=>$monitor_dir,
StartTime=>$StartTime,
StartDateTime=>$StartDateTime,
);
if ( $Event ) {
Debug("Found event matching starttime on monitor $monitor_dir at $StartTime: " . $Event->to_string());
Debug("Found event matching starttime on monitor $monitor_dir at $StartDateTime: " . $Event->to_string());
next;
}
@ -358,7 +358,7 @@ Debug("@Monitors");
$Event->Orientation( $Monitor->Orientation() );
$Event->StorageId( $Storage->Id() );
$Event->recover_timestamps();
if ( $$Event{StartTime} ) {
if ( $$Event{StartDateTime} ) {
$Event->save({}, 1);
Info("Event resurrected as " . $Event->to_string() );
} else {
@ -400,7 +400,7 @@ Debug("@Monitors");
$Event->Orientation( $Monitor->Orientation() );
$Event->StorageId( $Storage->Id() );
$Event->recover_timestamps();
if ( $$Event{StartTime} ) {
if ( $$Event{StartDateTime} ) {
$Event->save({}, 1);
Info("Event resurrected as " . $Event->to_string() );
} else {

View File

@ -43,10 +43,10 @@ while( 1 ) {
}
}
$dbh->do('DELETE FROM Events_Hour WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 hour)') or Error($dbh->errstr());
$dbh->do('DELETE FROM Events_Day WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 day)') or Error($dbh->errstr());
$dbh->do('DELETE FROM Events_Week WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 week)') or Error($dbh->errstr());
$dbh->do('DELETE FROM Events_Month WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 month)') or Error($dbh->errstr());
$dbh->do('DELETE FROM Events_Hour WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 hour)') or Error($dbh->errstr());
$dbh->do('DELETE FROM Events_Day WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 day)') or Error($dbh->errstr());
$dbh->do('DELETE FROM Events_Week WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 week)') or Error($dbh->errstr());
$dbh->do('DELETE FROM Events_Month WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 month)') or Error($dbh->errstr());
# Prune the Logs table if required
if ( $Config{ZM_LOG_DATABASE_LIMIT} ) {

View File

@ -187,7 +187,7 @@ while (1) {
} else {
Fatal("Can't select: $!");
}
} # end if select returned activitiy
} # end if select returned activity
# Check polled connections
foreach my $connection ( @in_poll_connections ) {
@ -266,7 +266,7 @@ while (1) {
Debug('Checking for timed actions');
my $now = time();
foreach my $action_time ( sort( grep { $_ < $now } @action_times ) ) {
Info("Found " . scalar @{$actions{$action_time}} . "actions expiring at $action_time");
Info('Found '.(scalar @{$actions{$action_time}}).'actions expiring at '.$action_time);
foreach my $action ( @{$actions{$action_time}} ) {
my $connection = $action->{connection};
Info("Found action '$$action{message}'");
@ -319,7 +319,7 @@ exit;
sub loadMonitor {
my $monitor = shift;
Debug("Loading monitor $monitor");
Debug('Loading monitor '.$monitor);
zmMemInvalidate($monitor);
if ( zmMemVerify($monitor) ) { # This will re-init shared memory
@ -334,7 +334,7 @@ sub loadMonitors {
my %new_monitors = ();
my $sql = 'SELECT * FROM `Monitors`
WHERE find_in_set( `Function`, \'Modect,Mocord,Nodect\' )'.
WHERE find_in_set( `Function`, \'Modect,Mocord,Nodect,Record\' )'.
( $Config{ZM_SERVER_ID} ? ' AND `ServerId`=?' : '' )
;
my $sth = $dbh->prepare_cached( $sql )
@ -372,9 +372,10 @@ sub handleMessage {
Warning("Can't find monitor '$id' for message '$message'");
return;
}
Debug("Found monitor for id '$id'");
next if !zmMemVerify($monitor);
if ( !zmMemVerify($monitor) ) {
Warning("Can't verify monitor '$id' for message '$message'");
return;
}
Debug("Handling action '$action'");
if ( $action =~ /^(enable|disable)(?:[\+ ](\d+))?$/ ) {
@ -387,21 +388,25 @@ sub handleMessage {
}
# Force a reload
$monitor_reload_time = 0;
Info("Set monitor to $state");
Info('Set monitor to '.$state);
if ( $delay ) {
my $action_text = $id.'|'.( ($state eq 'enable')
? 'disable'
: 'enable'
);
my $action_text = $id.'|'.(($state eq 'enable') ? 'disable' : 'enable');
handleDelay($delay, $connection, $action_text);
}
} elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) {
next if !$monitor->{Enabled};
if ( !$monitor->{Enabled} ) {
Info('Motion detection not enabled on monitor '.$id);
return;
}
my $trigger = $1;
my $delay = $2;
my $trigger_data;
if ( $trigger eq 'on' ) {
if ( $score <= 0 ) {
Warning('Triggering on with invalid score will have no result.');
return;
}
zmTriggerEventOn($monitor, $score, $cause, $text);
zmTriggerShowtext($monitor, $showtext) if defined($showtext);
Info("Trigger '$trigger' '$cause'");

View File

@ -201,7 +201,7 @@ if ( $event_id ) {
my $sql = " SELECT (SELECT max(Delta) FROM Frames WHERE EventId=Events.Id)-(SELECT min(Delta) FROM Frames WHERE EventId=Events.Id) as FullLength,
Events.*,
unix_timestamp(Events.StartTime) as Time,
unix_timestamp(Events.StartDateTime) as Time,
M.Name as MonitorName,
M.Palette
FROM Events

View File

@ -49,7 +49,7 @@ protected:
const int &mWd;
protected:
CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd ) {
CommsBase(const int &rd, const int &wd) : mRd(rd), mWd(wd) {
}
virtual ~CommsBase() {
}
@ -62,10 +62,10 @@ public:
public:
int getReadDesc() const {
return( mRd );
return mRd;
}
int getWriteDesc() const {
return( mWd );
return mWd;
}
int getMaxDesc() const {
return( mRd>mWd?mRd:mWd );

View File

@ -112,8 +112,9 @@ public:
double DecimalValue() const;
const char *StringValue() const;
ConfigItem &operator=(const ConfigItem item) {
Copy(item);return *this;
ConfigItem &operator=(const ConfigItem &item) {
Copy(item);
return *this;
}
inline operator bool() const {
return BooleanValue();

View File

@ -48,12 +48,12 @@ public:
return( result );
}
inline bool operator==( const Coord &coord ) { return( x == coord.x && y == coord.y ); }
inline bool operator!=( const Coord &coord ) { return( x != coord.x || y != coord.y ); }
inline bool operator>( const Coord &coord ) { return( x > coord.x && y > coord.y ); }
inline bool operator>=( const Coord &coord ) { return( !(operator<(coord)) ); }
inline bool operator<( const Coord &coord ) { return( x < coord.x && y < coord.y ); }
inline bool operator<=( const Coord &coord ) { return( !(operator>(coord)) ); }
inline bool operator==( const Coord &coord ) const { return( x == coord.x && y == coord.y ); }
inline bool operator!=( const Coord &coord ) const { return( x != coord.x || y != coord.y ); }
inline bool operator>( const Coord &coord ) const { return( x > coord.x && y > coord.y ); }
inline bool operator>=( const Coord &coord ) const { return( !(operator<(coord)) ); }
inline bool operator<( const Coord &coord ) const { return( x < coord.x && y < coord.y ); }
inline bool operator<=( const Coord &coord ) const { return( !(operator>(coord)) ); }
inline Coord &operator+=( const Coord &coord ) { x += coord.x; y += coord.y; return( *this ); }
inline Coord &operator-=( const Coord &coord ) { x -= coord.x; y -= coord.y; return( *this ); }

View File

@ -28,7 +28,7 @@ class zmDbRow {
MYSQL_RES *result_set;
MYSQL_ROW row;
public:
zmDbRow() { result_set = nullptr; row = nullptr; };
zmDbRow() : result_set(nullptr), row(nullptr) { };
MYSQL_RES *fetch( const char *query );
zmDbRow( MYSQL_RES *, MYSQL_ROW *row );
~zmDbRow();

View File

@ -39,6 +39,7 @@
//#define USE_PREPARED_SQL 1
const char * Event::frame_type_names[3] = { "Normal", "Bulk", "Alarm" };
#define MAX_DB_FRAMES 120
char frame_insert_sql[ZM_SQL_LGE_BUFSIZ] = "INSERT INTO `Frames` (`EventId`, `FrameId`, `Type`, `TimeStamp`, `Delta`, `Score`) VALUES ";
int Event::pre_alarm_count = 0;
@ -69,7 +70,7 @@ Event::Event(
start_time = now;
} else if ( start_time.tv_sec > now.tv_sec ) {
Error(
"StartTime in the future %u.%u > %u.%u",
"StartDateTime in the future %u.%u > %u.%u",
start_time.tv_sec, start_time.tv_usec, now.tv_sec, now.tv_usec
);
start_time = now;
@ -109,12 +110,10 @@ Event::Event(
);
db_mutex.lock();
if ( mysql_query(&dbconn, sql) ) {
while ( mysql_query(&dbconn, sql) ) {
db_mutex.unlock();
Error("Can't insert event: %s. sql was (%s)", mysql_error(&dbconn), sql);
return;
} else {
Debug(2, "Created new event with %s", sql);
db_mutex.lock();
}
id = mysql_insert_id(&dbconn);
@ -254,6 +253,11 @@ Event::~Event() {
videoStore = nullptr;
}
// endtime is set in AddFrame, so SHOULD be set to the value of the last frame timestamp.
if ( !end_time.tv_sec ) {
Warning("Empty endtime for event. Should not happen. Setting to now.");
gettimeofday(&end_time, nullptr);
}
struct DeltaTimeval delta_time;
DELTA_TIMEVAL(delta_time, end_time, start_time, DT_PREC_2);
Debug(2, "start_time:%d.%d end_time%d.%d", start_time.tv_sec, start_time.tv_usec, end_time.tv_sec, end_time.tv_usec);
@ -284,7 +288,7 @@ Event::~Event() {
// Should not be static because we might be multi-threaded
char sql[ZM_SQL_LGE_BUFSIZ];
snprintf(sql, sizeof(sql),
"UPDATE Events SET Name='%s%" PRIu64 "', EndTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64 " AND Name='New Event'",
"UPDATE Events SET Name='%s%" PRIu64 "', EndDateTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64 " AND Name='New Event'",
monitor->EventPrefix(), id, end_time.tv_sec,
delta_time.positive?"":"-", delta_time.sec, delta_time.fsec,
frames, alarm_frames,
@ -300,7 +304,7 @@ Event::~Event() {
if ( !mysql_affected_rows(&dbconn) ) {
// Name might have been changed during recording, so just do the update without changing the name.
snprintf(sql, sizeof(sql),
"UPDATE Events SET EndTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64,
"UPDATE Events SET EndDateTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64,
end_time.tv_sec,
delta_time.positive?"":"-", delta_time.sec, delta_time.fsec,
frames, alarm_frames,
@ -338,7 +342,7 @@ bool Event::WriteFrameImage(
Image *image,
struct timeval timestamp,
const char *event_file,
bool alarm_frame) {
bool alarm_frame) const {
int thisquality =
(alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality)) ?
@ -476,7 +480,7 @@ void Event::updateNotes(const StringSetMap &newNoteSetMap) {
} // void Event::updateNotes(const StringSetMap &newNoteSetMap)
void Event::AddFrames(int n_frames, Image **images, struct timeval **timestamps) {
for (int i = 0; i < n_frames; i += ZM_SQL_BATCH_SIZE) {
for ( int i = 0; i < n_frames; i += ZM_SQL_BATCH_SIZE ) {
AddFramesInternal(n_frames, i, images, timestamps);
}
}
@ -546,6 +550,7 @@ void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, str
} else {
Debug(1, "No valid pre-capture frames to add");
}
end_time = *timestamps[n_frames-1];
} // void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, struct timeval **timestamps)
void Event::AddPacket(ZMPacket *packet, int score, Image *alarm_image) {
@ -567,6 +572,10 @@ void Event::AddPacket(ZMPacket *packet, int score, Image *alarm_image) {
void Event::WriteDbFrames() {
char *frame_insert_values_ptr = (char *)&frame_insert_sql + 90; // 90 == strlen(frame_insert_sql);
/* Each frame needs about 63 chars. So if we buffer too many frames, we will exceed the size of frame_insert_sql;
*/
Debug(1, "Inserting %d frames", frame_data.size());
while ( frame_data.size() ) {
Frame *frame = frame_data.front();
frame_data.pop();
@ -582,7 +591,7 @@ void Event::WriteDbFrames() {
frame->score);
delete frame;
}
*(frame_insert_values_ptr-1) = '\0'; // The -2 is for the extra , added for values above
*(frame_insert_values_ptr-1) = '\0'; // The -1 is for the extra , added for values above
db_mutex.lock();
int rc = mysql_query(&dbconn, frame_insert_sql);
db_mutex.unlock();
@ -681,12 +690,20 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
// The idea is to write out 1/sec
frame_data.push(new Frame(id, frames, frame_type, timestamp, delta_time, score));
double fps = monitor->get_capture_fps();
if ( write_to_db or ( fps and (frame_data.size() > fps) ) or frame_type==BULK ) {
Debug(1, "Adding %d frames to DB because write_to_db:%d or frames > capture fps %f or BULK",
if ( write_to_db
or
(frame_data.size() > MAX_DB_FRAMES)
or
(frame_type==BULK)
or
( fps and (frame_data.size() > fps) )
) {
Debug(1, "Adding %d frames to DB because write_to_db:%d or frames > analysis fps %f or BULK",
frame_data.size(), write_to_db, fps);
WriteDbFrames();
last_db_frame = frames;
static char sql[ZM_SQL_MED_BUFSIZ];
snprintf(sql, sizeof(sql),
"UPDATE Events SET Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64,
( delta_time.positive?"":"-" ),
@ -706,6 +723,9 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
db_mutex.lock();
}
db_mutex.unlock();
} else {
Debug(1, "Not Adding %d frames to DB because write_to_db:%d or frames > analysis fps %f or BULK",
frame_data.size(), write_to_db, fps);
} // end if frame_type == BULK
} // end if db_frame

View File

@ -113,17 +113,16 @@ class Event {
~Event();
uint64_t Id() const { return id; }
const std::string &Cause() { return cause; }
const std::string &Cause() const { return cause; }
int Frames() const { return frames; }
int AlarmFrames() const { return alarm_frames; }
const struct timeval &StartTime() const { return start_time; }
const struct timeval &EndTime() const { return end_time; }
struct timeval &StartTime() { return start_time; }
struct timeval &EndTime() { return end_time; }
bool SendFrameImage( const Image *image, bool alarm_frame=false );
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false );
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false ) const;
bool WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow );
void updateNotes( const StringSetMap &stringSetMap );
@ -147,7 +146,7 @@ class Event {
return Event::getSubPath( localtime( time ) );
}
const char* getEventFile(void) {
const char* getEventFile(void) const {
return video_file.c_str();
}

View File

@ -45,7 +45,7 @@ bool EventStream::loadInitialEventData(int monitor_id, time_t event_time) {
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf(sql, sizeof(sql), "SELECT `Id` FROM `Events` WHERE "
"`MonitorId` = %d AND unix_timestamp(`EndTime`) > %ld "
"`MonitorId` = %d AND unix_timestamp(`EndDateTime`) > %ld "
"ORDER BY `Id` ASC LIMIT 1", monitor_id, event_time);
if ( mysql_query(&dbconn, sql) ) {
@ -116,8 +116,8 @@ bool EventStream::loadEventData(uint64_t event_id) {
static char sql[ZM_SQL_MED_BUFSIZ];
snprintf(sql, sizeof(sql),
"SELECT `MonitorId`, `StorageId`, `Frames`, unix_timestamp( `StartTime` ) AS StartTimestamp, "
"unix_timestamp( `EndTime` ) AS EndTimestamp, "
"SELECT `MonitorId`, `StorageId`, `Frames`, unix_timestamp( `StartDateTime` ) AS StartTimestamp, "
"unix_timestamp( `EndDateTime` ) AS EndTimestamp, "
"(SELECT max(`Delta`)-min(`Delta`) FROM `Frames` WHERE `EventId`=`Events`.`Id`) AS Duration, "
"`DefaultVideo`, `Scheme`, `SaveJPEGs`, `Orientation`+0 FROM `Events` WHERE `Id` = %" PRIu64, event_id);
@ -189,13 +189,13 @@ bool EventStream::loadEventData(uint64_t event_id) {
if ( storage_path[0] == '/' )
snprintf(event_data->path, sizeof(event_data->path),
"%s/%d/%02d/%02d/%02d/%02d/%02d/%02d",
"%s/%u/%02d/%02d/%02d/%02d/%02d/%02d",
storage_path, event_data->monitor_id,
event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday,
event_time->tm_hour, event_time->tm_min, event_time->tm_sec);
else
snprintf(event_data->path, sizeof(event_data->path),
"%s/%s/%d/%02d/%02d/%02d/%02d/%02d/%02d",
"%s/%s/%u/%02d/%02d/%02d/%02d/%02d/%02d",
staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id,
event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday,
event_time->tm_hour, event_time->tm_min, event_time->tm_sec);
@ -203,23 +203,23 @@ bool EventStream::loadEventData(uint64_t event_id) {
struct tm *event_time = localtime(&event_data->start_time);
if ( storage_path[0] == '/' )
snprintf(event_data->path, sizeof(event_data->path),
"%s/%d/%04d-%02d-%02d/%" PRIu64,
"%s/%u/%04d-%02d-%02d/%" PRIu64,
storage_path, event_data->monitor_id,
event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday,
event_data->event_id);
else
snprintf(event_data->path, sizeof(event_data->path),
"%s/%s/%d/%04d-%02d-%02d/%" PRIu64,
"%s/%s/%u/%04d-%02d-%02d/%" PRIu64,
staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id,
event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday,
event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday,
event_data->event_id);
} else {
if ( storage_path[0] == '/' )
snprintf(event_data->path, sizeof(event_data->path), "%s/%d/%" PRIu64,
snprintf(event_data->path, sizeof(event_data->path), "%s/%u/%" PRIu64,
storage_path, event_data->monitor_id, event_data->event_id);
else
snprintf(event_data->path, sizeof(event_data->path), "%s/%s/%d/%" PRIu64,
snprintf(event_data->path, sizeof(event_data->path), "%s/%s/%u/%" PRIu64,
staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id,
event_data->event_id);
}
@ -424,6 +424,7 @@ void EventStream::processCommand(const CmdMsg *msg) {
switch ( replay_rate ) {
case -1 * ZM_RATE_BASE :
replay_rate = -2 * ZM_RATE_BASE;
break;
case -2 * ZM_RATE_BASE :
replay_rate = -5 * ZM_RATE_BASE;
break;
@ -526,7 +527,7 @@ void EventStream::processCommand(const CmdMsg *msg) {
if ( offset < 0.0 ) {
Warning("Invalid offset, not seeking");
break;
}
}
// This should get us close, but not all frames will have the same duration
curr_frame_id = (int)(event_data->frame_count*offset/event_data->duration)+1;
if ( event_data->frames[curr_frame_id-1].offset > offset ) {
@ -538,10 +539,10 @@ void EventStream::processCommand(const CmdMsg *msg) {
}
if ( curr_frame_id < 1 ) {
curr_frame_id = 1;
} else if ( curr_frame_id > event_data->last_frame_id ) {
} else if ( (unsigned long)curr_frame_id > event_data->last_frame_id ) {
curr_frame_id = event_data->last_frame_id;
}
curr_stream_time = event_data->frames[curr_frame_id-1].timestamp;
Debug(1, "Got SEEK command, to %f (new current frame id: %d offset %f)",
offset, curr_frame_id, event_data->frames[curr_frame_id-1].offset);
@ -794,7 +795,7 @@ bool EventStream::sendFrame(int delta_us) {
Error("Unable to get a frame");
return false;
}
Image *send_image = prepareImage(image);
static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE];
int img_buffer_size = 0;
@ -881,7 +882,7 @@ void EventStream::runStream() {
// If we are streaming and this frame is due to be sent
// frame mod defaults to 1 and if we are going faster than max_fps will get multiplied by 2
// so if it is 2, then we send every other frame, if is it 4 then every fourth frame, etc.
if ( (frame_mod == 1) || (((curr_frame_id-1)%frame_mod) == 0) ) {
send_frame = true;
}
@ -963,7 +964,7 @@ void EventStream::runStream() {
if ( (mode == MODE_SINGLE) && (
(curr_frame_id < 1 )
||
((unsigned int)curr_frame_id >= event_data->frame_count)
((unsigned int)curr_frame_id >= event_data->frame_count)
)
) {
Debug(2, "Have mode==MODE_SINGLE and at end of event, looping back to start");
@ -1054,9 +1055,8 @@ void EventStream::runStream() {
closeComms();
} // end void EventStream::runStream()
bool EventStream::send_file(const char * filepath) {
bool EventStream::send_file(const char *filepath) {
static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE];
int rc;
int img_buffer_size = 0;
uint8_t *img_buffer = temp_img_buffer;
@ -1084,7 +1084,7 @@ bool EventStream::send_file(const char * filepath) {
Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
return false;
}
rc = zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size);
int rc = zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size);
if ( rc == (int)filestat.st_size ) {
// Success
fclose(fdj); /* Close the file handle */

View File

@ -76,7 +76,7 @@ class EventStream : public StreamBase {
StreamMode mode;
bool forceEventChange;
unsigned long curr_frame_id;
long curr_frame_id;
double curr_stream_time;
bool send_frame;
struct timeval start; // clock time when started the event
@ -133,11 +133,11 @@ class EventStream : public StreamBase {
void setStreamMode( StreamMode p_mode ) {
mode = p_mode;
}
void runStream();
void runStream() override;
Image *getImage();
private:
bool send_file( const char *file_path );
bool send_buffer( uint8_t * buffer, int size );
bool send_file(const char *filepath);
bool send_buffer(uint8_t * buffer, int size);
Storage *storage;
FFmpeg_Input *ffmpeg_input;
AVCodecContext *input_codec_context;

View File

@ -22,8 +22,7 @@
#include <string>
class Exception
{
class Exception {
protected:
typedef enum { INFO, WARNING, ERROR, FATAL } Severity;
@ -32,33 +31,28 @@ protected:
Severity mSeverity;
public:
Exception( const std::string &message, Severity severity=ERROR ) : mMessage( message ), mSeverity( severity )
explicit Exception(const std::string &message, const Severity severity=ERROR) :
mMessage(message),
mSeverity(severity)
{
}
public:
const std::string &getMessage() const
{
return( mMessage );
const std::string &getMessage() const {
return mMessage;
}
Severity getSeverity() const
{
return( mSeverity );
Severity getSeverity() const {
return mSeverity;
}
bool isInfo() const
{
return( mSeverity == INFO );
bool isInfo() const {
return mSeverity == INFO;
}
bool isWarning() const
{
bool isWarning() const {
return( mSeverity == WARNING );
}
bool isError() const
{
bool isError() const {
return( mSeverity == ERROR );
}
bool isFatal() const
{
bool isFatal() const {
return( mSeverity == FATAL );
}
};

View File

@ -24,10 +24,10 @@ class FFmpeg_Input {
int Close();
AVFrame *get_frame( int stream_id=-1 );
AVFrame *get_frame( int stream_id, double at );
int get_video_stream_id() {
int get_video_stream_id() const {
return video_stream_id;
}
int get_audio_stream_id() {
int get_audio_stream_id() const {
return audio_stream_id;
}

View File

@ -68,19 +68,26 @@ class FifoStream : public StreamBase {
);
protected:
typedef enum { MJPEG, RAW } StreamType;
typedef enum { UNKNOWN, MJPEG, RAW } StreamType;
StreamType stream_type;
bool sendMJEGFrames();
bool sendRAWFrames();
void processCommand(const CmdMsg *msg) {}
public:
FifoStream() {}
FifoStream() :
stream_path(nullptr),
fd(0),
total_read(0),
bytes_read(0),
frame_count(0),
stream_type(UNKNOWN)
{}
static void fifo_create_if_missing(
const char * path,
bool delete_fake_fifo = true);
void setStreamStart(const char * path);
void setStreamStart(int monitor_id, const char * format);
void runStream();
void runStream() override;
};
#endif // ZM_FIFO_H

View File

@ -149,16 +149,17 @@ public:
int Palette() const { return( palette ); }
int Extras() const { return( extras ); }
int Brightness( int p_brightness=-1 );
int Hue( int p_hue=-1 );
int Colour( int p_colour=-1 );
int Contrast( int p_contrast=-1 );
int Brightness( int p_brightness=-1 ) override;
int Hue( int p_hue=-1 ) override;
int Colour( int p_colour=-1 ) override;
int Contrast( int p_contrast=-1 ) override;
int PrimeCapture()override ;
int PreCapture()override ;
int Capture(ZMPacket &p) override;
int PostCapture()override ;
int Close() override { return 0; };
int PrimeCapture();
int PreCapture();
int Capture(ZMPacket &p);
int PostCapture();
int Close() { return 0; };
static bool GetCurrentSettings( const char *device, char *output, int version, bool verbose );
AVStream* get_VideoStream();
};

View File

@ -44,18 +44,6 @@ Logger *Logger::smInstance = nullptr;
Logger::StringMap Logger::smCodes;
Logger::IntMap Logger::smSyslogPriorities;
#if 0
static void subtractTime( struct timeval * const tp1, struct timeval * const tp2 ) {
tp1->tv_sec -= tp2->tv_sec;
if ( tp1->tv_usec <= tp2->tv_usec ) {
tp1->tv_sec--;
tp1->tv_usec = 1000000 - (tp2->tv_usec - tp1->tv_usec);
} else {
tp1->tv_usec = tp1->tv_usec - tp2->tv_usec;
}
}
#endif
void Logger::usrHandler(int sig) {
Logger *logger = fetch();
if ( sig == SIGUSR1 )

View File

@ -121,7 +121,7 @@ private:
Logger();
~Logger();
int limit(int level) {
int limit(const int level) const {
if ( level > DEBUG9 )
return DEBUG9;
if ( level < NOLOG )
@ -163,7 +163,7 @@ public:
}
Level level(Level=NOOPT);
bool debugOn() {
bool debugOn() const {
return mEffectiveLevel >= DEBUG1;
}

View File

@ -26,7 +26,7 @@
inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
uint8_t* retptr;
#if HAVE_POSIX_MEMALIGN
if ( posix_memalign((void**)&retptr,reqalignment,reqsize) != 0 )
if ( posix_memalign((void**)&retptr, reqalignment, reqsize) != 0 )
return nullptr;
return retptr;
@ -39,7 +39,7 @@ inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
alloc = retptr + sizeof(void*);
if(((long)alloc % reqalignment) != 0)
if ( ((long)alloc % reqalignment) != 0 )
alloc = alloc + (reqalignment - ((long)alloc % reqalignment));
/* Store a pointer before to the start of the block, just before returned aligned memory */

View File

@ -2465,7 +2465,6 @@ int Monitor::Capture() {
} // end if result
} // end if deinterlacing
// Icon: I'm not sure these should be here. They have nothing to do with capturing
if ( shared_data->action & GET_SETTINGS ) {
shared_data->brightness = camera->Brightness();
@ -2527,23 +2526,10 @@ void Monitor::TimestampImage(Image *ts_image, const struct timeval *ts_time) con
bool Monitor::closeEvent() {
if ( !event )
return true;
#if 0
if ( event_delete_thread ) {
event_delete_thread->join();
delete event_delete_thread;
event_delete_thread = NULL;
}
event_delete_thread = new std::thread([](Event *event) {
Event * e = event;
event = nullptr;
delete e;
e = nullptr;
}, event);
#else
return false;
delete event;
event = nullptr;
#endif
video_store_data->recording = (struct timeval){0};
return true;
} // end bool Monitor::closeEvent()

View File

@ -419,7 +419,7 @@ public:
inline Function GetFunction() const {
return function;
}
inline bool Enabled() {
inline bool Enabled() const {
if ( function <= MONITOR )
return false;
return enabled;
@ -427,7 +427,7 @@ public:
inline const char *EventPrefix() const {
return event_prefix;
}
inline bool Ready() {
inline bool Ready() const {
if ( function <= MONITOR ) {
Error("Should not be calling Ready if the function doesn't include motion detection");
return false;
@ -435,15 +435,15 @@ public:
if ( image_count >= ready_count ) {
return true;
}
Debug(2, "Not ready because image_count(%d) <= ready_count(%d)", image_count, ready_count );
Debug(2, "Not ready because image_count(%d) <= ready_count(%d)", image_count, ready_count);
return false;
}
inline bool Active() {
inline bool Active() const {
if ( function <= MONITOR )
return false;
return( enabled && shared_data->active );
}
inline bool Exif() {
inline bool Exif() const {
return embed_exif;
}
inline bool RecordAudio() {
@ -474,7 +474,7 @@ public:
void SetVideoWriterEventId( uint64_t p_event_id ) { video_store_data->current_event = p_event_id; }
struct timeval GetVideoWriterStartTime() const { return video_store_data->recording; }
void SetVideoWriterStartTime(struct timeval &t) { video_store_data->recording = t; }
void SetVideoWriterStartTime(const struct timeval &t) { video_store_data->recording = t; }
unsigned int GetPreEventCount() const { return pre_event_count; };
struct timeval GetVideoBufferDuration() const { return video_buffer_duration; };
@ -502,7 +502,7 @@ public:
inline void setStartupTime( time_t p_time ) { shared_data->startup_time = p_time; }
void get_ref_image();
int LabelSize() { return label_size; }
int LabelSize() const { return label_size; }
void actionReload();
void actionEnable();

View File

@ -292,7 +292,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
if ( (nbytes = sendto(sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr))) < 0 ) {
//if ( errno != EAGAIN )
{
Error( "Can't sendto on sd %d: %s", sd, strerror(errno) );
Error("Can't sendto on sd %d: %s", sd, strerror(errno));
//exit( -1 );
}
}
@ -507,7 +507,7 @@ void MonitorStream::runStream() {
const int max_swap_len_suffix = 15;
int swap_path_length = staticConfig.PATH_SWAP.length() + 1; // +1 for NULL terminator
int subfolder1_length = snprintf(nullptr, 0, "/zmswap-m%d", monitor->Id()) + 1;
int subfolder1_length = snprintf(nullptr, 0, "/zmswap-m%u", monitor->Id()) + 1;
int subfolder2_length = snprintf(nullptr, 0, "/zmswap-q%06d", connkey) + 1;
int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length;
@ -878,7 +878,7 @@ void MonitorStream::SingleImageRaw(int scale) {
}
fprintf(stdout,
"Content-Length: %d\r\n"
"Content-Length: %u\r\n"
"Content-Type: image/x-rgb\r\n\r\n",
snap_image->Size());
fwrite(snap_image->Buffer(), snap_image->Size(), 1, stdout);

View File

@ -71,7 +71,7 @@ class MonitorStream : public StreamBase {
bool setStreamStart(int monitor_id) {
return loadMonitor(monitor_id);
}
void runStream();
void runStream() override;
};
#endif // ZM_MONITORSTREAM_H

View File

@ -29,15 +29,13 @@
bool zm_reload = false;
bool zm_terminate = false;
RETSIGTYPE zm_hup_handler(int signal)
{
RETSIGTYPE zm_hup_handler(int signal) {
// Shouldn't do complex things in signal handlers, logging is complex and can block due to mutexes.
//Info("Got signal %d (%s), reloading", signal, strsignal(signal));
zm_reload = true;
}
RETSIGTYPE zm_term_handler(int signal)
{
RETSIGTYPE zm_term_handler(int signal) {
// Shouldn't do complex things in signal handlers, logging is complex and can block due to mutexes.
//Info("Got signal %d (%s), exiting", signal, strsignal(signal));
zm_terminate = true;
@ -55,8 +53,7 @@ RETSIGTYPE zm_die_handler(int signal)
#if ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T )
void *ip = nullptr;
void *cr2 = nullptr;
if (info && context) {
if ( info && context ) {
Debug(1,
"Signal information: number %d code %d errno %d pid %d uid %d status %d",
signal, info->si_code, info->si_errno, info->si_pid,
@ -79,7 +76,7 @@ RETSIGTYPE zm_die_handler(int signal)
#endif // defined(__x86_64__)
// Print the signal address and instruction pointer if available
if (ip) {
if ( ip ) {
Error("Signal address is %p, from %p", cr2, ip);
} else {
Error("Signal address is %p, no instruction pointer", cr2);
@ -115,8 +112,7 @@ RETSIGTYPE zm_die_handler(int signal)
exit(signal);
}
void zmSetHupHandler(SigHandler * handler)
{
void zmSetHupHandler(SigHandler * handler) {
sigset_t block_set;
sigemptyset(&block_set);
struct sigaction action, old_action;
@ -127,8 +123,7 @@ void zmSetHupHandler(SigHandler * handler)
sigaction(SIGHUP, &action, &old_action);
}
void zmSetTermHandler(SigHandler * handler)
{
void zmSetTermHandler(SigHandler * handler) {
sigset_t block_set;
sigemptyset(&block_set);
struct sigaction action, old_action;
@ -141,8 +136,7 @@ void zmSetTermHandler(SigHandler * handler)
sigaction(SIGQUIT, &action, &old_action);
}
void zmSetDieHandler(SigHandler * handler)
{
void zmSetDieHandler(SigHandler * handler) {
sigset_t block_set;
sigemptyset(&block_set);
struct sigaction action, old_action;
@ -163,19 +157,16 @@ void zmSetDieHandler(SigHandler * handler)
sigaction(SIGFPE, &action, &old_action);
}
void zmSetDefaultHupHandler()
{
void zmSetDefaultHupHandler() {
zmSetHupHandler((SigHandler *) zm_hup_handler);
}
void zmSetDefaultTermHandler()
{
void zmSetDefaultTermHandler() {
zmSetTermHandler((SigHandler *) zm_term_handler);
}
void zmSetDefaultDieHandler()
{
if (config.dump_cores) {
void zmSetDefaultDieHandler() {
if ( config.dump_cores ) {
// Do nothing
} else {
zmSetDieHandler((SigHandler *) zm_die_handler);

View File

@ -76,7 +76,9 @@ struct DeltaTimeval
#define USEC_PER_SEC 1000000
#define MSEC_PER_SEC 1000
/*
extern struct timeval tv;
*/
inline int tvDiffUsec( struct timeval first, struct timeval last )
{

View File

@ -46,7 +46,7 @@ class User {
User();
explicit User(const MYSQL_ROW &dbrow);
~User();
User(User &u) { Copy(u); }
User(const User &u) { Copy(u); }
void Copy(const User &u);
User& operator=(const User &u) {
Copy(u); return *this;

View File

@ -216,7 +216,7 @@ int X264MP4Writer::Open() {
int X264MP4Writer::Close() {
/* Flush all pending frames */
for ( int i = (x264_encoder_delayed_frames(x264enc) + 1); i > 0; i-- ) {
Debug(1,"Encoding delayed frame");
Debug(1, "Encoding delayed frame");
if ( x264encodeloop(true) < 0 )
break;
}
@ -227,7 +227,7 @@ Debug(1,"Encoding delayed frame");
/* Close MP4 handle */
MP4Close(mp4h);
Debug(1,"Optimising");
Debug(1, "Optimising");
/* Required for proper HTTP streaming */
MP4Optimize((path + ".incomplete").c_str(), path.c_str());

View File

@ -248,8 +248,8 @@ int main(int argc, char *argv[]) {
time_t now = (time_t)time(nullptr);
monitors[i]->setStartupTime(now);
snprintf(sql, sizeof(sql),
"REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','Running')",
snprintf(sql, sizeof(sql),
"INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Running') ON DUPLICATE KEY UPDATE Status='Running'",
monitors[i]->Id());
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
@ -270,7 +270,7 @@ int main(int argc, char *argv[]) {
}
for ( int i = 0; i < n_monitors; i++ ) {
snprintf(sql, sizeof(sql),
"REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','Connected')",
"INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Connected') ON DUPLICATE KEY UPDATE Status='Connected'",
monitors[i]->Id());
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
@ -391,7 +391,7 @@ int main(int argc, char *argv[]) {
for ( int i = 0; i < n_monitors; i++ ) {
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf(sql, sizeof(sql),
"REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','NotRunning')",
"INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Connected') ON DUPLICATE KEY UPDATE Status='NotRunning'",
monitors[i]->Id());
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));

View File

@ -95,91 +95,92 @@ int main(int argc, const char *argv[], char **envp) {
}
const char *query = getenv("QUERY_STRING");
if ( query ) {
Debug(1, "Query: %s", query);
char temp_query[1024];
strncpy(temp_query, query, sizeof(temp_query)-1);
char *q_ptr = temp_query;
char *parms[16]; // Shouldn't be more than this
int parm_no = 0;
while ( (parm_no < 16) && (parms[parm_no] = strtok(q_ptr, "&")) ) {
parm_no++;
q_ptr = nullptr;
}
for ( int p = 0; p < parm_no; p++ ) {
char *name = strtok(parms[p], "=");
char const *value = strtok(nullptr, "=");
if ( !value )
value = "";
if ( !strcmp(name, "source") ) {
source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR;
if ( !strcmp(value, "fifo") )
source = ZMS_FIFO;
} else if ( !strcmp(name, "mode") ) {
mode = !strcmp(value, "jpeg")?ZMS_JPEG:ZMS_MPEG;
mode = !strcmp(value, "raw")?ZMS_RAW:mode;
mode = !strcmp(value, "zip")?ZMS_ZIP:mode;
mode = !strcmp(value, "single")?ZMS_SINGLE:mode;
} else if ( !strcmp(name, "format") ) {
strncpy( format, value, sizeof(format) );
} else if ( !strcmp(name, "monitor") ) {
monitor_id = atoi(value);
if ( source == ZMS_UNKNOWN )
source = ZMS_MONITOR;
} else if ( !strcmp(name, "time") ) {
event_time = atoi(value);
} else if ( !strcmp(name, "event") ) {
event_id = strtoull(value, nullptr, 10);
source = ZMS_EVENT;
} else if ( !strcmp(name, "frame") ) {
frame_id = strtoull(value, nullptr, 10);
source = ZMS_EVENT;
} else if ( !strcmp(name, "scale") ) {
scale = atoi(value);
} else if ( !strcmp(name, "rate") ) {
rate = atoi(value);
} else if ( !strcmp(name, "maxfps") ) {
maxfps = atof(value);
} else if ( !strcmp(name, "bitrate") ) {
bitrate = atoi(value);
} else if ( !strcmp(name, "ttl") ) {
ttl = atoi(value);
} else if ( !strcmp(name, "replay") ) {
if ( !strcmp(value, "gapless") ) {
replay = EventStream::MODE_ALL_GAPLESS;
} else if ( !strcmp(value, "all") ) {
replay = EventStream::MODE_ALL;
} else if ( !strcmp(value, "none") ) {
replay = EventStream::MODE_NONE;
} else if ( !strcmp(value, "single") ) {
replay = EventStream::MODE_SINGLE;
} else {
Error("Unsupported value %s for replay, defaulting to none", value);
}
} else if ( !strcmp(name, "connkey") ) {
connkey = atoi(value);
} else if ( !strcmp(name, "buffer") ) {
playback_buffer = atoi(value);
} else if ( !strcmp(name, "auth") ) {
strncpy(auth, value, sizeof(auth)-1);
} else if ( !strcmp(name, "token") ) {
jwt_token_str = value;
Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str());
} else if ( !strcmp(name, "user") ) {
username = UriDecode(value);
} else if ( !strcmp(name, "pass") ) {
password = UriDecode(value);
Debug(1, "Have %s for password", password.c_str());
} else {
Debug(1, "Unknown parameter passed to zms %s=%s", name, value);
} // end if possible parameter names
} // end foreach parm
} else {
if ( query == nullptr ) {
Fatal("No query string.");
return 0;
} // end if query
Debug(1, "Query: %s", query);
char temp_query[1024];
strncpy(temp_query, query, sizeof(temp_query)-1);
char *q_ptr = temp_query;
char *parms[16]; // Shouldn't be more than this
int parm_no = 0;
while ( (parm_no < 16) && (parms[parm_no] = strtok(q_ptr, "&")) ) {
parm_no++;
q_ptr = nullptr;
}
for ( int p = 0; p < parm_no; p++ ) {
char *name = strtok(parms[p], "=");
char const *value = strtok(nullptr, "=");
if ( !value )
value = "";
if ( !strcmp(name, "source") ) {
source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR;
if ( !strcmp(value, "fifo") )
source = ZMS_FIFO;
} else if ( !strcmp(name, "mode") ) {
mode = !strcmp(value, "jpeg")?ZMS_JPEG:ZMS_MPEG;
mode = !strcmp(value, "raw")?ZMS_RAW:mode;
mode = !strcmp(value, "zip")?ZMS_ZIP:mode;
mode = !strcmp(value, "single")?ZMS_SINGLE:mode;
} else if ( !strcmp(name, "format") ) {
strncpy(format, value, sizeof(format)-1);
} else if ( !strcmp(name, "monitor") ) {
monitor_id = atoi(value);
if ( source == ZMS_UNKNOWN )
source = ZMS_MONITOR;
} else if ( !strcmp(name, "time") ) {
event_time = atoi(value);
} else if ( !strcmp(name, "event") ) {
event_id = strtoull(value, nullptr, 10);
source = ZMS_EVENT;
} else if ( !strcmp(name, "frame") ) {
frame_id = strtoull(value, nullptr, 10);
source = ZMS_EVENT;
} else if ( !strcmp(name, "scale") ) {
scale = atoi(value);
} else if ( !strcmp(name, "rate") ) {
rate = atoi(value);
} else if ( !strcmp(name, "maxfps") ) {
maxfps = atof(value);
} else if ( !strcmp(name, "bitrate") ) {
bitrate = atoi(value);
} else if ( !strcmp(name, "ttl") ) {
ttl = atoi(value);
} else if ( !strcmp(name, "replay") ) {
if ( !strcmp(value, "gapless") ) {
replay = EventStream::MODE_ALL_GAPLESS;
} else if ( !strcmp(value, "all") ) {
replay = EventStream::MODE_ALL;
} else if ( !strcmp(value, "none") ) {
replay = EventStream::MODE_NONE;
} else if ( !strcmp(value, "single") ) {
replay = EventStream::MODE_SINGLE;
} else {
Error("Unsupported value %s for replay, defaulting to none", value);
}
} else if ( !strcmp(name, "connkey") ) {
connkey = atoi(value);
} else if ( !strcmp(name, "buffer") ) {
playback_buffer = atoi(value);
} else if ( !strcmp(name, "auth") ) {
strncpy(auth, value, sizeof(auth)-1);
} else if ( !strcmp(name, "token") ) {
jwt_token_str = value;
Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str());
} else if ( !strcmp(name, "user") ) {
username = UriDecode(value);
} else if ( !strcmp(name, "pass") ) {
password = UriDecode(value);
Debug(1, "Have %s for password", password.c_str());
} else {
Debug(1, "Unknown parameter passed to zms %s=%s", name, value);
} // end if possible parameter names
} // end foreach parm
if ( monitor_id ) {
snprintf(log_id_string, sizeof(log_id_string), "zms_m%d", monitor_id);
} else {

View File

@ -482,7 +482,7 @@ int main(int argc, char *argv[]) {
} // end if ! MONITOR
if ( verbose ) {
printf("Monitor %d(%s)\n", monitor->Id(), monitor->Name());
printf("Monitor %u(%s)\n", monitor->Id(), monitor->Name());
}
if ( !monitor->connect() ) {
Error("Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name());
@ -521,19 +521,19 @@ int main(int argc, char *argv[]) {
}
if ( function & ZMU_READ_IDX ) {
if ( verbose )
printf("Last read index: %d\n", monitor->GetLastReadIndex());
printf("Last read index: %u\n", monitor->GetLastReadIndex());
else {
if ( have_output ) fputc(separator, stdout);
printf("%d", monitor->GetLastReadIndex());
printf("%u", monitor->GetLastReadIndex());
have_output = true;
}
}
if ( function & ZMU_WRITE_IDX ) {
if ( verbose ) {
printf("Last write index: %d\n", monitor->GetLastWriteIndex());
printf("Last write index: %u\n", monitor->GetLastWriteIndex());
} else {
if ( have_output ) fputc(separator, stdout);
printf("%d", monitor->GetLastWriteIndex());
printf("%u", monitor->GetLastWriteIndex());
have_output = true;
}
}
@ -558,9 +558,9 @@ int main(int argc, char *argv[]) {
if ( function & ZMU_IMAGE ) {
if ( verbose ) {
if ( image_idx == -1 )
printf("Dumping last image captured to Monitor%d.jpg", monitor->Id());
printf("Dumping last image captured to Monitor%u.jpg", monitor->Id());
else
printf("Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id());
printf("Dumping buffer image %d to Monitor%u.jpg", image_idx, monitor->Id());
if ( scale != -1 )
printf(", scaling by %d%%", scale);
printf("\n");
@ -569,7 +569,7 @@ int main(int argc, char *argv[]) {
}
if ( function & ZMU_ZONES ) {
if ( verbose )
printf("Dumping zone image to Zones%d.jpg\n", monitor->Id());
printf("Dumping zone image to Zones%u.jpg\n", monitor->Id());
monitor->DumpZoneImage(zoneString);
}
if ( function & ZMU_ALARM ) {
@ -735,17 +735,17 @@ int main(int argc, char *argv[]) {
Debug(1, "Got %d monitors", mysql_num_rows(result));
printf("%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate");
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) {
int mon_id = atoi(dbrow[0]);
int function = atoi(dbrow[1]);
if ( !user || user->canAccess(mon_id) ) {
if ( function > 1 ) {
Monitor *monitor = Monitor::Load(mon_id, false, Monitor::QUERY);
for ( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) {
int monitor_id = atoi(dbrow[0]);
int monitor_function = atoi(dbrow[1]);
if ( !user || user->canAccess(monitor_id) ) {
if ( monitor_function > 1 ) {
Monitor *monitor = Monitor::Load(monitor_id, false, Monitor::QUERY);
if ( monitor && monitor->connect() ) {
struct timeval tv = monitor->GetTimestamp();
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8" PRIu64 "%8.2f\n",
monitor->Id(),
function,
monitor_function,
monitor->GetState(),
monitor->GetTriggerState(),
tv.tv_sec, tv.tv_usec/10000,

View File

@ -94,12 +94,12 @@ commonprep () {
# The rpm specfile requires we download each submodule as a tarball then manually move it into place
# Might as well do this for Debian as well, rather than git submodule init
CRUDVER="3.1.0-zm"
CRUDVER="3.2.0"
if [ -e "build/crud-${CRUDVER}.tar.gz" ]; then
echo "Found existing Crud ${CRUDVER} tarball..."
else
echo "Retrieving Crud ${CRUDVER} submodule..."
curl -L https://github.com/ZoneMinder/crud/archive/v${CRUDVER}.tar.gz > build/crud-${CRUDVER}.tar.gz
curl -L https://github.com/FriendsOfCake/crud/archive/v${CRUDVER}.tar.gz > build/crud-${CRUDVER}.tar.gz
if [ $? -ne 0 ]; then
echo "ERROR: Crud tarball retreival failed..."
exit 1

View File

@ -1 +1 @@
1.35.10
1.35.14

View File

@ -26,22 +26,22 @@ if ( $message ) {
return;
}
$filter = isset($_REQUEST['filter']) ? ZM\Filter::parse($_REQUEST['filter']) : new ZM\Filter();
if ( $user['MonitorIds'] ) {
$filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds']));
}
// Search contains a user entered string to search on
$search = isset($_REQUEST['search']) ? $_REQUEST['search'] : '';
// Advanced search contains an array of "column name" => "search text" pairs
// Bootstrap table sends json_ecoded array, which we must decode
$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array();
$advsearch = isset($_REQUEST['advsearch']) ? json_decode($_REQUEST['advsearch'], JSON_OBJECT_AS_ARRAY) : array();
// Sort specifies the name of the column to sort on
$sort = 'StartTime';
$sort = 'StartDateTime';
if ( isset($_REQUEST['sort']) ) {
if ( !in_array($_REQUEST['sort'], array_merge($columns, $col_alt)) ) {
ZM\Error('Invalid sort field: ' . $_REQUEST['sort']);
} else {
$sort = $_REQUEST['sort'];
//if ( $sort == 'DateTime' ) $sort = 'TimeKey';
}
$sort = $_REQUEST['sort'];
}
// Offset specifies the starting row to return, used for pagination
@ -80,7 +80,7 @@ switch ( $task ) {
foreach ( $eids as $eid ) $data[] = deleteRequest($eid);
break;
case 'query' :
$data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit);
$data = queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit);
break;
default :
ZM\Fatal("Unrecognised task '$task'");
@ -114,62 +114,79 @@ function deleteRequest($eid) {
return $message;
}
function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) {
function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit) {
$data = array(
'total' => 0,
'totalNotFiltered' => 0,
'rows' => array(),
'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG)
);
$failed = !$filter->test_pre_sql_conditions();
if ( $failed ) {
ZM\Debug('Pre conditions failed, not doing sql');
return $data;
}
// Put server pagination code here
// The table we want our data from
$table = 'Events';
// The names of the dB columns in the log table we are interested in
$columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace');
// The names of the dB columns in the events table we are interested in
$columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartDateTime', 'EndDateTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace');
// The names of columns shown in the log view that are NOT dB columns in the database
// The names of columns shown in the event view that are NOT dB columns in the database
$col_alt = array('Monitor', 'Storage');
$col_str = implode(', ', $columns);
if ( !in_array($sort, array_merge($columns, $col_alt)) ) {
ZM\Error('Invalid sort field: ' . $sort);
$sort = 'Id';
}
$data = array();
$query = array();
$query['values'] = array();
$likes = array();
$where = '';
$where = ($filter->sql()?'('.$filter->sql().')' : '');
// There are two search bars in the log view, normal and advanced
// Making an exuctive decision to ignore the normal search, when advanced search is in use
// Alternatively we could try to do both
if ( count($advsearch) ) {
foreach ( $advsearch as $col=>$text ) {
if ( !in_array($col, array_merge($columns, $col_alt)) ) {
if ( in_array($col, $columns) ) {
array_push($likes, 'E.'.$col.' LIKE ?');
array_push($query['values'], $text);
} else if ( in_array($col, $col_alt) ) {
array_push($likes, 'M.'.$col.' LIKE ?');
array_push($query['values'], $text);
} else {
ZM\Error("'$col' is not a sortable column name");
continue;
}
$text = '%' .$text. '%';
array_push($likes, $col.' LIKE ?');
array_push($query['values'], $text);
}
} # end foreach col in advsearch
$wherevalues = $query['values'];
$where = ' WHERE (' .implode(' OR ', $likes). ')';
$where .= ($where != '') ? ' AND (' .implode(' OR ', $likes). ')' : implode(' OR ', $likes);
} else if ( $search != '' ) {
$search = '%' .$search. '%';
foreach ( $columns as $col ) {
array_push($likes, $col.' LIKE ?');
array_push($likes, 'E.'.$col.' LIKE ?');
array_push($query['values'], $search);
}
$wherevalues = $query['values'];
$where = ' WHERE (' .implode(' OR ', $likes). ')';
}
$where .= ( $where != '') ? ' AND (' .implode(' OR ', $likes). ')' : implode(' OR ', $likes);
}
if ( $where )
$where = ' WHERE '.$where;
$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?';
$sort = $sort == 'Monitor' ? 'M.Name' : 'E.'.$sort;
$col_str = 'E.*, M.Name AS Monitor';
$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?';
array_push($query['values'], $offset, $limit);
//ZM\Warning('Calling the following sql query: ' .$query['sql']);
$data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total');
if ( $search != '' || count($advsearch) ) {
$data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues);
} else {
$data['total'] = $data['totalNotFiltered'];
}
//ZM\Debug('Calling the following sql query: ' .$query['sql']);
$storage_areas = ZM\Storage::find();
$StorageById = array();
@ -177,37 +194,41 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) {
$StorageById[$S->Id()] = $S;
}
$monitor_names = ZM\Monitor::find();
$MonitorById = array();
foreach ( $monitor_names as $S ) {
$MonitorById[$S->Id()] = $S;
}
$rows = array();
foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) {
$event = new ZM\Event($row['Id']);
$event = new ZM\Event($row);
if ( !$filter->test_post_sql_conditions($event) ) {
$event->remove_from_cache();
continue;
}
$scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width());
$imgSrc = $event->getThumbnailSrc(array(),'&amp;');
$streamSrc = $event->getStreamSrc(array(
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&amp;');
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&amp;');
// Modify the row data as needed
$row['imgHtml'] = '<img id="thumbnail' .$event->Id(). '" src="' .$imgSrc. '" alt="' .validHtmlStr('Event ' .$event->Id()). '" style="width:' .validInt($event->ThumbnailWidth()). 'px;height:' .validInt($event->ThumbnailHeight()).'px;" stream_src="' .$streamSrc. '" still_src="' .$imgSrc. '"/>';
$row['Name'] = validHtmlStr($row['Name']);
$row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No');
$row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No');
$row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : '';
$row['Cause'] = validHtmlStr($row['Cause']);
$row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime']));
$row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime']));
$row['StartDateTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartDateTime']));
$row['EndDateTime'] = $row['EndDateTime'] ? strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['EndDateTime'])) : null;
$row['Length'] = gmdate('H:i:s', $row['Length'] );
$row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default';
$row['Notes'] = htmlspecialchars($row['Notes']);
$row['DiskSpace'] = human_filesize($row['DiskSpace']);
$row['Notes'] = nl2br(htmlspecialchars($row['Notes']));
$row['DiskSpace'] = human_filesize($event->DiskSpace());
$rows[] = $row;
}
$data['rows'] = $rows;
$data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG);
# totalNotFiltered must equal total, except when either search bar has been used
$data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total');
if ( $search != '' || count($advsearch) ) {
$data['total'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where , 'Total', $wherevalues);
} else {
$data['total'] = $data['totalNotFiltered'];
}
return $data;
}

View File

@ -1,132 +1,186 @@
<?php
global $Servers;
if ( !canView('System') ) {
ajaxError('Insufficient permissions to view log entries');
return;
}
// Only the query task is supported at the moment
if ( !isset($_REQUEST['task']) or $_REQUEST['task'] != 'query' ) {
ajaxError('Unrecognised action');
return;
}
// The table we want our data from
$table = 'Logs';
// The names of the dB columns in the log table we are interested in
$columns = array('TimeKey', 'Component', 'ServerId', 'Pid', 'Code', 'Message', 'File', 'Line');
// The names of columns shown in the log view that are NOT dB columns in the database
$col_alt = array('DateTime', 'Server');
// Search contains a user entered string to search on
$search = isset($_REQUEST['search']) ? $_REQUEST['search'] : '';
// Advanced search contains an array of "column name" => "search text" pairs
// Bootstrap table sends json_ecoded array, which we must decode
$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array();
// Sort specifies the name of the column to sort on
$sort = 'TimeKey';
if ( isset($_REQUEST['sort']) ) {
if ( !in_array($_REQUEST['sort'], array_merge($columns, $col_alt)) ) {
ZM\Error('Invalid sort field: ' . $_REQUEST['sort']);
} else {
$sort = $_REQUEST['sort'];
if ( $sort == 'DateTime' ) $sort = 'TimeKey';
}
}
// Offset specifies the starting row to return, used for pagination
$offset = 0;
if ( isset($_REQUEST['offset']) ) {
if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) {
ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']);
} else {
$offset = $_REQUEST['offset'];
}
}
// Order specifies the sort direction, either asc or desc
$order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC';
// Limit specifies the number of rows to return
$limit = 100;
if ( isset($_REQUEST['limit']) ) {
if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) {
ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']);
} else {
$limit = $_REQUEST['limit'];
}
}
$col_str = implode(', ', $columns);
$data = array();
$query = array();
$query['values'] = array();
$likes = array();
$where = '';
// There are two search bars in the log view, normal and advanced
// Making an exuctive decision to ignore the normal search, when advanced search is in use
// Alternatively we could try to do both
if ( count($advsearch) ) {
$message = '';
foreach ( $advsearch as $col=>$text ) {
if ( !in_array($col, array_merge($columns, $col_alt)) ) {
ZM\Error("'$col' is not a sortable column name");
continue;
}
$text = '%' .$text. '%';
array_push($likes, $col.' LIKE ?');
array_push($query['values'], $text);
}
$wherevalues = $query['values'];
$where = ' WHERE (' .implode(' OR ', $likes). ')';
//
// INITIALIZE AND CHECK SANITY
//
} else if ( $search != '' ) {
if ( !canView('System') )
$message = 'Insufficient permissions to view log entries for user '.$user['Username'];
$search = '%' .$search. '%';
foreach ( $columns as $col ) {
array_push($likes, $col.' LIKE ?');
array_push($query['values'], $search);
}
$wherevalues = $query['values'];
$where = ' WHERE (' .implode(' OR ', $likes). ')';
}
$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?';
array_push($query['values'], $offset, $limit);
//ZM\Warning('Calling the following sql query: ' .$query['sql']);
$data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total');
if ( $search != '' || count($advsearch) ) {
$data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues);
// task must be set
if ( !isset($_REQUEST['task']) ) {
$message = 'This request requires a task to be set';
} else if ( $_REQUEST['task'] != 'query' && $_REQUEST['task'] != 'create' ) {
// Only the query and create tasks are supported at the moment
$message = 'Unrecognised task '.$_REQUEST['task'];
} else {
$data['total'] = $data['totalNotFiltered'];
$task = $_REQUEST['task'];
}
if ( !$Servers )
$Servers = ZM\Server::find();
$servers_by_Id = array();
# There is probably a better way to do this.
foreach ( $Servers as $server ) {
$servers_by_Id[$server->Id()] = $server;
if ( $message ) {
ajaxError($message);
return;
}
$rows = array();
foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) {
$row['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($row['TimeKey']));
$row['Server'] = ( $row['ServerId'] and isset($servers_by_Id[$row['ServerId']]) ) ? $servers_by_Id[$row['ServerId']]->Name() : '';
// First strip out any html tags
// Second strip out all characters that are not ASCII 32-126 (yes, 126)
$row['Message'] = preg_replace('/[^\x20-\x7E]/', '', strip_tags($row['Message']));
$rows[] = $row;
}
$data['rows'] = $rows;
$data['logstate'] = logState();
$data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG);
//
// MAIN LOOP
//
switch ( $task ) {
case 'create' :
createRequest();
break;
case 'query' :
$data = queryRequest();
break;
default :
ZM\Fatal('Unrecognised task '.$task);
} // end switch task
ajaxResponse($data);
//
// FUNCTION DEFINITIONS
//
function createRequest() {
if ( !empty($_POST['level']) && !empty($_POST['message']) ) {
ZM\logInit(array('id'=>'web_js'));
$string = $_POST['message'];
$file = !empty($_POST['file']) ? preg_replace('/\w+:\/\/[\w.:]+\//', '', $_POST['file']) : '';
if ( !empty($_POST['line']) ) {
$line = validInt($_POST['line']);
} else {
$line = NULL;
}
$levels = array_flip(ZM\Logger::$codes);
if ( !isset($levels[$_POST['level']]) ) {
ZM\Panic('Unexpected logger level '.$_POST['level']);
}
$level = $levels[$_POST['level']];
ZM\Logger::fetch()->logPrint($level, $string, $file, $line);
} else {
ZM\Error('Invalid log create: '.print_r($_POST, true));
}
}
function queryRequest() {
// Offset specifies the starting row to return, used for pagination
$offset = 0;
if ( isset($_REQUEST['offset']) ) {
if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) {
ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']);
} else {
$offset = $_REQUEST['offset'];
}
}
// Limit specifies the number of rows to return
$limit = 100;
if ( isset($_REQUEST['limit']) ) {
if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) {
ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']);
} else {
$limit = $_REQUEST['limit'];
}
}
// The table we want our data from
$table = 'Logs';
// The names of the dB columns in the log table we are interested in
$columns = array('TimeKey', 'Component', 'ServerId', 'Pid', 'Code', 'Message', 'File', 'Line');
// The names of columns shown in the log view that are NOT dB columns in the database
$col_alt = array('DateTime', 'Server');
$sort = 'TimeKey';
if ( isset($_REQUEST['sort']) ) {
$sort = $_REQUEST['sort'];
if ( $sort == 'DateTime' ) $sort = 'TimeKey';
}
if ( !in_array($sort, array_merge($columns, $col_alt)) ) {
ZM\Error('Invalid sort field: ' . $sort);
return;
}
// Order specifies the sort direction, either asc or desc
$order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC';
$col_str = implode(', ', $columns);
$data = array();
$query = array();
$query['values'] = array();
$likes = array();
$where = '';
// There are two search bars in the log view, normal and advanced
// Making an exuctive decision to ignore the normal search, when advanced search is in use
// Alternatively we could try to do both
//
// Advanced search contains an array of "column name" => "search text" pairs
// Bootstrap table sends json_ecoded array, which we must decode
$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array();
// Search contains a user entered string to search on
$search = isset($_REQUEST['search']) ? $_REQUEST['search'] : '';
if ( count($advsearch) ) {
foreach ( $advsearch as $col=>$text ) {
if ( !in_array($col, array_merge($columns, $col_alt)) ) {
ZM\Error("'$col' is not a searchable column name");
continue;
}
// Don't use wildcards on advanced search
//$text = '%' .$text. '%';
array_push($likes, $col.' LIKE ?');
array_push($query['values'], $text);
}
$wherevalues = $query['values'];
$where = ' WHERE (' .implode(' OR ', $likes). ')';
} else if ( $search != '' ) {
$search = '%' .$search. '%';
foreach ( $columns as $col ) {
array_push($likes, $col.' LIKE ?');
array_push($query['values'], $search);
}
$wherevalues = $query['values'];
$where = ' WHERE (' .implode(' OR ', $likes). ')';
}
$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?';
array_push($query['values'], $offset, $limit);
$data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total');
if ( $search != '' || count($advsearch) ) {
$data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues);
} else {
$data['total'] = $data['totalNotFiltered'];
}
$rows = array();
$results = dbFetchAll($query['sql'], NULL, $query['values']);
if ( !$results ) {
return $data;
}
foreach ( $results as $row ) {
$row['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($row['TimeKey']));
$Server = new ZM\Server($row['ServerId']);
$row['Server'] = $Server->Name();
// First strip out any html tags
// Second strip out all characters that are not ASCII 32-126 (yes, 126)
$row['Message'] = preg_replace('/[^\x20-\x7E]/', '', strip_tags($row['Message']));
$rows[] = $row;
}
$data['rows'] = $rows;
$data['logstate'] = logState();
$data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG);
return $data;
}

View File

@ -6,6 +6,7 @@ if ( $_REQUEST['entity'] == 'navBar' ) {
$auth_hash = generateAuthHash(ZM_AUTH_HASH_IPS);
if ( isset($_REQUEST['auth']) and ($_REQUEST['auth'] != $auth_hash) ) {
$data['auth'] = $auth_hash;
$data['auth_relay'] = get_auth_relay();
}
}
// Each widget on the navbar has its own function
@ -108,9 +109,9 @@ $statusData = array(
'Name' => true,
'Cause' => true,
'Notes' => true,
'StartTime' => true,
'StartTimeShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
'EndTime' => true,
'StartDateTime' => true,
'StartTimeShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
'EndDateTime' => true,
'Width' => true,
'Height' => true,
'Length' => true,
@ -132,9 +133,9 @@ $statusData = array(
'MonitorName' => array('sql' => '(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)'),
'Name' => true,
'Cause' => true,
'StartTime' => true,
'StartTimeShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
'EndTime' => true,
'StartDateTime' => true,
'StartTimeShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
'EndDateTime' => true,
'Width' => true,
'Height' => true,
'Length' => true,
@ -179,7 +180,7 @@ $statusData = array(
'EventId' => true,
'Type' => true,
'TimeStamp' => true,
'TimeStampShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
'TimeStampShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
'Delta' => true,
'Score' => true,
//'Image' => array( 'postFunc' => 'getFrameImage' ),
@ -416,48 +417,54 @@ function getNearEvents() {
$event = dbFetchOne('SELECT * FROM Events WHERE Id=?', NULL, array($eventId));
if ( !$event ) return $NearEvents;
if ( isset($_REQUEST['filter']) )
parseFilter( $_REQUEST['filter'] );
$filter = ZM\Filter::parse($_REQUEST['filter']);
parseSort();
if ( $user['MonitorIds'] )
$midSql = ' AND MonitorId IN ('.join( ',', preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).')';
else
$midSql = '';
if ( $user['MonitorIds'] ) {
$filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds']));
}
# When listing, it may make sense to list them in descending order. But when viewing Prev should timewise earlier and Next should be after.
if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartTime' ) {
if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartDateTime' ) {
$sortOrder = 'ASC';
}
$sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn.' '.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\''.$_REQUEST['filter']['sql'].$midSql.' AND E.Id<'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC');
$sql = 'SELECT E.Id AS Id, E.StartDateTime AS StartDateTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn.' '.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\' AND ('.$filter->sql().') AND E.Id<'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC');
if ( $sortColumn != 'E.Id' ) {
# When sorting by starttime, if we have two events with the same starttime (diffreent monitors) then we should sort secondly by Id
$sql .= ', E.Id DESC';
}
$sql .= ' LIMIT 1';
$result = dbQuery($sql);
if ( !$result ) {
ZM\Error('Failed to load previous event using '.$sql);
return $NearEvents;
}
$prevEvent = dbFetchNext($result);
$sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn .' '.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql.' AND E.Id>'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC');
$sql = 'SELECT E.Id AS Id, E.StartDateTime AS StartDateTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn .' '.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']]."' AND (".$filter->sql().') AND E.Id>'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC');
if ( $sortColumn != 'E.Id' ) {
# When sorting by starttime, if we have two events with the same starttime (diffreent monitors) then we should sort secondly by Id
$sql .= ', E.Id ASC';
}
$sql .= ' LIMIT 1';
$result = dbQuery($sql);
if ( !$result ) {
ZM\Error('Failed to load next event using '.$sql);
return $NearEvents;
}
$nextEvent = dbFetchNext($result);
if ( $prevEvent ) {
$NearEvents['PrevEventId'] = $prevEvent['Id'];
$NearEvents['PrevEventStartTime'] = $prevEvent['StartTime'];
$NearEvents['PrevEventStartTime'] = $prevEvent['StartDateTime'];
$NearEvents['PrevEventDefVideoPath'] = getEventDefaultVideoPath($prevEvent['Id']);
} else {
$NearEvents['PrevEventId'] = $result['PrevEventStartTime'] = $result['PrevEventDefVideoPath'] = 0;
$NearEvents['PrevEventId'] = $NearEvents['PrevEventStartTime'] = $NearEvents['PrevEventDefVideoPath'] = 0;
}
if ( $nextEvent ) {
$NearEvents['NextEventId'] = $nextEvent['Id'];
$NearEvents['NextEventStartTime'] = $nextEvent['StartTime'];
$NearEvents['NextEventStartTime'] = $nextEvent['StartDateTime'];
$NearEvents['NextEventDefVideoPath'] = getEventDefaultVideoPath($nextEvent['Id']);
} else {
$NearEvents['NextEventId'] = $NearEvents['NextEventStartTime'] = $NearEvents['NextEventDefVideoPath'] = 0;

View File

@ -128,7 +128,7 @@ if ( sem_acquire($semaphore,1) !== false ) {
$data['auth'] = $auth_hash;
ZM\Debug("including nw auth hash " . $data['auth']);
} else {
ZM\Debug('Not including nw auth hash becase it hashn\'t changed '.$auth_hash);
ZM\Debug('Not including new auth hash becase it hasn\'t changed '.$auth_hash);
}
}
ajaxResponse(array('status'=>$data));

View File

@ -89,11 +89,11 @@ class ImageComponent extends Component {
}
// Take the StartTime of an Event and return
// Take the StartDateTime of an Event and return
// the path to its location on the filesystem
public function getEventPath( $event ) {
if ( $config['ZM_USE_DEEP_STORAGE'] == 1 )
return $event['Event']['MonitorId'].'/'.strftime( "%y/%m/%d/%H/%M/%S", strtotime($event['Event']['StartTime']) );
return $event['Event']['MonitorId'].'/'.strftime( '%y/%m/%d/%H/%M/%S', strtotime($event['Event']['StartDateTime']) );
else
return $event['Event']['MonitorId'].'/'.$event['Event']['Id'];
}

View File

@ -48,9 +48,24 @@ class EventsController extends AppController {
$mon_options = '';
}
if ( $this->request->params['named'] ) {
$named_params = $this->request->params['named'];
if ( $named_params ) {
# In 1.35.13 we renamed StartTime and EndTime to StartDateTime and EndDateTime.
# This hack renames the query string params
foreach ( $named_params as $k=>$v ) {
if ( false !== strpos($k, 'StartTime') ) {
$new_k = preg_replace('/StartTime/', 'StartDateTime', $k);
$named_params[$new_k] = $named_params[$k];
unset($named_params[$k]);
}
if ( false !== strpos($k, 'EndTime') ) {
$new_k = preg_replace('/EndTime/', 'EndDateTime', $k);
$named_params[$new_k] = $named_params[$k];
unset($named_params[$k]);
}
}
$this->FilterComponent = $this->Components->load('Filter');
$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
$conditions = $this->FilterComponent->buildFilter($named_params);
} else {
$conditions = array();
}
@ -65,7 +80,7 @@ class EventsController extends AppController {
// API
'limit' => '100',
'order' => array('StartTime'),
'order' => array('StartDateTime'),
'paramType' => 'querystring',
);
if ( isset($conditions['GroupId']) ) {
@ -309,7 +324,7 @@ class EventsController extends AppController {
} else {
$conditions = array();
}
array_push($conditions, array("StartTime >= DATE_SUB(NOW(), INTERVAL $expr $unit)"));
array_push($conditions, array("StartDateTime >= DATE_SUB(NOW(), INTERVAL $expr $unit)"));
$query = $this->Event->find('all', array(
'fields' => array(
'MonitorId',

View File

@ -31,6 +31,10 @@ class Event extends AppModel {
*/
public $displayField = 'Name';
public $virtualFields = array(
'StartTime' => 'StartDateTime',
'EndTime' => 'EndDateTime'
);
//The Associations below have been created with all possible keys, those that are not needed can be removed

View File

@ -14,8 +14,8 @@ class Event extends ZM_Object {
'StorageId' => null,
'SecondaryStorageId' => null,
'Cause' => '',
'StartTime' => null,
'EndTime' => null,
'StartDateTime' => null,
'EndDateTime' => null,
'Width' => null,
'Height' => null,
'Length' => null,
@ -93,7 +93,7 @@ class Event extends ZM_Object {
public function Time() {
if ( ! isset($this->{'Time'}) ) {
$this->{'Time'} = strtotime($this->{'StartTime'});
$this->{'Time'} = strtotime($this->{'StartDateTime'});
}
return $this->{'Time'};
}
@ -153,9 +153,9 @@ class Event extends ZM_Object {
if ( $this->{'Scheme'} == 'Deep' ) {
# Assumption: All events have a start time
$start_date = date_parse($this->{'StartTime'});
$start_date = date_parse($this->{'StartDateTime'});
if ( ! $start_date ) {
throw new Exception('Unable to parse start time for event ' . $this->{'Id'} . ' not deleting files.');
throw new Exception('Unable to parse start date time for event ' . $this->{'Id'} . ' not deleting files.');
}
$start_date['year'] = $start_date['year'] % 100;
@ -279,7 +279,7 @@ class Event extends ZM_Object {
}
if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) {
$this->{'DiskSpace'} = folder_size($this->Path());
if ( $this->{'EndTime'} ) {
if ( $this->{'EndDateTime'} ) {
# Finished events shouldn't grow in size much so we can commit it to the db.
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
}
@ -606,7 +606,7 @@ class Event extends ZM_Object {
if ( $this->Archived() ) {
return false;
}
if ( !$this->EndTime() ) {
if ( !$this->EndDateTime() ) {
return false;
}
if ( !canEdit('Events') ) {
@ -619,7 +619,7 @@ class Event extends ZM_Object {
public function cant_delete_reason() {
if ( $this->Archived() ) {
return 'You cannot delete an archived event. Unarchive it first.';
} else if ( ! $this->EndTime() ) {
} else if ( ! $this->EndDateTime() ) {
return 'You cannot delete an event while it is being recorded. Wait for it to finish.';
} else if ( ! canEdit('Events') ) {
return 'You do not have rights to edit Events.';

View File

@ -1,6 +1,7 @@
<?php
namespace ZM;
require_once('Object.php');
require_once('FilterTerm.php');
class Filter extends ZM_Object {
protected static $table = 'Filters';
@ -29,6 +30,7 @@ class Filter extends ZM_Object {
'Background' => 0,
'Concurrent' => 0,
'Query_json' => '',
'LockRows' => 0,
);
protected $_querystring;
@ -40,6 +42,7 @@ class Filter extends ZM_Object {
public function sql() {
if ( ! isset($this->_sql) ) {
$this->_sql = '';
foreach ( $this->FilterTerms() as $term ) {
#if ( ! ($term->is_pre_sql() or $term->is_post_sql()) ) {
$this->_sql .= $term->sql();
@ -51,13 +54,14 @@ class Filter extends ZM_Object {
return $this->_sql;
}
public function querystring($separator='&amp;') {
if ( (! isset($this->_querystring)) or ( $separator != '&amp;' ) ) {
public function querystring($objectname='filter', $separator='&amp;') {
if ( (! isset($this->_querystring)) or ( $separator != '&amp;' ) or ($objectname != 'filter') ) {
$this->_querystring = '';
foreach ( $this->FilterTerms() as $term ) {
$this->_querystring .= $term->querystring($separator);
$this->_querystring .= $term->querystring($objectname, $separator);
} # end foreach term
if ( $this->Id() ) {
$this->_querystring .= $separator.'filter[Id]='.$this->Id();
$this->_querystring .= $separator.$objectname.urlencode('[Id]').'='.$this->Id();
}
}
return $this->_querystring;
@ -65,6 +69,7 @@ class Filter extends ZM_Object {
public function hidden_fields() {
if ( ! isset($this->_hidden_fields) ) {
$this->_hidden_fields = '';
foreach ( $this->FilterTerms() as $term ) {
$this->_hidden_fields .= $term->hidden_fields();
} # end foreach term
@ -141,6 +146,13 @@ class Filter extends ZM_Object {
if ( func_num_args( ) ) {
$this->{'Query'} = func_get_arg(0);
$this->{'Query_json'} = jsonEncode($this->{'Query'});
# We have altered the query so need to reset all the calculated results.
unset($this->_querystring);
unset($this->_sql);
unset($this->_hidden_fields);
unset($this->_pre_sql_conditions);
unset($this->_post_sql_conditions);
unset($this->_Terms);
}
if ( !property_exists($this, 'Query') ) {
if ( property_exists($this, 'Query_json') and $this->{'Query_json'} ) {
@ -380,35 +392,35 @@ class Filter extends ZM_Object {
break;
case 'DateTime':
case 'StartDateTime':
$sqlValue = 'E.StartTime';
$sqlValue = 'E.StartDateTime';
$dtAttr = true;
break;
case 'Date':
case 'StartDate':
$sqlValue = 'to_days(E.StartTime)';
$sqlValue = 'to_days(E.StartDateTime)';
$dtAttr = true;
break;
case 'Time':
case 'StartTime':
$sqlValue = 'extract(hour_second from E.StartTime)';
$sqlValue = 'extract(hour_second from E.StartDateTime)';
break;
case 'Weekday':
case 'StartWeekday':
$sqlValue = 'weekday(E.StartTime)';
$sqlValue = 'weekday(E.StartDateTime)';
break;
case 'EndDateTime':
$sqlValue = 'E.EndTime';
$sqlValue = 'E.EndDateTime';
$dtAttr = true;
break;
case 'EndDate':
$sqlValue = 'to_days(E.EndTime)';
$sqlValue = 'to_days(E.EndDateTime)';
$dtAttr = true;
break;
case 'EndTime':
$sqlValue = 'extract(hour_second from E.EndTime)';
$sqlValue = 'extract(hour_second from E.EndDateTime)';
break;
case 'EndWeekday':
$sqlValue = 'weekday(E.EndTime)';
$sqlValue = 'weekday(E.EndDateTime)';
break;
case 'Id':
case 'Name':
@ -619,6 +631,37 @@ class Filter extends ZM_Object {
return array_pop($exprStack);
} # end function tree
} # end class Filter
function addTerm($term=false, $position=null) {
if ( !FilterTerm::is_valid_attr($term['attr']) ) {
Error('Unsupported filter attribute ' . $term['attr']);
return $this;
}
$terms = $this->terms();
if ( (!isset($position)) or ($position > count($terms)) )
$position = count($terms);
else if ( $position < 0 )
$position = 0;
if ( $term && ($position == 0) ) {
# if only 1 term, don't need AND or OR
unset($term['cnj']);
}
array_splice($terms, $position, 0, array($term ? $term : array()));
$this->terms($terms);
return $this;
} # end function addTerm
function addTerms($terms, $options=null) {
foreach ( $terms as $term ) {
$this->addTerm($term);
}
return $this;
}
} # end class Filter
?>

View File

@ -13,6 +13,7 @@ function getFilterQueryConjunctionTypes() {
return $validConjunctionTypes;
}
class FilterTerm {
public $filter;
public $index;
@ -35,7 +36,7 @@ class FilterTerm {
$this->val = $term['val'];
if ( isset($term['cnj']) ) {
if ( array_key_exists($term['cnj'], $validConjunctionTypes) ) {
$this->cnj = $term['cnj'];
$this->cnj = $term['cnj'];
} else {
Warning('Invalid cnj ' . $term['cnj'].' in '.print_r($term, true));
}
@ -65,7 +66,8 @@ class FilterTerm {
return $values;
}
foreach ( preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $this->val)) as $value ) {
$vals = is_array($this->val) ? $this->val : preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $this->val));
foreach ( $vals as $value ) {
switch ( $this->attr ) {
@ -75,7 +77,7 @@ class FilterTerm {
case 'ExistsInFileSystem':
$value = '';
break;
case 'DiskSpace':
case 'DiskPercent':
$value = '';
break;
case 'MonitorName':
@ -83,7 +85,7 @@ class FilterTerm {
case 'Name':
case 'Cause':
case 'Notes':
if ( $this->op == 'LIKE' || $this->op == 'NOT LIKE' ) {
if ( strstr($this->op, 'LIKE') and ! strstr($this->val, '%' ) ) {
$value = '%'.$value.'%';
}
$value = dbEscape($value);
@ -145,7 +147,7 @@ class FilterTerm {
case 'AlarmZoneId':
return ' EXISTS ';
case 'ExistsInFileSystem':
case 'DiskSpace':
case 'DiskPercent':
return '';
}
@ -185,7 +187,7 @@ class FilterTerm {
}
return ' IS NOT ';
default:
ZM\Warning('Invalid operator in filter: ' . print_r($this->op, true));
Warning('Invalid operator in filter: ' . print_r($this->op, true));
} // end switch op
} # end public function sql_operator
@ -202,7 +204,7 @@ class FilterTerm {
switch ( $this->attr ) {
case 'ExistsInFileSystem':
case 'DiskSpace':
case 'DiskPercent':
$sql .= 'TRUE /*'.$this->attr.'*/';
break;
case 'MonitorName':
@ -220,49 +222,50 @@ class FilterTerm {
break;
# Unspecified start or end, so assume start, this is to support legacy filters
case 'DateTime':
$sql .= 'E.StartTime';
$sql .= 'E.StartDateTime';
break;
case 'Date':
$sql .= 'to_days(E.StartTime)';
$sql .= 'to_days(E.StartDateTime)';
break;
case 'Time':
$sql .= 'extract(hour_second FROM E.StartTime)';
$sql .= 'extract(hour_second FROM E.StartDateTime)';
break;
case 'Weekday':
$sql .= 'weekday(E.StartTime)';
$sql .= 'weekday(E.StartDateTime)';
break;
# Starting Time
case 'StartDateTime':
$sql .= 'E.StartTime';
$sql .= 'E.StartDateTime';
break;
case 'FramesEventId':
$sql .= 'F.EventId';
break;
case 'StartDate':
$sql .= 'to_days(E.StartTime)';
$sql .= 'to_days(E.StartDateTime)';
break;
case 'StartTime':
$sql .= 'extract(hour_second FROM E.StartTime)';
$sql .= 'extract(hour_second FROM E.StartDateTime)';
break;
case 'StartWeekday':
$sql .= 'weekday(E.StartTime)';
$sql .= 'weekday(E.StartDateTime)';
break;
# Ending Time
case 'EndDateTime':
$sql .= 'E.EndTime';
$sql .= 'E.EndDateTime';
break;
case 'EndDate':
$sql .= 'to_days(E.EndTime)';
$sql .= 'to_days(E.EndDateTime)';
break;
case 'EndTime':
$sql .= 'extract(hour_second FROM E.EndTime)';
$sql .= 'extract(hour_second FROM E.EndDateTime)';
break;
case 'EndWeekday':
$sql .= 'weekday(E.EndTime)';
$sql .= 'weekday(E.EndDateTime)';
break;
case 'Emailed':
case 'Id':
case 'Name':
case 'EventDiskSpace':
case 'DiskSpace':
case 'MonitorId':
case 'StorageId':
case 'SecondaryStorageId':
@ -292,19 +295,19 @@ class FilterTerm {
return $sql;
} # end public function sql
public function querystring($querySep='&amp;') {
public function querystring($objectname='filter', $querySep='&amp;') {
# We don't validate the term parameters here
$query = '';
if ( $this->cnj )
$query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][cnj]').'='.$this->cnj;
$query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][cnj]').'='.$this->cnj;
if ( $this->obr )
$query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][obr]').'='.$this->obr;
$query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][obr]').'='.$this->obr;
$query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][attr]').'='.urlencode($this->attr);
$query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][op]').'='.urlencode($this->op);
$query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][val]').'='.urlencode($this->val);
$query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][attr]').'='.urlencode($this->attr);
$query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][op]').'='.urlencode($this->op);
$query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][val]').'='.urlencode($this->val);
if ( $this->cbr )
$query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][cbr]').'='.$this->cbr;
$query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][cbr]').'='.$this->cbr;
return $query;
} # end public function querystring
@ -400,21 +403,63 @@ class FilterTerm {
}
public function is_pre_sql() {
if ( $this->attr == 'DiskPercent' ) {
if ( $this->attr == 'DiskPercent' )
return true;
if ( $this->attr == 'DiskBlocks' )
return true;
}
return false;
}
public function is_post_sql() {
if ( $this->attr == 'ExistsInFileSystem' ) {
return true;
} else if ( $this->attr == 'DiskPercent' ) {
return true;
}
return false;
}
public static function is_valid_attr($attr) {
$attrs = array(
'ExistsInFileSystem',
'Emailed',
'DiskSpace',
'DiskPercent',
'DiskBlocks',
'MonitorName',
'ServerId',
'MonitorServerId',
'StorageServerId',
'FilterServerId',
'DateTime',
'Date',
'Time',
'Weekday',
'StartDateTime',
'FramesEventId',
'StartDate',
'StartTime',
'StartWeekday',
'EndDateTime',
'EndDate',
'EndTime',
'EndWeekday',
'Id',
'Name',
'MonitorId',
'StorageId',
'SecondaryStorageId',
'Length',
'Frames',
'AlarmFrames',
'TotScore',
'AvgScore',
'MaxScore',
'Cause',
'Notes',
'StateId',
'Archived'
);
return in_array($attr, $attrs);
}
} # end class FilterTerm
?>

View File

@ -114,18 +114,6 @@ class Monitor extends ZM_Object {
'WebColour' => '#ff0000',
'Exif' => array('type'=>'boolean','default'=>0),
'Sequence' => null,
'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ZoneCount' => 0,
'Refresh' => null,
'DefaultCodec' => 'auto',
@ -138,6 +126,18 @@ class Monitor extends ZM_Object {
'AnalysisFPS' => null,
'CaptureFPS' => null,
'CaptureBandwidth' => null,
'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
);
public function Control() {

View File

@ -11,7 +11,16 @@ class ZM_Object {
$row = NULL;
if ( $IdOrRow ) {
global $object_cache;
if ( ! isset($object_cache[$class]) ) {
$object_cache[$class] = array();
}
$cache = &$object_cache[$class];
if ( is_integer($IdOrRow) or ctype_digit($IdOrRow) ) {
if ( isset($cache[$IdOrRow]) ) {
return $cache[$IdOrRow];
}
$table = $class::$table;
$row = dbFetchOne("SELECT * FROM `$table` WHERE `Id`=?", NULL, array($IdOrRow));
if ( !$row ) {
@ -22,12 +31,6 @@ class ZM_Object {
}
if ( $row ) {
global $object_cache;
if ( ! isset($object_cache[$class]) ) {
$object_cache[$class] = array();
}
$cache = &$object_cache[$class];
foreach ($row as $k => $v) {
$this->{$k} = $v;
}

View File

@ -46,7 +46,6 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
}
} else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) {
$sql = '';
$_REQUEST['filter']['Query']['sort_field'] = validStr($_REQUEST['filter']['Query']['sort_field']);
$_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']);
$_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']);
@ -95,7 +94,7 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
} else if ( $filter->Background() ) {
$filter->control('start');
}
$redirect = '?view=filter&Id='.$filter->Id();
$redirect = '?view=filter'.$filter->querystring('filter', '&');
} else if ( $action == 'control' ) {
if ( $_REQUEST['command'] == 'start'

View File

@ -121,7 +121,8 @@ if ( $action == 'save' ) {
}
$saferNewName = basename($_REQUEST['newMonitor']['Name']);
$link_path = $NewStorage->Path().'/'.$saferNewName;
if ( !symlink($NewStorage->Path().'/'.$mid, $link_path) ) {
// Use a relative path for the target so the link continues to work from backups or directory changes.
if ( !symlink($mid, $link_path) ) {
if ( ! ( file_exists($link_path) and is_link($link_path) ) ) {
ZM\Warning('Unable to symlink ' . $NewStorage->Path().'/'.$mid . ' to ' . $NewStorage->Path().'/'.$saferNewName);
}

View File

@ -248,14 +248,12 @@ function userFromSession() {
if ( isset($_SESSION['AuthHash'.$_SESSION['remoteAddr']]) )
$user = getAuthUser($_SESSION['AuthHash'.$_SESSION['remoteAddr']]);
else
ZM\Debug("No auth hash in session, there should have been");
ZM\Debug('No auth hash in session, there should have been');
} else {
# Need to refresh permissions and validate that the user still exists
$sql = 'SELECT * FROM Users WHERE Enabled=1 AND Username=?';
$user = dbFetchOne($sql, NULL, array($_SESSION['username']));
}
} else {
ZM\Debug('No username in session');
}
return $user;
}

View File

@ -996,23 +996,19 @@ function parseSort($saveToSession=false, $querySep='&amp;') {
$sortColumn = 'E.Cause';
break;
case 'DateTime' :
$sortColumn = 'E.StartTime';
$_REQUEST['sort_field'] = 'StartTime';
$sortColumn = 'E.StartDateTime';
$_REQUEST['sort_field'] = 'StartDateTime';
break;
case 'DiskSpace' :
$sortColumn = 'E.DiskSpace';
break;
case 'StartTime' :
$sortColumn = 'E.StartTime';
break;
case 'StartDateTime' :
$sortColumn = 'E.StartTime';
$sortColumn = 'E.StartDateTime';
break;
case 'EndTime' :
$sortColumn = 'E.EndTime';
break;
case 'EndDateTime' :
$sortColumn = 'E.EndTime';
$sortColumn = 'E.EndDateTime';
break;
case 'Length' :
$sortColumn = 'E.Length';
@ -1048,7 +1044,7 @@ function parseSort($saveToSession=false, $querySep='&amp;') {
$sortColumn = 'F.Score';
break;
default:
$sortColumn = 'E.StartTime';
$sortColumn = 'E.StartDateTime';
break;
}
if ( !isset($_REQUEST['sort_asc']) )
@ -1077,7 +1073,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
$Filter = ZM\Filter::parse($filter, $querySep);
$filter['sql'] = $Filter->sql();
$filter['querystring'] = $Filter->querystring($querySep);
$filter['querystring'] = $Filter->querystring('filter', $querySep);
$filter['hidden_fields'] = $Filter->hidden_fields();
$filter['pre_sql_conditions'] = $Filter->pre_sql_conditions();
$filter['post_sql_conditions'] = $Filter->post_sql_conditions();

View File

@ -408,10 +408,10 @@ class Logger {
}
}
$message = $code.' ['.$string.']';
if ( $level <= $this->syslogLevel )
syslog( self::$syslogPriorities[$level], $message );
syslog(self::$syslogPriorities[$level], $message);
$message = $code.' ['.$string.']';
if ( $level <= $this->databaseLevel ) {
try {
global $dbConn;

View File

@ -144,8 +144,10 @@ class Session {
}
public function _gc($max) {
// Calculate what is to be deemed old
$old = time() - $max;
$sth = $this->db->prepare('DELETE * FROM Sessions WHERE access < :old');
$now = time();
$old = $now - $max;
ZM\Debug('doing session gc ' . $now . '-' . $max. '='.$old);
$sth = $this->db->prepare('DELETE FROM Sessions WHERE access < :old');
$sth->bindParam(':old', $old, PDO::PARAM_INT);
return $sth->execute() ? true : false;
}

View File

@ -371,6 +371,7 @@ $SLANG = array(
'FilterUpdateDiskSpace' => 'Update used disk space',
'FilterDeleteEvents' => 'Delete all matches',
'FilterCopyEvents' => 'Copy all matches',
'FilterLockRows' => 'Lock Rows',
'FilterMoveEvents' => 'Move all matches',
'FilterEmailEvents' => 'Email details of all matches',
'FilterEmailTo' => 'Email To',

View File

@ -123,7 +123,7 @@ table th:last-child{
a:link {
color: #3498db;
color: #0fbcf9;
text-decoration: none;
}

View File

@ -0,0 +1,3 @@
#imageFeed {
margin: 0 auto;
}

View File

@ -351,6 +351,11 @@ if ( currentView != 'none' && currentView != 'login' ) {
.done(setNavBar)
.fail(function(jqxhr, textStatus, error) {
console.log("Request Failed: " + textStatus + ", " + error);
if ( ! jqxhr.responseText ) {
console.log("No responseText in jqxhr");
console.log(jqxhr);
return;
}
console.log("Response Text: " + jqxhr.responseText.replace(/(<([^>]+)>)/gi, ''));
if ( textStatus != "timeout" ) {
// The idea is that this should only fail due to auth, so reload the page
@ -367,10 +372,14 @@ if ( currentView != 'none' && currentView != 'login' ) {
}
if ( data.auth ) {
if ( data.auth != auth_hash ) {
console.log("Update auth_hash to "+data.auth);
// Update authentication token.
auth_hash = data.auth;
}
}
if ( data.auth_relay ) {
auth_relay = data.auth_relay;
}
// iterate through all the keys then update each element id with the same name
for (var key of Object.keys(data)) {
if ( key == "auth" ) continue;
@ -752,8 +761,13 @@ function stateStuff(action, runState, newState) {
}
function logAjaxFail(jqxhr, textStatus, error) {
var responseText = jqxhr.responseText.replace(/(<([^>]+)>)/gi, '').trim(); // strip any html or whitespace from the response
console.log("Request Failed: " + textStatus + ", " + error);
if ( ! jqxhr.responseText ) {
console.log("Ajax request failed. No responseText. jqxhr follows:");
console.log(jqxhr);
return;
}
var responseText = jqxhr.responseText.replace(/(<([^>]+)>)/gi, '').trim(); // strip any html or whitespace from the response
if ( responseText ) console.log("Response Text: " + responseText);
}

View File

@ -182,7 +182,7 @@ xhtmlHeaders(__FILE__, translate('CycleWatch'));
?>
</div>
<div class="buttons">
<div id="buttons" class="buttons">
<button type="button" value="&lt;" id="prevBtn" title="<?php echo translate('PreviousMonitor') ?>" class="active" data-on-click-true="cyclePrev">&lt;&lt;</button>
<button type="button" value="||" id="pauseBtn" title="<?php echo translate('PauseCycle') ?>" class="active" data-on-click-true="cyclePause">||</button>
<button type="button" value="|&gt;" id="playBtn" title="<?php echo translate('PlayCycle') ?>" class="inactive" disabled="disabled" data-on-click-true="cycleStart">|&gt;</button>

View File

@ -49,9 +49,6 @@ if ( isset($_REQUEST['rate']) ) {
if ( isset($_REQUEST['scale']) ) {
$scale = validInt($_REQUEST['scale']);
} else if ( isset($_COOKIE['zmEventScaleAuto']) ) {
// If we're using scale to fit use it on all monitors
$scale = '0';
} else if ( isset($_COOKIE['zmEventScale'.$Event->MonitorId()]) ) {
$scale = $_COOKIE['zmEventScale'.$Event->MonitorId()];
} else {
@ -149,7 +146,7 @@ if ( !$Event->Id() ) {
<span id="dataId" title="<?php echo translate('Id') ?>"><?php echo $Event->Id() ?></span>
<span id="dataMonitor" title="<?php echo translate('Monitor') ?>"><?php echo $Monitor->Id().' '.validHtmlStr($Monitor->Name()) ?></span>
<span id="dataCause" title="<?php echo $Event->Notes()?validHtmlStr($Event->Notes()):translate('AttrCause') ?>"><?php echo validHtmlStr($Event->Cause()) ?></span>
<span id="dataTime" title="<?php echo translate('Time') ?>"><?php echo strftime(STRF_FMT_DATETIME_SHORT, strtotime($Event->StartTime())) ?></span>
<span id="dataTime" title="<?php echo translate('Time') ?>"><?php echo strftime(STRF_FMT_DATETIME_SHORT, strtotime($Event->StartDateTime())) ?></span>
<span id="dataDuration" title="<?php echo translate('Duration') ?>"><?php echo $Event->Length().'s' ?></span>
<span id="dataFrames" title="<?php echo translate('AttrFrames').'/'.translate('AttrAlarmFrames') ?>"><?php echo $Event->Frames() ?>/<?php echo $Event->AlarmFrames() ?></span>
<span id="dataScore" title="<?php echo translate('AttrTotalScore').'/'.translate('AttrAvgScore').'/'.translate('AttrMaxScore') ?>"><?php echo $Event->TotScore() ?>/<?php echo $Event->AvgScore() ?>/<?php echo $Event->MaxScore() ?></span>

View File

@ -42,73 +42,6 @@ if ( isset($_REQUEST['filter'])) {
parseSort();
$filterQuery = $filter->querystring();
ZM\Debug('Filter '.print_r($filter, true));
if ( $filter->sql() ) {
$eventsSql .= ' AND ('.$filter->sql().')';
} else {
ZM\Warning('No filters');
exit;
}
$eventsSql .= ' ORDER BY '.$sortColumn.' '.$sortOrder;
if ( $sortColumn != 'E.Id' ) $eventsSql .= ',E.Id '.$sortOrder;
$page = isset($_REQUEST['page']) ? validInt($_REQUEST['page']) : 0;
$limit = isset($_REQUEST['limit']) ? validInt($_REQUEST['limit']) : $filter['limit'];
if ( $_POST ) {
// I think this is basically so that a refresh doesn't repost
ZM\Debug('Redirecting to ' . $_SERVER['REQUEST_URI']);
header('Location: ?view=' . $view.htmlspecialchars_decode($filterQuery).htmlspecialchars_decode($sortQuery).$limitQuery.'&page='.$page);
exit();
}
$failed = !$filter->test_pre_sql_conditions();
if ( $failed ) {
ZM\Debug('Pre conditions failed, not doing sql');
}
$results = $failed ? null : dbQuery($eventsSql);
$nEvents = $results ? $results->rowCount() : 0;
if ( ! $results ) {
global $error_message;
$error_message = dbError($eventsSql);
}
ZM\Debug("Pre conditions succeeded sql return $nEvents events");
if ( !empty($limit) && ($nEvents > $limit) ) {
$nEvents = $limit;
}
$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE);
#Debug("Page $page Limit $limit #vents: $nEvents pages: $pages ");
if ( !empty($page) ) {
if ( $page < 0 )
$page = 1;
else if ( $pages and ( $page > $pages ) )
$page = $pages;
$limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE);
if ( empty($limit) ) {
$limitAmount = ZM_WEB_EVENTS_PER_PAGE;
} else {
$limitLeft = $limit - $limitStart;
$limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft;
}
$eventsSql .= ' LIMIT '.$limitStart.', '.$limitAmount;
} else if ( !empty($limit) ) {
$eventsSql .= ' LIMIT 0, '.$limit;
}
$maxShortcuts = 5;
$focusWindow = true;
$storage_areas = ZM\Storage::find();
$StorageById = array();
foreach ( $storage_areas as $S ) {
$StorageById[$S->Id()] = $S;
}
xhtmlHeaders(__FILE__, translate('Events'));
getBodyTopHTML();
@ -136,6 +69,8 @@ getBodyTopHTML();
<table
id="eventTable"
data-locale="<?php echo i18n() ?>"
data-side-pagination="server"
data-ajax="ajaxRequest"
data-pagination="true"
data-show-pagination-switch="true"
data-page-list="[10, 25, 50, 100, 200, All]"
@ -155,6 +90,7 @@ getBodyTopHTML();
data-mobile-responsive="true"
data-buttons-class="btn btn-normal"
data-show-jump-to="true"
data-show-refresh="true"
class="table-sm table-borderless"
style="display:none;"
>
@ -168,163 +104,24 @@ getBodyTopHTML();
<th data-sortable="true" data-field="Emailed"><?php echo translate('Emailed') ?></th>
<th data-sortable="true" data-field="Monitor"><?php echo translate('Monitor') ?></th>
<th data-sortable="true" data-field="Cause"><?php echo translate('Cause') ?></th>
<th data-sortable="true" data-field="AttrStartTime"><?php echo translate('AttrStartTime') ?></th>
<th data-sortable="true" data-field="AttrEndTime"><?php echo translate('AttrEndTime') ?></th>
<th data-sortable="true" data-field="Duration"><?php echo translate('Duration') ?></th>
<th data-sortable="true" data-field="StartDateTime"><?php echo translate('AttrStartTime') ?></th>
<th data-sortable="true" data-field="EndDateTime"><?php echo translate('AttrEndTime') ?></th>
<th data-sortable="true" data-field="Length"><?php echo translate('Duration') ?></th>
<th data-sortable="true" data-field="Frames"><?php echo translate('Frames') ?></th>
<th data-sortable="true" data-field="AlarmBrFrames"><?php echo translate('AlarmBrFrames') ?></th>
<th data-sortable="true" data-field="TotalBrScore"><?php echo translate('TotalBrScore') ?></th>
<th data-sortable="true" data-field="AvgBrScore"><?php echo translate('AvgBrScore') ?></th>
<th data-sortable="true" data-field="MaxBrScore"><?php echo translate('MaxBrScore') ?></th>
<?php
if ( count($storage_areas) > 1 ) {
?>
<th data-sortable="true" data-field="Storage"><?php echo translate('Storage') ?></th>
<?php
}
if ( ZM_WEB_EVENT_DISK_SPACE ) {
?>
<th data-sortable="true" data-field="AlarmFrames"><?php echo translate('AlarmBrFrames') ?></th>
<th data-sortable="true" data-field="TotScore"><?php echo translate('TotalBrScore') ?></th>
<th data-sortable="true" data-field="AvgScore"><?php echo translate('AvgBrScore') ?></th>
<th data-sortable="true" data-field="MaxScore"><?php echo translate('MaxBrScore') ?></th>
<th data-sortable="false" data-field="Storage"><?php echo translate('Storage') ?></th>
<th data-sortable="true" data-field="DiskSpace"><?php echo translate('DiskSpace') ?></th>
<?php
}
if ( ZM_WEB_LIST_THUMBS ) {
?>
<th data-sortable="false" data-field="Thumbnail"><?php echo translate('Thumbnail') ?></th>
<?php
}
?>
</tr>
</thead>
<tbody>
<?php
$count = 0;
$disk_space_total = 0;
if ( $results ) {
$events = array();
</thead>
while ( $event_row = dbFetchNext($results) ) {
$event = new ZM\Event($event_row);
if ( !$filter->test_post_sql_conditions($event) ) {
$event->remove_from_cache();
continue;
}
$events[] = $event;
if ( $limit and (count($events) >= $limit) ) {
break;
}
ZM\Debug("Have " . count($events) . " events, limit $limit");
}
foreach ( $events as $event ) {
$scale = max(reScale(SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE);
?>
<tr<?php echo $event->Archived() ? ' class="archived"' : '' ?>>
<td data-checkbox="true"></td>
<td><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.$event->Id() ?></a></td>
<td><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.validHtmlStr($event->Name())?></a>
<?php
$archived = $event->Archived() ? translate('Archived') : '';
$emailed = $event->Emailed() ? ' '.translate('Emailed') : '';
echo '<br/><div class="small text-nowrap text-muted">'.$archived.$emailed.'</div>';
?>
</td>
<td class="text-center"><?php echo ( $event->Archived() ) ? 'Yes' : 'No' ?></td>
<td class="text-center"><?php echo ( $event->Emailed() ) ? 'Yes' : 'No' ?></td>
<td><?php echo makeLink( '?view=monitor&amp;mid='.$event->MonitorId(), $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
<td><?php echo makeLink( '#', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="' .htmlspecialchars($event->Notes()). '" class="eDetailLink" data-eid=' .$event->Id(). '"') ?>
<?php
# display notes as small text
if ( $event->Notes() ) {
# if notes include detection objects, then link it to objdetect.jpg
if ( strpos($event->Notes(), 'detected:') !== false ) {
# make a link
echo makeLink( '?view=image&amp;eid='.$event->Id().'&amp;fid=objdetect', '<div class="small text-nowrap text-muted"><u>'.$event->Notes().'</u></div>');
} else if ( $event->Notes() != 'Forced Web: ' ) {
echo '<br/><div class="small text-nowrap text-muted">'.$event->Notes().'</div>';
}
}
?>
</td>
<td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) ?></td>
<td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime())) ?></td>
<td><?php echo gmdate('H:i:s', $event->Length() ) ?></td>
<td><a href="?view=frames&amp;eid=<?php echo $event->Id() ?>"><?php echo $event->Frames() ?></a></td>
<td><a href="?view=frames&amp;eid=<?php echo $event->Id() ?>"><?php echo $event->AlarmFrames() ?></a></td>
<td><?php echo $event->TotScore() ?></td>
<td><?php echo $event->AvgScore() ?></td>
<td><?php echo makeLink('?view=frame&amp;eid='.$event->Id().'&amp;fid=0', $event->MaxScore()); ?></td>
<?php
if ( count($storage_areas) > 1 ) {
?>
<td>
<?php
if ( $event->StorageId() ) {
echo isset($StorageById[$event->StorageId()]) ? $StorageById[$event->StorageId()]->Name() : 'Unknown Storage Id: '.$event->StorageId();
} else {
echo 'Default';
}
if ( $event->SecondaryStorageId() ) {
echo '<br/>'.(isset($StorageById[$event->SecondaryStorageId()]) ? $StorageById[$event->SecondaryStorageId()]->Name() : 'Unknown Storage Id '.$event->SecondaryStorageId());
}
?>
</td>
<?php
}
if ( ZM_WEB_EVENT_DISK_SPACE ) {
$disk_space_total += $event->DiskSpace();
?>
<td class="colDiskSpace"><?php echo human_filesize($event->DiskSpace()) ?></td>
<?php
}
if ( ZM_WEB_LIST_THUMBS ) {
echo '<td class="colThumbnail zoom">';
$imgSrc = $event->getThumbnailSrc(array(),'&amp;');
$streamSrc = $event->getStreamSrc(array(
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&amp;');
$imgHtml = '<img id="thumbnail'.$event->Id().'" src="'.$imgSrc.'" alt="'. validHtmlStr('Event '.$event->Id()) .'" style="width:'. validInt($event->ThumbnailWidth()) .'px;height:'. validInt($event->ThumbnailHeight()).'px;" stream_src="'.$streamSrc.'" still_src="'.$imgSrc.'"/>';
echo '<a href="?view=event&amp;eid='. $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.$imgHtml.'</a>';
echo '</td>';
} // end if ZM_WEB_LIST_THUMBS
?>
</tr>
<?php
} # end foreach row
?>
<tbody>
<!-- Row data populated via Ajax -->
</tbody>
<?php
} # end if $results
if ( ZM_WEB_EVENT_DISK_SPACE ) {
?>
<tfoot>
<tr>
<td colspan="11">Totals:</td>
<?php
if ( count($storage_areas)>1 ) {
?>
<td class="colStorage"></td>
<?php
}
?>
<td class="colDiskSpace"><?php echo human_filesize($disk_space_total) ?></td>
<?php
if ( ZM_WEB_LIST_THUMBS ) {
?>
<td></td>
<?php
}
?>
<td></td>
</tr>
</tfoot>
<?php
}
?>
</table>
</div>
</div>

View File

@ -152,8 +152,8 @@ while ( $event_row = dbFetchNext($results) ) {
<td class="colName"><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery ?>&amp;page=1"><?php echo validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a></td>
<td class="colMonitorName"><?php echo makeLink( '?view=monitor&amp;mid='.$event->MonitorId(), $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
<td class="colCause"><?php echo makeLink( '#', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="' .htmlspecialchars($event->Notes()). '" class="eDetailLink" data-eid=' .$event->Id(). '"') ?></td>
<td class="colTime"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) .
( $event->EndTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) : '' ) ?>
<td class="colTime"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartDateTime())) .
( $event->EndDateTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndDateTime()) ) : '' ) ?>
</td>
<td class="colDuration"><?php echo gmdate("H:i:s", $event->Length() ) ?></td>
<td class="colFrames"><?php echo makeLink( '?view=frames&amp;eid='.$event->Id(), $event->Frames() ) ?></td>

View File

@ -35,13 +35,12 @@ $filterNames = array(''=>translate('ChooseFilter'));
$filter = NULL;
$fid = 0;
if ( isset($_REQUEST['Id']) ) {
if ( isset($_REQUEST['Id']) and $_REQUEST['Id'] ) {
$fid = validInt($_REQUEST['Id']);
} else if ( isset($_REQUEST['filter[Id]']) ) {
$fid = validInt($_REQUEST['filter[Id]']);
ZM\Warning("got fid by object id $fid");
} else if ( isset($_REQUEST['filter']) and isset($_REQUEST['filter']['Id']) ) {
$fid = validInt($_REQUEST['filter']['Id']);
}
$filter = null;
foreach ( ZM\Filter::find(null,array('order'=>'lower(Name)')) as $Filter ) {
$filterNames[$Filter->Id()] = $Filter->Id() . ' ' . $Filter->Name();
if ( $Filter->Background() )
@ -53,17 +52,18 @@ foreach ( ZM\Filter::find(null,array('order'=>'lower(Name)')) as $Filter ) {
$filter = $Filter;
}
}
if ( !$filter ) {
if ( !$filter ) {
$filter = new ZM\Filter();
if ( isset($_REQUEST['filter']) ) {
# Update our filter object with whatever changes we have made before saving
$filter->set($_REQUEST['filter']);
}
} else {
ZM\Debug('filter: ' . print_r($filter,true));
}
ZM\Debug('filter: ' . print_r($filter,true));
if ( isset($_REQUEST['filter']) ) {
# Update our filter object with whatever changes we have made before saving
$filter->set($_REQUEST['filter']);
ZM\Debug("Setting filter from " . print_r($_REQUEST['filter'], true));
}
ZM\Debug('filter: ' . print_r($filter,true));
$conjunctionTypes = ZM\getFilterQueryConjunctionTypes();
$obracketTypes = array();
$cbracketTypes = array();
@ -89,8 +89,8 @@ $attrTypes = array(
'Cause' => translate('AttrCause'),
'DiskBlocks' => translate('AttrDiskBlocks'),
'DiskPercent' => translate('AttrDiskPercent'),
'DiskSpace' => translate('AttrDiskSpace'),
'EventDiskSpace' => translate('AttrEventDiskSpace'),
#'StorageDiskSpace' => translate('AttrStorageDiskSpace'),
'DiskSpace' => translate('AttrEventDiskSpace'),
'EndDateTime' => translate('AttrEndDateTime'),
'EndDate' => translate('AttrEndDate'),
'EndTime' => translate('AttrEndTime'),
@ -366,6 +366,7 @@ for ( $i=0; $i < count($terms); $i++ ) {
<td>
<label for="filter[Query][sort_field]"><?php echo translate('SortBy') ?></label>
<?php
# Note: The keys need to be actual column names
$sort_fields = array(
'Id' => translate('AttrId'),
'Name' => translate('AttrName'),
@ -373,7 +374,7 @@ $sort_fields = array(
'DiskSpace' => translate('AttrDiskSpace'),
'Notes' => translate('AttrNotes'),
'MonitorName' => translate('AttrMonitorName'),
'StartDateTime' => translate('AttrStartDateTime'),
'StartTime' => translate('AttrStartDateTime'),
'Length' => translate('AttrDuration'),
'Frames' => translate('AttrFrames'),
'AlarmFrames' => translate('AttrAlarmFrames'),
@ -381,7 +382,7 @@ $sort_fields = array(
'AvgScore' => translate('AttrAvgScore'),
'MaxScore' => translate('AttrMaxScore'),
);
echo htmlSelect( 'filter[Query][sort_field]', $sort_fields, $filter->sort_field() );
echo htmlSelect('filter[Query][sort_field]', $sort_fields, $filter->sort_field());
$sort_dirns = array(
'1' => translate('SortAsc'),
'0' => translate('SortDesc')
@ -484,6 +485,10 @@ if ( ZM_OPT_MESSAGE ) {
<label for="Concurrent"><?php echo translate('ConcurrentFilter') ?></label>
<input type="checkbox" id="filter[Concurrent]" name="filter[Concurrent]" value="1"<?php if ( $filter->Concurrent() ) { ?> checked="checked"<?php } ?> data-on-click-this="updateButtons"/>
</p>
<p>
<label for="LockRows"><?php echo translate('FilterLockRows') ?></label>
<input type="checkbox" id="filter[LockRows]" name="filter[LockRows]" value="1"<?php if ( $filter->LockRows() ) { ?> checked="checked"<?php } ?> data-on-click-this="updateButtons"/>
</p>
</div>
<hr/>
<div id="contentButtons">

View File

@ -181,8 +181,9 @@ if ( count($frames) ) {
<?php
if ( ZM_WEB_LIST_THUMBS ) {
$base_img_src = '?view=image&amp;fid=' .$Frame->Id();
$ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth();
$thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : '';
$thmb_height = ZM_WEB_LIST_THUMB_HEIGHT ? 'height='.ZM_WEB_LIST_THUMB_HEIGHT : '';
$thmb_height = 'height="'.( ZM_WEB_LIST_THUMB_HEIGHT ? ZM_WEB_LIST_THUMB_HEIGHT : ZM_WEB_LIST_THUMB_WIDTH*$ratio_factor ) .'"';
$thmb_fn = 'filename=' .$Event->MonitorId(). '_' .$frame['EventId']. '_' .$frame['FrameId']. '.jpg';
$img_src = join('&amp;', array_filter(array($base_img_src, $thmb_width, $thmb_height, $thmb_fn)));
$full_img_src = join('&amp;', array_filter(array($base_img_src, $thmb_fn)));

View File

@ -40,6 +40,8 @@ function cyclePrev() {
function initCycle() {
periodical_id = nextCycleView.periodical(cycleRefreshTimeout);
var scale = $j('#scale').val();
if ( scale == '0' || scale == 'auto' ) changeScale();
}
function changeSize() {
@ -100,6 +102,8 @@ function changeScale() {
}
if ( scale != '0' && scale != '' && scale != 'auto' ) {
var newWidth = ( monitorData[monIdx].width * scale ) / SCALE_BASE;
var newHeight = ( monitorData[monIdx].height * scale ) / SCALE_BASE;
if ( newWidth ) {
monitor_frame.css('width', newWidth+'px');
}
@ -107,8 +111,13 @@ function changeScale() {
monitor_frame.css('height', newHeight+'px');
}
} else {
monitor_frame.css('width', '100%');
monitor_frame.css('height', 'auto');
//var bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus');
var newSize = scaleToFit(monitorData[monIdx].width, monitorData[monIdx].height, monitor_frame, $j('#buttons'));
newWidth = newSize.width;
newHeight = newSize.height;
autoScale = newSize.autoScale;
monitor_frame.width(newWidth);
monitor_frame.height(newHeight);
}
/*Stream could be an applet so can't use moo tools*/
@ -124,6 +133,7 @@ function changeScale() {
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
// zms doesn't actually use width&height
if ( scale != '0' && scale != '' && scale != 'auto' ) {
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);

View File

@ -16,7 +16,7 @@ function vjsReplay() {
var overLaid = $j("#videoobj");
overLaid.append('<p class="vjsMessage" style="height: '+overLaid.height()+'px; line-height: '+overLaid.height()+'px;">No more events</p>');
} else {
var endTime = (Date.parse(eventData.EndTime)).getTime();
var endTime = (Date.parse(eventData.EndDateTime)).getTime();
var nextStartTime = nextEventStartTime.getTime(); //nextEventStartTime.getTime() is a mootools workaround, highjacks Date.parse
if ( nextStartTime <= endTime ) {
streamNext(true);
@ -176,12 +176,7 @@ function changeScale() {
} else {
alarmCue.html(renderAlarmCues(eventViewer));//just re-render alarmCues. skip ajax call
}
if ( scale == '0' ) {
Cookie.write('zmEventScaleAuto', 'auto', {duration: 10*365, samesite: 'strict'});
} else {
Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365, samesite: 'strict'});
Cookie.dispose('zmEventScaleAuto');
}
Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365, samesite: 'strict'});
} // end function changeScale
function changeReplayMode() {
@ -584,7 +579,7 @@ function getEventResponse(respObj, respText) {
$('dataCause').setProperty( 'title', causeString );
}
$('dataCause').set( 'text', eventData.Cause );
$('dataTime').set( 'text', eventData.StartTime );
$('dataTime').set( 'text', eventData.StartDateTime );
$('dataDuration').set( 'text', eventData.Length );
$('dataFrames').set( 'text', eventData.Frames+"/"+eventData.AlarmFrames );
$('dataScore').set( 'text', eventData.TotScore+"/"+eventData.AvgScore+"/"+eventData.MaxScore );
@ -606,7 +601,7 @@ function getEventResponse(respObj, respText) {
vid.src({type: 'video/mp4', src: CurEventDefVideoPath}); //Currently mp4 is all we use
console.log('getEventResponse');
initialAlarmCues(eventData.Id);//ajax and render, new event
addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime);
addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartDateTime);
CurEventDefVideoPath = null;
$j('#modeValue').html('Replay');
$j('#zoomValue').html('1');
@ -1088,7 +1083,7 @@ function initPage() {
//FIXME prevent blocking...not sure what is happening or best way to unblock
if ( $j('#videoobj').length ) {
vid = videojs('videoobj');
addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime);
addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartDateTime);
$j('.vjs-progress-control').append('<div class="alarmCue"></div>');//add a place for videojs only on first load
vid.on('ended', vjsReplay);
vid.on('play', vjsPlay);

View File

@ -44,8 +44,8 @@ var eventData = {
Width: '<?php echo $Event->Width() ?>',
Height: '<?php echo $Event->Height() ?>',
Length: '<?php echo $Event->Length() ?>',
StartTime: '<?php echo $Event->StartTime() ?>',
EndTime: '<?php echo $Event->EndTime() ?>',
StartDateTime: '<?php echo $Event->StartDateTime() ?>',
EndDateTime: '<?php echo $Event->EndDateTime() ?>',
Frames: '<?php echo $Event->Frames() ?>',
MonitorName: '<?php echo validJsStr($Monitor->Name()) ?>'
};

View File

@ -17,14 +17,14 @@ var params =
"data":
{
"search":"some search text",
"sort":"StartTime",
"sort":"StartDateTime",
"order":"asc",
"offset":0,
"limit":25
"filter":
{
"Name":"some advanced search text"
"StartTime":"some more advanced search text"
"StartDateTime":"some more advanced search text"
}
},
"cache":true,
@ -35,7 +35,11 @@ var params =
// Called by bootstrap-table to retrieve zm event data
function ajaxRequest(params) {
$j.getJSON(thisUrl + '?view=request&request=events&task=query', params.data)
if ( params.data && params.data.filter ) {
params.data.advsearch = params.data.filter;
delete params.data.filter;
}
$j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data)
.done(function(data) {
var rows = processRows(data.rows);
// rearrange the result into what bootstrap-table expects
@ -57,14 +61,14 @@ function processRows(rows) {
if ( canEditMonitors ) row.Monitor = '<a href="?view=monitor&amp;mid=' + mid + '">' + row.Monitor + '</a>';
if ( canEditEvents ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>';
if ( row.Notes.indexOf('detected:') >= 0 ) {
row.Cause = row.Cause + '<a href="#?view=image&amp;eid=' + eid + '&amp;fid=objdetect"><div class="small text-nowrap text-muted"><u>' + row.Notes + '</u></div></a>';
row.Cause = row.Cause + '<a href="?view=image&amp;eid=' + eid + '&amp;fid=objdetect"><div class="small text-nowrap text-muted"><u>' + row.Notes + '</u></div></a>';
} else if ( row.Notes != 'Forced Web: ' ) {
row.Cause = row.Cause + '<br/><div class="small text-nowrap text-muted">' + row.Notes + '</div>';
}
row.Frames = '<a href="?view=frames&amp;eid=' + eid + '">' + row.Frames + '</a>';
row.AlarmFrames = '<a href="?view=frames&amp;eid=' + eid + '">' + row.AlarmFrames + '</a>';
row.MaxScore = '<a href="?view=frame&amp;eid=' + eid + '&amp;fid=0">' + row.MaxScore + '</a>';
row.Thumbnail = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + row.imgHtml + '</a>';
if ( WEB_LIST_THUMBS ) row.Thumbnail = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + row.imgHtml + '</a>';
});
return rows;
@ -131,7 +135,7 @@ function manageDelConfirmModalBtns() {
$j.getJSON(thisUrl + '?request=events&task=delete&eids[]='+selections.join('&eids[]='))
.done( function(data) {
$j('#eventTable').bootstrapTable('refresh');
window.location.reload(true);
$j('#deleteConfirm').modal('hide');
})
.fail(logAjaxFail);
});
@ -157,6 +161,9 @@ function getEventDetailModal(eid) {
}
function initPage() {
// Remove the thumbnail column from the DOM if thumbnails are off globally
if ( !WEB_LIST_THUMBS ) $j('th[data-field="Thumbnail"]').remove();
// Load the delete confirmation modal into the DOM
getDelConfirmModal();
@ -234,7 +241,6 @@ function initPage() {
$j.getJSON(thisUrl + '?request=events&task=archive&eids[]='+selections.join('&eids[]='))
.done( function(data) {
$j('#eventTable').bootstrapTable('refresh');
window.location.reload(true);
})
.fail(logAjaxFail);
});
@ -247,17 +253,14 @@ function initPage() {
}
var selections = getIdSelections();
console.log(selections);
//console.log(selections);
evt.preventDefault();
$j.getJSON(thisUrl + '?request=events&task=unarchive&eids[]='+selections.join('&eids[]='))
.done( function(data) {
$j('#eventTable').bootstrapTable('refresh');
window.location.reload(true);
})
.fail(logAjaxFail);
//window.location.reload(true);
});
// Manage the EDIT button
@ -317,13 +320,6 @@ function initPage() {
$j('#deleteConfirm').modal('show');
});
// Manage the eventdetail links in the events list
$j(".eDetailLink").click(function(evt) {
evt.preventDefault();
var eid = $j(this).data('eid');
getEventDetailModal(eid);
});
// Update table links each time after new data is loaded
table.on('post-body.bs.table', function(data) {
// Manage the eventdetail links in the events list
@ -339,6 +335,7 @@ function initPage() {
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass('colThumbnail zoom');
});
table.bootstrapTable('resetSearch');
// The table is initially given a hidden style, so now that we are done rendering, show it
table.show();
}

View File

@ -11,3 +11,4 @@ var archivedString = "<?php echo translate('Archived') ?>";
var emailedString = "<?php echo translate('Emailed') ?>";
var yesString = "<?php echo translate('Yes') ?>";
var noString = "<?php echo translate('No') ?>";
var WEB_LIST_THUMBS = <?php echo ZM_WEB_LIST_THUMBS?'true':'false' ?>;

View File

@ -74,35 +74,32 @@ function validateForm(form) {
function updateButtons(element) {
var form = element.form;
if ( element.type == 'checkbox' && element.checked ) {
form.elements['executeButton'].disabled = false;
} else {
var canExecute = false;
if ( form.elements['filter[AutoArchive]'] && form.elements['filter[AutoArchive]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoUnarchive]'] && form.elements['filter[AutoUnarchive]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoCopy]'] && form.elements['filter[AutoCopy]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoMove]'] && form.elements['filter[AutoMove]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoVideo]'] && form.elements['filter[AutoVideo]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoUpload]'] && form.elements['filter[AutoUpload]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoEmail]'] && form.elements['filter[AutoEmail]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoMessage]'] && form.elements['filter[AutoMessage]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoExecute]'].checked && form.elements['filter[AutoExecuteCmd]'].value != '' ) {
canExecute = true;
} else if ( form.elements['filter[AutoDelete]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[UpdateDiskSpace]'].checked ) {
canExecute = true;
}
form.elements['executeButton'].disabled = !canExecute;
var canExecute = false;
if ( form.elements['filter[AutoArchive]'] && form.elements['filter[AutoArchive]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoUnarchive]'] && form.elements['filter[AutoUnarchive]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoCopy]'] && form.elements['filter[AutoCopy]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoMove]'] && form.elements['filter[AutoMove]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoVideo]'] && form.elements['filter[AutoVideo]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoUpload]'] && form.elements['filter[AutoUpload]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoEmail]'] && form.elements['filter[AutoEmail]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoMessage]'] && form.elements['filter[AutoMessage]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[AutoExecute]'].checked && form.elements['filter[AutoExecuteCmd]'].value != '' ) {
canExecute = true;
} else if ( form.elements['filter[AutoDelete]'].checked ) {
canExecute = true;
} else if ( form.elements['filter[UpdateDiskSpace]'].checked ) {
canExecute = true;
}
form.elements['executeButton'].disabled = !canExecute;
if ( form.elements['filter[Name]'].value ) {
form.elements['Save'].disabled = false;
form.elements['SaveAs'].disabled = false;

View File

@ -105,7 +105,6 @@ function initPage() {
document.querySelectorAll('input[name="newMonitor[MaxFPS]"]').forEach(function(el) {
el.oninput = el.onclick = function(e) {
if ( e.target.value ) {
console.log('showing');
$j('#newMonitor\\[MaxFPS\\]').show();
} else {
$j('#newMonitor\\[MaxFPS\\]').hide();
@ -115,7 +114,6 @@ function initPage() {
document.querySelectorAll('input[name="newMonitor[AlarmMaxFPS]"]').forEach(function(el) {
el.oninput = el.onclick = function(e) {
if ( e.target.value ) {
console.log('showing');
$j('#newMonitor\\[AlarmMaxFPS\\]').show();
} else {
$j('#newMonitor\\[AlarmMaxFPS\\]').hide();
@ -209,7 +207,6 @@ function initPage() {
var form = document.getElementById('contentForm');
var latitude = form.elements['newMonitor[Latitude]'].value;
var longitude = form.elements['newMonitor[Longitude]'].value;
console.log("lat: " + latitude + ', long:'+longitude);
map = L.map('LocationMap', {
center: L.latLng(latitude, longitude),
zoom: 13,
@ -258,13 +255,9 @@ function random_WebColour() {
function update_estimated_ram_use() {
var buffer_count = document.querySelectorAll('input[name="newMonitor[ImageBufferCount]"]')[0].value;
console.log(buffer_count);
var width = document.querySelectorAll('input[name="newMonitor[Width]"]')[0].value;
console.log(width);
var height = document.querySelectorAll('input[name="newMonitor[Height]"]')[0].value;
console.log(height);
var colours = document.querySelectorAll('select[name="newMonitor[Colours]"]')[0].value;
console.log(colours);
document.getElementById('estimated_ram_use').innerHTML = human_filesize(buffer_count * width * height * colours, 0);
}

View File

@ -1,4 +1,4 @@
var ZM_OPT_USE_GEOLOCATION = '<?php echo ZM_OPT_USE_GEOLOCATION ?>';
var ZM_OPT_USE_GEOLOCATION = '<?php echo ZM_OPT_USE_GEOLOCATION ?>' == '1' ? true : false;
<?php
if ( ZM_OPT_USE_GEOLOCATION ) {
echo 'var ZM_OPT_GEOLOCATION_TILE_PROVIDER=\''.ZM_OPT_GEOLOCATION_TILE_PROVIDER.'\''.PHP_EOL;

View File

@ -76,7 +76,7 @@ if ( !$liveMode ) {
if ( !isset($event['FramesById']) ) {
// Please note that this is the last frame as we sort DESC
$event['FramesById'] = array();
$frame['NextTimeStampSecs'] = $event['EndTime'];
$frame['NextTimeStampSecs'] = $event['EndTimeSecs'];
} else {
$frame['NextTimeStampSecs'] = $next_frames[$frame['EventId']]['TimeStampSecs'];
$frame['NextFrameId'] = $next_frames[$frame['EventId']]['Id'];

View File

@ -24,7 +24,7 @@ function createEventHtml(zm_event, frame) {
new Element('p').inject(eventHtml).set('text', monitors[zm_event.MonitorId].Name);
new Element('p').inject(eventHtml).set('text', zm_event.Name+(frame?('('+frame.FrameId+')'):''));
new Element('p').inject(eventHtml).set('text', zm_event.StartTime+' - '+zm_event.Length+'s');
new Element('p').inject(eventHtml).set('text', zm_event.StartDateTime+' - '+zm_event.Length+'s');
new Element('p').inject(eventHtml).set('text', zm_event.Cause);
if ( zm_event.Notes ) {
new Element('p').inject(eventHtml).set('text', zm_event.Notes);
@ -90,7 +90,7 @@ function showEventData(eventId, frameId) {
showEventDetail( zm_event['frames'][frameId]['html'] );
var imagePath = 'index.php?view=image&eid='+eventId+'&fid='+frameId;
var videoName = zm_event.DefaultVideo;
loadEventImage( imagePath, eventId, frameId, zm_event.Width, zm_event.Height, zm_event.Frames/zm_event.Length, videoName, zm_event.Length, zm_event.StartTime, monitors[zm_event.MonitorId]);
loadEventImage( imagePath, eventId, frameId, zm_event.Width, zm_event.Height, zm_event.Frames/zm_event.Length, videoName, zm_event.Length, zm_event.StartDateTime, monitors[zm_event.MonitorId]);
return;
} else {
console.log('No frames for ' + frameId);

View File

@ -603,7 +603,7 @@ function getEventCmdResponse( respObj, respText ) {
link.set('text', zm_event.Name);
link.inject(row.getElement('td.colName'));
row.getElement('td.colTime').set('text', zm_event.StartTime);
row.getElement('td.colTime').set('text', zm_event.StartDateTime);
row.getElement('td.colSecs').set('text', zm_event.Length);
link = new Element('a', {'href': '#', 'events': {'click': openFrames.pass( [zm_event.Id] )}});
@ -946,8 +946,9 @@ function initPage() {
});
// Only enable the settings button for local cameras
settingsBtn.prop('disabled', !(monitorType == 'Local' && canViewControl));
}
settingsBtn.prop('disabled', !canViewControl);
if ( monitorType != 'Local' ) settingsBtn.hide();
} // initPage
// Kick everything off
$j(document).ready(initPage);

View File

@ -114,19 +114,19 @@ if ( count($filter) ) {
$eventsSql = 'SELECT
E.Id,E.Name,E.StorageId,
E.StartTime AS StartTime,UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs,
CASE WHEN E.EndTime IS NULL THEN (SELECT NOW()) ELSE E.EndTime END AS EndTime,
UNIX_TIMESTAMP(EndTime) AS EndTimeSecs,
E.StartDateTime AS StartDateTime,UNIX_TIMESTAMP(E.StartDateTime) AS StartTimeSecs,
CASE WHEN E.EndDateTime IS NULL THEN (SELECT NOW()) ELSE E.EndDateTime END AS EndDateTime,
UNIX_TIMESTAMP(EndDateTime) AS EndTimeSecs,
E.Length, E.Frames, E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId
FROM Events AS E
WHERE 1 > 0
';
// select E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartTime, Interval Delta+0.5 Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId
// select E.Id,E.Name,UNIX_TIMESTAMP(E.StartDateTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartDateTime, Interval Delta+0.5 Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId
// from Events as E
// inner join Monitors as M on (E.MonitorId = M.Id)
// inner join Frames F on F.EventId=E.Id
// where not isnull(E.Frames) and not isnull(StartTime) ";
// where not isnull(E.Frames) and not isnull(StartDateTime) ";
// Note that the delta value seems more accurate than the time stamp for some reason.
$framesSql = '
@ -219,14 +219,14 @@ $initialDisplayInterval = 1000;
if ( isset($_REQUEST['displayinterval']) )
$initialDisplayInterval = validHtmlStr($_REQUEST['displayinterval']);
#$eventsSql .= ' GROUP BY E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId';
#$eventsSql .= ' GROUP BY E.Id,E.Name,E.StartDateTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId';
$minTimeSecs = $maxTimeSecs = 0;
if ( isset($minTime) && isset($maxTime) ) {
$minTimeSecs = strtotime($minTime);
$maxTimeSecs = strtotime($maxTime);
$eventsSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'";
$framesSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'";
$eventsSql .= " AND EndDateTime > '" . $minTime . "' AND StartDateTime < '" . $maxTime . "'";
$framesSql .= " AND EndDateTime > '" . $minTime . "' AND StartDateTime < '" . $maxTime . "'";
$framesSql .= ") AND TimeStamp > '" . $minTime . "' AND TimeStamp < '" . $maxTime . "'";
} else {
$framesSql .= ')';

View File

@ -231,6 +231,7 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
<td class="colUrl"><?php echo makeLink('#', validHtmlStr($Server->Url()), $canEdit, $svr_opt ) ?></td>
<td class="colPathToIndex"><?php echo makeLink('#', validHtmlStr($Server->PathToIndex()), $canEdit, $svr_opt ) ?></td>
<td class="colPathToZMS"><?php echo makeLink('#', validHtmlStr($Server->PathToZMS()), $canEdit, $svr_opt ) ?></td>
<td class="colPathToAPI"><?php echo makeLink('#', validHtmlStr($Server->PathToAPI()), $canEdit, $svr_opt ) ?></td>
<td class="colStatus <?php if ( $Server->Status() == 'NotRunning' ) { echo 'danger'; } ?>">
<?php echo makeLink('#', validHtmlStr($Server->Status()), $canEdit, $svr_opt) ?></td>
<td class="colMonitorCount"><?php echo makeLink('#', validHtmlStr($monitor_counts[$Server->Id()]), $canEdit, $svr_opt) ?></td>
@ -279,17 +280,23 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
<tbody>
<?php
foreach( ZM\Storage::find( null, array('order'=>'lower(Name)') ) as $Storage ) {
$filter = new ZM\Filter();
$filter->addTerm(array('attr'=>'StorageId','op'=>'=','val'=>$Storage->Id()));
if ( $user['MonitorIds'] ) {
$filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds']));
}
$str_opt = 'class="storageCol" data-sid="'.$Storage->Id().'"';
?>
<tr>
<td class="colId"><?php echo makeLink('#', validHtmlStr($Storage->Id()), $canEdit, $str_opt ) ?></td>
<td class="colName"><?php echo makeLink('#', validHtmlStr($Storage->Name()), $canEdit, $str_opt ) ?></td>
<td class="colPath"><?php echo makeLink('#', validHtmlStr($Storage->Path()), $canEdit, $str_opt ) ?></td>
<td class="colType"><?php echo makeLink('#', validHtmlStr($Storage->Type()), $canEdit, $str_opt ) ?></td>
<td class="colScheme"><?php echo makeLink('#', validHtmlStr($Storage->Scheme()), $canEdit, $str_opt ) ?></td>
<td class="colServer"><?php echo makeLink('#', validHtmlStr($Storage->Server()->Name()), $canEdit, $str_opt ) ?></td>
<td class="colId"><?php echo makeLink('#', validHtmlStr($Storage->Id()), $canEdit, $str_opt) ?></td>
<td class="colName"><?php echo makeLink('#', validHtmlStr($Storage->Name()), $canEdit, $str_opt) ?></td>
<td class="colPath"><?php echo makeLink('#', validHtmlStr($Storage->Path()), $canEdit, $str_opt) ?></td>
<td class="colType"><?php echo makeLink('#', validHtmlStr($Storage->Type()), $canEdit, $str_opt) ?></td>
<td class="colScheme"><?php echo makeLink('#', validHtmlStr($Storage->Scheme()), $canEdit, $str_opt) ?></td>
<td class="colServer"><?php echo makeLink('#', validHtmlStr($Storage->Server()->Name()), $canEdit, $str_opt) ?></td>
<td class="colDiskSpace"><?php echo human_filesize($Storage->disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?></td>
<td class="ColEvents"><?php echo $Storage->EventCount().' using '.human_filesize($Storage->event_disk_space()) ?></td>
<td class="ColEvents"><?php echo makeLink('?view=events'.$filter->querystring(), $Storage->EventCount().' using '.human_filesize($Storage->event_disk_space()) ); ?></td>
<td class="colMark"><input type="checkbox" name="markIds[]" value="<?php echo $Storage->Id() ?>" data-on-click-this="configureDeleteButton"<?php if ( $Storage->EventCount() or !$canEdit ) { ?> disabled="disabled"<?php } ?><?php echo $Storage->EventCount() ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/></td>
</tr>
<?php } #end foreach Server ?>
@ -302,13 +309,12 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
</form>
<?php
} else if ($tab == 'API') {
} else if ( $tab == 'API' ) {
$apiEnabled = dbFetchOne("SELECT Value FROM Config WHERE Name='ZM_OPT_USE_API'");
if ($apiEnabled['Value']!='1') {
echo "<div class='errorText'>APIs are disabled. To enable, please turn on OPT_USE_API in Options->System</div>";
}
else {
$apiEnabled = dbFetchOne('SELECT Value FROM Config WHERE Name=\'ZM_OPT_USE_API\'');
if ( $apiEnabled['Value'] != '1' ) {
echo '<div class="errorText">APIs are disabled. To enable, please turn on OPT_USE_API in Options->System</div>';
} else {
?>
<form name="userForm" method="post" action="?">

View File

@ -65,8 +65,8 @@ $filterQuery = $filter['query'];
ZM\Debug($filterQuery);
$eventsSql = 'SELECT *,
UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs,
UNIX_TIMESTAMP(EndTime) AS EndTimeSecs
UNIX_TIMESTAMP(E.StartDateTime) AS StartTimeSecs,
UNIX_TIMESTAMP(EndDateTime) AS EndTimeSecs
FROM Events AS E
WHERE 1 > 0
';
@ -77,7 +77,7 @@ if ( count($selected_monitor_ids) ) {
$eventsSql .= ' AND MonitorId IN ('.implode(',', $selected_monitor_ids).')';
}
if ( isset($minTime) && isset($maxTime) ) {
$eventsSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'";
$eventsSql .= " AND EndDateTime > '" . $minTime . "' AND StartDateTime < '" . $maxTime . "'";
}
$eventsSql .= ' ORDER BY Id ASC';
@ -211,8 +211,8 @@ for ( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
</div></td>
<td class="colServer"><?php echo validHtmlStr($Monitor->Server()->Name())?></td>
<td class="colEvents"><a href="?view=<?php echo ZM_WEB_EVENTS_VIEW ?>&amp;page=1<?php echo $monitor_filter['query'] ?>"><?php echo isset($EventsByMonitor[$Monitor->Id()])?count($EventsByMonitor[$Monitor->Id()]['Events']):0 ?></a></td>
<td class="colFirstEvent"><?php echo $FirstEvent ? $FirstEvent->link_to($FirstEvent->Id().' at '.$FirstEvent->StartTime()) : 'none'?></td>
<td class="colLastEvent"><?php echo $LastEvent ? $LastEvent->link_to($LastEvent->Id().' at '.$LastEvent->StartTime()) : 'none'?></td>
<td class="colFirstEvent"><?php echo $FirstEvent ? $FirstEvent->link_to($FirstEvent->Id().' at '.$FirstEvent->StartDateTime()) : 'none'?></td>
<td class="colLastEvent"><?php echo $LastEvent ? $LastEvent->link_to($LastEvent->Id().' at '.$LastEvent->StartDateTime()) : 'none'?></td>
<td class="colMinGap"><?php echo $MinGap ?></td>
<td class="colMaxGap"><?php echo $MaxGap ?></td>
<td class="colFileMissing<?php echo count($FileMissing) ? ' errorText' : ''?>">

View File

@ -128,9 +128,9 @@ $chart = array(
$monitors = array();
# The as E, and joining with Monitors is required for the filterSQL filters.
$rangeSql = 'SELECT min(E.StartTime) AS MinTime, max(E.EndTime) AS MaxTime FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(E.StartTime) AND NOT isnull(E.EndTime)';
$eventsSql = 'SELECT E.* FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartTime)';
$eventIdsSql = 'SELECT E.Id FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartTime)';
$rangeSql = 'SELECT min(E.StartDateTime) AS MinTime, max(E.EndDateTime) AS MaxTime FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(E.StartDateTime) AND NOT isnull(E.EndDateTime)';
$eventsSql = 'SELECT E.* FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartDateTime)';
$eventIdsSql = 'SELECT E.Id FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartDateTime)';
$eventsValues = array();
if ( !empty($user['MonitorIds']) ) {
@ -277,8 +277,8 @@ $midTimeT = $minTimeT + $halfRange;
$midTime = strftime(STRF_FMT_DATETIME_DB, $midTimeT);
if ( isset($minTime) && isset($maxTime) ) {
$eventsSql .= " AND EndTime >= '$minTime' AND StartTime <= '$maxTime'";
$eventIdsSql .= " AND EndTime >= '$minTime' AND StartTime <= '$maxTime'";
$eventsSql .= " AND EndDateTime >= '$minTime' AND StartDateTime <= '$maxTime'";
$eventIdsSql .= " AND EndDateTime >= '$minTime' AND StartDateTime <= '$maxTime'";
}
if ( 0 ) {
@ -332,13 +332,13 @@ while( $event = $events_result->fetch(PDO::FETCH_ASSOC) ) {
$currEventSlots = &$monEventSlots[$event['MonitorId']];
$currFrameSlots = &$monFrameSlots[$event['MonitorId']];
$startTimeT = strtotime($event['StartTime']);
$startTimeT = strtotime($event['StartDateTime']);
$startIndex = $rawStartIndex = (int)(($startTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
if ( $startIndex < 0 )
$startIndex = 0;
if ( isset($event['EndTime']) )
$endTimeT = strtotime($event['EndTime']);
if ( isset($event['EndDateTime']) )
$endTimeT = strtotime($event['EndDateTime']);
else
$endTimeT = time();
$endIndex = $rawEndIndex = (int)(($endTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);

View File

@ -242,17 +242,21 @@ if ( empty($_REQUEST['path']) ) {
header('HTTP/1.0 404 Not Found');
ZM\Fatal("Can't create frame images from video because there is no video file for this event at (".$Event->Path().'/'.$Event->DefaultVideo() );
}
$command = ZM_PATH_FFMPEG.' -ss '. $Frame->Delta() .' -i '.$Event->Path().'/'.$Event->DefaultVideo().' -frames:v 1 '.$path;
$command = ZM_PATH_FFMPEG.' -ss '. $Frame->Delta() .' -i '.$Event->Path().'/'.$Event->DefaultVideo().' -frames:v 1 '.$path . ' 2>&1';
#$command ='ffmpeg -ss '. $Frame->Delta() .' -i '.$Event->Path().'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$Frame->FrameId().'),setpts=PTS-STARTPTS" '.$path;
#$command ='ffmpeg -v 0 -i '.$Storage->Path().'/'.$Event->Path().'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$Frame->FrameId().'),setpts=PTS-STARTPTS" '.$path;
ZM\Debug("Running $command");
$output = array();
$retval = 0;
exec( $command, $output, $retval );
exec($command, $output, $retval);
ZM\Debug("Command: $command, retval: $retval, output: " . implode("\n", $output));
if ( ! file_exists( $path ) ) {
if ( ! file_exists($path) ) {
header('HTTP/1.0 404 Not Found');
ZM\Fatal('Can\'t create frame images from video for this event '.$Event->DefaultVideo() );
ZM\Fatal('Can\'t create frame images from video for this event '.$Event->DefaultVideo().'
Command was: '.$command.'
Output was: '.implode(PHP_EOL,$output) );
}
# Generating an image file will use up more disk space, so update the Event record.
$Event->DiskSpace(null);