Mon May 14 04:43:14 2007

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"

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)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Alarm Receiver for Asterisk")
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 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
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 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_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, 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 invocation 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 }

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Alarm Receiver for Asterisk"   
)

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, "%u", &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_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_log(), ast_strlen_zero(), ast_verbose(), event, 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_log(), ast_safe_sleep(), ast_strlen_zero(), ast_verbose(), database_increment(), event, 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_verbose(), ast_waitfor(), f, LOG_DEBUG, 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.

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_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

char* app = "AlarmReceiver" [static]

Definition at line 71 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 Mon May 14 04:43:15 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1