ZM Perl Interface Issue
ZM Perl Interface Issue
(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.
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.
Re: ZM Perl API Issue
Is there some reason why you can't just run your monitor in "nodect" mode and use zmtrigger.pl to trigger alarms?
Re: ZM Perl API Issue
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
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
- knight-of-ni
- Posts: 2406
- Joined: Thu Oct 18, 2007 1:55 pm
- Location: Shiloh, IL
Re: ZM Perl API Issue
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.
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/
All of these can be found at https://zoneminder.blogspot.com/
Re: ZM Perl API Issue
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
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
Re: ZM Perl API Issue
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
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
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
Re: ZM Perl API Issue
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
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
Re: ZM Perl API Issue
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
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
- knight-of-ni
- Posts: 2406
- Joined: Thu Oct 18, 2007 1:55 pm
- Location: Shiloh, IL
Re: ZM Perl API Issue
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.
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/
All of these can be found at https://zoneminder.blogspot.com/
Re: ZM Perl API Issue
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
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
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
- knight-of-ni
- Posts: 2406
- Joined: Thu Oct 18, 2007 1:55 pm
- Location: Shiloh, IL
Re: ZM Perl Interface Issue
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.
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/
All of these can be found at https://zoneminder.blogspot.com/
Re: ZM Perl Interface Issue
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 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
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
- knight-of-ni
- Posts: 2406
- Joined: Thu Oct 18, 2007 1:55 pm
- Location: Shiloh, IL
Re: ZM Perl Interface Issue
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.
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/
All of these can be found at https://zoneminder.blogspot.com/
Re: ZM Perl Interface Issue
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.
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
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
- knight-of-ni
- Posts: 2406
- Joined: Thu Oct 18, 2007 1:55 pm
- Location: Shiloh, IL
Re: ZM Perl Interface Issue
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?
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/
All of these can be found at https://zoneminder.blogspot.com/