Simple Alarm call center
Simple Alarm call center script. This script can by used as after script for Asterisk AlarmReceiver cmd.
This script read saved events from asterisk alarm receiver. If the event is important (Alarm event) script create asterisk call file which make a call and play sound message to selected numbers.
You can also receive formated events to email.
Notes:For better results in communication you can try increase output gain on your ATA (default setting is -3)
FXS Port Output Gain: +1
You must set all other regional settings to match your alarm !!! (FXS Port Impedance, Ring Frequency, Ring Voltage, ...)
Other info for Asterisk AlarmReceiver cmd can be found here: http://www.voip-info.org/wiki/index.php?page=Asterisk+cmd+AlarmReceiver
Written by
Uroš Indihar
Alphito d.o.o.
Changelog 0.1 Initial release 0.2 1.12.1008 Added mail support
License GNU GPL3.
Warranty: None. Use at your own risk !
Asterisk settings
Example: alarmreceiver.conf [general] timestampformat = %a %b %d, %Y @ %H:%M:%S %Z eventcmd = /usr/local/bin/after_alarm_event.php eventspooldir = /var/spool/asterisk/alarm_events logindividualevents = yes fdtimeout = 2000 sdtimeout = 200 loudness = 8192 ------------------------------------------------------------------------------------------------ Example: sip.conf (pstn to sip part) [31] type=friend context=phones host=dynamic secret=******* callerid="Ademco Alarm" <31> dtmfmode=inband disallow=all allow=ulaw ------------------------------------------------------------------------------------------------ Example: extension.conf [internal] ;alarm receiver exten => 560,1,Verbose(1|Extension 560 - Alarm Receiver) exten => 560,n,Ringing() exten => 560,n,Wait(2) exten => 560,n,AlarmReceiver() exten => 560,n,Hangup() [alarmreport] exten => start,1,Answer() exten => start,n,Wait(1) exten => start,n,Playback(ha/alarm) exten => start,n,Wait(1) exten => start,n,Playback(ha/alarm) exten => start,n,Wait(1) exten => start,n,Playback(ha/alarm) exten => start,n,Wait(1) exten => start,n,Playback(ha/alarm) exten => start,n,Wait(1) exten => start,n,Playback(ha/alarm) exten => start,n,Wait(1) exten => start,n,Playback(ha/alarm) exten => start,n,Wait(1) exten => start,n,Playback(ha/alarm) exten => start,n,Wait(1) exten => start,n,Playback(vm-goodbye) exten => start,n,Hangup()
Script after_alarm_event.php
Download source here:
<?php
class ademcoEventParser {
var $eventMap=array(
110 => "Fire Alarm",
121 => "Duress",
122 => "Alarm, 24-hour Silent",
123 => "Alarm, 24-hour Audible",
131 => "Alarm, Perimeter",
132 => "Alarm, Interior",
134 => "Alarm, Entry/Exit",
135 => "Alarm, Day/Night",
143 => "Alarm, Expansion Module",
146 => "Silent Burglary",
150 => "Alarm, 24-Hour Auxiliary",
301 => "AC Power",
302 => "Low System Battery/Battery Test Fail",
305 => "System Reset",
333 => "Trouble or Tamper Expansion Module",
351 => "Telco Line Fault",
353 => "Long Range Radio Trouble",
373 => "Fire Loop Trouble",
374 => "Exit Error Alarm",
380 => "Global Trouble, Trouble Day/Night",
381 => "RF Supervision Trouble",
383 => "RF Sensor Tamper",
384 => "RF Sensor Low Battery",
401 => "Disarmed, Armed AWAY (MAX), Armed AWAY",
406 => "Cancel by User",
407 => "Remote Arm/Disarm (Downloading)",
408 => "Quick Arm AWAY/MAX",
441 => "Disarmed/Armed STAY/INSTANT , Quick Arm STAY/INSTANT",
570 => "Bypass",
602 => "Periodic Test",
606 => "AAV to follow",
607 => "System Test",
623 => "Event Log 80% Full",
629 => "1-1/3 Day No Event",
);
var $eventsDir="/var/spool/asterisk/alarm_events/";
var $eventPrefix="event-";
var $lastEventSave="last_received_event";
var $actionChannels=array( //ademco_id => array(channel1,channel2,...);
"NNNN(ADEMCO_ID 1)"=>array(
"SIP/NNNNNN (Asterisk channel)",
"SIP/NNNNNN (Asterisk channel)",
),
"NNNN(ADEMCO_ID 2)"=>array(
"SIP/NNNNNN (Asterisk channel)",
),
);
var $callFileDir="/var/spool/asterisk/outgoing/";
var $actionChannelsMail=array( //ademco_id => array(Email1=>Name1,Email2=>Name2,...);
"NNNN(ADEMCO_ID 1)"=>array(
"example@example.com"=>"My Name",
"example1@example.com"=>"My Name1",
),
"NNNN(ADEMCO_ID 2)"=>array(
"example@example.com"=>"My Name",
),
);
var $emailFromName="Ademco Alarm Report";
var $emailFrom="cron@alphito.si";
var $callerId="Alarm Report <NNNNNNNNNNNN>";
function setEventsDir($dir) {
$this->eventsDir=$dir;
}
function getEventFiles() {
$eventFiles=array();
$eventPrefixLen=strlen($this->eventPrefix);
$dh = opendir($this->eventsDir);
while (($file = readdir($dh)) !== false) {
if (substr($file,0,$eventPrefixLen) == $this->eventPrefix) {
$eventFiles[$file]=filemtime($this->eventsDir.$file);
}
}
asort($eventFiles);
closedir($dh);
$this->eventFiles=$eventFiles;
}
function loop() {
foreach ($this->eventFiles as $file => $mtime) {
$data=$this->parse($file);
foreach ($data["events"] as $event) {
//echo $event;
$e=$this->parseEvent($event);
if ($this->getSavedEvent() == $event) {
//event is duplicated to last event
$this->log($data["metadata"],$event,"Duplicated event",$e);
} else {
$this->saveEvent($event);
$this->log($data["metadata"],$event,"New event",$e);
$this->action($e,$data["metadata"],$event);
}
}
//print_r($data);
//remove file
unlink($this->eventsDir.$file);
}
}
function action($e,$metadata,$event) {
if(intval($e["e"]) < 200) {
//do action on alarm events
$this->log($metadata,$event,"Starting action",$e);
foreach ($this->actionChannels[$e["id"]] as $callChannel) {
$this->createCallFile($callChannel);
}
}
//send email report
if (is_array($this->actionChannelsMail[$e["id"]])) {
$msg ="Ademco alarm report.\n\n";
$msg.="Logged event at ".date("d.m.Y H:i:s",time()).".\n\n";
$msg."Event data:\n\n";
$msg.=implode(", ",$metadata)."\n";
$msg.=$event."\n";
$msg.=implode(", ",$e)."\n";
$msg.=$this->eventMap[$e["e"]]."\n\n";
$subject ="[ ALARM ] ".$this->eventMap[$e["e"]];
foreach ($this->actionChannelsMail[$e["id"]] as $email => $name) {
$this->sendMail($subject,$name,$email,$this->emailFromName,$this->emailFrom,$msg);
}
}
}
function createCallFile($channel) {
$callFile ="Channel: ".$channel."\n";
$callFile.="CallerID: ".$this->callerId."\n";
$callFile.="MaxRetries: 10\n";
$callFile.="RetryTime: 60\n";
$callFile.="WaitTime: 30\n";
$callFile.="Context: alarmreport\n";
$callFile.="Extension: start\n";
$callFile.="Priority: 1\n";
file_put_contents($this->callFileDir.uniqid("alarm").".call",$callFile);
}
function getSavedEvent () {
$lastEvent=@file_get_contents($this->eventsDir.$this->lastEventSave);
return $lastEvent;
}
function saveEvent($event) {
file_put_contents($this->eventsDir.$this->lastEventSave,$event);
}
function parseEvent($event) {
$e=array(
"id" => substr($event,0,4),
"q" => substr($event,4,3),
"e" => substr($event,7,3),
"z" => substr($event,10),
);
//print_r($e);
return($e);
}
function log($metadata,$event,$string,$e) {
syslog(LOG_NOTICE,implode(", ",$metadata).", ".$event.", ".$string.", ".implode(", ",$e).", ".$this->eventMap[$e["e"]]);
}
function parse($file) {
$fp=fopen($this->eventsDir.$file,"r");
$section="";
$data=array();
while (!feof($fp)) {
$line = trim(fgets($fp,4096));
if (substr($line,0,1) == "[") {
//new section started
$section=substr($line,1,-1);
$data[$section]=array();
} elseif (strlen($section) > 0) {
//we are in section
switch ($section) {
case "metadata":
if (strlen($line) > 0) {
//dont include empty lines
list($key,$val)=explode("=",$line);
//echo $key."->".$val."\n";
$data[$section][trim($key)]=trim($val);
}
break;
case "events":
if (strlen($line) > 0) {
$data[$section][]=trim($line);
}
break;
}
}
//echo $line."\n";
}
fclose($fp);
return $data;
}
function sendMail($subject,$tostr,$toemail,$fromstr,$fromemail,$msg) {
$from = '"';
$from.=$this->encode($fromstr);
$from.= '"';
$from.="<".$fromemail.">";
$to = '"';
$to.=$this->encode($tostr);
$to.= '"';
$to.="<".$toemail.">";
//$msubject=$this->encode($subject);
$msubject=$subject;
$headers = "MIME-Version: 1.0\n";
$headers .= "Content-type: text/plain; charset=utf-8\n";
$headers .= "From: ".$from."\n";
return mail($to, $msubject, $msg, $headers);
}
function encode($in_str, $charset="UTF-8") {
$out_str = $in_str;
if ($out_str && $charset) {
$end = "?=";
$start = "=?" . $charset . "?B?";
$spacer = $end . "\n " . $start;
$length = 75 - strlen($start) - strlen($end);
$length = floor($length/2) * 2;
$out_str = base64_encode($out_str);
$out_str = chunk_split($out_str, $length, $spacer);
$spacer = preg_quote($spacer);
$out_str = preg_replace("/" . $spacer . "$/", "", $out_str);
$out_str = $start . $out_str . $end;
}
return $out_str;
}
}
$aep=new ademcoEventParser();
$aep->getEventFiles();
$aep->loop();
?>