Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
Data Structures | Macros | Typedefs | Functions | Variables
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 "asterisk/format_cache.h"

Go to the source code of this file.

Data Structures

struct  event_node
 

Macros

#define ADEMCO_AUDIO_CALL_NEXT   "606"
 
#define ADEMCO_CONTACT_ID   "ADEMCO_CONTACT_ID"
 
#define ADEMCO_EXPRESS_4_1   "ADEMCO_EXPRESS_4_1"
 
#define ADEMCO_EXPRESS_4_2   "ADEMCO_EXPRESS_4_2"
 
#define ADEMCO_HIGH_SPEED   "ADEMCO_HIGH_SPEED"
 
#define ADEMCO_MSG_TYPE_1   "18"
 
#define ADEMCO_MSG_TYPE_2   "98"
 
#define ADEMCO_MSG_TYPE_3   "17"
 
#define ADEMCO_MSG_TYPE_4   "27"
 
#define ADEMCO_MSG_TYPE_5   "55"
 
#define ADEMCO_MSG_TYPE_6   "56"
 
#define ADEMCO_SUPER_FAST   "ADEMCO_SUPER_FAST"
 
#define ALMRCV_CONFIG   "alarmreceiver.conf"
 
#define UNKNOWN_FORMAT   "UNKNOWN_FORMAT"
 

Typedefs

typedef struct event_node event_node_t
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int ademco_check_valid (char *signalling_type, char *event)
 Check if the message is in known and valid Ademco format. More...
 
static int ademco_detect_format (char *signalling_type, char *event, int *no_checksum)
 Detect the message format of an event. More...
 
static int ademco_verify_checksum (char *event, int expected)
 Verify Ademco checksum. More...
 
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. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void database_increment (char *key)
 Attempt to access a database variable and increment it. More...
 
static int load_config (int reload)
 Load the configuration from the configuration file. More...
 
static int load_module (void)
 Load the module. More...
 
static int log_events (struct ast_channel *chan, char *signalling_type, event_node_t *event, int no_checksum)
 Log events if configuration key logindividualevents is enabled or on exit. More...
 
static int receive_ademco_event (struct ast_channel *chan, event_node_t **ehead, char *signalling_type, int *no_checksum)
 Receive Ademco ContactID or other format Data String. More...
 
static int receive_dtmf_digits (struct ast_channel *chan, char *digit_string, int buf_size, int expected, int *received)
 Receive a fixed length DTMF string. More...
 
static int reload (void)
 
static int send_tone_burst (struct ast_channel *chan, const char *tone_freq, int tone_duration, int delay)
 Send a single tone burst for a specified duration and frequency. More...
 
static int unload_module (void)
 Unregister Alarm Receiver App. More...
 
static int write_event (FILE *logfile, event_node_t *event)
 Log a single event. More...
 
static int write_metadata (FILE *logfile, char *signalling_type, struct ast_channel *chan, int no_checksum)
 Write metadata to log file. More...
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, }
 
static int answait = 1250
 
static const char app [] = "AlarmReceiver"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
struct timeval call_start_time
 
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 no_group_meta = 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

◆ ADEMCO_AUDIO_CALL_NEXT

#define ADEMCO_AUDIO_CALL_NEXT   "606"

Definition at line 128 of file app_alarmreceiver.c.

Referenced by receive_ademco_event().

◆ ADEMCO_CONTACT_ID

#define ADEMCO_CONTACT_ID   "ADEMCO_CONTACT_ID"

◆ ADEMCO_EXPRESS_4_1

#define ADEMCO_EXPRESS_4_1   "ADEMCO_EXPRESS_4_1"

◆ ADEMCO_EXPRESS_4_2

#define ADEMCO_EXPRESS_4_2   "ADEMCO_EXPRESS_4_2"

◆ ADEMCO_HIGH_SPEED

#define ADEMCO_HIGH_SPEED   "ADEMCO_HIGH_SPEED"

Definition at line 94 of file app_alarmreceiver.c.

Referenced by ademco_check_valid(), and ademco_detect_format().

◆ ADEMCO_MSG_TYPE_1

#define ADEMCO_MSG_TYPE_1   "18"

Definition at line 121 of file app_alarmreceiver.c.

Referenced by ademco_check_valid(), and ademco_detect_format().

◆ ADEMCO_MSG_TYPE_2

#define ADEMCO_MSG_TYPE_2   "98"

Definition at line 122 of file app_alarmreceiver.c.

Referenced by ademco_check_valid(), and ademco_detect_format().

◆ ADEMCO_MSG_TYPE_3

#define ADEMCO_MSG_TYPE_3   "17"

Definition at line 123 of file app_alarmreceiver.c.

Referenced by ademco_check_valid(), and ademco_detect_format().

◆ ADEMCO_MSG_TYPE_4

#define ADEMCO_MSG_TYPE_4   "27"

Definition at line 124 of file app_alarmreceiver.c.

Referenced by ademco_check_valid(), and ademco_detect_format().

◆ ADEMCO_MSG_TYPE_5

#define ADEMCO_MSG_TYPE_5   "55"

Definition at line 125 of file app_alarmreceiver.c.

Referenced by ademco_check_valid(), and ademco_detect_format().

◆ ADEMCO_MSG_TYPE_6

#define ADEMCO_MSG_TYPE_6   "56"

Definition at line 126 of file app_alarmreceiver.c.

Referenced by ademco_check_valid(), and ademco_detect_format().

◆ ADEMCO_SUPER_FAST

#define ADEMCO_SUPER_FAST   "ADEMCO_SUPER_FAST"

Definition at line 115 of file app_alarmreceiver.c.

Referenced by ademco_check_valid(), and ademco_detect_format().

◆ ALMRCV_CONFIG

#define ALMRCV_CONFIG   "alarmreceiver.conf"

Definition at line 68 of file app_alarmreceiver.c.

Referenced by load_config().

◆ UNKNOWN_FORMAT

#define UNKNOWN_FORMAT   "UNKNOWN_FORMAT"

Typedef Documentation

◆ event_node_t

typedef struct event_node event_node_t

Definition at line 142 of file app_alarmreceiver.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1000 of file app_alarmreceiver.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1000 of file app_alarmreceiver.c.

◆ ademco_check_valid()

static int ademco_check_valid ( char *  signalling_type,
char *  event 
)
static

Check if the message is in known and valid Ademco format.

Parameters
signalling_typeExpected signalling type for the message
eventevent received
Return values
0The event is valid
-1The event is not valid

Definition at line 523 of file app_alarmreceiver.c.

References ADEMCO_CONTACT_ID, ADEMCO_EXPRESS_4_1, ADEMCO_EXPRESS_4_2, ADEMCO_HIGH_SPEED, ADEMCO_MSG_TYPE_1, ADEMCO_MSG_TYPE_2, ADEMCO_MSG_TYPE_3, ADEMCO_MSG_TYPE_4, ADEMCO_MSG_TYPE_5, ADEMCO_MSG_TYPE_6, ADEMCO_SUPER_FAST, and UNKNOWN_FORMAT.

Referenced by receive_ademco_event().

524 {
525  if (!strcmp(signalling_type, UNKNOWN_FORMAT)) {
526  return 1;
527  }
528 
529  if (!strcmp(signalling_type, ADEMCO_CONTACT_ID)
530  && strncmp(event + 4, ADEMCO_MSG_TYPE_1, 2)
531  && strncmp(event + 4, ADEMCO_MSG_TYPE_2, 2)) {
532  return -1;
533  }
534 
535  if (!strcmp(signalling_type, ADEMCO_EXPRESS_4_1) && strncmp(event + 4, ADEMCO_MSG_TYPE_3, 2)) {
536  return -1;
537  }
538 
539  if (!strcmp(signalling_type, ADEMCO_EXPRESS_4_2) && strncmp(event + 4, ADEMCO_MSG_TYPE_4, 2)) {
540  return -1;
541  }
542 
543  if (!strcmp(signalling_type, ADEMCO_HIGH_SPEED) && strncmp(event + 4, ADEMCO_MSG_TYPE_5, 2)) {
544  return -1;
545  }
546 
547  if (!strcmp(signalling_type, ADEMCO_SUPER_FAST) && strncmp(event + 4, ADEMCO_MSG_TYPE_6, 2)) {
548  return -1;
549  }
550 
551  return 0;
552 }
#define ADEMCO_EXPRESS_4_2
#define ADEMCO_MSG_TYPE_6
Definition: astman.c:222
#define ADEMCO_MSG_TYPE_4
#define ADEMCO_HIGH_SPEED
#define ADEMCO_SUPER_FAST
#define ADEMCO_MSG_TYPE_1
#define ADEMCO_MSG_TYPE_3
#define ADEMCO_MSG_TYPE_2
#define ADEMCO_EXPRESS_4_1
#define UNKNOWN_FORMAT
#define ADEMCO_CONTACT_ID
#define ADEMCO_MSG_TYPE_5

◆ ademco_detect_format()

static int ademco_detect_format ( char *  signalling_type,
char *  event,
int *  no_checksum 
)
static

Detect the message format of an event.

Parameters
signalling_typeExpected signalling type for the message
eventevent received
no_checksumShould we calculate checksum for the message
Returns
The expected digits for the detected event type

Definition at line 563 of file app_alarmreceiver.c.

References ADEMCO_CONTACT_ID, ADEMCO_EXPRESS_4_1, ADEMCO_EXPRESS_4_2, ADEMCO_HIGH_SPEED, ADEMCO_MSG_TYPE_1, ADEMCO_MSG_TYPE_2, ADEMCO_MSG_TYPE_3, ADEMCO_MSG_TYPE_4, ADEMCO_MSG_TYPE_5, ADEMCO_MSG_TYPE_6, ADEMCO_SUPER_FAST, ast_debug, ast_verb, and UNKNOWN_FORMAT.

Referenced by receive_ademco_event().

564 {
565  int res = 16;
566 
567  if (!strncmp(event + 4, ADEMCO_MSG_TYPE_1, 2)
568  || !strncmp(event + 4, ADEMCO_MSG_TYPE_2, 2)) {
569  sprintf(signalling_type, "%s", ADEMCO_CONTACT_ID);
570  }
571 
572  if (!strncmp(event + 4, ADEMCO_MSG_TYPE_3, 2)) {
573  sprintf(signalling_type, "%s", ADEMCO_EXPRESS_4_1);
574  res = 8;
575  }
576 
577  if (!strncmp(event + 4, ADEMCO_MSG_TYPE_4, 2)) {
578  sprintf(signalling_type, "%s", ADEMCO_EXPRESS_4_2);
579  res = 9;
580  }
581 
582  if (!strncmp(event + 4, ADEMCO_MSG_TYPE_5, 2)) {
583  sprintf(signalling_type, "%s", ADEMCO_HIGH_SPEED);
584  }
585 
586  if (!strncmp(event + 4, ADEMCO_MSG_TYPE_6, 2)) {
587  sprintf(signalling_type, "%s", ADEMCO_SUPER_FAST);
588  *no_checksum = 1;
589  res = 15;
590  }
591 
592  if (strcmp(signalling_type, UNKNOWN_FORMAT)) {
593  ast_verb(4, "AlarmMonitoring: Detected format %s.\n", signalling_type);
594  ast_debug(1, "AlarmMonitoring: Autodetected format %s.\n", signalling_type);
595  }
596 
597  return res;
598 }
#define ADEMCO_EXPRESS_4_2
#define ADEMCO_MSG_TYPE_6
Definition: astman.c:222
#define ADEMCO_MSG_TYPE_4
#define ADEMCO_HIGH_SPEED
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ADEMCO_SUPER_FAST
#define ADEMCO_MSG_TYPE_1
#define ADEMCO_MSG_TYPE_3
#define ADEMCO_MSG_TYPE_2
#define ADEMCO_EXPRESS_4_1
#define UNKNOWN_FORMAT
#define ADEMCO_CONTACT_ID
#define ADEMCO_MSG_TYPE_5

◆ ademco_verify_checksum()

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

Verify Ademco checksum.

Since
11.0
Parameters
eventReceived DTMF String
expectedNumber of Digits expected
Return values
0success
-1failure

Definition at line 456 of file app_alarmreceiver.c.

References ARRAY_LEN, ast_verb, digit, and digits_mapping.

Referenced by receive_ademco_event().

457 {
458  int checksum = 0;
459  int i, j;
460 
461  for (j = 0; j < expected; j++) {
462  for (i = 0; i < ARRAY_LEN(digits_mapping); i++) {
463  if (digits_mapping[i].digit == event[j]) {
464  break;
465  }
466  }
467 
468  if (i >= ARRAY_LEN(digits_mapping)) {
469  ast_verb(2, "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
470  return -1;
471  }
472 
473  checksum += digits_mapping[i].weight;
474  }
475 
476  /* Checksum is mod(15) of the total */
477  if (!(checksum % 15)) {
478  return 0;
479  }
480 
481  return -1;
482 }
char digit
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
struct @10 digits_mapping[]
Definition: astman.c:222
#define ast_verb(level,...)
Definition: logger.h:455

◆ alarmreceiver_exec()

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
chanAsterisk Channel
dataApplication data
Return values
0success
-1failure

Definition at line 792 of file app_alarmreceiver.c.

References answait, ast_answer(), ast_channel_name(), ast_channel_readformat(), ast_channel_writeformat(), ast_copy_string(), ast_debug, ast_format_alaw, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, 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_tvnow(), ast_verb, call_start_time, event_app, log_events(), log_individual_events, LOG_WARNING, event_node::next, NULL, receive_ademco_event(), and UNKNOWN_FORMAT.

Referenced by load_module().

793 {
794  int res = 0;
795  int no_checksum = 0;
796  event_node_t *elp, *efree;
797  char signalling_type[64] = "";
798  event_node_t *event_head = NULL;
799 
802  ast_verb(4, "AlarmReceiver: Setting write format to Mu-law\n");
804  ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",ast_channel_name(chan));
805  return -1;
806  }
807  }
808 
811  ast_verb(4, "AlarmReceiver: Setting read format to Mu-law\n");
813  ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",ast_channel_name(chan));
814  return -1;
815  }
816  }
817 
818  /* Set default values for this invocation of the application */
819  ast_copy_string(signalling_type, UNKNOWN_FORMAT, sizeof(signalling_type));
821 
822  /* Answer the channel if it is not already */
823  if (ast_channel_state(chan) != AST_STATE_UP) {
824  ast_verb(4, "AlarmReceiver: Answering channel\n");
825  if (ast_answer(chan)) {
826  return -1;
827  }
828  }
829 
830  /* Wait for the connection to settle post-answer */
831  ast_verb(4, "AlarmReceiver: Waiting for connection to stabilize\n");
832  if (ast_safe_sleep(chan, answait)) {
833  return -1;
834  }
835 
836  /* Attempt to receive the events */
837  receive_ademco_event(chan, &event_head, signalling_type, &no_checksum);
838 
839  /* Events queued by receiver, write them all out here if so configured */
840  if (!log_individual_events) {
841  res = log_events(chan, signalling_type, event_head, no_checksum);
842  }
843 
844  /* Do we exec a command line at the end? */
845  if ((!res) && (!ast_strlen_zero(event_app)) && (event_head)) {
846  ast_debug(1,"Alarmreceiver: executing: %s\n", event_app);
848  }
849 
850  /* Free up the data allocated in our linked list */
851  for (elp = event_head; (elp != NULL);) {
852  efree = elp;
853  elp = elp->next;
854  ast_free(efree);
855  }
856 
857  return 0;
858 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1554
static int answait
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define LOG_WARNING
Definition: logger.h:274
ast_channel_state
ast_channel states
Definition: channelstate.h:35
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:455
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5724
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5765
struct event_node * next
static char event_app[128]
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
#define ast_strlen_zero(a)
Definition: muted.c:73
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event, int no_checksum)
Log events if configuration key logindividualevents is enabled or on exit.
#define ast_free(a)
Definition: astmm.h:182
#define UNKNOWN_FORMAT
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:401
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
const char * ast_channel_name(const struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2780
struct timeval call_start_time
static int receive_ademco_event(struct ast_channel *chan, event_node_t **ehead, char *signalling_type, int *no_checksum)
Receive Ademco ContactID or other format Data String.
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1000 of file app_alarmreceiver.c.

◆ database_increment()

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
keyA database key to increment
Returns
Nothing

Definition at line 208 of file app_alarmreceiver.c.

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

Referenced by receive_ademco_event().

209 {
210  unsigned v;
211  char value[16];
212 
213  if (ast_strlen_zero(db_family)) {
214  return; /* If not defined, don't do anything */
215  }
216 
217  if (ast_db_get(db_family, key, value, sizeof(value) - 1)) {
218  ast_verb(4, "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
219  /* Guess we have to create it */
220  ast_db_put(db_family, key, "1");
221  return;
222  }
223 
224  sscanf(value, "%30u", &v);
225  v++;
226 
227  ast_verb(4, "AlarmReceiver: New value for %s: %u\n", key, v);
228  snprintf(value, sizeof(value), "%u", v);
229 
230  if (ast_db_put(db_family, key, value)) {
231  ast_verb(4, "AlarmReceiver: database_increment write error\n");
232  }
233 
234  return;
235 }
int value
Definition: syslog.c:37
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_strlen_zero(a)
Definition: muted.c:73
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:412
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
static char db_family[128]

◆ load_config()

static int load_config ( int  reload)
static

Load the configuration from the configuration file.

Parameters
reloadTrue on reload
Return values
1success
0failure

Definition at line 868 of file app_alarmreceiver.c.

References ALMRCV_CONFIG, answait, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_log, ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, db_family, event_app, event_spool_dir, fdtimeout, LOG_ERROR, log_individual_events, no_group_meta, NULL, sdtimeout, time_stamp_format, toneloudness, and value.

Referenced by load_module(), and reload().

869 {
870  struct ast_config *cfg;
871  const char *value;
872  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
873 
874  /* Read in the config file */
875  cfg = ast_config_load(ALMRCV_CONFIG, config_flags);
876 
877  if (!cfg) {
878  ast_verb(4, "AlarmReceiver: No config file\n");
879  return 0;
880  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
881  return 1;
882  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
883  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n",
884  ALMRCV_CONFIG);
885  return 0;
886  }
887 
888  if ((value = ast_variable_retrieve(cfg, "general", "eventcmd")) != NULL) {
889  ast_copy_string(event_app, value, sizeof(event_app));
890  }
891 
892  if ((value = ast_variable_retrieve(cfg, "general", "loudness")) != NULL) {
893  toneloudness = atoi(value);
894  if (toneloudness < 100) {
895  toneloudness = 100;
896  } else if (toneloudness > 8192) {
897  toneloudness = 8192;
898  }
899  }
900 
901  if ((value = ast_variable_retrieve(cfg, "general", "fdtimeout")) != NULL) {
902  fdtimeout = atoi(value);
903  if (fdtimeout < 1000) {
904  fdtimeout = 1000;
905  } else if (fdtimeout > 10000) {
906  fdtimeout = 10000;
907  }
908  }
909 
910  if ((value = ast_variable_retrieve(cfg, "general", "sdtimeout")) != NULL) {
911  sdtimeout = atoi(value);
912  if (sdtimeout < 110) {
913  sdtimeout = 110;
914  } else if (sdtimeout > 4000) {
915  sdtimeout = 4000;
916  }
917  }
918 
919  if ((value = ast_variable_retrieve(cfg, "general", "answait")) != NULL) {
920  answait = atoi(value);
921  if (answait < 500) {
922  answait = 500;
923  } else if (answait > 10000) {
924  answait = 10000;
925  }
926  }
927 
928  if ((value = ast_variable_retrieve(cfg, "general", "no_group_meta")) != NULL) {
929  no_group_meta = ast_true(value);
930  }
931 
932  if ((value = ast_variable_retrieve(cfg, "general", "logindividualevents")) != NULL) {
934  }
935 
936  if ((value = ast_variable_retrieve(cfg, "general", "eventspooldir")) != NULL) {
938  }
939 
940  if ((value = ast_variable_retrieve(cfg, "general", "timestampformat")) != NULL) {
942  }
943 
944  if ((value = ast_variable_retrieve(cfg, "general", "db-family")) != NULL) {
945  ast_copy_string(db_family, value, sizeof(db_family));
946  }
947 
948  ast_config_destroy(cfg);
949 
950  return 1;
951 }
#define ALMRCV_CONFIG
static int answait
static int fdtimeout
static int reload(void)
#define CONFIG_STATUS_FILEINVALID
static int toneloudness
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define CONFIG_STATUS_FILEUNCHANGED
static char event_app[128]
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1821
Structure used to handle boolean flags.
Definition: utils.h:199
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
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:401
static int sdtimeout
static char time_stamp_format[128]
static char event_spool_dir[128]
static char db_family[128]
static int no_group_meta

◆ load_module()

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 974 of file app_alarmreceiver.c.

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

Referenced by reload().

975 {
976  if (load_config(0)) {
979  }
981  }
982 
984 }
static int load_config(int reload)
Load the configuration from the configuration file.
static const char app[]
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...
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ log_events()

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

Log events if configuration key logindividualevents is enabled or on exit.

Parameters
chanAsterisk Channel
signalling_typeSignaling Type
eventEvent Structure
no_checksumExpecting messages without checksum
Return values
0success
-1failure

Definition at line 402 of file app_alarmreceiver.c.

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

Referenced by alarmreceiver_exec(), and receive_ademco_event().

403 {
404  char workstring[sizeof(event_spool_dir) + sizeof(event_file)] = "";
405  int fd;
406  FILE *logfile;
407  event_node_t *elp = event;
408 
410 
411  /* Make a template */
412  ast_copy_string(workstring, event_spool_dir, sizeof(workstring));
413  strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
414 
415  /* Make the temporary file */
416  fd = mkstemp(workstring);
417 
418  if (fd == -1) {
419  ast_verb(3, "AlarmReceiver: can't make temporary file\n");
420  ast_debug(1, "AlarmReceiver: can't make temporary file\n");
421  return -1;
422  }
423 
424  if ((logfile = fdopen(fd, "w")) == NULL) {
425  return -1;
426  }
427 
428  /* Write the file */
429  if (write_metadata(logfile, signalling_type, chan, no_checksum)) {
430  fflush(logfile);
431  fclose(logfile);
432  return -1;
433  }
434 
435  while ((elp != NULL) && (write_event(logfile, elp) == 0)) {
436  elp = elp->next;
437  }
438 
439  fflush(logfile);
440  fclose(logfile);
441  }
442 
443  return 0;
444 }
static char event_file[14]
static int write_metadata(FILE *logfile, char *signalling_type, struct ast_channel *chan, int no_checksum)
Write metadata to log file.
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
struct event_node * next
#define ast_strlen_zero(a)
Definition: muted.c:73
static int write_event(FILE *logfile, event_node_t *event)
Log a single event.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char event_spool_dir[128]

◆ receive_ademco_event()

static int receive_ademco_event ( struct ast_channel chan,
event_node_t **  ehead,
char *  signalling_type,
int *  no_checksum 
)
static

Receive Ademco ContactID or other format Data String.

Parameters
chanAsterisk Channel
eheadPointer to events list
signalling_typeExpected signalling type for the message
no_checksumShould we calculate checksum for the message
Return values
0success
-1failure

Definition at line 611 of file app_alarmreceiver.c.

References ADEMCO_AUDIO_CALL_NEXT, ademco_check_valid(), ADEMCO_CONTACT_ID, ademco_detect_format(), ADEMCO_EXPRESS_4_1, ADEMCO_EXPRESS_4_2, ademco_verify_checksum(), ast_calloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_strlen_zero, ast_tvdiff_ms(), ast_tvnow(), ast_verb, call_start_time, event_node::data, database_increment(), log_events(), log_individual_events, event_node::next, NULL, pbx_builtin_getvar_helper(), receive_dtmf_digits(), send_tone_burst(), and UNKNOWN_FORMAT.

Referenced by alarmreceiver_exec().

612 {
613  int res = 0;
614  const char *limit;
615  char event[17];
616  event_node_t *enew, *elp;
617  int got_some_digits = 0;
618  int events_received = 0;
619  int ack_retries = 0;
620  int limit_retries = 0;
621  int expected_length = sizeof(event) - 1;
622 
623  database_increment("calls-received");
624 
625  /* Wait for first event */
626  ast_verb(4, "AlarmReceiver: Waiting for first event from panel...\n");
627 
628  while (res >= 0) {
629  int digits_received = 0;
630 
631  res = 0;
632 
633  if (log_individual_events) {
634  sprintf(signalling_type, "%s", UNKNOWN_FORMAT);
635  expected_length = 16;
636  *no_checksum = 0;
637  }
638 
639  if (got_some_digits == 0) {
640  /* Send ACK tone sequence */
641  ast_verb(4, "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
642  res = send_tone_burst(chan, "1400", 100, 0);
643  if (!res) {
644  ast_verb(4, "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
645  res = send_tone_burst(chan, "2300", 100, 100);
646  }
647  }
648  if (res) {
649  return -1;
650  }
651 
652  res = receive_dtmf_digits(chan, event, sizeof(event), expected_length, &digits_received);
653  if (res < 0) {
654  if (events_received == 0) {
655  /* Hangup with no events received should be logged in the DB */
656  database_increment("no-events-received");
657  ast_verb(4, "AlarmReceiver: No events received!\n");
658  } else {
659  if (ack_retries) {
660  database_increment("ack-retries");
661  ast_verb(4, "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
662  }
663  }
664  ast_verb(4, "AlarmReceiver: App exiting...\n");
665  break;
666  }
667 
668  if (!strcmp(signalling_type, UNKNOWN_FORMAT) && digits_received > 5) {
669  expected_length = ademco_detect_format(signalling_type, event, no_checksum);
670 
671  if (res > 0) {
672  if (digits_received == expected_length) {
673  res = limit_retries = 0;
674  } else if (digits_received == expected_length - 1
675  && (!strcmp(signalling_type, ADEMCO_EXPRESS_4_2)
676  || !strcmp(signalling_type, ADEMCO_EXPRESS_4_1))) {
677  /* ADEMCO EXPRESS without checksum */
678  res = limit_retries = 0;
679  expected_length--;
680  *no_checksum = 1;
681  ast_verb(4, "AlarmMonitoring: Skipping checksum for format %s.\n", signalling_type);
682  ast_debug(1, "AlarmMonitoring: Skipping checksum for format %s.\n", signalling_type);
683  }
684  }
685  }
686 
687  ast_channel_lock(chan);
688  limit = pbx_builtin_getvar_helper(chan, "ALARMRECEIVER_CALL_LIMIT");
689  if (!ast_strlen_zero(limit)) {
690  if (ast_tvdiff_ms(ast_tvnow(), call_start_time) > atoi(limit)) {
691  ast_channel_unlock(chan);
692  return -1;
693  }
694  }
695  limit = pbx_builtin_getvar_helper(chan, "ALARMRECEIVER_RETRIES_LIMIT");
696  ast_channel_unlock(chan);
697  if (!ast_strlen_zero(limit)) {
698  if (limit_retries + 1 >= atoi(limit)) {
699  return -1;
700  }
701  }
702 
703  if (res) {
704  /* Didn't get all of the digits */
705  ast_verb(2, "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
706  limit_retries++;
707 
708  if (!events_received && strcmp(signalling_type, UNKNOWN_FORMAT))
709  {
710  sprintf(signalling_type, "%s", UNKNOWN_FORMAT);
711  expected_length = sizeof(event) - 1;
712  }
713 
714  if (!got_some_digits) {
715  got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
716  ack_retries++;
717  }
718  continue;
719  }
720 
721  got_some_digits = 1;
722 
723  ast_verb(2, "AlarmReceiver: Received Event %s\n", event);
724  ast_debug(1, "AlarmReceiver: Received event: %s\n", event);
725 
726  /* Calculate checksum */
727  if (!(*no_checksum) && ademco_verify_checksum(event, expected_length)) {
728  database_increment("checksum-errors");
729  ast_verb(2, "AlarmReceiver: Nonzero checksum\n");
730  ast_debug(1, "AlarmReceiver: Nonzero checksum\n");
731  continue;
732  }
733 
734  /* Check the message type for correctness */
735  if (ademco_check_valid(signalling_type, event)) {
736  database_increment("format-errors");
737  ast_verb(2, "AlarmReceiver: Wrong message type\n");
738  ast_debug(1, "AlarmReceiver: Wrong message type\n");
739  continue;
740  }
741 
742  events_received++;
743 
744  /* Queue the Event */
745  if (!(enew = ast_calloc(1, sizeof(*enew)))) {
746  return -1;
747  }
748 
749  enew->next = NULL;
750  ast_copy_string(enew->data, event, sizeof(enew->data));
751 
752  /* Insert event onto end of list */
753  if (*ehead == NULL) {
754  *ehead = enew;
755  } else {
756  for (elp = *ehead; elp->next != NULL; elp = elp->next) {
757  ;
758  }
759  elp->next = enew;
760  }
761 
762  /* Let the user have the option of logging the single event before sending the kissoff tone */
763  if (log_individual_events && log_events(chan, signalling_type, enew, *no_checksum)) {
764  return -1;
765  }
766 
767  /* Send the kissoff tone (1400 Hz, 900 ms, after 200ms delay) */
768  if (send_tone_burst(chan, "1400", 900, 200)) {
769  return -1;
770  }
771 
772  /* If audio call follows, exit alarm receiver app */
773  if (!strcmp(signalling_type, ADEMCO_CONTACT_ID)
774  && !strncmp(event + 7, ADEMCO_AUDIO_CALL_NEXT, 3)) {
775  ast_verb(4, "AlarmReceiver: App exiting... Audio call next!\n");
776  return 0;
777  }
778  }
779 
780  return res;
781 }
#define ast_channel_lock(chan)
Definition: channel.h:2837
#define ADEMCO_EXPRESS_4_2
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int buf_size, int expected, int *received)
Receive a fixed length DTMF string.
Definition: astman.c:222
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
static void database_increment(char *key)
Attempt to access a database variable and increment it.
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:455
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
struct event_node * next
static int ademco_verify_checksum(char *event, int expected)
Verify Ademco checksum.
#define ADEMCO_EXPRESS_4_1
static int send_tone_burst(struct ast_channel *chan, const char *tone_freq, int tone_duration, int delay)
Send a single tone burst for a specified duration and frequency.
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event, int no_checksum)
Log events if configuration key logindividualevents is enabled or on exit.
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define UNKNOWN_FORMAT
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:401
#define ADEMCO_CONTACT_ID
static int ademco_check_valid(char *signalling_type, char *event)
Check if the message is in known and valid Ademco format.
struct timeval call_start_time
static int ademco_detect_format(char *signalling_type, char *event, int *no_checksum)
Detect the message format of an event.
#define ADEMCO_AUDIO_CALL_NEXT

◆ receive_dtmf_digits()

static int receive_dtmf_digits ( struct ast_channel chan,
char *  digit_string,
int  buf_size,
int  expected,
int *  received 
)
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
chanAsterisk Channel
digit_stringDigits String
buf_sizeThe size of the Digits String buffer
expectedDigits expected for this message type
receivedPointer to number of digits received so far
Return values
0if all digits were successfully received
1if a timeout occurred
-1if the caller hung up or on channel errors

Definition at line 253 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, fdtimeout, ast_frame::frametype, ast_frame_subclass::integer, NULL, sdtimeout, ast_frame::subclass, and ast_frame::uint32.

Referenced by receive_ademco_event().

254 {
255  int rtn = 0;
256  int r;
257  struct ast_frame *f;
258  struct timeval lastdigittime;
259 
260  lastdigittime = ast_tvnow();
261  while (*received < expected && *received < buf_size - 1) {
262  /* If timed out, leave */
263  if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((*received > 0) ? sdtimeout : fdtimeout)) {
264  ast_verb(4, "AlarmReceiver: DTMF Digit Timeout on %s\n", ast_channel_name(chan));
265  ast_debug(1, "AlarmReceiver: DTMF timeout on chan %s\n", ast_channel_name(chan));
266  rtn = 1;
267  break;
268  }
269 
270  if ((r = ast_waitfor(chan, -1)) < 0) {
271  ast_debug(1, "Waitfor returned %d\n", r);
272  continue;
273  }
274 
275  if ((f = ast_read(chan)) == NULL) {
276  rtn = -1;
277  break;
278  }
279 
280  /* If they hung up, leave */
281  if ((f->frametype == AST_FRAME_CONTROL)
282  && (f->subclass.integer == AST_CONTROL_HANGUP)) {
283  if (f->data.uint32) {
285  }
286  ast_frfree(f);
287  rtn = -1;
288  break;
289  }
290 
291  /* If not DTMF, just do it again */
292  if (f->frametype != AST_FRAME_DTMF) {
293  ast_frfree(f);
294  continue;
295  }
296 
297  /* Save digit */
298  digit_string[(*received)++] = f->subclass.integer;
299  ast_frfree(f);
300 
301  lastdigittime = ast_tvnow();
302  }
303 
304  /* Null terminate the end of the digit_string */
305  digit_string[*received] = '\0';
306 
307  return rtn;
308 }
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
static int fdtimeout
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4251
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
#define ast_verb(level,...)
Definition: logger.h:455
struct ast_frame_subclass subclass
union ast_frame::@255 data
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3137
static int sdtimeout
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
Data structure associated with a single frame of data.
enum ast_frame_type frametype

◆ reload()

static int reload ( void  )
static

Definition at line 986 of file app_alarmreceiver.c.

References AST_MODFLAG_DEFAULT, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_EXTENDED, ASTERISK_GPL_KEY, load_config(), load_module(), and unload_module().

987 {
988  if (load_config(1)) {
990  }
991 
993 }
static int load_config(int reload)
Load the configuration from the configuration file.
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78

◆ send_tone_burst()

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

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

Since
11.0
Parameters
chanAsterisk Channel
tone_freqFrequency of the tone to send
tone_durationTone duration in ms
delayDelay before sending the tone
Return values
0success
-1failure

Definition at line 496 of file app_alarmreceiver.c.

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

Referenced by receive_ademco_event().

497 {
498  if (delay && ast_safe_sleep(chan, delay)) {
499  return -1;
500  }
501 
502  if (ast_playtones_start(chan, toneloudness, tone_freq, 0)) {
503  return -1;
504  }
505 
506  if (ast_safe_sleep(chan, tone_duration)) {
507  return -1;
508  }
509 
510  ast_playtones_stop(chan);
511  return 0;
512 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1554
static int toneloudness
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302

◆ unload_module()

static int unload_module ( void  )
static

Unregister Alarm Receiver App.

Return values
0success
-1failure

Definition at line 959 of file app_alarmreceiver.c.

References app, and ast_unregister_application().

Referenced by reload().

960 {
962 }
static const char app[]
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

◆ write_event()

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

Log a single event.

Parameters
logfileLog File Pointer
eventEvent Structure
Return values
0success
-1failure

Definition at line 382 of file app_alarmreceiver.c.

References event_node::data, and no_group_meta.

Referenced by log_events().

383 {
384  if (fprintf(logfile, "%s%s\n", no_group_meta ? "event=" : "", event->data) < 0) {
385  return -1;
386  }
387 
388  return 0;
389 }
static int no_group_meta

◆ write_metadata()

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

Write metadata to log file.

Parameters
logfileLog File Pointer
signalling_typeSignaling Type
chanAsterisk Channel
no_checksumExpecting messages without checksum
Return values
0success
-1failure

Definition at line 321 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, ast_bridge::name, no_group_meta, NULL, S_COR, and time_stamp_format.

Referenced by log_events().

322 {
323  struct timeval t;
324  struct ast_tm now;
325  char *cl;
326  char *cn;
327  char workstring[80];
328  char timestamp[80];
329 
330  /* Extract the caller ID location */
331  ast_copy_string(workstring,
332  S_COR(ast_channel_caller(chan)->id.number.valid,
333  ast_channel_caller(chan)->id.number.str, ""), sizeof(workstring));
334  ast_shrink_phone_number(workstring);
335  if (ast_strlen_zero(workstring)) {
336  cl = "<unknown>";
337  } else {
338  cl = workstring;
339  }
340  cn = S_COR(ast_channel_caller(chan)->id.name.valid,
341  ast_channel_caller(chan)->id.name.str, "<unknown>");
342 
343  /* Get the current time */
344  t = ast_tvnow();
345  ast_localtime(&t, &now, NULL);
346 
347  /* Format the time */
348  ast_strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
349 
350  if (no_group_meta && fprintf(logfile, "PROTOCOL=%s\n"
351  "CHECKSUM=%s\n"
352  "CALLINGFROM=%s\n"
353  "CALLERNAME=%s\n"
354  "TIMESTAMP=%s\n\n",
355  signalling_type, (!no_checksum) ? "yes" : "no", cl, cn, timestamp) > -1) {
356  return 0;
357  } else if (fprintf(logfile, "\n\n[metadata]\n\n"
358  "PROTOCOL=%s\n"
359  "CHECKSUM=%s\n"
360  "CALLINGFROM=%s\n"
361  "CALLERNAME=%s\n"
362  "TIMESTAMP=%s\n\n"
363  "[events]\n\n",
364  signalling_type, (!no_checksum) ? "yes" : "no", cl, cn, timestamp) > -1) {
365  return 0;
366  }
367 
368  ast_verb(3, "AlarmReceiver: can't write metadata\n");
369  ast_debug(1, "AlarmReceiver: can't write metadata\n");
370  return -1;
371 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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:1739
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:455
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#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:85
#define ast_strlen_zero(a)
Definition: muted.c:73
static const char name[]
Definition: cdr_mysql.c:74
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:2524
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char time_stamp_format[128]
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:947
static int no_group_meta

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, }
static

Definition at line 1000 of file app_alarmreceiver.c.

◆ answait

int answait = 1250
static

Definition at line 184 of file app_alarmreceiver.c.

Referenced by alarmreceiver_exec(), and load_config().

◆ app

const char app[] = "AlarmReceiver"
static

Definition at line 146 of file app_alarmreceiver.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1000 of file app_alarmreceiver.c.

◆ call_start_time

struct timeval call_start_time

Definition at line 144 of file app_alarmreceiver.c.

Referenced by alarmreceiver_exec(), and receive_ademco_event().

◆ db_family

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

Definition at line 190 of file app_alarmreceiver.c.

Referenced by database_increment(), and load_config().

◆ digit

char digit

◆ digits_mapping

struct { ... } digits_mapping[]
Initial value:
= { {'0', 10}, {'1', 1} , {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5},
{'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'*', 11}, {'#', 12},
{'A', 13}, {'B', 14}, {'C', 15} }

Referenced by ademco_verify_checksum().

◆ event_app

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

Definition at line 189 of file app_alarmreceiver.c.

Referenced by alarmreceiver_exec(), and load_config().

◆ event_file

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

Definition at line 194 of file app_alarmreceiver.c.

Referenced by log_events().

◆ event_spool_dir

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

Definition at line 188 of file app_alarmreceiver.c.

Referenced by load_config(), and log_events().

◆ fdtimeout

int fdtimeout = 2000
static

Definition at line 182 of file app_alarmreceiver.c.

Referenced by acf_faxopt_write(), load_config(), and receive_dtmf_digits().

◆ log_individual_events

int log_individual_events = 0
static

Definition at line 186 of file app_alarmreceiver.c.

Referenced by alarmreceiver_exec(), load_config(), and receive_ademco_event().

◆ no_group_meta

int no_group_meta = 0
static

Definition at line 187 of file app_alarmreceiver.c.

Referenced by load_config(), write_event(), and write_metadata().

◆ sdtimeout

int sdtimeout = 200
static

Definition at line 183 of file app_alarmreceiver.c.

Referenced by load_config(), and receive_dtmf_digits().

◆ time_stamp_format

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

Definition at line 191 of file app_alarmreceiver.c.

Referenced by load_config(), and write_metadata().

◆ toneloudness

int toneloudness = 4096
static

Definition at line 185 of file app_alarmreceiver.c.

Referenced by load_config(), and send_tone_burst().

◆ weight

char weight