Thu Oct 11 06:34:05 2012

Asterisk developer's documentation


app_alarmreceiver.c File Reference

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

#include "asterisk.h"
#include <math.h>
#include <sys/wait.h>
#include <sys/time.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.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 "asterisk/indications.h"

Include dependency graph for app_alarmreceiver.c:

Go to the source code of this file.

Data Structures

struct  event_node

Defines

#define ADEMCO_AUDIO_CALL_NEXT   "606"
#define ADEMCO_CONTACT_ID   "ADEMCO_CONTACT_ID"
#define ADEMCO_MSG_TYPE_1   "18"
#define ADEMCO_MSG_TYPE_2   "98"
#define ALMRCV_CONFIG   "alarmreceiver.conf"

Typedefs

typedef struct event_node event_node_t

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int ademco_verify_checksum (char *event, int expected)
 Verify Ademco checksum.
static int alarmreceiver_exec (struct ast_channel *chan, const char *data)
 This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
static void database_increment (char *key)
 Attempt to access a database variable and increment it.
static int load_config (void)
 Load the configuration from the configuration file.
static int load_module (void)
 Load the module.
static int log_events (struct ast_channel *chan, char *signalling_type, event_node_t *event)
 Log events if configuration key logindividualevents is enabled.
static int receive_ademco_contact_id (struct ast_channel *chan, int fdto, int sdto, int tldn, event_node_t **ehead)
 Receive Ademco ContactID Data String.
static int receive_dtmf_digits (struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
 Receive a fixed length DTMF string.
static int send_tone_burst (struct ast_channel *chan, const char *tone_freq, int tone_duration, int tldn, int delay)
 Send a single tone burst for a specifed duration and frequency.
static int unload_module (void)
 Unregister Alarm Receiver App.
static int write_event (FILE *logfile, event_node_t *event)
 Log a single event.
static int write_metadata (FILE *logfile, char *signalling_type, struct ast_channel *chan)
 Write metadata to log file.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Alarm Receiver for Asterisk" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static const char app [] = "AlarmReceiver"
static struct ast_module_infoast_module_info = &__mod_info
static char db_family [128] = {'\0'}
struct {
   char   digit
   char   weight
digits_mapping []
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 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_AUDIO_CALL_NEXT   "606"

Definition at line 74 of file app_alarmreceiver.c.

Referenced by receive_ademco_contact_id().

#define ADEMCO_CONTACT_ID   "ADEMCO_CONTACT_ID"

Definition at line 71 of file app_alarmreceiver.c.

Referenced by alarmreceiver_exec(), and receive_ademco_contact_id().

#define ADEMCO_MSG_TYPE_1   "18"

Definition at line 72 of file app_alarmreceiver.c.

Referenced by receive_ademco_contact_id().

#define ADEMCO_MSG_TYPE_2   "98"

Definition at line 73 of file app_alarmreceiver.c.

Referenced by receive_ademco_contact_id().

#define ALMRCV_CONFIG   "alarmreceiver.conf"

Definition at line 70 of file app_alarmreceiver.c.

Referenced by load_config().


Typedef Documentation

typedef struct event_node event_node_t

Definition at line 88 of file app_alarmreceiver.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 759 of file app_alarmreceiver.c.

static void __unreg_module ( void   )  [static]

Definition at line 759 of file app_alarmreceiver.c.

static int ademco_verify_checksum ( char *  event,
int  expected 
) [static]

Verify Ademco checksum.

Since:
11.0
Parameters:
event Received DTMF String
expected Number of Digits expected
Return values:
0 success
-1 failure

Definition at line 374 of file app_alarmreceiver.c.

References ARRAY_LEN, ast_verb, digit, and digits_mapping.

Referenced by receive_ademco_contact_id().

00375 {
00376    int checksum = 0;
00377    int i, j;
00378 
00379    for (j = 0; j < expected; j++) {
00380       for (i = 0; i < ARRAY_LEN(digits_mapping); i++) {
00381          if (digits_mapping[i].digit == event[j]) {
00382             break;
00383          }
00384       }
00385 
00386       if (i >= ARRAY_LEN(digits_mapping)) {
00387          ast_verb(2, "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
00388          return -1;
00389       }
00390 
00391       checksum += digits_mapping[i].weight;
00392    }
00393 
00394    /* Checksum is mod(15) of the total */
00395    if (!(checksum % 15)) {
00396       return 0;
00397    }
00398 
00399    return -1;
00400 }

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

This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.

Parameters:
chan Asterisk Channel
data Application data
Return values:
0 success
-1 failure

Definition at line 582 of file app_alarmreceiver.c.

References ADEMCO_CONTACT_ID, ast_answer(), ast_channel_name(), ast_copy_string(), ast_debug, AST_FORMAT_ULAW, ast_free, ast_log(), ast_safe_sleep(), ast_safe_system(), ast_set_read_format_by_id(), ast_set_write_format_by_id(), AST_STATE_UP, ast_strlen_zero(), ast_verb, log_events(), LOG_WARNING, event_node::next, and receive_ademco_contact_id().

Referenced by load_module().

00583 {
00584    int res = 0;
00585    event_node_t *elp, *efree;
00586    char signalling_type[64] = "";
00587    event_node_t *event_head = NULL;
00588 
00589    /* Set write and read formats to ULAW */
00590    ast_verb(4, "AlarmReceiver: Setting read and write formats to ULAW\n");
00591 
00592    if (ast_set_write_format_by_id(chan,AST_FORMAT_ULAW)) {
00593       ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",ast_channel_name(chan));
00594       return -1;
00595    }
00596 
00597    if (ast_set_read_format_by_id(chan,AST_FORMAT_ULAW)) {
00598       ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",ast_channel_name(chan));
00599       return -1;
00600    }
00601 
00602    /* Set default values for this invocation of the application */
00603    ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type));
00604 
00605    /* Answer the channel if it is not already */
00606    ast_verb(4, "AlarmReceiver: Answering channel\n");
00607    if (ast_channel_state(chan) != AST_STATE_UP) {
00608       if ((res = ast_answer(chan))) {
00609          return -1;
00610       }
00611    }
00612 
00613    /* Wait for the connection to settle post-answer */
00614    ast_verb(4, "AlarmReceiver: Waiting for connection to stabilize\n");
00615    res = ast_safe_sleep(chan, 1250);
00616 
00617    /* Attempt to receive the events */
00618    if (!res) {
00619       /* Determine the protocol to receive in advance */
00620       /* Note: Ademco contact is the only one supported at this time */
00621       /* Others may be added later */
00622       if (!strcmp(signalling_type, ADEMCO_CONTACT_ID)) {
00623          receive_ademco_contact_id(chan, fdtimeout, sdtimeout, toneloudness, &event_head);
00624       } else {
00625          res = -1;
00626       }
00627    }
00628 
00629    /* Events queued by receiver, write them all out here if so configured */
00630    if ((!res) && (log_individual_events == 0)) {
00631       res = log_events(chan, signalling_type, event_head);
00632    }
00633 
00634    /* Do we exec a command line at the end? */
00635    if ((!res) && (!ast_strlen_zero(event_app)) && (event_head)) {
00636       ast_debug(1,"Alarmreceiver: executing: %s\n", event_app);
00637       ast_safe_system(event_app);
00638    }
00639 
00640    /* Free up the data allocated in our linked list */
00641    for (elp = event_head; (elp != NULL);) {
00642       efree = elp;
00643       elp = elp->next;
00644       ast_free(efree);
00645    }
00646 
00647    return 0;
00648 }

static void database_increment ( char *  key  )  [static]

Attempt to access a database variable and increment it.

Note:
Only if the user defined db-family in alarmreceiver.conf
The alarmreceiver app will write statistics to a few variables in this family if it is defined. If the new key doesn't exist in the family, then create it and set its value to 1.

Parameters:
key A database key to increment
Returns:
Nothing

Definition at line 138 of file app_alarmreceiver.c.

References ast_db_get(), ast_db_put(), ast_strlen_zero(), ast_verb, and value.

Referenced by receive_ademco_contact_id().

00139 {
00140    unsigned v;
00141    char value[16];
00142 
00143    if (ast_strlen_zero(db_family)) {
00144       return;  /* If not defined, don't do anything */
00145    }
00146 
00147    if (ast_db_get(db_family, key, value, sizeof(value) - 1)) {
00148       ast_verb(4, "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
00149       /* Guess we have to create it */
00150       ast_db_put(db_family, key, "1");
00151       return;
00152    }
00153 
00154    sscanf(value, "%30u", &v);
00155    v++;
00156 
00157    ast_verb(4, "AlarmReceiver: New value for %s: %u\n", key, v);
00158    snprintf(value, sizeof(value), "%u", v);
00159 
00160    if (ast_db_put(db_family, key, value)) {
00161       ast_verb(4, "AlarmReceiver: database_increment write error\n");
00162    }
00163 
00164    return;
00165 }

static int load_config ( void   )  [static]

Load the configuration from the configuration file.

Return values:
1 success
0 failure

Definition at line 656 of file app_alarmreceiver.c.

References ALMRCV_CONFIG, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_STATUS_FILEINVALID, LOG_ERROR, and value.

Referenced by __reload(), ast_features_init(), ast_features_reload(), handle_voicemail_reload(), load_module(), reload(), and reload_module().

00657 {
00658    struct ast_config *cfg;
00659    const char *value;
00660    struct ast_flags config_flags = { 0 };
00661 
00662    /* Read in the config file */
00663    cfg = ast_config_load(ALMRCV_CONFIG, config_flags);
00664 
00665    if (!cfg) {
00666       ast_verb(4, "AlarmReceiver: No config file\n");
00667       return 0;
00668    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
00669       ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n",
00670          ALMRCV_CONFIG);
00671       return 0;
00672    }
00673 
00674    if ((value = ast_variable_retrieve(cfg, "general", "eventcmd")) != NULL) {
00675       ast_copy_string(event_app, value, sizeof(event_app));
00676    }
00677 
00678    if ((value = ast_variable_retrieve(cfg, "general", "loudness")) != NULL) {
00679       toneloudness = atoi(value);
00680       if (toneloudness < 100) {
00681          toneloudness = 100;
00682       } else if (toneloudness > 8192) {
00683          toneloudness = 8192;
00684       }
00685    }
00686 
00687    if ((value = ast_variable_retrieve(cfg, "general", "fdtimeout")) != NULL) {
00688       fdtimeout = atoi(value);
00689       if (fdtimeout < 1000) {
00690          fdtimeout = 1000;
00691       } else if (fdtimeout > 10000) {
00692          fdtimeout = 10000;
00693       }
00694    }
00695 
00696    if ((value = ast_variable_retrieve(cfg, "general", "sdtimeout")) != NULL) {
00697       sdtimeout = atoi(value);
00698       if (sdtimeout < 110) {
00699          sdtimeout = 110;
00700       } else if (sdtimeout > 4000) {
00701          sdtimeout = 4000;
00702       }
00703    }
00704 
00705    if ((value = ast_variable_retrieve(cfg, "general", "logindividualevents")) != NULL) {
00706       log_individual_events = ast_true(value);
00707    }
00708 
00709    if ((value = ast_variable_retrieve(cfg, "general", "eventspooldir")) != NULL) {
00710       ast_copy_string(event_spool_dir, value, sizeof(event_spool_dir));
00711    }
00712 
00713    if ((value = ast_variable_retrieve(cfg, "general", "timestampformat")) != NULL) {
00714       ast_copy_string(time_stamp_format, value, sizeof(time_stamp_format));
00715    }
00716 
00717    if ((value = ast_variable_retrieve(cfg, "general", "db-family")) != NULL) {
00718       ast_copy_string(db_family, value, sizeof(db_family));
00719    }
00720 
00721    ast_config_destroy(cfg);
00722 
00723    return 1;
00724 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 747 of file app_alarmreceiver.c.

References alarmreceiver_exec(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, and load_config().

00748 {
00749    if (load_config()) {
00750       if (ast_register_application_xml(app, alarmreceiver_exec)) {
00751          return AST_MODULE_LOAD_FAILURE;
00752       }
00753       return AST_MODULE_LOAD_SUCCESS;
00754    } else {
00755       return AST_MODULE_LOAD_DECLINE;
00756    }
00757 }

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

Log events if configuration key logindividualevents is enabled.

Parameters:
chan Asterisk Channel
signalling_type Signaling Type
event Event Structure
Return values:
0 success
-1 failure

Definition at line 320 of file app_alarmreceiver.c.

References ast_copy_string(), ast_debug, ast_strlen_zero(), ast_verb, event_node::next, write_event(), and write_metadata().

Referenced by alarmreceiver_exec(), and receive_ademco_contact_id().

00321 {
00322    char workstring[sizeof(event_spool_dir) + sizeof(event_file)] = "";
00323    int fd;
00324    FILE *logfile;
00325    event_node_t *elp = event;
00326 
00327    if (!ast_strlen_zero(event_spool_dir)) {
00328 
00329       /* Make a template */
00330       ast_copy_string(workstring, event_spool_dir, sizeof(workstring));
00331       strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
00332 
00333       /* Make the temporary file */
00334       fd = mkstemp(workstring);
00335 
00336       if (fd == -1) {
00337          ast_verb(3, "AlarmReceiver: can't make temporary file\n");
00338          ast_debug(1, "AlarmReceiver: can't make temporary file\n");
00339          return -1;
00340       }
00341 
00342       if ((logfile = fdopen(fd, "w")) == NULL) {
00343          return -1;
00344       }
00345 
00346       /* Write the file */
00347       if (write_metadata(logfile, signalling_type, chan) != 0) {
00348          fflush(logfile);
00349          fclose(logfile);
00350          return -1;
00351       }
00352 
00353       while ((write_event(logfile, elp) > 0) && (elp != NULL)) {
00354          elp = elp->next;
00355       }
00356 
00357       fflush(logfile);
00358       fclose(logfile);
00359    }
00360 
00361    return 0;
00362 }

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

Receive Ademco ContactID Data String.

Parameters:
chan Asterisk Channel
fdto First Digit Timeout
sdto Other Digits Timeout
tldn Tone loudness
ehead Pointer to events list
Return values:
0 success
-1 failure

Definition at line 445 of file app_alarmreceiver.c.

References ADEMCO_AUDIO_CALL_NEXT, ADEMCO_CONTACT_ID, ADEMCO_MSG_TYPE_1, ADEMCO_MSG_TYPE_2, ademco_verify_checksum(), ast_calloc, ast_copy_string(), ast_debug, ast_strlen_zero(), ast_verb, event_node::data, database_increment(), log_events(), event_node::next, receive_dtmf_digits(), and send_tone_burst().

Referenced by alarmreceiver_exec().

00446 {
00447    int res = 0;
00448    int exit_on_next = 0;
00449    char event[17];
00450    event_node_t *enew, *elp;
00451    int got_some_digits = 0;
00452    int events_received = 0;
00453    int ack_retries = 0;
00454 
00455    database_increment("calls-received");
00456 
00457    /* Wait for first event */
00458    ast_verb(4, "AlarmReceiver: Waiting for first event from panel...\n");
00459 
00460    while (res >= 0) {
00461       res = 0;
00462       if (got_some_digits == 0) {
00463          /* Send ACK tone sequence */
00464          ast_verb(4, "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
00465          res = send_tone_burst(chan, "1400", 100, tldn, 0);
00466          if (!res) {
00467             ast_verb(4, "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
00468             res = send_tone_burst(chan, "2300", 100, tldn, 0);
00469          }
00470       }
00471       if (res) {
00472          return -1;
00473       }
00474 
00475       if (exit_on_next) {
00476          res = send_tone_burst(chan, "1400", 900, tldn, 200);
00477          return 0;
00478       }
00479 
00480       res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
00481       if (res < 0) {
00482          if (events_received == 0) {
00483             /* Hangup with no events received should be logged in the DB */
00484             database_increment("no-events-received");
00485          } else {
00486             if (ack_retries) {
00487                ast_verb(4, "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
00488                database_increment("ack-retries");
00489             }
00490          }
00491          ast_verb(4, "AlarmReceiver: App exiting...\n");
00492          break;
00493       }
00494 
00495       if (res) {
00496          /* Didn't get all of the digits */
00497          ast_verb(2, "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
00498 
00499          if (!got_some_digits) {
00500             got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
00501             ack_retries++;
00502          }
00503          continue;
00504       }
00505 
00506       got_some_digits = 1;
00507 
00508       ast_verb(2, "AlarmReceiver: Received Event %s\n", event);
00509       ast_debug(1, "AlarmReceiver: Received event: %s\n", event);
00510 
00511       /* Calculate checksum */
00512       if (ademco_verify_checksum(event, 16)) {
00513          database_increment("checksum-errors");
00514          ast_verb(2, "AlarmReceiver: Nonzero checksum\n");
00515          ast_debug(1, "AlarmReceiver: Nonzero checksum\n");
00516          continue;
00517       }
00518 
00519       /* Check the message type for correctness */
00520       if (strncmp(event + 4, ADEMCO_MSG_TYPE_1, 2)) {
00521          if (strncmp(event + 4, ADEMCO_MSG_TYPE_2, 2)) {
00522             database_increment("format-errors");
00523             ast_verb(2, "AlarmReceiver: Wrong message type\n");
00524             ast_debug(1, "AlarmReceiver: Wrong message type\n");
00525          continue;
00526          }
00527       }
00528 
00529       events_received++;
00530 
00531       /* Queue the Event */
00532       if (!(enew = ast_calloc(1, sizeof(*enew)))) {
00533          return -1;
00534       }
00535 
00536       enew->next = NULL;
00537       ast_copy_string(enew->data, event, sizeof(enew->data));
00538 
00539       /* Insert event onto end of list */
00540       if (*ehead == NULL) {
00541          *ehead = enew;
00542       } else {
00543          for (elp = *ehead; elp->next != NULL; elp = elp->next) {
00544             ;
00545          }
00546          elp->next = enew;
00547       }
00548 
00549       /* Audio call follows, exit alarm receiver app */
00550       if (!strncmp(event + 7, ADEMCO_AUDIO_CALL_NEXT, 3)) {
00551          ast_verb(4, "AlarmReceiver: App exiting... Audio call next!\n");
00552          exit_on_next = 1;
00553       }
00554 
00555       /* Let the user have the option of logging the single event before sending the kissoff tone */
00556       if (log_individual_events) {
00557          res = log_events(chan, ADEMCO_CONTACT_ID, enew);
00558          if (res) {
00559             return -1;
00560          }
00561       }
00562 
00563       /* Send the kissoff tone (1400 Hz, 900 ms, after 200ms delay) */
00564       res = send_tone_burst(chan, "1400", 900, tldn, 200);
00565       if (res) {
00566          return -1;
00567       }
00568    }
00569 
00570    return res;
00571 }

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

Receive a fixed length DTMF string.

Note:
Doesn't give preferential treatment to any digit,

allow different timeout values for the first and all subsequent digits

Parameters:
chan Asterisk Channel
digit_string Digits String
length Length of the message we expect
fdto First Digit Timeout
sdto Other Digits Timeout
Return values:
0 if all digits were successfully received
1 if a timeout occurred
-1 if the caller hung up or on channel errors

Definition at line 183 of file app_alarmreceiver.c.

References ast_channel_hangupcause_set(), ast_channel_name(), AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_read(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, ast_waitfor(), ast_frame::data, f, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::subclass, and ast_frame::uint32.

Referenced by receive_ademco_contact_id().

00184 {
00185    int rtn = 0;
00186    int i = 0;
00187    int r;
00188    struct ast_frame *f;
00189    struct timeval lastdigittime;
00190 
00191    lastdigittime = ast_tvnow();
00192    while (i < length && i < sizeof(digit_string) - 1) {
00193       /* If timed out, leave */
00194       if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((i > 0) ? sdto : fdto)) {
00195          ast_verb(4, "AlarmReceiver: DTMF Digit Timeout on %s\n", ast_channel_name(chan));
00196          ast_debug(1, "AlarmReceiver: DTMF timeout on chan %s\n", ast_channel_name(chan));
00197          rtn = 1;
00198          break;
00199       }
00200 
00201       if ((r = ast_waitfor(chan, -1)) < 0) {
00202          ast_debug(1, "Waitfor returned %d\n", r);
00203          continue;
00204       }
00205 
00206       if ((f = ast_read(chan)) == NULL) {
00207          rtn = -1;
00208          break;
00209       }
00210 
00211       /* If they hung up, leave */
00212       if ((f->frametype == AST_FRAME_CONTROL)
00213          && (f->subclass.integer == AST_CONTROL_HANGUP)) {
00214          if (f->data.uint32) {
00215             ast_channel_hangupcause_set(chan, f->data.uint32);
00216          }
00217          ast_frfree(f);
00218          rtn = -1;
00219          break;
00220       }
00221 
00222       /* If not DTMF, just do it again */
00223       if (f->frametype != AST_FRAME_DTMF) {
00224          ast_frfree(f);
00225          continue;
00226       }
00227 
00228       /* Save digit */
00229       digit_string[i++] = f->subclass.integer;
00230       ast_frfree(f);
00231 
00232       lastdigittime = ast_tvnow();
00233    }
00234 
00235    /* Null terminate the end of the digit string */
00236    digit_string[i] = '\0';
00237    return rtn;
00238 }

static int send_tone_burst ( struct ast_channel chan,
const char *  tone_freq,
int  tone_duration,
int  tldn,
int  delay 
) [static]

Send a single tone burst for a specifed duration and frequency.

Since:
11.0
Parameters:
chan Asterisk Channel
tone_freq Frequency of the tone to send
tone_duration Tone duration in ms
tldn Tone loudness
delay Delay before sending the tone
Return values:
0 success
-1 failure

Definition at line 415 of file app_alarmreceiver.c.

References ast_playtones_start(), ast_playtones_stop(), and ast_safe_sleep().

Referenced by receive_ademco_contact_id().

00416 {
00417    if (delay && ast_safe_sleep(chan, delay)) {
00418       return -1;
00419    }
00420 
00421    if (ast_playtones_start(chan, tldn, tone_freq, 0)) {
00422       return -1;
00423    }
00424 
00425    if (ast_safe_sleep(chan, tone_duration)) {
00426       return -1;
00427    }
00428 
00429    ast_playtones_stop(chan);
00430    return 0;
00431 }

static int unload_module ( void   )  [static]

Unregister Alarm Receiver App.

Return values:
0 success
-1 failure

Definition at line 732 of file app_alarmreceiver.c.

References ast_unregister_application().

00733 {
00734    return ast_unregister_application(app);
00735 }

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

Log a single event.

Parameters:
logfile Log File Pointer
event Event Structure
Return values:
0 success
-1 failure

Definition at line 302 of file app_alarmreceiver.c.

References event_node::data.

Referenced by log_events().

00303 {
00304    if (fprintf(logfile, "%s\n", event->data) < 0) {
00305       return -1;
00306    }
00307    return 0;
00308 }

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

Write metadata to log file.

Parameters:
logfile Log File Pointer
signalling_type Signaling Type
chan Asterisk Channel
Return values:
0 success
-1 failure

Definition at line 250 of file app_alarmreceiver.c.

References ast_channel_caller(), ast_copy_string(), ast_debug, ast_localtime(), ast_shrink_phone_number(), ast_strftime(), ast_strlen_zero(), ast_tvnow(), ast_verb, name, and S_COR.

Referenced by log_events().

00251 {
00252    struct timeval t;
00253    struct ast_tm now;
00254    char *cl;
00255    char *cn;
00256    char workstring[80];
00257    char timestamp[80];
00258 
00259    /* Extract the caller ID location */
00260    ast_copy_string(workstring,
00261       S_COR(ast_channel_caller(chan)->id.number.valid,
00262       ast_channel_caller(chan)->id.number.str, ""), sizeof(workstring));
00263    ast_shrink_phone_number(workstring);
00264    if (ast_strlen_zero(workstring)) {
00265       cl = "<unknown>";
00266    } else {
00267       cl = workstring;
00268    }
00269    cn = S_COR(ast_channel_caller(chan)->id.name.valid,
00270       ast_channel_caller(chan)->id.name.str, "<unknown>");
00271 
00272    /* Get the current time */
00273    t = ast_tvnow();
00274    ast_localtime(&t, &now, NULL);
00275 
00276    /* Format the time */
00277    ast_strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
00278 
00279    if (fprintf(logfile, "\n\n[metadata]\n\n"
00280          "PROTOCOL=%s\n"
00281          "CALLINGFROM=%s\n"
00282          "CALLERNAME=%s\n"
00283          "TIMESTAMP=%s\n\n"
00284          "[events]\n\n", signalling_type, cl, cn, timestamp) < 0) {
00285       ast_verb(3, "AlarmReceiver: can't write metadata\n");
00286       ast_debug(1, "AlarmReceiver: can't write metadata\n");
00287       return -1;
00288    }
00289 
00290    return 0;
00291 }


Variable Documentation

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

Definition at line 759 of file app_alarmreceiver.c.

const char app[] = "AlarmReceiver" [static]

Definition at line 90 of file app_alarmreceiver.c.

Definition at line 759 of file app_alarmreceiver.c.

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

Definition at line 120 of file app_alarmreceiver.c.

char digit

struct { ... } digits_mapping[]

Referenced by ademco_verify_checksum().

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

Definition at line 119 of file app_alarmreceiver.c.

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

Definition at line 124 of file app_alarmreceiver.c.

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

Definition at line 118 of file app_alarmreceiver.c.

int fdtimeout = 2000 [static]

Definition at line 114 of file app_alarmreceiver.c.

Referenced by acf_faxopt_write().

int log_individual_events = 0 [static]

Definition at line 117 of file app_alarmreceiver.c.

int sdtimeout = 200 [static]

Definition at line 115 of file app_alarmreceiver.c.

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

Definition at line 121 of file app_alarmreceiver.c.

int toneloudness = 4096 [static]

Definition at line 116 of file app_alarmreceiver.c.

char weight


Generated on Thu Oct 11 06:34:06 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6