ZM Perl Interface Issue

Forum for questions and support relating to the 1.28.x releases only.
waynieack
Posts: 6
Joined: Thu May 24, 2012 11:24 pm

ZM Perl Interface Issue

Post by waynieack »

(Modified subject line from "API" to "Interface" so as not to confuse folks with the new cakePHP APIs ~ asker)

Hello,

I wrote a script that connects to Hikvision cameras http push stream and listens for motion events, then using the ZM perl API, enables or disables the ZM alarm for that camera. This allows for offloading motion detection to the camera allowing for greater scalability of the system.

My problem is that when ZM is restarted and my program continues to run, the alarms are no longer activated in ZM when motion is detected on the camera. In my application logs I can see the event getting to the point where the ZM perl API function is run, but in zoneminder the alarm is not activated. I have to restart my program in order for the events to get activated again. So far I have not been able to figure out how to recover from this with out just restarting my program. At this point I am at a loss on why it will not activate the alarm after ZM restarts, all the zmTriggerEventOn function is looking for is a hash of the monitor ID.

I currently have the camera set in record mode so it works like mocord, constant recording with motion (from my script/the camera) so I can easily find events.



If you want a copy of my script its located here https://github.com/waynieack/HikvisionZM.
User avatar
dvarapala
Posts: 54
Joined: Sat Nov 06, 2010 2:30 pm

Re: ZM Perl API Issue

Post by dvarapala »

Is there some reason why you can't just run your monitor in "nodect" mode and use zmtrigger.pl to trigger alarms?

:?
waynieack
Posts: 6
Joined: Thu May 24, 2012 11:24 pm

Re: ZM Perl API Issue

Post by waynieack »

I am recording 24x7 on outdoor cameras and using the motion to mark motion events (like mocord) to help when reviewing the video, I cant risk missing something using motion detection alone.

Also zmtrigger.pl uses the same zmTriggerEventOn function, so it would be over kill to open a tcp session to connect back to localhost and trigger the zmtrigger script. I also use some of the other perl API functions to get the alarm status of the zone.

I believe that the zmtrigger script starts and stops with zoneminder. If I could get some pointers on how to start and stop my script in the same way as the zmtrigger script, that might be the best solution.

-Wayne
User avatar
knight-of-ni
Posts: 2404
Joined: Thu Oct 18, 2007 1:55 pm
Location: Shiloh, IL

Re: ZM Perl API Issue

Post by knight-of-ni »

Well, technically, there is no documented Perl API. You've taken the ZoneMinder Perl modules and used them in your own script.
I'm not saying you can't do that, but please don't call it an API because you are going to confuse others who are attempting to use the real API, which uses php.

This sounds like the same issue we think zmtrigger itself has. The underlying issue is that the mmap gets redone after a monitor is restarted, which then breaks zmtrigger because it is not aware of the change. I simply have not had time to follow up with this and figure out if the problem is real and what is the best way to solve the problem.

In your case, restarting your script should work.

What I would do is create a systemd service file for the script in question. Place the file under /etc/systemd/system and include "Requires=zoneminder" in it.

You should read the systemd documentation to become familiar with creating a local service file:
http://www.freedesktop.org/software/sys ... .unit.html

Doing it this way prevents your changes from getting overwritten during an upgrade.
This of course assumes you are running a distro that uses systemd, which you have not told us.
Visit my blog for ZoneMinder related projects using the Raspberry Pi, Orange Pi, Odroid, and the ESP8266
All of these can be found at https://zoneminder.blogspot.com/
waynieack
Posts: 6
Joined: Thu May 24, 2012 11:24 pm

Re: ZM Perl API Issue

Post by waynieack »

I am running:
Ubuntu 14.04.3 LTS (GNU/Linux 3.16.0-57-generic x86_64)
zoneminder 1.28.1-trusty-1 amd64

Systemd looks like it would work, but it seems that Ubuntu uses upstart. From what I've read, Ubuntu will be switching to systemd in the next year though.

I've been using monit, but the way I had it configured it would not restart my script if zoneminder was restarted outside of monit. I did more digging last night and figured out how to run an action if the zoneminder pid changes, my monit config is below. Although this works for the most part, I would like to detect failures in my script and restart. If I could see the failure in my script then my failure detection would be much more accurate and would work in instances where the mmap issue happens when zoneminder has not been completely restarted. I thought about checking the monitor to verify that it was alarmed with zmIsAlarmed after I activate it with zmTriggerEventOn, but I believe that there is a short delay between when I run the zmTriggerEventOn and when the zmIsAlarmed can detect that its actually alarmed, so this could get into some timing issues and possibly cause my script to restart when it shouldn't. Maybe there is something I can check with zmMemRead that will always work unless the mmap issue happens?




check process mysql with pidfile /var/run/mysqld/mysqld.pid
start program = "/etc/init.d/mysql start"
stop program = "/etc/init.d/mysql stop"
if changed PID then exec "/etc/init.d/zoneminder restart"

check process zoneminder with pidfile /var/run/zm/zm.pid
start program = "/etc/init.d/zoneminder start"
stop program = "/etc/init.d/zoneminder stop"
depends on mysql
if changed PID then exec "/usr/bin/killall motionstream.pl; /home/wayne/motionstream.pl&"

check process motionstream with pidfile /var/run/motionstream.pid
start program = "/home/wayne/motionstream.pl&" with timeout 60 seconds
stop program = "/usr/bin/killall motionstream.pl"
depends on zoneminder
User avatar
asker
Posts: 1553
Joined: Sun Mar 01, 2015 12:12 pm

Re: ZM Perl API Issue

Post by asker »

Zm perl modules use shared memory to communicate with zm core processes. After Zm restarts those handles are invalid.
One solution is to start an stop your script along with zm. Google for zmeventserver and see how I've attached it to zmdc.pl -- in addition to being in sync it will also be restarted if it crashes.

I think there are some perl routines to reinit the memory handles. Forgot - I'll check later
I no longer work on zmNinja, zmeventnotification, pyzm or mlapi. I may respond on occasion based on my available time/interest.

Please read before posting:
How to set up logging properly
How to troubleshoot and report - ES
How to troubleshoot and report - zmNinja
ES docs
zmNinja docs
bbunge
Posts: 2934
Joined: Mon Mar 26, 2012 11:40 am
Location: Pennsylvania

Re: ZM Perl API Issue

Post by bbunge »

There is a write up on the WIKI where I set up Ubuntu 14.10 to run Zoneminder on systemd. You could likely do this for 14.04 but 16.04 is a couple of months away and uses systemd as the 15.x versions do.

https://wiki.zoneminder.com/Ubuntu_Serv ... se_systemd
waynieack wrote:I am running:
Ubuntu 14.04.3 LTS (GNU/Linux 3.16.0-57-generic x86_64)
zoneminder 1.28.1-trusty-1 amd64


Systemd looks like it would work, but it seems that Ubuntu uses upstart. From what I've read, Ubuntu will be switching to systemd in the next year though.

I've been using monit, but the way I had it configured it would not restart my script if zoneminder was restarted outside of monit. I did more digging last night and figured out how to run an action if the zoneminder pid changes, my monit config is below. Although this works for the most part, I would like to detect failures in my script and restart. If I could see the failure in my script then my failure detection would be much more accurate and would work in instances where the mmap issue happens when zoneminder has not been completely restarted. I thought about checking the monitor to verify that it was alarmed with zmIsAlarmed after I activate it with zmTriggerEventOn, but I believe that there is a short delay between when I run the zmTriggerEventOn and when the zmIsAlarmed can detect that its actually alarmed, so this could get into some timing issues and possibly cause my script to restart when it shouldn't. Maybe there is something I can check with zmMemRead that will always work unless the mmap issue happens?




check process mysql with pidfile /var/run/mysqld/mysqld.pid
start program = "/etc/init.d/mysql start"
stop program = "/etc/init.d/mysql stop"
if changed PID then exec "/etc/init.d/zoneminder restart"
https://wiki.zoneminder.com/Ubuntu_Serv ... se_systemd
check process zoneminder with pidfile /var/run/zm/zm.pid
start program = "/etc/init.d/zoneminder start"
stop program = "/etc/init.d/zoneminder stop"
depends on mysql
if changed PID then exec "/usr/bin/killall motionstream.pl; /home/wayne/motionstream.pl&"

check process motionstream with pidfile /var/run/motionstream.pid
start program = "/home/wayne/motionstream.pl&" with timeout 60 seconds
stop program = "/usr/bin/killall motionstream.pl"
depends on zoneminder
waynieack
Posts: 6
Joined: Thu May 24, 2012 11:24 pm

Re: ZM Perl API Issue

Post by waynieack »

asker,

zmdc.pl will work perfectly for starting and stopping, that's what I was looking for! I'm going to work on adding it as a daemon tonight. Thanks for the pointer! I am definitely interested in the perl routines to reinit the memory handles to fix the memory handle issue.

bbunge,

I saw the systemd conversions, but I didn't want to possibly cause other system problems trying to get systemd working on a very stable system.

-Wayne
User avatar
knight-of-ni
Posts: 2404
Joined: Thu Oct 18, 2007 1:55 pm
Location: Shiloh, IL

Re: ZM Perl API Issue

Post by knight-of-ni »

I had previously not suggested the idea of changing the source code because your changes will be overwritten each time you upgrade.
But if you are willing to go down that path, look in the php where the daemonControl function is called to restart the zmc process after a monitor has been saved or modified. It is in functions.php. If you add a call alongside there to restart your script at the same time, then that might work. You can restart your script directly with an exec call, or use the built in daemonControl function, which will tell zmdc.pl to do it.

If I can't figure out a better way to do it, this is how I plan to fix zmtrigger.pl from corrupting after a monitor is saved or modified.
Visit my blog for ZoneMinder related projects using the Raspberry Pi, Orange Pi, Odroid, and the ESP8266
All of these can be found at https://zoneminder.blogspot.com/
User avatar
asker
Posts: 1553
Joined: Sun Mar 01, 2015 12:12 pm

Re: ZM Perl API Issue

Post by asker »

Actually, a better place to put it is in the array list of zmdc.pl - so that if the process crashes, it will be automatically restarted as ZM watches all daemons in this list.

Specifically, there are two places to put in (which is what I do in zmeventserver)

https://github.com/pliablepixels/zmeven ... zoneminder
I no longer work on zmNinja, zmeventnotification, pyzm or mlapi. I may respond on occasion based on my available time/interest.

Please read before posting:
How to set up logging properly
How to troubleshoot and report - ES
How to troubleshoot and report - zmNinja
ES docs
zmNinja docs
User avatar
knight-of-ni
Posts: 2404
Joined: Thu Oct 18, 2007 1:55 pm
Location: Shiloh, IL

Re: ZM Perl Interface Issue

Post by knight-of-ni »

Right, but the idea behind what I was suggesting is to restart it before it crashes. zmdc.pl does not have a triggering mechanism, other than when the process in question has crashed. The php portion does.

Since the script in question needs to be handled the same way as the zmc process, then the best way to do this is the same way we handle zmc.

This is how it is done:
Monitor is saved/modified -> daemoncontrol is called to restart zma/zmc -> zmdc.pl is called to do the actual work

You are purposing to do just the last step, while I am proposing a better way would be to do the whole thing, so one can avoid any process crashes altogether.
Visit my blog for ZoneMinder related projects using the Raspberry Pi, Orange Pi, Odroid, and the ESP8266
All of these can be found at https://zoneminder.blogspot.com/
User avatar
asker
Posts: 1553
Joined: Sun Mar 01, 2015 12:12 pm

Re: ZM Perl Interface Issue

Post by asker »

Right, that is how the flow works, but I really don't think one should put in a personal perl script restart inside functions.php - that's too core a file. His function ideally should be restarted when communication to mapped memory fails.

I don't think he needs to get a trigger when a zmc fails - its sufficient if he gets to know when his communication to zmc fails and then re-init the memory handle if needed. The core job of his script is to monitor the external camera and then trigger a recording on ZM - he doesn't need to be notified real-time when zmc fails - he just needs to somehow "re init" the memory handle if the memory is invalid

Let me explore this a bit more - to the best of my knowledge the perl interfaces like zmMemInvalidate/etc abstract this out.
I no longer work on zmNinja, zmeventnotification, pyzm or mlapi. I may respond on occasion based on my available time/interest.

Please read before posting:
How to set up logging properly
How to troubleshoot and report - ES
How to troubleshoot and report - zmNinja
ES docs
zmNinja docs
User avatar
knight-of-ni
Posts: 2404
Joined: Thu Oct 18, 2007 1:55 pm
Location: Shiloh, IL

Re: ZM Perl Interface Issue

Post by knight-of-ni »

zmdc.pl is just as much a core file as functions.php.

Twice now I've stated that, what I am suggesting, gets you the ability to pro-actively restart something before the script fails. Now that makes three times. What you are proposing can only happen after the script fails.

When a monitor is saved or modified, we would not want to wait until zmc crashed and then let zmdc.pl restart it. Right? Instead, we proactively restart zmc so it doesn't crash at all. Why wouldn't you want to handle a third party script that same way? Why would you wait until it crashed to restart it? That is not good programming, and is prone to cause one to lose the one event that caused the crash.

Maybe in the future, we could add some kind of hook in the API to make this easier to implement for a third party script.
Visit my blog for ZoneMinder related projects using the Raspberry Pi, Orange Pi, Odroid, and the ESP8266
All of these can be found at https://zoneminder.blogspot.com/
User avatar
asker
Posts: 1553
Joined: Sun Mar 01, 2015 12:12 pm

Re: ZM Perl Interface Issue

Post by asker »

I got what you meant, all 3 times. I don't happen to agree with the approach.

Our difference in perspective is that you are attaching the same relevance to zmc and his script. I'm not. I actually think doing this inside functions.php is doing things at a more low-level because one can, not because one should. zmc is a core process, and it makes complete sense to restart it when you change the definition of a monitor. I don't see how that is relevant to restarting his script along with it when it doesn't need to.

The script is not "failing" -- the script should check if its memory handle is valid and if not, re-attach. I don't call that failing - I call that validation. And its in the confines of his script, which is the approach I prefer. Calling zmMemValidate automatically reattaches.
I no longer work on zmNinja, zmeventnotification, pyzm or mlapi. I may respond on occasion based on my available time/interest.

Please read before posting:
How to set up logging properly
How to troubleshoot and report - ES
How to troubleshoot and report - zmNinja
ES docs
zmNinja docs
User avatar
knight-of-ni
Posts: 2404
Joined: Thu Oct 18, 2007 1:55 pm
Location: Shiloh, IL

Re: ZM Perl Interface Issue

Post by knight-of-ni »

Your reference to getting a trigger after zmc crashed implied you did not get what I meant, but I will apologize for the misundertanding.

There is nothing I can see either in zoneminder, nor the op's script, nor your event script that reattaches after the memory handle changes. I don't see a zmMemValidate function in any of these scripts. Where does that happen?
Visit my blog for ZoneMinder related projects using the Raspberry Pi, Orange Pi, Odroid, and the ESP8266
All of these can be found at https://zoneminder.blogspot.com/
Locked