#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"

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_info * | ast_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 |
*** 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 ADEMCO_AUDIO_CALL_NEXT "606" |
| #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" |
| #define ADEMCO_MSG_TYPE_2 "98" |
| #define ALMRCV_CONFIG "alarmreceiver.conf" |
| typedef struct event_node event_node_t |
Definition at line 88 of file app_alarmreceiver.c.
| 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.
| event | Received DTMF String | |
| expected | Number of Digits expected |
| 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.
| chan | Asterisk Channel | |
| data | Application data |
| 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.
| key | A database key to increment |
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.
| 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.
| chan | Asterisk Channel | |
| signalling_type | Signaling Type | |
| event | Event Structure |
| 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.
| chan | Asterisk Channel | |
| fdto | First Digit Timeout | |
| sdto | Other Digits Timeout | |
| tldn | Tone loudness | |
| ehead | Pointer to events list |
| 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.
allow different timeout values for the first and all subsequent digits
| chan | Asterisk Channel | |
| digit_string | Digits String | |
| length | Length of the message we expect | |
| fdto | First Digit Timeout | |
| sdto | Other Digits Timeout |
| 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.
| 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 |
| 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.
| 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.
| logfile | Log File Pointer | |
| event | Event Structure |
| 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.
| logfile | Log File Pointer | |
| signalling_type | Signaling Type | |
| chan | Asterisk Channel |
| 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 }
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.
struct ast_module_info* ast_module_info = &__mod_info [static] |
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 |
Definition at line 77 of file app_alarmreceiver.c.
Referenced by __ast_pbx_run(), __ast_read(), action_playback_and_continue(), ademco_verify_checksum(), ast_dsp_process(), ast_translate_number_ka(), collect_digits(), compare(), controlplayback_exec(), dial_exec_full(), dictate_exec(), directory_exec(), handle_keypad_button_message(), handle_message(), manager_play_dtmf(), morsecode_exec(), phone_call(), phone_check_exception(), phone_exception(), and try_calling().
| 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] |
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 |
Definition at line 78 of file app_alarmreceiver.c.
Referenced by cache_lookup_internal(), dundi_lookup_thread(), dundi_show_cache(), dundi_show_mappings(), precache_trans(), and srv_result_read().
1.5.6