273
273
<para>Consequently, to have a sensor that always triggers a breach alarm immediately, set this option to 1 second.</para>
274
274
</description>
275
275
</configOption>
276
+ <configOption name="concurrent_device">
277
+ <synopsis>Device to dial concurrently when the sensor is triggered</synopsis>
278
+ <description>
279
+ <para>An additional device that will be dialed simultaneously when the sensor is triggered.
280
+ This device will be disconnected when the sensor is restored to normal.</para>
281
+ <para>This can be used to sound an audible alarm while this sensor is triggered. For example, if a bell chime is connected to a specific
282
+ channel, specifying that device for this setting will ensure that whenever this sensor is off-normal, the bell chime will be activated.</para>
283
+ </description>
284
+ </configOption>
276
285
</configObject>
277
286
<configObject name="keypad">
278
287
<synopsis>Configuration section for a keypad</synopsis>
@@ -532,6 +541,7 @@ struct alarm_sensor {
532
541
char sensor_id [AST_MAX_EXTENSION ];
533
542
int disarm_delay ;
534
543
const char * device ;
544
+ char * concurrent_device ;
535
545
AST_LIST_ENTRY (alarm_sensor ) entry ;
536
546
unsigned int triggered :1 ; /* Sensor triggered? */
537
547
char data [];
@@ -665,6 +675,9 @@ static void cleanup_server(struct alarm_server *s)
665
675
666
676
static void cleanup_sensor (struct alarm_sensor * s )
667
677
{
678
+ if (s -> concurrent_device ) {
679
+ ast_free (s -> concurrent_device );
680
+ }
668
681
ast_free (s );
669
682
}
670
683
@@ -2136,6 +2149,8 @@ static int load_config(void)
2136
2149
ast_copy_string (s -> sensor_id , var -> value , sizeof (s -> sensor_id ));
2137
2150
} else if (!strcasecmp (var -> name , "disarm_delay" ) && !ast_strlen_zero (var -> value )) {
2138
2151
s -> disarm_delay = atoi (var -> value );
2152
+ } else if (!strcasecmp (var -> name , "concurrent_device" ) && !ast_strlen_zero (var -> value )) {
2153
+ s -> concurrent_device = ast_strdup (var -> value );
2139
2154
} else {
2140
2155
ast_log (LOG_WARNING , "Unknown keyword in section '%s': %s at line %d of %s\n" , cat , var -> name , var -> lineno , CONFIG_FILE );
2141
2156
}
@@ -2211,6 +2226,7 @@ static int alarmsensor_exec(struct ast_channel *chan, const char *data)
2211
2226
struct alarm_sensor * s ;
2212
2227
time_t breach_time ;
2213
2228
int is_egress ;
2229
+ struct ast_channel * concurrent_chan = NULL ;
2214
2230
2215
2231
AST_DECLARE_APP_ARGS (args ,
2216
2232
AST_APP_ARG (client );
@@ -2298,6 +2314,27 @@ static int alarmsensor_exec(struct ast_channel *chan, const char *data)
2298
2314
orig_app_device (c -> keypad_device , NULL , "AlarmKeypad" , c -> name , c -> cid_num , c -> cid_name );
2299
2315
}
2300
2316
2317
+ if (s -> concurrent_device ) {
2318
+ int res ;
2319
+ char * tech , * resource = ast_strdupa (s -> concurrent_device );
2320
+ tech = strsep (& resource , "/" );
2321
+ concurrent_chan = new_channel (tech , resource );
2322
+ if (!concurrent_chan ) {
2323
+ ast_log (LOG_ERROR , "Failed to set up concurrent channel\n" );
2324
+ } else {
2325
+ /* Place the call, but don't wait on the answer */
2326
+ res = ast_call (concurrent_chan , resource , 0 );
2327
+ if (res ) {
2328
+ ast_log (LOG_ERROR , "Failed to call on %s\n" , ast_channel_name (concurrent_chan ));
2329
+ ast_hangup (concurrent_chan );
2330
+ concurrent_chan = NULL ;
2331
+ } else {
2332
+ ast_verb (3 , "Called %s/%s\n" , tech , resource );
2333
+ ast_autoservice_start (concurrent_chan );
2334
+ }
2335
+ }
2336
+ }
2337
+
2301
2338
/* Now, wait for the sensor to be restored. This could be soon, it could not be. */
2302
2339
while (ast_safe_sleep (chan , 60000 ) != -1 );
2303
2340
@@ -2310,6 +2347,9 @@ static int alarmsensor_exec(struct ast_channel *chan, const char *data)
2310
2347
2311
2348
cleanup :
2312
2349
AST_RWLIST_UNLOCK (& clients );
2350
+ if (concurrent_chan ) {
2351
+ ast_hangup (concurrent_chan );
2352
+ }
2313
2353
return -1 ; /* Never continue executing dialplan */
2314
2354
}
2315
2355
0 commit comments