Asterisk.org: Developer Documentation (28 Oct 2009)

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.

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.