Sat Aug 6 00:39:33 2011

Asterisk developer's documentation


app_alarmreceiver.c File Reference

Central Station Alarm receiver for Ademco Contact ID. More...

#include "asterisk.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/time.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/ulaw.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/config.h"
#include "asterisk/localtime.h"
#include "asterisk/callerid.h"
#include "asterisk/astdb.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Data Structures

struct  event_node

Defines

#define ADEMCO_CONTACT_ID   "ADEMCO_CONTACT_ID"
#define ALMRCV_CONFIG   "alarmreceiver.conf"

Typedefs

typedef event_node event_node_t

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int alarmreceiver_exec (struct ast_channel *chan, void *data)
static void database_increment (char *key)
static int load_config (void)
static int load_module (void)
static int log_events (struct ast_channel *chan, char *signalling_type, event_node_t *event)
static void make_tone_burst (unsigned char *data, float freq, float loudness, int len, int *x)
static int receive_ademco_contact_id (struct ast_channel *chan, void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
static int receive_dtmf_digits (struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
static int send_tone_burst (struct ast_channel *chan, float freq, int duration, int tldn)
static int unload_module (void)
static int write_event (FILE *logfile, event_node_t *event)
static int write_metadata (FILE *logfile, char *signalling_type, struct ast_channel *chan)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Alarm Receiver for Asterisk" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, }
static char * app = "AlarmReceiver"
static const struct ast_module_infoast_module_info = &__mod_info
static char db_family [128] = {'\0'}
static char * descrip
static char event_app [128] = {'\0'}
static char event_file [14] = "/event-XXXXXX"
static char event_spool_dir [128] = {'\0'}
static int fdtimeout = 2000
static int log_individual_events = 0
static int sdtimeout = 200
static char * synopsis = "Provide support for receiving alarm reports from a burglar or fire alarm panel"
static char time_stamp_format [128] = {"%a %b %d, %Y @ %H:%M:%S %Z"}
static int toneloudness = 4096


Detailed Description

Central Station Alarm receiver for Ademco Contact ID.

Author:
Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
*** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***

Use at your own risk. Please consult the GNU GPL license document included with Asterisk. *

*** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***

Definition in file app_alarmreceiver.c.


Define Documentation

#define ADEMCO_CONTACT_ID   "ADEMCO_CONTACT_ID"

Definition at line 62 of file app_alarmreceiver.c.

Referenced by alarmreceiver_exec(), and receive_ademco_contact_id().

#define ALMRCV_CONFIG   "alarmreceiver.conf"

Definition at line 61 of file app_alarmreceiver.c.

Referenced by load_config().


Typedef Documentation

typedef struct event_node event_node_t

Definition at line 69 of file app_alarmreceiver.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 841 of file app_alarmreceiver.c.

static void __unreg_module ( void   )  [static]

Definition at line 841 of file app_alarmreceiver.c.

static int alarmreceiver_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 626 of file app_alarmreceiver.c.

References ast_channel::_state, ADEMCO_CONTACT_ID, ast_answer(), ast_copy_string(), AST_FORMAT_ULAW, ast_log(), ast_module_user_add, ast_module_user_remove, ast_safe_sleep(), ast_safe_system(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_strlen_zero(), ast_verbose(), ast_module_user::chan, free, LOG_DEBUG, log_events(), LOG_WARNING, ast_channel::name, event_node::next, option_verbose, receive_ademco_contact_id(), and VERBOSE_PREFIX_4.

Referenced by load_module().

00627 {
00628    int res = 0;
00629    struct ast_module_user *u;
00630    event_node_t *elp, *efree;
00631    char signalling_type[64] = "";
00632 
00633    event_node_t *event_head = NULL;
00634 
00635    u = ast_module_user_add(chan);
00636 
00637    /* Set write and read formats to ULAW */
00638 
00639    if(option_verbose >= 4)
00640       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Setting read and write formats to ULAW\n");
00641 
00642    if (ast_set_write_format(chan,AST_FORMAT_ULAW)){
00643       ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
00644       ast_module_user_remove(u);
00645       return -1;
00646    }
00647    
00648    if (ast_set_read_format(chan,AST_FORMAT_ULAW)){
00649       ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
00650       ast_module_user_remove(u);
00651       return -1;
00652    }
00653 
00654    /* Set default values for this invokation of the application */
00655    
00656    ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type));
00657 
00658 
00659    /* Answer the channel if it is not already */
00660 
00661    if(option_verbose >= 4)
00662       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Answering channel\n");
00663 
00664    if (chan->_state != AST_STATE_UP) {
00665    
00666       res = ast_answer(chan);
00667       
00668       if (res) {
00669          ast_module_user_remove(u);
00670          return -1;
00671       }
00672    }
00673 
00674    /* Wait for the connection to settle post-answer */
00675 
00676    if(option_verbose >= 4)
00677       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for connection to stabilize\n");
00678 
00679    res = ast_safe_sleep(chan, 1250);
00680 
00681    /* Attempt to receive the events */
00682 
00683    if(!res){
00684    
00685       /* Determine the protocol to receive in advance */
00686       /* Note: Ademco contact is the only one supported at this time */
00687       /* Others may be added later */
00688       
00689       if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
00690          receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
00691       else
00692          res = -1;
00693    }
00694    
00695       
00696    
00697    /* Events queued by receiver, write them all out here if so configured */
00698 
00699    if((!res) && (log_individual_events == 0)){
00700       res = log_events(chan, signalling_type, event_head);
00701 
00702    }
00703 
00704    /*
00705    * Do we exec a command line at the end?
00706    */
00707    
00708    if((!res) && (!ast_strlen_zero(event_app)) && (event_head)){
00709       ast_log(LOG_DEBUG,"Alarmreceiver: executing: %s\n", event_app);
00710       ast_safe_system(event_app);
00711    }
00712 
00713    /*
00714    * Free up the data allocated in our linked list
00715    */
00716       
00717    for(elp = event_head; (elp != NULL);){
00718       efree = elp;
00719       elp = elp->next;
00720       free(efree);
00721    }
00722 
00723 
00724    ast_module_user_remove(u);
00725 
00726    return 0;
00727 }

static void database_increment ( char *  key  )  [static]

Definition at line 108 of file app_alarmreceiver.c.

References ast_db_get(), ast_db_put(), ast_strlen_zero(), ast_verbose(), option_verbose, and VERBOSE_PREFIX_4.

Referenced by receive_ademco_contact_id().

00109 {
00110    int res = 0;
00111    unsigned v;
00112    char value[16];
00113    
00114    
00115    if (ast_strlen_zero(db_family))
00116       return; /* If not defined, don't do anything */
00117    
00118    res = ast_db_get(db_family, key, value, sizeof(value) - 1);
00119    
00120    if(res){
00121       if(option_verbose >= 4)
00122          ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
00123       /* Guess we have to create it */
00124       res = ast_db_put(db_family, key, "1");
00125       return;
00126    }
00127    
00128    sscanf(value, "%30u", &v);
00129    v++;
00130    
00131    if(option_verbose >= 4)
00132       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: New value for %s: %u\n", key, v);
00133       
00134    snprintf(value, sizeof(value), "%u", v);
00135    
00136    res = ast_db_put(db_family, key, value);
00137    
00138    if((res)&&(option_verbose >= 4))
00139       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: database_increment write error\n");
00140    
00141    return;  
00142 }

static int load_config ( void   )  [static]

Definition at line 733 of file app_alarmreceiver.c.

References ALMRCV_CONFIG, ast_config_destroy(), ast_config_load(), ast_copy_string(), ast_true(), ast_variable_retrieve(), ast_verbose(), option_verbose, and VERBOSE_PREFIX_4.

Referenced by load_module(), and reload().

00734 {
00735    struct ast_config *cfg;
00736    const char *p;
00737 
00738    /* Read in the config file */
00739 
00740    cfg = ast_config_load(ALMRCV_CONFIG);
00741                                                                                                                                   
00742    if(!cfg){
00743    
00744       if(option_verbose >= 4)
00745          ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: No config file\n");
00746       return 0;
00747    }
00748    else{
00749 
00750       
00751       p = ast_variable_retrieve(cfg, "general", "eventcmd");
00752       
00753       if(p){
00754          ast_copy_string(event_app, p, sizeof(event_app));
00755          event_app[sizeof(event_app) - 1] = '\0';
00756       }
00757       
00758       p = ast_variable_retrieve(cfg, "general", "loudness");
00759       if(p){
00760          toneloudness = atoi(p);
00761          if(toneloudness < 100)
00762             toneloudness = 100;
00763          if(toneloudness > 8192)
00764             toneloudness = 8192;
00765       }
00766       p = ast_variable_retrieve(cfg, "general", "fdtimeout");
00767       if(p){
00768          fdtimeout = atoi(p);
00769          if(fdtimeout < 1000)
00770             fdtimeout = 1000;
00771          if(fdtimeout > 10000)
00772             fdtimeout = 10000;   
00773       }
00774       
00775       p = ast_variable_retrieve(cfg, "general", "sdtimeout");
00776       if(p){
00777          sdtimeout = atoi(p);
00778          if(sdtimeout < 110)
00779             sdtimeout = 110;
00780          if(sdtimeout > 4000)
00781             sdtimeout = 4000;       
00782 
00783       }
00784       
00785       p = ast_variable_retrieve(cfg, "general", "logindividualevents");
00786       if(p){
00787          log_individual_events = ast_true(p);
00788 
00789       }
00790       
00791       p = ast_variable_retrieve(cfg, "general", "eventspooldir");
00792          
00793       if(p){
00794          ast_copy_string(event_spool_dir, p, sizeof(event_spool_dir));
00795          event_spool_dir[sizeof(event_spool_dir) - 1] = '\0';
00796       }
00797       
00798       p = ast_variable_retrieve(cfg, "general", "timestampformat");
00799          
00800       if(p){
00801          ast_copy_string(time_stamp_format, p, sizeof(time_stamp_format));
00802          time_stamp_format[sizeof(time_stamp_format) - 1] = '\0';
00803       }
00804 
00805       p = ast_variable_retrieve(cfg, "general", "db-family");
00806                                                                                                                                             
00807       if(p){
00808          ast_copy_string(db_family, p, sizeof(db_family));
00809          db_family[sizeof(db_family) - 1] = '\0';
00810       }
00811       ast_config_destroy(cfg);
00812    }
00813    return 1;
00814 
00815 }

static int load_module ( void   )  [static]

Definition at line 833 of file app_alarmreceiver.c.

References alarmreceiver_exec(), AST_MODULE_LOAD_DECLINE, ast_register_application(), and load_config().

00834 {
00835    if(load_config())
00836       return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
00837    else
00838       return AST_MODULE_LOAD_DECLINE;
00839 }

static int log_events ( struct ast_channel chan,
char *  signalling_type,
event_node_t event 
) [static]

Definition at line 383 of file app_alarmreceiver.c.

References ast_copy_string(), ast_log(), ast_strlen_zero(), ast_verbose(), LOG_DEBUG, event_node::next, VERBOSE_PREFIX_4, write_event(), and write_metadata().

Referenced by alarmreceiver_exec(), and receive_ademco_contact_id().

00384 {
00385 
00386    int res = 0;
00387    char workstring[sizeof(event_spool_dir)+sizeof(event_file)] = "";
00388    int fd;
00389    FILE *logfile;
00390    event_node_t *elp = event;
00391    
00392    if (!ast_strlen_zero(event_spool_dir)) {
00393       
00394       /* Make a template */
00395       
00396       ast_copy_string(workstring, event_spool_dir, sizeof(workstring));
00397       strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
00398       
00399       /* Make the temporary file */
00400       
00401       fd = mkstemp(workstring);
00402       
00403       if(fd == -1){
00404          ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't make temporary file\n");   
00405          ast_log(LOG_DEBUG,"AlarmReceiver: can't make temporary file\n");
00406          res = -1;
00407       }
00408       
00409       if(!res){
00410          logfile = fdopen(fd, "w");
00411          if(logfile){
00412             /* Write the file */
00413             res = write_metadata(logfile, signalling_type, chan);
00414             if(!res)
00415                while((!res) && (elp != NULL)){
00416                   res = write_event(logfile, elp);
00417                   elp = elp->next;
00418                }
00419             if(!res){
00420                if(fflush(logfile) == EOF)
00421                   res = -1;
00422                if(!res){
00423                   if(fclose(logfile) == EOF)
00424                      res = -1;
00425                }           
00426             }
00427          }
00428          else
00429             res = -1;
00430       }
00431    }
00432 
00433    return res; 
00434 }

static void make_tone_burst ( unsigned char *  data,
float  freq,
float  loudness,
int  len,
int *  x 
) [static]

Definition at line 149 of file app_alarmreceiver.c.

References AST_LIN2MU.

Referenced by send_tone_burst().

00150 {
00151    int     i;
00152    float   val;
00153                                                                                                                                     
00154         for(i = 0; i < len; i++){
00155       val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
00156       data[i] = AST_LIN2MU((int)val);
00157    }
00158 
00159    /* wrap back around from 8000 */
00160 
00161    if (*x >= 8000) *x = 0;
00162    return;
00163 }

static int receive_ademco_contact_id ( struct ast_channel chan,
void *  data,
int  fdto,
int  sdto,
int  tldn,
event_node_t **  ehead 
) [static]

Definition at line 442 of file app_alarmreceiver.c.

References ADEMCO_CONTACT_ID, ast_calloc, ast_copy_string(), ast_log(), ast_safe_sleep(), ast_strlen_zero(), ast_verbose(), database_increment(), LOG_DEBUG, log_events(), event_node::next, option_verbose, receive_dtmf_digits(), send_tone_burst(), VERBOSE_PREFIX_2, and VERBOSE_PREFIX_4.

Referenced by alarmreceiver_exec().

00443 {
00444    int i,j;
00445    int res = 0;
00446    int checksum;
00447    char event[17];
00448    event_node_t *enew, *elp;
00449    int got_some_digits = 0;
00450    int events_received = 0;
00451    int ack_retries = 0;
00452    
00453    static char digit_map[15] = "0123456789*#ABC";
00454         static unsigned char digit_weights[15] = {10,1,2,3,4,5,6,7,8,9,11,12,13,14,15};
00455                                                                                                                       
00456    database_increment("calls-received");
00457 
00458    /* Wait for first event */
00459 
00460    if(option_verbose >= 4)
00461       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for first event from panel\n");
00462 
00463    while(res >= 0){
00464 
00465       if(got_some_digits == 0){
00466 
00467             /* Send ACK tone sequence */
00468                         
00469                                                                                                                           
00470             if(option_verbose >= 4)
00471                      ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
00472                                                                                                                                             
00473                                                                                                                                             
00474             res = send_tone_burst(chan, 1400.0, 100, tldn);
00475                                                                                                                                             
00476             if(!res)
00477                      res = ast_safe_sleep(chan, 100);
00478                                                                                                                                             
00479             if(!res){
00480                      if(option_verbose >= 4)
00481                               ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
00482                                                                                                                                             
00483                      res = send_tone_burst(chan, 2300.0, 100, tldn);
00484             }
00485                                                                                                                                             
00486       }
00487 
00488       if( res >= 0)
00489          res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
00490       
00491       if (res < 0){
00492       
00493          if(events_received == 0)
00494             /* Hangup with no events received should be logged in the DB */
00495             database_increment("no-events-received");
00496          else{
00497             if(ack_retries){
00498                if(option_verbose >= 4)
00499                   ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
00500                
00501                database_increment("ack-retries");
00502             }
00503          }
00504          if(option_verbose >= 4)
00505             ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: App exiting...\n");
00506          res = -1;
00507          break;
00508       }
00509       
00510       if(res != 0){
00511           /* Didn't get all of the digits */
00512          if(option_verbose >= 2)
00513             ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
00514 
00515          if(!got_some_digits){
00516             got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
00517             ack_retries++;
00518          }
00519          continue;   
00520       }     
00521       
00522       got_some_digits = 1;
00523 
00524       if(option_verbose >= 2)
00525          ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Received Event %s\n", event);
00526       ast_log(LOG_DEBUG, "AlarmReceiver: Received event: %s\n", event);
00527       
00528       /* Calculate checksum */
00529       
00530       for(j = 0, checksum = 0; j < 16; j++){
00531          for(i = 0 ; i < sizeof(digit_map) ; i++){
00532             if(digit_map[i] == event[j])
00533                break;
00534          }
00535          
00536          if(i == 16)
00537             break;
00538             
00539          checksum += digit_weights[i];
00540       }
00541       
00542       if(i == 16){
00543          if(option_verbose >= 2)
00544             ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
00545          continue; /* Bad character */
00546       }
00547 
00548       /* Checksum is mod(15) of the total */
00549 
00550       checksum = checksum % 15;
00551 
00552       if (checksum) {
00553          database_increment("checksum-errors");
00554          if (option_verbose >= 2)
00555             ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Nonzero checksum\n");
00556          ast_log(LOG_DEBUG, "AlarmReceiver: Nonzero checksum\n");
00557          continue;
00558       }
00559 
00560       /* Check the message type for correctness */
00561 
00562       if(strncmp(event + 4, "18", 2)){
00563          if(strncmp(event + 4, "98", 2)){
00564             database_increment("format-errors");
00565             if(option_verbose >= 2)
00566                ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Wrong message type\n");
00567             ast_log(LOG_DEBUG, "AlarmReceiver: Wrong message type\n");
00568          continue;
00569          }
00570       }
00571 
00572       events_received++;
00573       
00574       /* Queue the Event */      
00575       if (!(enew = ast_calloc(1, sizeof(*enew)))) {
00576          res = -1;
00577          break;
00578       }
00579       
00580       enew->next = NULL;
00581       ast_copy_string(enew->data, event, sizeof(enew->data));
00582 
00583       /*
00584       * Insert event onto end of list
00585       */
00586       
00587       if(*ehead == NULL){
00588          *ehead = enew;
00589       }
00590       else{
00591          for(elp = *ehead; elp->next != NULL; elp = elp->next)
00592          ;
00593          
00594          elp->next = enew;
00595       }
00596       
00597       if(res > 0)
00598          res = 0;
00599       
00600       /* Let the user have the option of logging the single event before sending the kissoff tone */
00601 
00602       if((res == 0) && (log_individual_events))
00603          res = log_events(chan, ADEMCO_CONTACT_ID, enew);
00604    
00605       /* Wait 200 msec before sending kissoff */   
00606          
00607       if(res == 0)   
00608          res = ast_safe_sleep(chan, 200);
00609 
00610       /* Send the kissoff tone */
00611 
00612       if(res == 0)      
00613          res = send_tone_burst(chan, 1400.0, 900, tldn);
00614    }
00615 
00616    
00617    return res;
00618 }

static int receive_dtmf_digits ( struct ast_channel chan,
char *  digit_string,
int  length,
int  fdto,
int  sdto 
) [static]

Definition at line 238 of file app_alarmreceiver.c.

References AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_read(), ast_tvdiff_ms(), ast_tvnow(), ast_verbose(), ast_waitfor(), f, LOG_DEBUG, ast_channel::name, option_verbose, and VERBOSE_PREFIX_4.

Referenced by receive_ademco_contact_id().

00239 {
00240    int res = 0;
00241    int i = 0;
00242    int r;
00243    struct ast_frame *f;
00244    struct timeval lastdigittime;
00245    
00246    lastdigittime = ast_tvnow();
00247    for(;;){
00248         /* if outa time, leave */
00249       if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) >
00250           ((i > 0) ? sdto : fdto)){
00251          if(option_verbose >= 4)
00252             ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
00253             
00254          ast_log(LOG_DEBUG,"AlarmReceiver: DTMF timeout on chan %s\n",chan->name);
00255             
00256          res = 1;
00257          break;
00258       }
00259       
00260       if ((r = ast_waitfor(chan, -1) < 0)) {
00261          ast_log(LOG_DEBUG, "Waitfor returned %d\n", r);
00262          continue;
00263       }
00264          
00265       f = ast_read(chan);
00266       
00267       if (f == NULL){
00268          res = -1;
00269          break;
00270       }
00271       
00272       /* If they hung up, leave */
00273       if ((f->frametype == AST_FRAME_CONTROL) &&
00274           (f->subclass == AST_CONTROL_HANGUP)){
00275          ast_frfree(f);
00276          res = -1;
00277          break;
00278       }
00279       
00280       /* if not DTMF, just do it again */
00281       if (f->frametype != AST_FRAME_DTMF){
00282          ast_frfree(f);
00283          continue;
00284       }
00285 
00286       digit_string[i++] = f->subclass;  /* save digit */
00287       
00288       ast_frfree(f);
00289       
00290       /* If we have all the digits we expect, leave */
00291       if(i >= length)
00292          break;
00293       
00294       lastdigittime = ast_tvnow();
00295    }
00296    
00297    digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
00298    return res;
00299 
00300 }

static int send_tone_burst ( struct ast_channel chan,
float  freq,
int  duration,
int  tldn 
) [static]

Definition at line 170 of file app_alarmreceiver.c.

References AST_FORMAT_ULAW, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_read(), ast_verbose(), ast_waitfor(), ast_write(), ast_frame::data, ast_frame::datalen, f, ast_frame::frametype, LOG_WARNING, make_tone_burst(), ast_frame::mallocd, ast_frame::offset, option_verbose, ast_frame::samples, ast_frame::subclass, and VERBOSE_PREFIX_4.

Referenced by receive_ademco_contact_id().

00171 {
00172    int res = 0;
00173    int i = 0;
00174    int x = 0;
00175    struct ast_frame *f, wf;
00176    
00177    struct {
00178       unsigned char offset[AST_FRIENDLY_OFFSET];
00179       unsigned char buf[640];
00180    } tone_block;
00181 
00182    for(;;)
00183    {
00184    
00185       if (ast_waitfor(chan, -1) < 0){
00186          res = -1;
00187          break;
00188       }
00189       
00190       f = ast_read(chan);
00191       if (!f){
00192          res = -1;
00193          break;
00194       }
00195       
00196       if (f->frametype == AST_FRAME_VOICE) {
00197          wf.frametype = AST_FRAME_VOICE;
00198          wf.subclass = AST_FORMAT_ULAW;
00199          wf.offset = AST_FRIENDLY_OFFSET;
00200          wf.mallocd = 0;
00201          wf.data = tone_block.buf;
00202          wf.datalen = f->datalen;
00203          wf.samples = wf.datalen;
00204          
00205          make_tone_burst(tone_block.buf, freq, (float) tldn, wf.datalen, &x);
00206 
00207          i += wf.datalen / 8;
00208          if (i > duration) {
00209             ast_frfree(f);
00210             break;
00211          }
00212          if (ast_write(chan, &wf)){
00213             if(option_verbose >= 4)
00214                ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Failed to write frame on %s\n", chan->name);
00215             ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
00216             res = -1;
00217             ast_frfree(f);
00218             break;
00219          }
00220       }
00221       
00222       ast_frfree(f);
00223    }
00224    return res;
00225 }

static int unload_module ( void   )  [static]

Definition at line 822 of file app_alarmreceiver.c.

References ast_module_user_hangup_all, and ast_unregister_application().

00823 {
00824    int res;
00825 
00826    res = ast_unregister_application(app);
00827 
00828    ast_module_user_hangup_all();
00829 
00830    return res;
00831 }

static int write_event ( FILE *  logfile,
event_node_t event 
) [static]

Definition at line 367 of file app_alarmreceiver.c.

References event_node::data.

Referenced by log_events().

00368 {
00369    int res = 0;
00370 
00371    if( fprintf(logfile, "%s\n", event->data) < 0)
00372       res = -1;
00373          
00374    return res;
00375 }

static int write_metadata ( FILE *  logfile,
char *  signalling_type,
struct ast_channel chan 
) [static]

Definition at line 306 of file app_alarmreceiver.c.

References ast_callerid_parse(), ast_copy_string(), ast_localtime(), ast_log(), ast_shrink_phone_number(), ast_verbose(), ast_channel::cid, ast_callerid::cid_num, LOG_DEBUG, t, and VERBOSE_PREFIX_4.

Referenced by log_events().

00307 {
00308    int res = 0;
00309    time_t t;
00310    struct tm now;
00311    char *cl,*cn;
00312    char workstring[80];
00313    char timestamp[80];
00314    
00315    /* Extract the caller ID location */
00316    if (chan->cid.cid_num)
00317       ast_copy_string(workstring, chan->cid.cid_num, sizeof(workstring));
00318    workstring[sizeof(workstring) - 1] = '\0';
00319    
00320    ast_callerid_parse(workstring, &cn, &cl);
00321    if (cl) 
00322       ast_shrink_phone_number(cl);
00323                 
00324 
00325    /* Get the current time */
00326       
00327    time(&t);
00328    ast_localtime(&t, &now, NULL);
00329    
00330    /* Format the time */
00331    
00332    strftime(timestamp, sizeof(timestamp), time_stamp_format, &now); 
00333 
00334    
00335    res = fprintf(logfile, "\n\n[metadata]\n\n");
00336    
00337    if(res >= 0)
00338       res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
00339       
00340    if(res >= 0)   
00341       res = fprintf(logfile, "CALLINGFROM=%s\n", (!cl) ? "<unknown>" : cl);
00342       
00343    if(res >- 0)
00344       res = fprintf(logfile, "CALLERNAME=%s\n", (!cn) ? "<unknown>" : cn);
00345       
00346    if(res >= 0)
00347       res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
00348    
00349    if(res >= 0)
00350       res = fprintf(logfile, "[events]\n\n");
00351    
00352    if(res < 0){
00353       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't write metadata\n");  
00354       
00355       ast_log(LOG_DEBUG,"AlarmReceiver: can't write metadata\n");
00356    }
00357    else
00358       res = 0;
00359 
00360    return res;
00361 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Alarm Receiver for Asterisk" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 841 of file app_alarmreceiver.c.

char* app = "AlarmReceiver" [static]

Definition at line 71 of file app_alarmreceiver.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 841 of file app_alarmreceiver.c.

char db_family[128] = {'\0'} [static]

Definition at line 93 of file app_alarmreceiver.c.

char* descrip [static]

Definition at line 74 of file app_alarmreceiver.c.

char event_app[128] = {'\0'} [static]

Definition at line 92 of file app_alarmreceiver.c.

char event_file[14] = "/event-XXXXXX" [static]

Definition at line 98 of file app_alarmreceiver.c.

char event_spool_dir[128] = {'\0'} [static]

Definition at line 91 of file app_alarmreceiver.c.

int fdtimeout = 2000 [static]

Definition at line 87 of file app_alarmreceiver.c.

int log_individual_events = 0 [static]

Definition at line 90 of file app_alarmreceiver.c.

int sdtimeout = 200 [static]

Definition at line 88 of file app_alarmreceiver.c.

char* synopsis = "Provide support for receiving alarm reports from a burglar or fire alarm panel" [static]

Definition at line 73 of file app_alarmreceiver.c.

char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"} [static]

Definition at line 94 of file app_alarmreceiver.c.

int toneloudness = 4096 [static]

Definition at line 89 of file app_alarmreceiver.c.


Generated on Sat Aug 6 00:39:33 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7