Wed Oct 28 15:47:58 2009

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 struct 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(), and receive_ademco_contact_id().

#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 641 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(), 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().

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

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, "%30u", &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\n");
00149    
00150    return;  
00151 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 853 of file app_alarmreceiver.c.

00854 {
00855    return tdesc;
00856 }

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

References ASTERISK_GPL_KEY.

00866 {
00867    return ASTERISK_GPL_KEY;
00868 }

static int load_config ( void   )  [static]

Definition at line 748 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.

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

int load_module ( void   ) 

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.
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.
TE STUFF END

Definition at line 847 of file app_alarmreceiver.c.

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

00848 {
00849    load_config();
00850    return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
00851 }

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

Definition at line 392 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(), and receive_ademco_contact_id().

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

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.

Referenced by send_tone_burst().

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

References ADEMCO_CONTACT_ID, ast_log(), ast_safe_sleep(), ast_strlen_zero(), ast_verbose(), event_node::data, database_increment(), LOG_DEBUG, log_events(), LOG_WARNING, malloc, event_node::next, option_verbose, receive_dtmf_digits(), send_tone_burst(), VERBOSE_PREFIX_1, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_4.

Referenced by alarmreceiver_exec().

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

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

Definition at line 247 of file app_alarmreceiver.c.

References AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_log(), ast_read(), ast_verbose(), ast_waitfor(), ast_frame::frametype, LOG_DEBUG, ast_channel::name, option_verbose, ast_frame::subclass, and VERBOSE_PREFIX_4.

Referenced by receive_ademco_contact_id().

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

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_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, ast_frame::frametype, LOG_WARNING, make_tone_burst(), ast_frame::mallocd, ast_channel::name, ast_frame::offset, option_verbose, ast_frame::samples, ast_frame::subclass, and VERBOSE_PREFIX_4.

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             ast_frfree(f);
00219             break;
00220          }
00221          if (ast_write(chan, &wf)){
00222             if(option_verbose >= 4)
00223                ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Failed to write frame on %s\n", chan->name);
00224             ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
00225             res = -1;
00226             ast_frfree(f);
00227             break;
00228          }
00229       }
00230       
00231       ast_frfree(f);
00232    }
00233    return res;
00234 }

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

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

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

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

References STANDARD_USECOUNT.

00859 {
00860    int res;
00861    STANDARD_USECOUNT(res);
00862    return res;
00863 }

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

Definition at line 376 of file app_alarmreceiver.c.

References event_node::data.

Referenced by log_events().

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

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

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

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


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.

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.

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 Wed Oct 28 15:47:58 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6