You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First up, thank you for ZM. The improvements in 1.37 branch is significant.
I looked into this problem and possibly identified the issue and logic fix. Not being familiar with ZM code base though, I am hesitant to produce a pull request until a review of the logic and impact assessment.
Environment
Tested with a camera that only generates 'start' ONVIF motion events
Expected
Whenever ZM receives a start ONVIF Motion Event it will trigger or continue recording. Recording will stop from ZM normal stop recording settings.
Observed
ZM starts the initial recording then stops the initial recording. Any additional start ONVIF Motion Events fail to trigger any further recordings.
Evidence
The logs below demonstrate this.
Start the camera. The first ONVIF motion alarm triggers a recording as noted by the Triggered Start Event on ONVIF log.
There are two source files involved being zm_monitor.cpp and zm_monitor_onvif.cpp.
In zm_monitor_onvif.cpp void Monitor::ONVIF::WaitForMessage() a motionAlert event triggers the following code on line 202:
} else {
// Event StartInfo("Triggered Start on ONVIF");
if (alarms.count(last_topic) == 0) {
alarms[last_topic] = last_value;
if (!alarmed) {
Info("Triggered Start Event on ONVIF");
alarmed = true;
// Why sleep?std::this_thread::sleep_for(std::chrono::seconds(1)); //thread sleep
}
}
}
So we need to understand this code further. There are two types of cameras, one capable of generating Motion off / stop events, and one that only generates Motion on / start events. The code logic needs to handle both types.
Initially a camera is marked as only producing start events. This is done by Monitor::Monitor() : Event_Poller_Closes_Event(false) in zm_monitor.cpp line 319.
When an off event is received, Event_Poller_Closes_Event is set to true and off events are then expected for event termination. zm_monitor_onvif.cpp line 198.
if (!parent->Event_Poller_Closes_Event) { //If we get a close event, then we know to expect them.
parent->Event_Poller_Closes_Event = true;
Info("Setting ClosesEvent");
}
So, we need to understand what receiving an off event does. zm_monitor.cpp lines 190 to 197 relevant code.
Whenever an off / close event happens, the alarm is erased and if it was the last alarm message type received, the ONVIF camera is removed from alarmed state.
What happens for ONVIF cameras that don't generate an off / close event. zm_monitor.cpp lines 1960 gives us the answer
// If the camera isn't going to send an event close, we need to close it here, but only after it has actually triggered an alarm.if (!Event_Poller_Closes_Event && state == ALARM)
onvif->setAlarmed(false);
} // end ONVIF_Trigger
} // end if (onvif_event_listener && Event_Poller_Healthy)
If the camera does not generate ONVIF off / close events then the camera alarmed is set to false upon receipt.
What happens to the alarms array? Only the alarmed state variable gets updated. Alarms array remains untouched.
Going back to the Event Start code
} else {
// Event StartInfo("Triggered Start on ONVIF");
if (alarms.count(last_topic) == 0) {
alarms[last_topic] = last_value;
if (!alarmed) {
Info("Triggered Start Event on ONVIF");
alarmed = true;
// Why sleep?std::this_thread::sleep_for(std::chrono::seconds(1)); //thread sleep
}
}
}
On the first motion start event received, the alarms.count for the message will be 0. So the alarm message is recorded and the camera is alarmed.
On subsequent motion start events received, the alarms.count is not zero and alarms[last_topic] will contain the same value.
The if statement will not be true and the camera will never trigger a further start event recording because alarmed state will never be set again.
Let's test this logic out replacing the above code at line 202 in zm_monitor_onvif.cpp with the following code
} else {
// Event StartInfo("Triggered Start on ONVIF");
if (alarms.count(last_topic) == 0) {
// Support close event logic and only trigger alarmed state once.
alarms[last_topic] = last_value;
if (!alarmed) {
Info("Triggered Start Event on ONVIF");
alarmed = true;
}
} else {
// zm_monitor will generate a pseudo close event for us. Need to trigger on every start event.if (!alarmed) {
Info("Triggered Start Event on ONVIF");
alarmed = true;
}
}
}
By the way, that sleep_for line is deleted. Can't see any justification for it.
Testing the camera and ZM out gives us the below logs:
INF-zm_monitor_onvif.cpp/186 [ONVIF Got Motion Alarm! tns1:VideoSource/MotionAlarm State]
INF-zm_monitor_onvif.cpp/204 [Triggered Start on ONVIF]
INF-zm_monitor_onvif.cpp/215 [Triggered Start Event on ONVIF]
INF-zm_monitor.cpp/2179 [Slate: 1506781 - Gone into alarm state PreAlarmCount: 0 > AlarmFrameCount:1 Cause:ONVIF]
INF-zm_monitor.cpp/2367 [Slate: 1506781 - Opening event timestamp 1734083109 % 309]
INF-zm_monitor.cpp/2369 [Opened new event 891 ONVIF]
INF-zm_monitor.cpp/2211 [Slate: 1506751 - Gone into alert state]
INF-zm_monitor.cpp/2216 [Slate: 1506756 - Left alert state]
INF-zm_monitor_onvif.cpp/186 [ONVIF Got Motion Alarm! tns1:VideoSource/MotionAlarm State]
INF-zm_monitor_onvif.cpp/204 [Triggered Start on ONVIF]
INF-zm_monitor_onvif.cpp/215 [Triggered Start Event on ONVIF]
INF-zm_monitor.cpp/2179 [Slate: 1507230 - Gone into alarm state PreAlarmCount: 0 > AlarmFrameCount:1 Cause:ONVIF]
INF-zm_monitor.cpp/2211 [Slate: 1507199 - Gone into alert state]
INF-zm_monitor.cpp/2216 [Slate: 1507204 - Left alert state]
INF-zm_monitor.cpp/2344 [Slate: 1510234 - Closing event 891 1734083224 - 1734083104 = 120 >= 600]
INF-zm_monitor_onvif.cpp/186 [ONVIF Got Motion Alarm! tns1:VideoSource/MotionAlarm State]
INF-zm_monitor_onvif.cpp/204 [Triggered Start on ONVIF]
INF-zm_monitor_onvif.cpp/215 [Triggered Start Event on ONVIF]
INF-zm_monitor.cpp/2179 [Slate: 1513741 - Gone into alarm state PreAlarmCount: 0 > AlarmFrameCount:1 Cause:ONVIF]
INF-zm_monitor.cpp/2367 [Slate: 1513741 - Opening event timestamp 1734083341 % 541]
INF-zm_monitor.cpp/2369 [Opened new event 892 ONVIF]
INF-zm_monitor.cpp/2211 [Slate: 1513711 - Gone into alert state]
INF-zm_monitor.cpp/2216 [Slate: 1513716 - Left alert state]
INF-zm_monitor_onvif.cpp/186 [ONVIF Got Motion Alarm! tns1:VideoSource/MotionAlarm State]
INF-zm_monitor_onvif.cpp/204 [Triggered Start on ONVIF]
INF-zm_monitor_onvif.cpp/215 [Triggered Start Event on ONVIF]
INF-zm_monitor.cpp/2179 [Slate: 1514191 - Gone into alarm state PreAlarmCount: 0 > AlarmFrameCount:1 Cause:ONVIF]
INF-zm_monitor.cpp/2211 [Slate: 1514161 - Gone into alert state]
INF-zm_monitor.cpp/2216 [Slate: 1514166 - Left alert state]
INF-zm_monitor.cpp/2344 [Slate: 1517194 - Closing event 892 1734083456 - 1734083336 = 120 >= 600]
INF-zm_monitor_onvif.cpp/186 [ONVIF Got Motion Alarm! tns1:VideoSource/MotionAlarm State]
INF-zm_monitor_onvif.cpp/204 [Triggered Start on ONVIF]
INF-zm_monitor_onvif.cpp/215 [Triggered Start Event on ONVIF]
INF-zm_monitor.cpp/2179 [Slate: 1517611 - Gone into alarm state PreAlarmCount: 0 > AlarmFrameCount:1 Cause:ONVIF]
INF-zm_monitor.cpp/2367 [Slate: 1517611 - Opening event timestamp 1734083470 % 70]
INF-zm_monitor.cpp/2369 [Opened new event 893 ONVIF]
INF-zm_monitor.cpp/2211 [Slate: 1517581 - Gone into alert state]
INF-zm_monitor.cpp/2216 [Slate: 1517586 - Left alert state]
INF-zm_monitor_onvif.cpp/186 [ONVIF Got Motion Alarm! tns1:VideoSource/MotionAlarm State]
INF-zm_monitor_onvif.cpp/204 [Triggered Start on ONVIF]
INF-zm_monitor_onvif.cpp/215 [Triggered Start Event on ONVIF]
INF-zm_monitor.cpp/2179 [Slate: 1518061 - Gone into alarm state PreAlarmCount: 0 > AlarmFrameCount:1 Cause:ONVIF]
INF-zm_monitor.cpp/2211 [Slate: 1518031 - Gone into alert state]
INF-zm_monitor.cpp/2216 [Slate: 1518036 - Left alert state]
INF-zm_monitor_onvif.cpp/186 [ONVIF Got Motion Alarm! tns1:VideoSource/MotionAlarm State]
INF-zm_monitor_onvif.cpp/204 [Triggered Start on ONVIF]
INF-zm_monitor_onvif.cpp/215 [Triggered Start Event on ONVIF]
INF-zm_monitor.cpp/2179 [Slate: 1518525 - Gone into alarm state PreAlarmCount: 0 > AlarmFrameCount:1 Cause:ONVIF]
INF-zm_monitor.cpp/2211 [Slate: 1518495 - Gone into alert state]
INF-zm_monitor.cpp/2216 [Slate: 1518500 - Left alert state]
INF-zm_monitor.cpp/2344 [Slate: 1521094 - Closing event 893 1734083586 - 1734083466 = 120 >= 600]
Three recording events successfully triggered. Much better outcome. The alarms not being erased seems a non issue and does not leak memory.
So the logic appears incorrect as demonstrated by the test code.
I am running the test code change for a few days now without observing any issue.
I hope the above code review assists in developing a proper fix.
The text was updated successfully, but these errors were encountered:
First up, thank you for ZM. The improvements in 1.37 branch is significant.
I looked into this problem and possibly identified the issue and logic fix. Not being familiar with ZM code base though, I am hesitant to produce a pull request until a review of the logic and impact assessment.
Environment
Expected
Whenever ZM receives a start ONVIF Motion Event it will trigger or continue recording. Recording will stop from ZM normal stop recording settings.
Observed
ZM starts the initial recording then stops the initial recording. Any additional start ONVIF Motion Events fail to trigger any further recordings.
Evidence
The logs below demonstrate this.
Start the camera. The first ONVIF motion alarm triggers a recording as noted by the Triggered Start Event on ONVIF log.
After this, logs are just the following repeated ad nauseam. There is no further triggering of recording.
Explaining why
There are two source files involved being zm_monitor.cpp and zm_monitor_onvif.cpp.
In zm_monitor_onvif.cpp void Monitor::ONVIF::WaitForMessage() a motionAlert event triggers the following code on line 202:
So we need to understand this code further. There are two types of cameras, one capable of generating Motion off / stop events, and one that only generates Motion on / start events. The code logic needs to handle both types.
Initially a camera is marked as only producing start events. This is done by Monitor::Monitor() : Event_Poller_Closes_Event(false) in zm_monitor.cpp line 319.
When an off event is received, Event_Poller_Closes_Event is set to true and off events are then expected for event termination. zm_monitor_onvif.cpp line 198.
So, we need to understand what receiving an off event does. zm_monitor.cpp lines 190 to 197 relevant code.
Whenever an off / close event happens, the alarm is erased and if it was the last alarm message type received, the ONVIF camera is removed from alarmed state.
What happens for ONVIF cameras that don't generate an off / close event. zm_monitor.cpp lines 1960 gives us the answer
If the camera does not generate ONVIF off / close events then the camera alarmed is set to false upon receipt.
What happens to the alarms array? Only the alarmed state variable gets updated. Alarms array remains untouched.
Going back to the Event Start code
On the first motion start event received, the alarms.count for the message will be 0. So the alarm message is recorded and the camera is alarmed.
On subsequent motion start events received, the alarms.count is not zero and alarms[last_topic] will contain the same value.
The if statement will not be true and the camera will never trigger a further start event recording because alarmed state will never be set again.
Let's test this logic out replacing the above code at line 202 in zm_monitor_onvif.cpp with the following code
By the way, that sleep_for line is deleted. Can't see any justification for it.
Testing the camera and ZM out gives us the below logs:
Three recording events successfully triggered. Much better outcome. The alarms not being erased seems a non issue and does not leak memory.
So the logic appears incorrect as demonstrated by the test code.
I am running the test code change for a few days now without observing any issue.
I hope the above code review assists in developing a proper fix.
The text was updated successfully, but these errors were encountered: