28 #include <netinet/in.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
33 extern int evalExpr(
double *vp,
char *errmsg);
38 extern int setOperand(
char *name,
double valu);
41 static void compileINDI(
char *expr);
42 static FILE *openINDIServer();
43 static void getProps(FILE *fp);
44 static void initProps(FILE *fp);
45 static int pstatestr(
char *state);
46 static time_t timestampINDI(
char *ts);
47 static int devcmp(
char *op1,
char *op2);
48 static int runEval(FILE *fp);
49 static int setOp(
XMLEle *root);
50 static XMLEle *nxtEle(FILE *fp);
51 static int readServerChar(FILE *fp);
52 static void onAlarm(
int dummy);
55 static char host_def[] =
"localhost";
56 static char *host = host_def;
62 static int directfd = -1;
71 int main(
int ac,
char *av[])
79 while (--ac && **++av ==
'-')
92 fprintf(stderr,
"-d requires open fileno\n");
95 directfd = atoi(*++av);
107 fprintf(stderr,
"Can not combine -d and -h\n");
112 fprintf(stderr,
"-h requires host name\n");
127 fprintf(stderr,
"Can not combine -d and -p\n");
132 fprintf(stderr,
"-p requires tcp port number\n");
141 fprintf(stderr,
"-t requires timeout\n");
144 timeout = atoi(*++av);
154 fprintf(stderr,
"Unknown flag: %c\n", *s);
173 fp = fdopen(directfd,
"r+");
177 fprintf(stderr,
"Direct fd %d: %s\n", directfd, strerror(
errno));
181 fprintf(stderr,
"Using direct fd %d\n", directfd);
185 fp = openINDIServer();
187 fprintf(stderr,
"Connected to %s on port %d\n", host, port);
194 signal(SIGALRM, onAlarm);
203 return (runEval(fp));
208 fprintf(stderr,
"Usage: %s [options] [exp]\n", me);
209 fprintf(stderr,
"Purpose: evaluate an expression of INDI operands\n");
210 fprintf(stderr,
"Version: $Revision: 1.5 $\n");
211 fprintf(stderr,
"Options:\n");
212 fprintf(stderr,
" -b : beep when expression evaluates as true\n");
213 fprintf(stderr,
" -d f : use file descriptor f already open to server\n");
215 fprintf(stderr,
" -e : print each updated expression value\n");
216 fprintf(stderr,
" -f : print final expression value\n");
217 fprintf(stderr,
" -h h : alternate host, default is %s\n", host_def);
218 fprintf(stderr,
" -i : read expression from stdin\n");
219 fprintf(stderr,
" -o : print operands as they change\n");
220 fprintf(stderr,
" -p p : alternate port, default is %d\n",
INDIPORT);
221 fprintf(stderr,
" -t t : max secs to wait, 0 is forever, default is %d\n",
TIMEOUT);
222 fprintf(stderr,
" -v : verbose (cumulative)\n");
223 fprintf(stderr,
" -w : wait for expression to evaluate as true\n");
224 fprintf(stderr,
"[exp] is an arith expression built from the following operators and functions:\n");
225 fprintf(stderr,
" ! + - * / && || > >= == != < <=\n");
226 fprintf(stderr,
" pi sin(rad) cos(rad) tan(rad) asin(x) acos(x) atan(x) atan2(y,x) abs(x)\n");
227 fprintf(stderr,
" degrad(deg) raddeg(rad) floor(x) log(x) log10(x) exp(x) sqrt(x) pow(x,exp)\n");
228 fprintf(stderr,
" operands are of the form \"device.name.element\" (including quotes), where\n");
229 fprintf(stderr,
" element may be:\n");
230 fprintf(stderr,
" _STATE evaluated to 0,1,2,3 from Idle,Ok,Busy,Alert.\n");
231 fprintf(stderr,
" _TS evaluated to UNIX seconds from epoch.\n");
232 fprintf(stderr,
" Switch vectors are evaluated to 0,1 from Off,On.\n");
233 fprintf(stderr,
" Light vectors are evaluated to 0-3 as per _STATE.\n");
234 fprintf(stderr,
"Examples:\n");
235 fprintf(stderr,
" To print 0/1 whether Security.Doors.Front or .Rear are in Alert:\n");
236 fprintf(stderr,
" evalINDI -f '\"Security.Doors.Front\"==3 || \"Security.Doors.Rear\"==3'\n");
237 fprintf(stderr,
" To exit 0 if the Security property as a whole is in a state of Ok:\n");
238 fprintf(stderr,
" evalINDI '\"Security.Security._STATE\"==1'\n");
239 fprintf(stderr,
" To wait for RA and Dec to be near zero and watch their values as they change:\n");
240 fprintf(stderr,
" evalINDI -t 0 -wo 'abs(\"Mount.EqJ2K.RA\")<.01 && abs(\"Mount.EqJ2K.Dec\")<.01'\n");
241 fprintf(stderr,
"Exit 0 if expression evaluates to non-0, 1 if 0, else 2\n");
249 static void compileINDI(
char *expr)
259 while ((nr = fread(exp + nexp, 1, 1024, stdin)) > 0)
260 exp = realloc(exp, (nexp += nr) + 1024);
265 fprintf(stderr,
"Compiling: %s\n", exp);
268 fprintf(stderr,
"Compile err: %s\n", errmsg);
279 static FILE *openINDIServer()
281 struct sockaddr_in serv_addr;
286 hp = gethostbyname(host);
289 perror(
"gethostbyname");
294 (void)memset((
char *)&serv_addr, 0,
sizeof(serv_addr));
295 serv_addr.sin_family = AF_INET;
296 serv_addr.sin_addr.s_addr = ((
struct in_addr *)(hp->h_addr_list[0]))->s_addr;
297 serv_addr.sin_port = htons(port);
298 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
305 if (connect(sockfd, (
struct sockaddr *)&serv_addr,
sizeof(serv_addr)) < 0)
312 return (fdopen(sockfd,
"r+"));
317 static void getProps(FILE *fp)
327 for (i = 0; i < nops; i++)
329 for (j = 0; j < i; j++)
330 if (devcmp(ops[i], ops[j]) == 0)
335 fprintf(stderr,
"sending getProperties for %.*s\n", (
int)(strchr(ops[i],
'.') - ops[i]), ops[i]);
336 fprintf(fp,
"<getProperties version='%g' device='%.*s'/>\n",
INDIV, (
int)(strchr(ops[i],
'.') - ops[i]),
345 static void initProps(FILE *fp)
350 if (setOp(nxtEle(fp)) == 0)
360 static int setOp(
XMLEle *root)
371 if (!strcmp(t,
"defNumberVector") || !strcmp(t,
"setNumberVector"))
376 if (!strcmp(et,
"defNumber") || !strcmp(et,
"oneNumber"))
384 fprintf(stderr,
"%s=%g\n", prop, v);
389 else if (!strcmp(t,
"defSwitchVector") || !strcmp(t,
"setSwitchVector"))
395 if (!strcmp(et,
"defSwitch") || !strcmp(et,
"oneSwitch"))
403 fprintf(stderr,
"%s=%g\n", prop, v);
408 else if (!strcmp(t,
"defLightVector") || !strcmp(t,
"setLightVector"))
413 if (!strcmp(et,
"defLight") || !strcmp(et,
"oneLight"))
421 fprintf(stderr,
"%s=%g\n", prop, v);
431 sprintf(prop,
"%s.%s._STATE", d, n);
432 v = (double)pstatestr(t);
437 fprintf(stderr,
"%s=%g\n", prop, v);
443 sprintf(prop,
"%s.%s._TS", d, n);
444 v = (double)timestampINDI(t);
449 fprintf(stderr,
"%s=%g\n", prop, v);
454 return (nset > 0 ? 0 : -1);
461 static int runEval(FILE *fp)
471 fprintf(stderr,
"Eval: %s\n", errmsg);
475 fprintf(stderr,
"\a");
477 fprintf(stderr,
"%g\n", v);
478 if (!wflag || v != 0)
480 while (setOp(nxtEle(fp)) < 0)
487 fprintf(stderr,
"%g\n", v);
494 static int pstatestr(
char *state)
496 if (!strcmp(state,
"Idle"))
498 if (!strncmp(state,
"Ok", 2))
500 if (!strcmp(state,
"Busy"))
507 static time_t timestampINDI(
char *ts)
511 if (6 == sscanf(ts,
"%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec))
516 return (mktime(&tm));
524 static int devcmp(
char *op1,
char *op2)
526 int n1 = strchr(op1,
'.') - op1;
527 int n2 = strchr(op2,
'.') - op2;
528 return (n1 != n2 || strncmp(op1, op2, n1));
535 static XMLEle *nxtEle(FILE *fp)
552 fprintf(stderr,
"Bad XML from %s/%d: %s\n", host, port, msg);
559 static int readServerChar(FILE *fp)
568 fprintf(stderr,
"INDI server %s/%d disconnected\n", host, port);
573 fprintf(stderr,
"Read %c\n", c);
581 static void onAlarm(
int dummy)
591 fprintf(stderr,
"No values seen for");
593 fprintf(stderr,
" %s", ops[nops]);
594 fprintf(stderr,
"\n");
597 fprintf(stderr,
"Timed out waiting for new values\n");
int getAllOperands(char ***ops)
int evalExpr(double *vp, char *errmsg)
int getSetOperands(char ***ops)
int compileExpr(char *expr, char *errmsg)
int getUnsetOperands(char ***ops)
int main(int ac, char *av[])
int setOperand(char *name, double valu)
Constants and Data structure definitions for the interface to the reference INDI C API implementation...
Interface to the reference INDI C API device implementation on the Device Driver side.
LilXML * newLilXML()
Create a new lilxml parser.
const char * findXMLAttValu(XMLEle *ep, const char *name)
Find an XML element's attribute value.
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
char * tagXMLEle(XMLEle *ep)
Return the tag of an XML element.
void prXMLEle(FILE *fp, XMLEle *ep, int level)
Print an XML element.
XMLEle * readXMLEle(LilXML *lp, int newc, char ynot[])
Process an XML one char at a time.
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
A little DOM-style library to handle parsing and processing an XML file.