Sat Mar 24 23:26:11 2007

Asterisk developer's documentation


app_alarmreceiver.c File Reference

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

#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.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 dependency graph for app_alarmreceiver.c:

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 int alarmreceiver_exec (struct ast_channel *chan, void *data)
static void database_increment (char *key)
char * description (void)
 Provides a description of the module.
char * key ()
 Returns the ASTERISK_GPL_KEY.
static int load_config (void)
int load_module (void)
 Initialize the module.
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)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.
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 char * app = "AlarmReceiver"
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
 LOCAL_USER_DECL
static int log_individual_events = 0
static int sdtimeout = 200
 STANDARD_LOCAL_USER
static char * synopsis = "Provide support for receving alarm reports from a burglar or fire alarm panel"
static char * tdesc = "Alarm Receiver for Asterisk"
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 details. *

*** 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 61 of file app_alarmreceiver.c.

Referenced by alarmreceiver_exec().

#define ALMRCV_CONFIG   "alarmreceiver.conf"
 

Definition at line 60 of file app_alarmreceiver.c.

Referenced by load_config().


Typedef Documentation

typedef struct event_node event_node_t
 

Definition at line 68 of file app_alarmreceiver.c.


Function Documentation

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

Definition at line 639 of file app_alarmreceiver.c.

References ast_channel::_state, ADEMCO_CONTACT_ID, ast_answer(), AST_FORMAT_ULAW, ast_log(), ast_safe_sleep(), ast_safe_system(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_strlen_zero(), ast_verbose(), localuser::chan, free, LOCAL_USER_ADD, LOCAL_USER_REMOVE, 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().

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

static void database_increment char *  key  )  [static]
 

Definition at line 117 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().

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

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 851 of file app_alarmreceiver.c.

00852 {
00853    return tdesc;
00854 }

char* key void   ) 
 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 863 of file app_alarmreceiver.c.

References ASTERISK_GPL_KEY.

00864 {
00865    return ASTERISK_GPL_KEY;
00866 }

static int load_config void   )  [static]
 

Definition at line 746 of file app_alarmreceiver.c.

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

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

int load_module void   ) 
 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 845 of file app_alarmreceiver.c.

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

00846 {
00847    load_config();
00848    return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
00849 }

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

Definition at line 390 of file app_alarmreceiver.c.

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

Referenced by alarmreceiver_exec().

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

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

Definition at line 158 of file app_alarmreceiver.c.

References AST_LIN2MU.

00159 {
00160    int     i;
00161    float   val;
00162                                                                                                                                     
00163         for(i = 0; i < len; i++){
00164       val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
00165       data[i] = AST_LIN2MU((int)val);
00166    }
00167 
00168    /* wrap back around from 8000 */
00169 
00170    if (*x >= 8000) *x = 0;
00171    return;
00172 }

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 449 of file app_alarmreceiver.c.

References ast_log(), ast_safe_sleep(), ast_strlen_zero(), ast_verbose(), database_increment(), LOG_DEBUG, option_verbose, receive_dtmf_digits(), send_tone_burst(), VERBOSE_PREFIX_2, and VERBOSE_PREFIX_4.

Referenced by alarmreceiver_exec().

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

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

Definition at line 245 of file app_alarmreceiver.c.

References ast_log(), ast_verbose(), LOG_DEBUG, ast_channel::name, option_verbose, and VERBOSE_PREFIX_4.

Referenced by receive_ademco_contact_id().

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

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

Definition at line 179 of file app_alarmreceiver.c.

References AST_FRIENDLY_OFFSET, ast_waitfor(), and ast_frame::offset.

Referenced by receive_ademco_contact_id().

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

int unload_module void   ) 
 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 834 of file app_alarmreceiver.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00835 {
00836    int res;
00837 
00838    res = ast_unregister_application(app);
00839 
00840    STANDARD_HANGUP_LOCALUSERS;
00841 
00842    return res;
00843 }

int usecount void   ) 
 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 856 of file app_alarmreceiver.c.

References STANDARD_USECOUNT.

00857 {
00858    int res;
00859    STANDARD_USECOUNT(res);
00860    return res;
00861 }

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

Definition at line 374 of file app_alarmreceiver.c.

References event_node::data.

Referenced by log_events().

00375 {
00376    int res = 0;
00377 
00378    if( fprintf(logfile, "%s\n", event->data) < 0)
00379       res = -1;
00380          
00381    return res;
00382 }

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

Definition at line 313 of file app_alarmreceiver.c.

References ast_callerid_parse(), 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().

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


Variable Documentation

char* app = "AlarmReceiver" [static]
 

Definition at line 72 of file app_alarmreceiver.c.

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

Definition at line 94 of file app_alarmreceiver.c.

char* descrip [static]
 

Definition at line 75 of file app_alarmreceiver.c.

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

Definition at line 93 of file app_alarmreceiver.c.

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

Definition at line 101 of file app_alarmreceiver.c.

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

Definition at line 92 of file app_alarmreceiver.c.

int fdtimeout = 2000 [static]
 

Definition at line 88 of file app_alarmreceiver.c.

LOCAL_USER_DECL
 

Definition at line 107 of file app_alarmreceiver.c.

int log_individual_events = 0 [static]
 

Definition at line 91 of file app_alarmreceiver.c.

int sdtimeout = 200 [static]
 

Definition at line 89 of file app_alarmreceiver.c.

STANDARD_LOCAL_USER
 

Definition at line 105 of file app_alarmreceiver.c.

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

Definition at line 74 of file app_alarmreceiver.c.

char* tdesc = "Alarm Receiver for Asterisk" [static]
 

Definition at line 70 of file app_alarmreceiver.c.

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

Definition at line 95 of file app_alarmreceiver.c.

int toneloudness = 4096 [static]
 

Definition at line 90 of file app_alarmreceiver.c.


Generated on Sat Mar 24 23:26:11 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.6