Wed Jan 8 2020 09:49:52

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/ulaw.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"

Go to the source code of this file.

Data Structures

struct  event_node
 

Macros

#define ADEMCO_CONTACT_ID   "ADEMCO_CONTACT_ID"
 
#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 alarmreceiver_exec (struct ast_channel *chan, const char *data)
 
static void database_increment (char *key)
 
static int load_config (void)
 
static int load_module (void)
 
static int log_events (struct ast_channel *chan, char *signalling_type, event_node_t *event)
 
static void make_tone_burst (unsigned char *data, float freq, float loudness, int len, int *x)
 
static int receive_ademco_contact_id (struct ast_channel *chan, const void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
 
static int receive_dtmf_digits (struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
 
static int send_tone_burst (struct ast_channel *chan, float freq, int duration, int tldn)
 
static int unload_module (void)
 
static int write_event (FILE *logfile, event_node_t *event)
 
static int write_metadata (FILE *logfile, char *signalling_type, struct ast_channel *chan)
 

Variables

static 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 = "ac1f6a56484a8820659555499174e588" , .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'}
 
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 hwsta.nosp@m.r@ro.nosp@m.dgers.nosp@m..sdc.nosp@m.oxmai.nosp@m.l.co.nosp@m.m

*** 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.

Macro Definition Documentation

#define ADEMCO_CONTACT_ID   "ADEMCO_CONTACT_ID"

Definition at line 60 of file app_alarmreceiver.c.

Referenced by alarmreceiver_exec(), and receive_ademco_contact_id().

#define ALMRCV_CONFIG   "alarmreceiver.conf"

Definition at line 59 of file app_alarmreceiver.c.

Referenced by load_config().

Typedef Documentation

typedef struct event_node event_node_t

Definition at line 67 of file app_alarmreceiver.c.

Function Documentation

static void __reg_module ( void  )
static

Definition at line 738 of file app_alarmreceiver.c.

static void __unreg_module ( void  )
static

Definition at line 738 of file app_alarmreceiver.c.

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

Definition at line 575 of file app_alarmreceiver.c.

References ast_channel::_state, ADEMCO_CONTACT_ID, ast_answer(), ast_copy_string(), ast_debug, AST_FORMAT_ULAW, ast_free, ast_log(), ast_safe_sleep(), ast_safe_system(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_strlen_zero(), ast_verb, log_events(), LOG_WARNING, ast_channel::name, event_node::next, and receive_ademco_contact_id().

Referenced by load_module().

576 {
577  int res = 0;
578  event_node_t *elp, *efree;
579  char signalling_type[64] = "";
580  event_node_t *event_head = NULL;
581 
582  /* Set write and read formats to ULAW */
583  ast_verb(4, "AlarmReceiver: Setting read and write formats to ULAW\n");
584 
586  ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
587  return -1;
588  }
589 
591  ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
592  return -1;
593  }
594 
595  /* Set default values for this invocation of the application */
596  ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type));
597 
598  /* Answer the channel if it is not already */
599  ast_verb(4, "AlarmReceiver: Answering channel\n");
600  if (chan->_state != AST_STATE_UP) {
601  if ((res = ast_answer(chan)))
602  return -1;
603  }
604 
605  /* Wait for the connection to settle post-answer */
606  ast_verb(4, "AlarmReceiver: Waiting for connection to stabilize\n");
607  res = ast_safe_sleep(chan, 1250);
608 
609  /* Attempt to receive the events */
610  if (!res) {
611  /* Determine the protocol to receive in advance */
612  /* Note: Ademco contact is the only one supported at this time */
613  /* Others may be added later */
614  if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
616  else
617  res = -1;
618  }
619 
620  /* Events queued by receiver, write them all out here if so configured */
621  if ((!res) && (log_individual_events == 0))
622  res = log_events(chan, signalling_type, event_head);
623 
624  /*
625  * Do we exec a command line at the end?
626  */
627  if ((!res) && (!ast_strlen_zero(event_app)) && (event_head)) {
628  ast_debug(1,"Alarmreceiver: executing: %s\n", event_app);
630  }
631 
632  /*
633  * Free up the data allocated in our linked list
634  */
635  for (elp = event_head; (elp != NULL);) {
636  efree = elp;
637  elp = elp->next;
638  ast_free(efree);
639  }
640 
641  return 0;
642 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1077
static int fdtimeout
#define LOG_WARNING
Definition: logger.h:144
static int toneloudness
#define ast_verb(level,...)
Definition: logger.h:243
static int receive_ademco_contact_id(struct ast_channel *chan, const void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct event_node * next
static char event_app[128]
char data[2048]
Definition: app_adsiprog.c:141
#define AST_FORMAT_ULAW
Definition: frame.h:246
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
static int log_individual_events
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define ADEMCO_CONTACT_ID
static int sdtimeout
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event)
static void database_increment ( char *  key)
static

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

113 {
114  int res = 0;
115  unsigned v;
116  char value[16];
117 
118 
120  return; /* If not defined, don't do anything */
121 
122  res = ast_db_get(db_family, key, value, sizeof(value) - 1);
123 
124  if (res) {
125  ast_verb(4, "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
126  /* Guess we have to create it */
127  res = ast_db_put(db_family, key, "1");
128  return;
129  }
130 
131  sscanf(value, "%30u", &v);
132  v++;
133 
134  ast_verb(4, "AlarmReceiver: New value for %s: %u\n", key, v);
135 
136  snprintf(value, sizeof(value), "%u", v);
137 
138  res = ast_db_put(db_family, key, value);
139 
140  if (res)
141  ast_verb(4, "AlarmReceiver: database_increment write error\n");
142 
143  return;
144 }
int ast_db_get(const char *family, const char *key, char *out, int outlen)
Get key value specified by family/key.
Definition: db.c:348
int value
Definition: syslog.c:39
#define ast_verb(level,...)
Definition: logger.h:243
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:260
static char db_family[128]
static int load_config ( void  )
static

Definition at line 647 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, db_family, event_app, event_spool_dir, LOG_ERROR, and time_stamp_format.

Referenced by load_module().

648 {
649  struct ast_config *cfg;
650  const char *p;
651  struct ast_flags config_flags = { 0 };
652 
653  /* Read in the config file */
654  cfg = ast_config_load(ALMRCV_CONFIG, config_flags);
655 
656  if (!cfg) {
657  ast_verb(4, "AlarmReceiver: No config file\n");
658  return 0;
659  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
660  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", ALMRCV_CONFIG);
661  return 0;
662  } else {
663  p = ast_variable_retrieve(cfg, "general", "eventcmd");
664  if (p) {
665  ast_copy_string(event_app, p, sizeof(event_app));
666  event_app[sizeof(event_app) - 1] = '\0';
667  }
668  p = ast_variable_retrieve(cfg, "general", "loudness");
669  if (p) {
670  toneloudness = atoi(p);
671  if(toneloudness < 100)
672  toneloudness = 100;
673  if(toneloudness > 8192)
674  toneloudness = 8192;
675  }
676  p = ast_variable_retrieve(cfg, "general", "fdtimeout");
677  if (p) {
678  fdtimeout = atoi(p);
679  if(fdtimeout < 1000)
680  fdtimeout = 1000;
681  if(fdtimeout > 10000)
682  fdtimeout = 10000;
683  }
684 
685  p = ast_variable_retrieve(cfg, "general", "sdtimeout");
686  if (p) {
687  sdtimeout = atoi(p);
688  if(sdtimeout < 110)
689  sdtimeout = 110;
690  if(sdtimeout > 4000)
691  sdtimeout = 4000;
692  }
693 
694  p = ast_variable_retrieve(cfg, "general", "logindividualevents");
695  if (p)
697 
698  p = ast_variable_retrieve(cfg, "general", "eventspooldir");
699  if (p) {
701  event_spool_dir[sizeof(event_spool_dir) - 1] = '\0';
702  }
703 
704  p = ast_variable_retrieve(cfg, "general", "timestampformat");
705  if (p) {
707  time_stamp_format[sizeof(time_stamp_format) - 1] = '\0';
708  }
709 
710  p = ast_variable_retrieve(cfg, "general", "db-family");
711  if (p) {
712  ast_copy_string(db_family, p, sizeof(db_family));
713  db_family[sizeof(db_family) - 1] = '\0';
714  }
715  ast_config_destroy(cfg);
716  }
717  return 1;
718 }
#define ALMRCV_CONFIG
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
static int fdtimeout
static int toneloudness
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static char event_app[128]
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
static int log_individual_events
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int sdtimeout
static char time_stamp_format[128]
static char event_spool_dir[128]
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static char db_family[128]
static int load_module ( void  )
static

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

729 {
730  if (load_config()) {
734  } else
736 }
static const char app[]
static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
static int load_config(void)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int log_events ( struct ast_channel chan,
char *  signalling_type,
event_node_t event 
)
static

Definition at line 372 of file app_alarmreceiver.c.

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

Referenced by alarmreceiver_exec(), and receive_ademco_contact_id().

373 {
374 
375  int res = 0;
376  char workstring[sizeof(event_spool_dir)+sizeof(event_file)] = "";
377  int fd;
378  FILE *logfile;
379  event_node_t *elp = event;
380 
382 
383  /* Make a template */
384  ast_copy_string(workstring, event_spool_dir, sizeof(workstring));
385  strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
386 
387  /* Make the temporary file */
388  fd = mkstemp(workstring);
389 
390  if (fd == -1) {
391  ast_verb(3, "AlarmReceiver: can't make temporary file\n");
392  ast_debug(1,"AlarmReceiver: can't make temporary file\n");
393  res = -1;
394  }
395 
396  if (!res) {
397  logfile = fdopen(fd, "w");
398  if (logfile) {
399  /* Write the file */
400  res = write_metadata(logfile, signalling_type, chan);
401  if (!res)
402  while ((!res) && (elp != NULL)) {
403  res = write_event(logfile, elp);
404  elp = elp->next;
405  }
406  if (!res) {
407  if (fflush(logfile) == EOF)
408  res = -1;
409  if (!res) {
410  if (fclose(logfile) == EOF)
411  res = -1;
412  }
413  }
414  } else
415  res = -1;
416  }
417  }
418 
419  return res;
420 }
static char event_file[14]
static int write_metadata(FILE *logfile, char *signalling_type, struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:243
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct event_node * next
static int write_event(FILE *logfile, event_node_t *event)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char event_spool_dir[128]
static void make_tone_burst ( unsigned char *  data,
float  freq,
float  loudness,
int  len,
int *  x 
)
static

Definition at line 150 of file app_alarmreceiver.c.

References AST_LIN2MU, len(), and M_PI.

Referenced by send_tone_burst().

151 {
152  int i;
153  float val;
154 
155  for (i = 0; i < len; i++) {
156  val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
157  data[i] = AST_LIN2MU((int)val);
158  }
159 
160  /* wrap back around from 8000 */
161 
162  if (*x >= 8000)
163  *x = 0;
164  return;
165 }
Definition: ast_expr2.c:325
#define M_PI
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_LIN2MU(a)
Definition: ulaw.h:49
static int receive_ademco_contact_id ( struct ast_channel chan,
const void *  data,
int  fdto,
int  sdto,
int  tldn,
event_node_t **  ehead 
)
static

Definition at line 427 of file app_alarmreceiver.c.

References ADEMCO_CONTACT_ID, ast_calloc, ast_copy_string(), ast_debug, ast_safe_sleep(), 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().

428 {
429  int i, j;
430  int res = 0;
431  int checksum;
432  char event[17];
433  event_node_t *enew, *elp;
434  int got_some_digits = 0;
435  int events_received = 0;
436  int ack_retries = 0;
437 
438  static char digit_map[15] = "0123456789*#ABC";
439  static unsigned char digit_weights[15] = {10,1,2,3,4,5,6,7,8,9,11,12,13,14,15};
440 
441  database_increment("calls-received");
442 
443  /* Wait for first event */
444  ast_verb(4, "AlarmReceiver: Waiting for first event from panel\n");
445 
446  while (res >= 0) {
447  if (got_some_digits == 0) {
448  /* Send ACK tone sequence */
449  ast_verb(4, "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
450  res = send_tone_burst(chan, 1400.0, 100, tldn);
451  if (!res)
452  res = ast_safe_sleep(chan, 100);
453  if (!res) {
454  ast_verb(4, "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
455  res = send_tone_burst(chan, 2300.0, 100, tldn);
456  }
457  }
458  if ( res >= 0)
459  res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
460  if (res < 0) {
461  if (events_received == 0) {
462  /* Hangup with no events received should be logged in the DB */
463  database_increment("no-events-received");
464  } else {
465  if (ack_retries) {
466  ast_verb(4, "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
467  database_increment("ack-retries");
468  }
469  }
470  ast_verb(4, "AlarmReceiver: App exiting...\n");
471  res = -1;
472  break;
473  }
474 
475  if (res != 0) {
476  /* Didn't get all of the digits */
477  ast_verb(2, "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
478 
479  if (!got_some_digits) {
480  got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
481  ack_retries++;
482  }
483  continue;
484  }
485 
486  got_some_digits = 1;
487 
488  ast_verb(2, "AlarmReceiver: Received Event %s\n", event);
489  ast_debug(1, "AlarmReceiver: Received event: %s\n", event);
490 
491  /* Calculate checksum */
492 
493  for (j = 0, checksum = 0; j < 16; j++) {
494  for (i = 0; i < sizeof(digit_map); i++) {
495  if (digit_map[i] == event[j])
496  break;
497  }
498 
499  if (i == 16)
500  break;
501 
502  checksum += digit_weights[i];
503  }
504  if (i == 16) {
505  ast_verb(2, "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
506  continue; /* Bad character */
507  }
508 
509  /* Checksum is mod(15) of the total */
510 
511  checksum = checksum % 15;
512 
513  if (checksum) {
514  database_increment("checksum-errors");
515  ast_verb(2, "AlarmReceiver: Nonzero checksum\n");
516  ast_debug(1, "AlarmReceiver: Nonzero checksum\n");
517  continue;
518  }
519 
520  /* Check the message type for correctness */
521 
522  if (strncmp(event + 4, "18", 2)) {
523  if (strncmp(event + 4, "98", 2)) {
524  database_increment("format-errors");
525  ast_verb(2, "AlarmReceiver: Wrong message type\n");
526  ast_debug(1, "AlarmReceiver: Wrong message type\n");
527  continue;
528  }
529  }
530 
531  events_received++;
532 
533  /* Queue the Event */
534  if (!(enew = ast_calloc(1, sizeof(*enew)))) {
535  res = -1;
536  break;
537  }
538 
539  enew->next = NULL;
540  ast_copy_string(enew->data, event, sizeof(enew->data));
541 
542  /*
543  * Insert event onto end of list
544  */
545  if (*ehead == NULL)
546  *ehead = enew;
547  else {
548  for(elp = *ehead; elp->next != NULL; elp = elp->next)
549  ;
550  elp->next = enew;
551  }
552 
553  if (res > 0)
554  res = 0;
555 
556  /* Let the user have the option of logging the single event before sending the kissoff tone */
557  if ((res == 0) && (log_individual_events))
558  res = log_events(chan, ADEMCO_CONTACT_ID, enew);
559  /* Wait 200 msec before sending kissoff */
560  if (res == 0)
561  res = ast_safe_sleep(chan, 200);
562 
563  /* Send the kissoff tone */
564  if (res == 0)
565  res = send_tone_burst(chan, 1400.0, 900, tldn);
566  }
567 
568  return res;
569 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
static int send_tone_burst(struct ast_channel *chan, float freq, int duration, int tldn)
static void database_increment(char *key)
#define ast_verb(level,...)
Definition: logger.h:243
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct event_node * next
static int log_individual_events
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define ADEMCO_CONTACT_ID
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event)
static int receive_dtmf_digits ( struct ast_channel chan,
char *  digit_string,
int  length,
int  fdto,
int  sdto 
)
static

Definition at line 236 of file app_alarmreceiver.c.

References 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_channel::hangupcause, ast_frame_subclass::integer, ast_channel::name, ast_frame::subclass, and ast_frame::uint32.

Referenced by receive_ademco_contact_id().

237 {
238  int res = 0;
239  int i = 0;
240  int r;
241  struct ast_frame *f;
242  struct timeval lastdigittime;
243 
244  lastdigittime = ast_tvnow();
245  for (;;) {
246  /* if outa time, leave */
247  if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((i > 0) ? sdto : fdto)) {
248  ast_verb(4, "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
249  ast_debug(1,"AlarmReceiver: DTMF timeout on chan %s\n",chan->name);
250  res = 1;
251  break;
252  }
253 
254  if ((r = ast_waitfor(chan, -1) < 0)) {
255  ast_debug(1, "Waitfor returned %d\n", r);
256  continue;
257  }
258 
259  f = ast_read(chan);
260 
261  if (f == NULL) {
262  res = -1;
263  break;
264  }
265 
266  /* If they hung up, leave */
268  if (f->data.uint32) {
269  chan->hangupcause = f->data.uint32;
270  }
271  ast_frfree(f);
272  res = -1;
273  break;
274  }
275 
276  /* if not DTMF, just do it again */
277  if (f->frametype != AST_FRAME_DTMF) {
278  ast_frfree(f);
279  continue;
280  }
281 
282  digit_string[i++] = f->subclass.integer; /* save digit */
283 
284  ast_frfree(f);
285 
286  /* If we have all the digits we expect, leave */
287  if(i >= length)
288  break;
289 
290  lastdigittime = ast_tvnow();
291  }
292 
293  digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
294  return res;
295 }
union ast_frame_subclass subclass
Definition: frame.h:146
#define AST_FRAME_DTMF
Definition: frame.h:128
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
#define ast_verb(level,...)
Definition: logger.h:243
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const ast_string_field name
Definition: channel.h:787
static struct ast_format f[]
Definition: format_g726.c:181
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
Data structure associated with a single frame of data.
Definition: frame.h:142
int hangupcause
Definition: channel.h:849
uint32_t uint32
Definition: frame.h:160
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
union ast_frame::@172 data
static int send_tone_burst ( struct ast_channel chan,
float  freq,
int  duration,
int  tldn 
)
static

Definition at line 171 of file app_alarmreceiver.c.

References AST_FORMAT_ULAW, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_read(), ast_verb, ast_waitfor(), ast_write(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, f, ast_frame::frametype, LOG_WARNING, make_tone_burst(), ast_frame::mallocd, ast_channel::name, ast_frame::offset, ast_frame::ptr, ast_frame::samples, and ast_frame::subclass.

Referenced by receive_ademco_contact_id().

172 {
173  int res = 0;
174  int i = 0;
175  int x = 0;
176  struct ast_frame *f, wf;
177 
178  struct {
179  unsigned char offset[AST_FRIENDLY_OFFSET];
180  unsigned char buf[640];
181  } tone_block;
182 
183  for (;;) {
184 
185  if (ast_waitfor(chan, -1) < 0) {
186  res = -1;
187  break;
188  }
189 
190  f = ast_read(chan);
191  if (!f) {
192  res = -1;
193  break;
194  }
195 
196  if (f->frametype == AST_FRAME_VOICE) {
200  wf.mallocd = 0;
201  wf.data.ptr = tone_block.buf;
202  wf.datalen = f->datalen;
203  wf.samples = wf.datalen;
204 
205  make_tone_burst(tone_block.buf, freq, (float) tldn, wf.datalen, &x);
206 
207  i += wf.datalen / 8;
208  if (i > duration) {
209  ast_frfree(f);
210  break;
211  }
212  if (ast_write(chan, &wf)) {
213  ast_verb(4, "AlarmReceiver: Failed to write frame on %s\n", chan->name);
214  ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
215  res = -1;
216  ast_frfree(f);
217  break;
218  }
219  }
220 
221  ast_frfree(f);
222  }
223  return res;
224 }
union ast_frame_subclass subclass
Definition: frame.h:146
int offset
Definition: frame.h:156
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
format_t codec
Definition: frame.h:137
#define ast_verb(level,...)
Definition: logger.h:243
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
static void make_tone_burst(unsigned char *data, float freq, float loudness, int len, int *x)
int datalen
Definition: frame.h:148
#define AST_FORMAT_ULAW
Definition: frame.h:246
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
int mallocd
Definition: frame.h:152
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
union ast_frame::@172 data
int samples
Definition: frame.h:150
static int unload_module ( void  )
static

Definition at line 723 of file app_alarmreceiver.c.

References ast_unregister_application().

724 {
726 }
static const char app[]
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static int write_event ( FILE *  logfile,
event_node_t event 
)
static

Definition at line 358 of file app_alarmreceiver.c.

References event_node::data.

Referenced by log_events().

359 {
360  int res = 0;
361 
362  if (fprintf(logfile, "%s\n", event->data) < 0)
363  res = -1;
364 
365  return res;
366 }
static int write_metadata ( FILE *  logfile,
char *  signalling_type,
struct ast_channel chan 
)
static

Definition at line 300 of file app_alarmreceiver.c.

References ast_copy_string(), ast_debug, ast_localtime(), ast_shrink_phone_number(), ast_strftime(), ast_strlen_zero(), ast_tvnow(), ast_verb, ast_channel::caller, ast_party_caller::id, ast_party_id::name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.

Referenced by log_events().

301 {
302  int res = 0;
303  struct timeval t;
304  struct ast_tm now;
305  char *cl;
306  char *cn;
307  char workstring[80];
308  char timestamp[80];
309 
310  /* Extract the caller ID location */
311  ast_copy_string(workstring,
312  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
313  sizeof(workstring));
314  ast_shrink_phone_number(workstring);
315  if (ast_strlen_zero(workstring)) {
316  cl = "<unknown>";
317  } else {
318  cl = workstring;
319  }
320  cn = S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>");
321 
322  /* Get the current time */
323  t = ast_tvnow();
324  ast_localtime(&t, &now, NULL);
325 
326  /* Format the time */
327  ast_strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
328 
329  res = fprintf(logfile, "\n\n[metadata]\n\n");
330  if (res >= 0) {
331  res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
332  }
333  if (res >= 0) {
334  res = fprintf(logfile, "CALLINGFROM=%s\n", cl);
335  }
336  if (res >= 0) {
337  res = fprintf(logfile, "CALLERNAME=%s\n", cn);
338  }
339  if (res >= 0) {
340  res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
341  }
342  if (res >= 0) {
343  res = fprintf(logfile, "[events]\n\n");
344  }
345  if (res < 0) {
346  ast_verb(3, "AlarmReceiver: can't write metadata\n");
347  ast_debug(1,"AlarmReceiver: can't write metadata\n");
348  } else {
349  res = 0;
350  }
351 
352  return res;
353 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
char * str
Subscriber name (Malloced)
Definition: channel.h:214
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ast_verb(level,...)
Definition: logger.h:243
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char time_stamp_format[128]
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()&#39;s, .&#39;s, and -&#39;s...
Definition: callerid.c:948
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 738 of file app_alarmreceiver.c.

const char app[] = "AlarmReceiver"
static

Definition at line 69 of file app_alarmreceiver.c.

Definition at line 738 of file app_alarmreceiver.c.

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

Definition at line 99 of file app_alarmreceiver.c.

Referenced by load_config().

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

Definition at line 98 of file app_alarmreceiver.c.

Referenced by load_config().

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

Definition at line 103 of file app_alarmreceiver.c.

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

Definition at line 97 of file app_alarmreceiver.c.

Referenced by load_config(), and log_events().

int fdtimeout = 2000
static

Definition at line 93 of file app_alarmreceiver.c.

int log_individual_events = 0
static

Definition at line 96 of file app_alarmreceiver.c.

int sdtimeout = 200
static

Definition at line 94 of file app_alarmreceiver.c.

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

Definition at line 100 of file app_alarmreceiver.c.

Referenced by load_config().

int toneloudness = 4096
static

Definition at line 95 of file app_alarmreceiver.c.