diff options
-rwxr-xr-x | apps/app_rpt.c | 188 |
1 files changed, 159 insertions, 29 deletions
diff --git a/apps/app_rpt.c b/apps/app_rpt.c index 526af3e8d..838a71f28 100755 --- a/apps/app_rpt.c +++ b/apps/app_rpt.c @@ -3,7 +3,7 @@ * Asterisk -- A telephony toolkit for Linux. * * Radio Repeater / Remote Base program - * version 0.5 6/22/04 + * version 0.7 6/25/04 * * Copyright (C) 2002-2004, Jim Dixon, WB6NIL * @@ -23,7 +23,9 @@ * *6 - autopatch access/send (*) * *7 - system status * *8 - force ID - * *9 - system reset + * *90 - system disable (and reset) + * *91 - system enable + * *99 - system reset * * To send an asterisk (*) while dialing or talking on phone, * use the autopatch acess code. @@ -32,7 +34,9 @@ /* number of digits for function after *. Must be at least 1 */ #define FUNCTION_LEN 4 /* string containing all of the 1 digit functions */ -#define SHORTFUNCS "056789" +#define SHORTFUNCS "05678" +/* string containing all of the 2 digit functions */ +#define MEDFUNCS "9" /* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */ @@ -48,7 +52,7 @@ enum {REM_OFF,REM_MONITOR,REM_TX}; enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO, - CONNECTED,CONNFAIL,STATUS}; + CONNECTED,CONNFAIL,STATUS,TIMEOUT}; #include <asterisk/lock.h> #include <asterisk/file.h> @@ -80,7 +84,7 @@ enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO, #include <tonezone.h> #include <linux/zaptel.h> -static char *tdesc = "Radio Repeater / Remote Base version 0.3 06/18/2004"; +static char *tdesc = "Radio Repeater / Remote Base version 0.7 06/25/2004"; static char *app = "Rpt"; static char *synopsis = "Radio Repeater/Remote Base Control System"; @@ -154,6 +158,9 @@ static struct rpt char remoteon; char simple; char remote; + char tounkeyed; + char tonotify; + char enable; char dtmfbuf[MAXDTMF]; char rem_dtmfbuf[MAXDTMF]; char cmdnode[50]; @@ -402,6 +409,16 @@ struct ast_channel *mychannel; } imdone = 1; break; + case TIMEOUT: + res = ast_streamfile(mychannel, "rpt/node", mychannel->language); + if (!res) + res = ast_waitstream(mychannel, ""); + else + ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); + ast_stopstream(mychannel); + ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language); + res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language); + break; } if (!imdone) { @@ -667,15 +684,12 @@ struct rpt_link *l; /* first, see if our dude is there */ while(l != &myrpt->links) { - if (!l->isremote) + /* if we found it, write it and were done */ + if (!strcmp(l->name,myrpt->cmdnode)) { - /* if we found it, write it and were done */ - if (!strcmp(l->name,myrpt->cmdnode)) - { - wf.data = strdup(str); - ast_write(l->chan,&wf); - return; - } + wf.data = strdup(str); + ast_write(l->chan,&wf); + return; } l = l->next; } @@ -683,11 +697,8 @@ struct rpt_link *l; /* if not, give it to everyone */ while(l != &myrpt->links) { - if (!l->isremote) - { - wf.data = strdup(str); - ast_write(l->chan,&wf); - } + wf.data = strdup(str); + ast_write(l->chan,&wf); l = l->next; } return; @@ -703,6 +714,7 @@ ZT_CONFINFO ci; /* conference info */ switch(atoi(cmd) / 1000) { case 6: /* autopatch on / send asterisk (*) */ + if (!myrpt->enable) return; ast_mutex_lock(&myrpt->lock); /* if on call, force * into current audio stream */ if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) @@ -725,6 +737,7 @@ ZT_CONFINFO ci; /* conference info */ pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt); return; case 0: /* autopatch off */ + if (!myrpt->enable) return; ast_mutex_lock(&myrpt->lock); if (!myrpt->callmode) { @@ -735,8 +748,19 @@ ZT_CONFINFO ci; /* conference info */ ast_mutex_unlock(&myrpt->lock); rpt_telemetry(myrpt,TERM,NULL); return; - case 9: /* master reset */ + case 9: /* system control group */ + /* if invalid, just ignore */ + if ((cmd[1] >= '2') && (cmd[1] <= '8')) return; ast_mutex_lock(&myrpt->lock); + if (cmd[1] == '1') /* system enable */ + { + myrpt->enable = 1; + } + if (cmd[1] == '0') /* system disable */ + { + myrpt->enable = 0; + } + /* reset system */ myrpt->callmode = 0; ast_mutex_unlock(&myrpt->lock); l = myrpt->links.next; @@ -748,6 +772,7 @@ ZT_CONFINFO ci; /* conference info */ } break; case 1: /* remote base off */ + if (!myrpt->enable) return; val = ast_variable_retrieve(cfg,NODES,cmd + 1); if (!val) { @@ -775,6 +800,7 @@ ZT_CONFINFO ci; /* conference info */ ast_mutex_unlock(&myrpt->lock); return; case 2: /* remote base monitor */ + if (!myrpt->enable) return; val = ast_variable_retrieve(cfg,NODES,cmd + 1); if (!val) { @@ -872,6 +898,7 @@ ZT_CONFINFO ci; /* conference info */ ast_mutex_unlock(&myrpt->lock); break; case 3: /* remote base tranceieve */ + if (!myrpt->enable) return; val = ast_variable_retrieve(cfg,NODES,cmd + 1); if (!val) { @@ -888,6 +915,7 @@ ZT_CONFINFO ci; /* conference info */ { /* if found matching string */ if (!strcmp(l->name,cmd + 1)) break; + l = l->next; } /* if found */ if (l != &myrpt->links) @@ -970,6 +998,7 @@ ZT_CONFINFO ci; /* conference info */ ast_mutex_unlock(&myrpt->lock); break; case 4: /* remote cmd mode */ + if (!myrpt->enable) return; /* if doesnt allow link cmd, return */ if ((!allow_linkcmd) || (myrpt->links.next == &myrpt->links)) return; /* if already in cmd mode, or selected self, forget it */ @@ -995,18 +1024,22 @@ ZT_CONFINFO ci; /* conference info */ rpt_telemetry(myrpt,REMGO,NULL); return; case 7: /* system status */ + if (!myrpt->enable) return; rpt_telemetry(myrpt,STATUS,NULL); return; case 8: /* force ID */ + if (!myrpt->enable) return; myrpt->idtimer = 0; return; default: return; } + if (!myrpt->enable) return; rpt_telemetry(myrpt,COMPLETE,NULL); } -static void handle_link_data(struct rpt *myrpt, char *str) +static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink, + char *str) { char tmp[300],cmd[300],dest[300],src[300],c; int seq; @@ -1021,7 +1054,6 @@ struct ast_frame wf; wf.mallocd = 1; wf.datalen = strlen(str) + 1; wf.samples = 0; - l = myrpt->links.next; /* put string in our buffer */ strncpy(tmp,str,sizeof(tmp) - 1); if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5) @@ -1038,10 +1070,39 @@ struct ast_frame wf; if (strcmp(dest,myrpt->name)) { l = myrpt->links.next; + /* see if this is one in list */ while(l != &myrpt->links) { - if (!l->isremote) + /* dont send back from where it came */ + if ((l == mylink) || (!strcmp(l->name,mylink->name))) { + l = l->next; + continue; + } + /* if it is, send it and we're done */ + if (!strcmp(l->name,dest)) + { + /* send, but not to src */ + if (strcmp(l->name,src)) { + wf.data = strdup(str); + ast_write(l->chan,&wf); + } + return; + } + l = l->next; + } + l = myrpt->links.next; + /* otherwise, send it to all of em */ + while(l != &myrpt->links) + { + /* dont send back from where it came */ + if ((l == mylink) || (!strcmp(l->name,mylink->name))) + { + l = l->next; + continue; + } + /* send, but not to src */ + if (strcmp(l->name,src)) { wf.data = strdup(str); ast_write(l->chan,&wf); } @@ -1072,6 +1133,13 @@ struct ast_frame wf; myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = '0'; myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; } + /* if to terminate function now */ + if ((myrpt->rem_dtmfidx == 2) && strchr(MEDFUNCS,myrpt->rem_dtmfbuf[0])) + { + while(myrpt->rem_dtmfidx < FUNCTION_LEN) + myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = '0'; + myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; + } } if (myrpt->rem_dtmfidx == FUNCTION_LEN) { @@ -1087,6 +1155,29 @@ struct ast_frame wf; return; } +static void handle_remote_data(struct rpt *myrpt, char *str) +{ +char tmp[300],cmd[300],dest[300],src[300],c; +int seq; + + /* put string in our buffer */ + strncpy(tmp,str,sizeof(tmp) - 1); + if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5) + { + ast_log(LOG_WARNING, "Unable to parse link string %s\n",str); + return; + } + if (strcmp(cmd,"D")) + { + ast_log(LOG_WARNING, "Unable to parse link string %s\n",str); + return; + } + /* if not for me, ignore */ + if (strcmp(dest,myrpt->name)) return; + printf("Remote %s got DTMF %c\n",myrpt->name,c); + return; +} + /* single thread with one file (request) to dial */ static void *rpt(void *this) { @@ -1223,7 +1314,8 @@ pthread_attr_t attr; myrpt->totimer = 0; myrpt->idtimer = 0; myrpt->callmode = 0; - ast_mutex_unlock(&myrpt->lock); + myrpt->tounkeyed = 0; + myrpt->tonotify = 0; lasttx = 0; keyed = 0; myrpt->dtmfidx = -1; @@ -1232,6 +1324,8 @@ pthread_attr_t attr; myrpt->rem_dtmfbuf[0] = 0; dtmf_time = 0; myrpt->rem_dtmf_time = 0; + myrpt->enable = 1; + ast_mutex_unlock(&myrpt->lock); val = 0; ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0); val = 1; @@ -1258,15 +1352,32 @@ pthread_attr_t attr; totx = (keyed || myrpt->callmode || (myrpt->tele.next != &myrpt->tele)); myrpt->exttx = totx; - totx |= remrx; - if (!totx) myrpt->totimer = myrpt->totime; + totx = totx || remrx; + if (!totx) + { + myrpt->totimer = myrpt->totime; + myrpt->tounkeyed = 0; + myrpt->tonotify = 0; + } else myrpt->tailtimer = myrpt->hangtime; - totx = (totx || myrpt->tailtimer) && myrpt->totimer; + totx = totx && myrpt->totimer; + /* if timed-out and not said already, say it */ + if ((!myrpt->totimer) && (!myrpt->tonotify)) + { + myrpt->tonotify = 1; + rpt_telemetry(myrpt,TIMEOUT,NULL); + } /* if wants to transmit and in phone call, but timed out, reset time-out timer if keyed */ - if ((!totx) && (!myrpt->totimer) && myrpt->callmode && keyed) + if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!keyed)) + { + myrpt->tounkeyed = 1; + } + if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && keyed) { myrpt->totimer = myrpt->totime; + myrpt->tounkeyed = 0; + myrpt->tonotify = 0; ast_mutex_unlock(&myrpt->lock); continue; } @@ -1275,6 +1386,11 @@ pthread_attr_t attr; { myrpt->callmode = 0; } + /* get rid of tail if timed out */ + if (!myrpt->totimer) myrpt->tailtimer = 0; + /* if not timed-out, add in tail */ + if (myrpt->totimer) totx = totx || myrpt->tailtimer; + /* if time to ID */ if (totx && (!myrpt->idtimer)) { myrpt->idtimer = myrpt->idtime; @@ -1282,6 +1398,8 @@ pthread_attr_t attr; rpt_telemetry(myrpt,ID,NULL); ast_mutex_lock(&myrpt->lock); } + /* let telemetry transmit anyway (regardless of timeout) */ + totx = totx || (myrpt->tele.next != &myrpt->tele); if (totx && (!lasttx)) { lasttx = 1; @@ -1289,6 +1407,7 @@ pthread_attr_t attr; ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY); ast_mutex_lock(&myrpt->lock); } + totx = totx && myrpt->enable; if ((!totx) && lasttx) { lasttx = 0; @@ -1421,6 +1540,13 @@ pthread_attr_t attr; myrpt->dtmfbuf[myrpt->dtmfidx++] = '0'; myrpt->dtmfbuf[myrpt->dtmfidx] = 0; } + /* if to terminate function now */ + if ((myrpt->dtmfidx == 2) && strchr(MEDFUNCS,myrpt->dtmfbuf[0])) + { + while(myrpt->dtmfidx < FUNCTION_LEN) + myrpt->dtmfbuf[myrpt->dtmfidx++] = '0'; + myrpt->dtmfbuf[myrpt->dtmfidx] = 0; + } } if (myrpt->dtmfidx == FUNCTION_LEN) { @@ -1589,7 +1715,7 @@ pthread_attr_t attr; } if (f->frametype == AST_FRAME_TEXT) { - handle_link_data(myrpt,f->data); + handle_link_data(myrpt,l,f->data); } if (f->frametype == AST_FRAME_CONTROL) { @@ -1839,6 +1965,7 @@ static int rpt_exec(struct ast_channel *chan, void *data) { /* if found matching string */ if (!strcmp(l->name,b1)) break; + l = l->next; } /* if found */ if (l != &myrpt->links) @@ -2027,7 +2154,7 @@ static int rpt_exec(struct ast_channel *chan, void *data) } else if (f->frametype == AST_FRAME_TEXT) { - handle_link_data(myrpt,f->data); + handle_remote_data(myrpt,f->data); } else if (f->frametype == AST_FRAME_CONTROL) { @@ -2113,9 +2240,12 @@ static int rpt_exec(struct ast_channel *chan, void *data) int unload_module(void) { int i; + STANDARD_HANGUP_LOCALUSERS; for(i = 0; i < nrpts; i++) { + if (!strcmp(rpt_vars[i].name,NODES)) continue; ast_mutex_destroy(&rpt_vars[i].lock); + } return ast_unregister_application(app); return 0; } |