Add MaxScoreFrameId to the events table and automatically update it during event creation so we don't have to look it up later. Finding the frame with the max score is actually a very heavy query, so lets not do it.

This commit is contained in:
Isaac Connor
2025-07-15 16:17:36 -04:00
parent be1cc5fbb1
commit 97877335db
7 changed files with 32 additions and 9 deletions

View File

@@ -203,6 +203,7 @@ CREATE TABLE `Events` (
`TotScore` int(10) unsigned NOT NULL default '0',
`AvgScore` smallint(5) unsigned default '0',
`MaxScore` smallint(5) unsigned default '0',
`MaxScoreFrameId` int(10) unsigned default NULL,
`Archived` tinyint(3) unsigned NOT NULL default '0',
`Videoed` tinyint(3) unsigned NOT NULL default '0',
`Uploaded` tinyint(3) unsigned NOT NULL default '0',

17
db/zm_update-1.37.68.sql Normal file
View File

@@ -0,0 +1,17 @@
--
-- Update Events table to have MaxScoreFrameId
--
SELECT 'Checking for MaxScoreFrameId in Events';
SET @s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Events'
AND table_schema = DATABASE()
AND column_name = 'MaxScoreFrameId'
) > 0,
"SELECT 'Column MaxScoreFrameId already exists in Events'",
"ALTER TABLE `Events` ADD COLUMN `MaxScoreFrameId` int(10) unsigned default NULL AFTER `MaxScore`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@@ -18,7 +18,7 @@
%global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}}
Name: zoneminder
Version: 1.37.67
Version: 1.37.68
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons

View File

@@ -62,6 +62,7 @@ Event::Event(
alarm_frame_written(false),
tot_score(0),
max_score(-1),
max_score_frame_id(0),
//path(""),
//snapshit_file(),
snapshot_file_written(false),
@@ -200,11 +201,11 @@ Event::~Event() {
}
std::string sql = stringtf(
"UPDATE Events SET Name='%s%" PRIu64 "', EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo='%s', DiskSpace=%" PRIu64 " WHERE Id = %" PRIu64 " AND Name='New Event'",
"UPDATE Events SET Name='%s%" PRIu64 "', EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, MaxScoreFrameId=%d, DefaultVideo='%s', DiskSpace=%" PRIu64 " WHERE Id = %" PRIu64 " AND Name='New Event'",
monitor->Substitute(monitor->EventPrefix(), start_time).c_str(), id, std::chrono::system_clock::to_time_t(end_time),
delta_time.count(),
frames, alarm_frames,
tot_score, static_cast<uint32>(alarm_frames ? (tot_score / alarm_frames) : 0), max_score,
tot_score, static_cast<uint32>(alarm_frames ? (tot_score / alarm_frames) : 0), max_score, max_score_frame_id,
video_file.c_str(), // defaults to ""
video_size,
id);
@@ -212,11 +213,11 @@ Event::~Event() {
if (!zmDbDoUpdate(sql)) {
// Name might have been changed during recording, so just do the update without changing the name.
sql = stringtf(
"UPDATE Events SET EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo='%s', DiskSpace=%" PRIu64 " WHERE Id = %" PRIu64,
"UPDATE Events SET EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, MaxScoreFrameId=%d, DefaultVideo='%s', DiskSpace=%" PRIu64 " WHERE Id = %" PRIu64,
std::chrono::system_clock::to_time_t(end_time),
delta_time.count(),
frames, alarm_frames,
tot_score, static_cast<uint32>(alarm_frames ? (tot_score / alarm_frames) : 0), max_score,
tot_score, static_cast<uint32>(alarm_frames ? (tot_score / alarm_frames) : 0), max_score, max_score_frame_id,
video_file.c_str(), // defaults to ""
video_size,
id);
@@ -516,6 +517,7 @@ void Event::AddFrame(const std::shared_ptr<ZMPacket>&packet) {
if (score > max_score) {
max_score = score;
max_score_frame_id = frames;
}
if (db_frame) {
@@ -543,13 +545,14 @@ void Event::AddFrame(const std::shared_ptr<ZMPacket>&packet) {
last_db_frame = frames;
std::string sql = stringtf(
"UPDATE Events SET Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64,
"UPDATE Events SET Length=%.2f, Frames=%d, AlarmFrames=%d, TotScore=%d, AvgScore=%d, MaxScore=%d, MaxScoreFrameId=%d WHERE Id=%" PRIu64,
FPSeconds(delta_time).count(),
frames,
alarm_frames,
tot_score,
static_cast<uint32>(alarm_frames ? (tot_score / alarm_frames) : 0),
max_score,
max_score_frame_id,
id);
dbQueue.push(std::move(sql));
} else {

View File

@@ -90,6 +90,7 @@ class Event {
bool alarm_frame_written;
int tot_score;
int max_score;
int max_score_frame_id;
std::string path;
std::string snapshot_file;
bool snapshot_file_written;

View File

@@ -1 +1 @@
1.37.67
1.37.68

View File

@@ -108,8 +108,9 @@ class EventsController extends AppController {
foreach ( $events as $key => $value ) {
$EventObj = new ZM\Event($value['Event']);
$maxScoreFrameId = $this->getMaxScoreAlarmFrameId($value['Event']['Id']);
$events[$key]['Event']['MaxScoreFrameId'] = $maxScoreFrameId;
if ($EventObj['MaxScoreFrameId'] == NULL) {
$EventObj['MaxScoreFrameId'] = $this->getMaxScoreAlarmFrameId($value['Event']['Id']);
}
$events[$key]['Event']['FileSystemPath'] = $EventObj->Path();
}