pb with a modified perl script to trigger an alarm

Forum for questions and support relating to the 1.24.x releases only.
Locked
gilles
Posts: 19
Joined: Tue Jun 07, 2011 6:46 am

pb with a modified perl script to trigger an alarm

Post by gilles »

Hi all,

Sorry for the title of that post but I don't find anything else.

I search but don' find in the web and forum.

I want to use that script from the FAQ: http://www.zoneminder.com/wiki/index.ph ... n_alarm.3F

I want to detect an alarm and print to screen (for the moment): I want to print the name of the monitor, the notes (Motion: Blah blha), and the last event id number.

for that I modify my sql selection and add the notes like that:
my $sql = "select M.*, E.Id as LastEventId, Notes from Monitors as M left join Events as E on M.Id = E.MonitorId ORDER BY E.Id DESC LIMIT 0,1";

Before using the While (1), I print all my informations and that's good for the lasevnetId (I verify In mysql).

So my problem is to detect an alarm and print the last alarm with what I want upper.
I understand approximatively all the code except: !zmMemVerify( $monitor ) and the expression zmHasAlarmed( $monitor, $monitor->{LastEventId}

Could someone help me please.

I Think this isn't too hard but I'm new to perl and don't know where to find that two expression.

Gilles.
gilles
Posts: 19
Joined: Tue Jun 07, 2011 6:46 am

Re: pb with a modified perl script to trigger an alarm

Post by gilles »

Hi,

Nobody can help me.

Sure I'm not alone, that I want to get my alarm by script.

So please help.

Thank you.

Gilles.
gilles
Posts: 19
Joined: Tue Jun 07, 2011 6:46 am

Re: pb with a modified perl script to trigger an alarm

Post by gilles »

So nobody. :(

I can do it myself if only I know how "zmMemVerify( $monitor )" and zmHasAlarmed work.

thank you.
User avatar
zoneminder
Site Admin
Posts: 5215
Joined: Wed Jul 09, 2003 2:07 pm
Location: Bristol, UK
Contact:

Re: pb with a modified perl script to trigger an alarm

Post by zoneminder »

I'm not quite sure what you are asking. You have the script from the FAQ, you should leave all that code as it is (though you may wish to rerun the monitor selection code periodically). Do not modify the sql that is in the example as that is not to select events but only to select monitors.

Basically all you need to do is add you code into this section

Code: Select all

            print( "Monitor ".$monitor->{Name}." has alarmed\n" );
            #
            # Do your stuff here
            #
. In there you can do what you want, knowing that you will only get there is there is an alarm. For instance that section would be where you would select the event details from the database and output them or do something else.
Phil
gilles
Posts: 19
Joined: Tue Jun 07, 2011 6:46 am

Re: pb with a modified perl script to trigger an alarm

Post by gilles »

ok If I understand, I'm wrong.

I have to use your code and then in the personal part I do my database selection and use what I want in the "do your stuff zone".

Right ?

If it is that, thank you, you open my eyes.

Gilles.
gilles
Posts: 19
Joined: Tue Jun 07, 2011 6:46 am

Re: pb with a modified perl script to trigger an alarm

Post by gilles »

I think my explanations aren't good.

I add in your script that:

print( "Monitor ".$monitor->{Name}." has alarmed ".$monitor->{Notes}."\n" );


because I want to know what is the zone who has got an alarm. I've got what I want except that this the Notes at a certain time but not the last time.

If there is an alarm it's ok, but if I got a new alarm it writes the old one. You understand.

I just want to know the "Name" and the "Notes" of the "Motion" in real time if there is alarm.

Could you help me please.

PS:
If I use your script I've got that error: Use of uninitialized value $last_event_id in numeric ne (!=) at /usr/share/perl5/ZoneMinder/Memory.pm line 497
If I do a modification on the mysql selection like that, it works: my $sql = "select M.*, E.Id as LastEventId, Notes from Monitors as M left join Events as E on M.Id = E.MonitorId ORDER BY E.Id DESC LIMIT 0,1";


Gilles.
User avatar
zoneminder
Site Admin
Posts: 5215
Joined: Wed Jul 09, 2003 2:07 pm
Location: Bristol, UK
Contact:

Re: pb with a modified perl script to trigger an alarm

Post by zoneminder »

The monitor SQL is excuted only once, at the beginning so the results you get from that will never change. The Notes field in that context does not make any sense.

You need to be querying the Events table to get Notes out, and do that in the block I identified each time there is a new alarm.

Something like

Code: Select all

my $eventSql = "select * from Events where Id = ?";
my $eventSth = $dbh->prepare_cached( $eventSql ) or die( "Can't prepare '$eventSql': ".$dbh->errstr() );

my $eventRes = $eventSth->execute( $last_event_id ) or die( "Can't execute '$sql': ".$eventSth->errstr() );
my $event = $eventSth->fetchrow_hashref();

// Do something with $event

$eventSth->finish();
The first two lines can go anywhere in the file (they only need to be executed once) but the others should go in the loop.
Phil
gilles
Posts: 19
Joined: Tue Jun 07, 2011 6:46 am

Re: pb with a modified perl script to trigger an alarm

Post by gilles »

Thank you a lot.

I will try and let you an info, if I'm ok or not.


If it works my zoneminder will trigger in real time some zones with boolean decision to avoid false detection in first plan of my monitor.

I know my explanation is too long but if it's work I will post what I do for others.

Gilles.
gilles
Posts: 19
Joined: Tue Jun 07, 2011 6:46 am

Re: pb with a modified perl script to trigger an alarm

Post by gilles »

Hi Phil,

Really sorry, but always got a problem.

When I add your code and mine like that:

Code: Select all

my $eventRes = $eventSth->execute($last_event_id) or die( "Can't execute '$sql': ".$eventSth->errstr() );
           my @eventRes;
           while ( my $eventRes = $eventSth->fetchrow_hashref() )
                {
                    push( @eventRes, $eventRes);
                }
            print("event".$eventRes->{MonitorId}."\n");

and When an alarm happen, I've got that error:

DBD::mysql::st execute failed: called with 1 bind variables when 0 are needed at ./zm_alarm_def3.pl line 36.
Can't execute 'select M.*, max(E.Id) as LastEventId from Monitors as M left join Events as E on M.Id = E.MonitorId where M.Function != 'None' group by (M.Id)': called with 1 bind variables when 0 are needed at ./zm_alarm_def3.pl line 36.

The line 36 is: my $eventRes = $eventSth->execute($last_event_id) or die( "Can't execute '$sql': ".$eventSth->errstr() );

Could you help me a last time, please ? :oops:

gilles.
User avatar
zoneminder
Site Admin
Posts: 5215
Joined: Wed Jul 09, 2003 2:07 pm
Location: Bristol, UK
Contact:

Re: pb with a modified perl script to trigger an alarm

Post by zoneminder »

Please post your whole script.

By the way this line
gilles wrote:

Code: Select all

my $eventRes = $eventSth->execute($last_event_id) or die( "Can't execute '$sql': ".$eventSth->errstr() );
Should be

Code: Select all

my $eventRes = $eventSth->execute($last_event_id) or die( "Can't execute '$eventSql': ".$eventSth->errstr() );
but that only means that the correct SQL stateent will be reported in the error and won't make any difference other than that.
Phil
gilles
Posts: 19
Joined: Tue Jun 07, 2011 6:46 am

Re: pb with a modified perl script to trigger an alarm

Post by gilles »

Hi Phil,

Here is the code:

Code: Select all

#!/usr/bin/perl -w

use strict;

use ZoneMinder;

$| = 1;

zmDbgInit( "myscript", level=>0, to_log=>0, to_syslog=>0, to_term=>1 );

my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS );

my $sql = "select M.*, max(E.Id) as LastEventId from Monitors as M left join Events as E on M.Id = E.MonitorId where M.Function != 'None' group by (M.Id)";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );

my $eventSql = "select max(Notes) from Events";
my $eventSth = $dbh->prepare_cached( $eventSql ) or die( "Can't prepare '$eventSql': ".$dbh->errstr() );

my @monitors;
while ( my $monitor = $sth->fetchrow_hashref() )
{
    push( @monitors, $monitor );
}

while( 1 )
{
    foreach my $monitor ( @monitors )
    {
        next if ( !zmMemVerify( $monitor ) );
 
        if ( my $last_event_id = zmHasAlarmed( $monitor, $monitor->{LastEventId} ) )
        {
            $monitor->{LastEventId} = $last_event_id;
            print( "Monitor ".$monitor->{Name}." has alarmed\n" );
            my $eventRes = $eventSth->execute( $last_event_id ) or die( "Can't execute '$sql': ".$eventSth->errstr() );
           my @eventRes;
           while ( my $eventRes = $eventSth->fetchrow_hashref() )
                {
                    push( @eventRes, $eventRes);
                }
            print("event".$eventRes->{MonitorId}."\n");
            sleep (1);
            $eventSth->finish();
        }
    }
    sleep( 1 );
}
In order to test my script, I put a basic selection like : "select max(Notes) from Events", if it works I will put a better selection.

Really sorry to disturb you but it's impotant for me that this script works.

Thank you for your help.

Gilles.
User avatar
zoneminder
Site Admin
Posts: 5215
Joined: Wed Jul 09, 2003 2:07 pm
Location: Bristol, UK
Contact:

Re: pb with a modified perl script to trigger an alarm

Post by zoneminder »

That is your problem,

Code: Select all

my $eventSql = "select max(Notes) from Events";
does not make any sense and is also what is causing the error.

You need to use a query like I suggested in my example,

Code: Select all

my $eventSql = "select * from Events where Id = ?";
If you only want the Notes field then you can change it to

Code: Select all

my $eventSql = "select Notes from Events where Id = ?";
It is probably worth your while spending some time reading up on SQL and perl DBI if you want to do anything more sophisticated than that.
Phil
Locked