Instrument Neutral Distributed Interface INDI 2.2.5
indiuserio.c
Go to the documentation of this file.
1/*
2 Copyright (C) 2021 by Pawel Soja <[email protected]>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18#include "indiuserio.h"
19#include "indiapi.h"
20#include "indidevapi.h"
21#include "indicom.h"
22#include "locale_compat.h"
23#include "base64.h"
24
25#include <stdlib.h>
26#include <string.h>
27
28static void s_userio_xml_message_vprintf(const userio *io, void *user, const char *fmt, va_list ap)
29{
30 char message[MAXINDIMESSAGE];
31 if (fmt)
32 {
33 vsnprintf(message, MAXINDIMESSAGE, fmt, ap);
34
35 userio_prints (io, user, " message='");
36 userio_xml_escape(io, user, message);
37 userio_prints (io, user, "'\n");
38 }
39}
40
41
42void IUUserIONumberContext(const userio *io, void *user, const INumberVectorProperty *nvp)
43{
44 for (int i = 0; i < nvp->nnp; i++)
45 {
46 INumber *np = &nvp->np[i];
47 userio_prints (io, user, " <oneNumber name='");
48 userio_xml_escape(io, user, np->name);
49 userio_prints (io, user, "'>\n");
50 userio_printf (io, user, " %.20g\n", np->value); // safe
51 userio_prints (io, user, " </oneNumber>\n");
52 }
53}
54
55void IUUserIOTextContext(const userio *io, void *user, const ITextVectorProperty *tvp)
56{
57 for (int i = 0; i < tvp->ntp; i++)
58 {
59 IText *tp = &tvp->tp[i];
60 userio_prints (io, user, " <oneText name='");
61 userio_xml_escape(io, user, tp->name);
62 userio_prints (io, user, "'>\n"
63 " ");
64 if (tp->text)
65 userio_xml_escape(io, user, tp->text);
66 userio_prints (io, user, "\n"
67 " </oneText>\n");
68 }
69}
70
71void IUUserIOSwitchContextOne(const userio *io, void *user, const ISwitch *sp)
72{
73 userio_prints (io, user, " <oneSwitch name='");
74 userio_xml_escape(io, user, sp->name);
75 userio_prints (io, user, "'>\n"
76 " ");
77 userio_prints (io, user, sstateStr(sp->s));
78 userio_prints (io, user, "\n"
79 " </oneSwitch>\n");
80}
81
82void IUUserIOSwitchContextFull(const userio *io, void *user, const ISwitchVectorProperty *svp)
83{
84 for (int i = 0; i < svp->nsp; i++)
85 {
86 ISwitch *sp = &svp->sp[i];
87 IUUserIOSwitchContextOne(io, user, sp);
88 }
89}
90
91void IUUserIOSwitchContext(const userio *io, void *user, const ISwitchVectorProperty *svp)
92{
93 ISwitch *onSwitch = IUFindOnSwitch(svp);
94
95 if (svp->r == ISR_1OFMANY && onSwitch)
96 IUUserIOSwitchContextOne(io, user, onSwitch);
97 else
98 IUUserIOSwitchContextFull(io, user, svp);
99}
100
102 const userio *io, void *user,
103 const char *name, unsigned int size, unsigned int bloblen, const void *blob, const char *format
104)
105{
106 unsigned char *encblob;
107 int l;
108
109 userio_prints (io, user, " <oneBLOB\n"
110 " name='");
111 userio_xml_escape(io, user, name);
112 userio_prints (io, user, "'\n");
113 userio_printf (io, user, " size='%d'\n", size); // safe
114
115 // If size is zero, we are only sending a state-change
116 if (size == 0)
117 {
118 userio_prints (io, user, " enclen='0'\n"
119 " format='");
120 userio_xml_escape(io, user, format);
121 userio_prints (io, user, "'>\n");
122 }
123 else
124 {
125 if (io->joinbuff) {
126 userio_prints (io, user, " format='");
127 userio_xml_escape(io, user, format);
128 userio_prints (io, user, "'\n");
129 userio_printf (io, user, " len='%d'\n", bloblen);
130
131 io->joinbuff(user, " attached='true'>\n", (void*)blob, bloblen);
132 } else {
133 size_t sz = 4 * bloblen / 3 + 4;
134 assert_mem(encblob = (unsigned char *)malloc(sz)); // #PS: TODO
135 l = to64frombits_s(encblob, blob, bloblen, sz);
136 if (l == 0) {
137 fprintf(stderr, "%s: Not enough memory for decoding.\n", __func__);
138 exit(1);
139 }
140 userio_printf (io, user, " enclen='%d'\n", l); // safe
141 userio_prints (io, user, " format='");
142 userio_xml_escape(io, user, format);
143 userio_prints (io, user, "'>\n");
144 size_t written = 0;
145 // FIXME: this is not efficient. The CR/LF imply one more copy... Do we need them ?
146 while ((int)written < l)
147 {
148 size_t towrite = ((l - written) > 72) ? 72 : l - written;
149 size_t wr = userio_write(io, user, encblob + written, towrite);
150
151 if (wr == 0)
152 {
153 free(encblob);
154 return;
155 }
156
157 written += wr;
158 if ((written % 72) == 0)
159 userio_putc(io, user, '\n');
160 }
161
162 if ((written % 72) != 0)
163 userio_putc(io, user, '\n');
164
165 free(encblob);
166 }
167 }
168
169 userio_prints (io, user, " </oneBLOB>\n");
170}
171
172void IUUserIOBLOBContext(const userio *io, void *user, const IBLOBVectorProperty *bvp)
173{
174 for (int i = 0; i < bvp->nbp; i++)
175 {
176 IBLOB *bp = &bvp->bp[i];
178 io, user,
179 bp->name, bp->size, bp->bloblen, bp->blob, bp->format
180 );
181 }
182}
183
184void IUUserIOLightContext(const userio *io, void *user, const ILightVectorProperty *lvp)
185{
186 for (int i = 0; i < lvp->nlp; i++)
187 {
188 ILight *lp = &lvp->lp[i];
189 userio_prints (io, user, " <oneLight name='");
190 userio_xml_escape(io, user, lp->name);
191 userio_prints (io, user, "'>\n"
192 " ");
193 userio_prints (io, user, pstateStr(lp->s));
194 userio_prints (io, user, "\n"
195 " </oneLight>\n");
196 }
197}
198
199void IUUserIONewNumber(const userio *io, void *user, const INumberVectorProperty *nvp)
200{
201 locale_char_t *orig = indi_locale_C_numeric_push();
202
203 userio_prints (io, user, "<newNumberVector device='");
204 userio_xml_escape(io, user, nvp->device);
205 userio_prints (io, user, "' name='");
206 userio_xml_escape(io, user, nvp->name);
207 userio_prints (io, user, "'>\n");
208
209 IUUserIONumberContext(io, user, nvp);
210
211 userio_prints (io, user, "</newNumberVector>\n");
212
213 indi_locale_C_numeric_pop(orig);
214}
215
216void IUUserIONewText(const userio *io, void *user, const ITextVectorProperty *tvp)
217{
218 userio_prints (io, user, "<newTextVector device='");
219 userio_xml_escape(io, user, tvp->device);
220 userio_prints (io, user, "' name='");
221 userio_xml_escape(io, user, tvp->name);
222 userio_prints (io, user, "'>\n");
223
224 IUUserIOTextContext(io, user, tvp);
225
226 userio_prints (io, user, "</newTextVector>\n");
227}
228
229void IUUserIONewSwitchFull(const userio *io, void *user, const ISwitchVectorProperty *svp)
230{
231 userio_prints (io, user, "<newSwitchVector device='");
232 userio_xml_escape(io, user, svp->device);
233 userio_prints (io, user, "' name='");
234 userio_xml_escape(io, user, svp->name);
235 userio_prints (io, user, "'>\n");
236 IUUserIOSwitchContextFull(io, user, svp);
237 userio_prints (io, user, "</newSwitchVector>\n");
238}
239
240void IUUserIONewSwitch(const userio *io, void *user, const ISwitchVectorProperty *svp)
241{
242 userio_prints (io, user, "<newSwitchVector device='");
243 userio_xml_escape(io, user, svp->device);
244 userio_prints (io, user, "' name='");
245 userio_xml_escape(io, user, svp->name);
246 userio_prints (io, user, "'>\n");
247 IUUserIOSwitchContext(io, user, svp);
248 userio_prints (io, user, "</newSwitchVector>\n");
249}
250
251void IUUserIONewBLOB(const userio *io, void *user, const IBLOBVectorProperty *bvp)
252{
253 IUUserIONewBLOBStart(io, user, bvp->device, bvp->name, NULL);
254
255 IUUserIOBLOBContext(io, user, bvp);
256
257 IUUserIONewBLOBFinish(io, user);
258}
259
261 const userio *io, void *user,
262 const char *dev, const char *name, const char *timestamp
263)
264{
265 userio_prints (io, user, "<newBLOBVector\n"
266 " device='");
267 userio_xml_escape(io, user, dev);
268 userio_prints (io, user, "'\n"
269 " name='");
270 userio_xml_escape(io, user, name);
271 userio_prints (io, user, "'\n");
272 if (timestamp != NULL)
273 {
274 userio_prints (io, user, " timestamp='");
275 userio_xml_escape(io, user, timestamp);
276 userio_prints (io, user, "'\n");
277 }
278 userio_prints (io, user, ">\n");
279}
280
281void IUUserIONewBLOBFinish(const userio *io, void *user)
282{
283 userio_prints (io, user, "</newBLOBVector>\n");
284}
285
287 const userio *io, void *user,
288 const char *dev, const char *name, const char *fmt, va_list ap
289)
290{
291 userio_prints (io, user, "<delProperty\n device='");
292 userio_xml_escape(io, user, dev);
293 userio_prints (io, user, "'\n");
294 if (name)
295 {
296 userio_prints (io, user, " name='");
297 userio_xml_escape(io, user, name);
298 userio_prints (io, user, "'\n");
299 }
300 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
301
302 s_userio_xml_message_vprintf(io, user, fmt, ap);
303
304 userio_prints (io, user, "/>\n");
305}
306
308 const userio *io, void *user,
309 const char *dev, const char *name
310)
311{
312 userio_printf (io, user, "<getProperties version='%g'", INDIV); // safe
313 // special case for INDI::BaseClient::listenINDI INDI::BaseClientQt::connectServer
314 if (dev && dev[0])
315 {
316 userio_prints (io, user, " device='");
317 userio_xml_escape(io, user, dev);
318 userio_prints (io, user, "'");
319 }
320 if (name && name[0])
321 {
322 userio_prints (io, user, " name='");
323 userio_xml_escape(io, user, name);
324 userio_prints (io, user, "'");
325 }
326 userio_prints (io, user, "/>\n");
327}
328
329// temporary
330static const char *s_BLOBHandlingtoString(BLOBHandling bh)
331{
332 switch (bh)
333 {
334 case B_NEVER: return "Never";
335 case B_ALSO: return "Also";
336 case B_ONLY: return "Only";
337 default: return "Unknown";
338 }
339}
340
342 const userio *io, void *user,
343 const char *dev, const char *name, BLOBHandling blobH
344)
345{
346 userio_prints(io, user, "<enableBLOB device='");
347 userio_xml_escape(io, user, dev);
348 if (name != NULL)
349 {
350 userio_prints(io, user, "' name='");
351 userio_xml_escape(io, user, name);
352 }
353 userio_prints(io, user, "'>");
354 userio_prints(io, user, s_BLOBHandlingtoString(blobH));
355 userio_prints(io, user, "</enableBLOB>\n");
356}
357
359 const userio *io, void *user,
360 const char *dev, const char *fmt, va_list ap
361)
362{
363 userio_prints (io, user, "<message\n");
364 if (dev)
365 {
366 userio_prints (io, user, " device='");
367 userio_xml_escape(io, user, dev);
368 userio_prints (io, user, "'\n");
369 }
370 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
371 s_userio_xml_message_vprintf(io, user, fmt, ap);
372 userio_prints (io, user, "/>\n");
373}
374
376 const userio *io, void *user,
377 const char *dev, const char *fmt, ...
378)
379{
380 va_list ap;
381 va_start(ap, fmt);
382 IDUserIOMessageVA(io, user, dev, fmt, ap);
383 va_end(ap);
384}
385
387 const userio *io, void *user, int ctag
388)
389{
390 /* Opening tag */
391 if (ctag == 0)
392 {
393 userio_prints(io, user, "<INDIDriver>\n");
394 }
395 /* Closing tag */
396 else
397 {
398 userio_prints(io, user, "</INDIDriver>\n");
399 }
400}
401
403 const userio *io, void *user,
404 const ITextVectorProperty *tvp, const char *fmt, va_list ap
405)
406{
407 locale_char_t *orig = indi_locale_C_numeric_push();
408 userio_prints (io, user, "<defTextVector\n"
409 " device='");
410 userio_xml_escape(io, user, tvp->device);
411 userio_prints (io, user, "'\n"
412 " name='");
413 userio_xml_escape(io, user, tvp->name);
414 userio_prints (io, user, "'\n"
415 " label='");
416 userio_xml_escape(io, user, tvp->label);
417 userio_prints (io, user, "'\n"
418 " group='");
419 userio_xml_escape(io, user, tvp->group);
420 userio_prints (io, user, "'\n");
421 userio_printf (io, user, " state='%s'\n", pstateStr(tvp->s)); // safe
422 userio_printf (io, user, " perm='%s'\n", permStr(tvp->p)); // safe
423 userio_printf (io, user, " timeout='%g'\n", tvp->timeout); // safe
424 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
425 s_userio_xml_message_vprintf(io, user, fmt, ap);
426 userio_prints (io, user, ">\n");
427
428 for (int i = 0; i < tvp->ntp; i++)
429 {
430 IText *tp = &tvp->tp[i];
431 userio_prints (io, user, " <defText\n"
432 " name='");
433 userio_xml_escape(io, user, tp->name);
434 userio_prints (io, user, "'\n"
435 " label='");
436 userio_xml_escape(io, user, tp->label);
437 userio_prints (io, user, "'>\n"
438 " ");
439 if (tp->text)
440 userio_xml_escape(io, user, tp->text);
441 userio_prints (io, user, "\n"
442 " </defText>\n");
443 }
444
445 userio_prints (io, user, "</defTextVector>\n");
446 indi_locale_C_numeric_pop(orig);
447}
448
450 const userio *io, void *user,
451 const INumberVectorProperty *n, const char *fmt, va_list ap
452)
453{
454 locale_char_t *orig = indi_locale_C_numeric_push();
455 userio_prints (io, user, "<defNumberVector\n"
456 " device='");
457 userio_xml_escape(io, user, n->device);
458 userio_prints (io, user, "'\n"
459 " name='");
460 userio_xml_escape(io, user, n->name);
461 userio_prints (io, user, "'\n"
462 " label='");
463 userio_xml_escape(io, user, n->label);
464 userio_prints (io, user, "'\n"
465 " group='");
466 userio_xml_escape(io, user, n->group);
467 userio_prints (io, user, "'\n");
468 userio_printf (io, user, " state='%s'\n", pstateStr(n->s)); // safe
469 userio_printf (io, user, " perm='%s'\n", permStr(n->p)); // safe
470 userio_printf (io, user, " timeout='%g'\n", n->timeout); // safe
471 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
472 s_userio_xml_message_vprintf(io, user, fmt, ap);
473 userio_prints (io, user, ">\n");
474
475 for (int i = 0; i < n->nnp; i++)
476 {
477 INumber *np = &n->np[i];
478
479 userio_prints (io, user, " <defNumber\n"
480 " name='");
481 userio_xml_escape(io, user, np->name);
482 userio_prints (io, user, "'\n"
483 " label='");
484 userio_xml_escape(io, user, np->label);
485 userio_prints (io, user, "'\n"
486 " format='");
487 userio_xml_escape(io, user, np->format);
488 userio_prints (io, user, "'\n");
489 userio_printf (io, user, " min='%.20g'\n", np->min); // safe
490 userio_printf (io, user, " max='%.20g'\n", np->max); // safe
491 userio_printf (io, user, " step='%.20g'>\n", np->step); // safe
492 userio_printf (io, user, " %.20g\n", np->value); // safe
493
494 userio_prints (io, user, " </defNumber>\n");
495 }
496
497 userio_prints (io, user, "</defNumberVector>\n");
498 indi_locale_C_numeric_pop(orig);
499}
500
502 const userio *io, void *user,
503 const ISwitchVectorProperty *s, const char *fmt, va_list ap
504)
505{
506 locale_char_t *orig = indi_locale_C_numeric_push();
507 userio_prints (io, user, "<defSwitchVector\n"
508 " device='");
509 userio_xml_escape(io, user, s->device);
510 userio_prints (io, user, "'\n"
511 " name='");
512 userio_xml_escape(io, user, s->name);
513 userio_prints (io, user, "'\n"
514 " label='");
515 userio_xml_escape(io, user, s->label);
516 userio_prints (io, user, "'\n"
517 " group='");
518 userio_xml_escape(io, user, s->group);
519 userio_prints (io, user, "'\n");
520 userio_printf (io, user, " state='%s'\n", pstateStr(s->s)); // safe
521 userio_printf (io, user, " perm='%s'\n", permStr(s->p)); // safe
522 userio_printf (io, user, " rule='%s'\n", ruleStr(s->r)); // safe
523 userio_printf (io, user, " timeout='%g'\n", s->timeout); // safe
524 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
525 s_userio_xml_message_vprintf(io, user, fmt, ap);
526 userio_prints (io, user, ">\n");
527
528 for (int i = 0; i < s->nsp; i++)
529 {
530 ISwitch *sp = &s->sp[i];
531 userio_prints (io, user, " <defSwitch\n"
532 " name='");
533 userio_xml_escape(io, user, sp->name);
534 userio_prints (io, user, "'\n"
535 " label='");
536 userio_xml_escape(io, user, sp->label);
537 userio_prints (io, user, "'>\n");
538 userio_printf (io, user, " %s\n", sstateStr(sp->s)); // safe
539 userio_prints (io, user, " </defSwitch>\n");
540 }
541
542 userio_prints (io, user, "</defSwitchVector>\n");
543 indi_locale_C_numeric_pop(orig);
544}
545
547 const userio *io, void *user,
548 const ILightVectorProperty *lvp, const char *fmt, va_list ap
549)
550{
551 userio_prints (io, user, "<defLightVector\n"
552 " device='");
553 userio_xml_escape(io, user, lvp->device);
554 userio_prints (io, user, "'\n"
555 " name='");
556 userio_xml_escape(io, user, lvp->name);
557 userio_prints (io, user, "'\n"
558 " label='");
559 userio_xml_escape(io, user, lvp->label);
560 userio_prints (io, user, "'\n"
561 " group='");
562 userio_xml_escape(io, user, lvp->group);
563 userio_prints (io, user, "'\n");
564 userio_printf (io, user, " state='%s'\n", pstateStr(lvp->s)); // safe
565 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
566 s_userio_xml_message_vprintf(io, user, fmt, ap);
567 userio_prints (io, user, ">\n");
568
569 for (int i = 0; i < lvp->nlp; i++)
570 {
571 ILight *lp = &lvp->lp[i];
572 userio_prints (io, user, " <defLight\n"
573 " name='");
574 userio_xml_escape(io, user, lp->name);
575 userio_prints (io, user, "'\n"
576 " label='");
577 userio_xml_escape(io, user, lp->label);
578 userio_prints (io, user, "'>\n");
579 userio_printf (io, user, " %s\n", pstateStr(lp->s)); // safe
580 userio_prints (io, user, " </defLight>\n");
581 }
582
583 userio_prints (io, user, "</defLightVector>\n");
584}
585
587 const userio *io, void *user,
588 const IBLOBVectorProperty *b, const char *fmt, va_list ap
589)
590{
591 locale_char_t *orig = indi_locale_C_numeric_push();
592 userio_prints (io, user, "<defBLOBVector\n"
593 " device='");
594 userio_xml_escape(io, user, b->device);
595 userio_prints (io, user, "'\n"
596 " name='");
597 userio_xml_escape(io, user, b->name);
598 userio_prints (io, user, "'\n"
599 " label='");
600 userio_xml_escape(io, user, b->label);
601 userio_prints (io, user, "'\n"
602 " group='");
603 userio_xml_escape(io, user, b->group);
604 userio_prints (io, user, "'\n");
605 userio_printf (io, user, " state='%s'\n", pstateStr(b->s)); // safe
606 userio_printf (io, user, " perm='%s'\n", permStr(b->p)); // safe
607 userio_printf (io, user, " timeout='%g'\n", b->timeout); // safe
608 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
609 s_userio_xml_message_vprintf(io, user, fmt, ap);
610 userio_prints (io, user, ">\n");
611
612 for (int i = 0; i < b->nbp; i++)
613 {
614 IBLOB *bp = &b->bp[i];
615 userio_prints (io, user, " <defBLOB\n"
616 " name='");
617 userio_xml_escape(io, user, bp->name);
618 userio_prints (io, user, "'\n"
619 " label='");
620 userio_xml_escape(io, user, bp->label);
621 userio_prints (io, user, "'\n"
622 " />\n");
623 }
624
625 userio_prints (io, user, "</defBLOBVector>\n");
626 indi_locale_C_numeric_pop(orig);
627}
628
630 const userio *io, void *user,
631 const ITextVectorProperty *tvp, const char *fmt, va_list ap
632)
633{
634 locale_char_t *orig = indi_locale_C_numeric_push();
635 userio_prints (io, user, "<setTextVector\n"
636 " device='");
637 userio_xml_escape(io, user, tvp->device);
638 userio_prints (io, user, "'\n"
639 " name='");
640 userio_xml_escape(io, user, tvp->name);
641 userio_prints (io, user, "'\n");
642 userio_printf (io, user, " state='%s'\n", pstateStr(tvp->s)); // safe
643 userio_printf (io, user, " timeout='%g'\n", tvp->timeout); // safe
644 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
645 s_userio_xml_message_vprintf(io, user, fmt, ap);
646 userio_prints (io, user, ">\n");
647
648 IUUserIOTextContext(io, user, tvp);
649
650 userio_prints (io, user, "</setTextVector>\n");
651 indi_locale_C_numeric_pop(orig);
652}
653
655 const userio *io, void *user,
656 const INumberVectorProperty *nvp, const char *fmt, va_list ap
657)
658{
659 locale_char_t *orig = indi_locale_C_numeric_push();
660 userio_prints (io, user, "<setNumberVector\n"
661 " device='");
662 userio_xml_escape(io, user, nvp->device);
663 userio_prints (io, user, "'\n"
664 " name='");
665 userio_xml_escape(io, user, nvp->name);
666 userio_prints (io, user, "'\n");
667 userio_printf (io, user, " state='%s'\n", pstateStr(nvp->s)); // safe
668 userio_printf (io, user, " timeout='%g'\n", nvp->timeout); // safe
669 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
670 s_userio_xml_message_vprintf(io, user, fmt, ap);
671 userio_prints (io, user, ">\n");
672
673 IUUserIONumberContext(io, user, nvp);
674
675 userio_prints (io, user, "</setNumberVector>\n");
676 indi_locale_C_numeric_pop(orig);
677}
678
680 const userio *io, void *user,
681 const ISwitchVectorProperty *svp, const char *fmt, va_list ap
682)
683{
684 locale_char_t *orig = indi_locale_C_numeric_push();
685 userio_prints (io, user, "<setSwitchVector\n"
686 " device='");
687 userio_xml_escape(io, user, svp->device);
688 userio_prints (io, user, "'\n"
689 " name='");
690 userio_xml_escape(io, user, svp->name);
691 userio_prints (io, user, "'\n");
692 userio_printf (io, user, " state='%s'\n", pstateStr(svp->s)); // safe
693 userio_printf (io, user, " timeout='%g'\n", svp->timeout); // safe
694 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
695 s_userio_xml_message_vprintf(io, user, fmt, ap);
696 userio_prints (io, user, ">\n");
697
698 IUUserIOSwitchContextFull(io, user, svp);
699
700 userio_prints (io, user, "</setSwitchVector>\n");
701 indi_locale_C_numeric_pop(orig);
702}
703
705 const userio *io, void *user,
706 const ILightVectorProperty *lvp, const char *fmt, va_list ap
707)
708{
709 userio_prints (io, user, "<setLightVector\n"
710 " device='");
711 userio_xml_escape(io, user, lvp->device);
712 userio_prints (io, user, "'\n"
713 " name='");
714 userio_xml_escape(io, user, lvp->name);
715 userio_prints (io, user, "'\n");
716 userio_printf (io, user, " state='%s'\n", pstateStr(lvp->s)); // safe
717 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
718 s_userio_xml_message_vprintf(io, user, fmt, ap);
719 userio_prints (io, user, ">\n");
720
721 IUUserIOLightContext(io, user, lvp);
722
723 userio_prints (io, user, "</setLightVector>\n");
724}
725
727 const userio *io, void *user,
728 const IBLOBVectorProperty *bvp, const char *fmt, va_list ap
729)
730{
731 locale_char_t *orig = indi_locale_C_numeric_push();
732 userio_prints (io, user, "<setBLOBVector\n"
733 " device='");
734 userio_xml_escape(io, user, bvp->device);
735 userio_prints (io, user, "'\n"
736 " name='");
737 userio_xml_escape(io, user, bvp->name);
738 userio_prints (io, user, "'\n");
739 userio_printf (io, user, " state='%s'\n", pstateStr(bvp->s)); // safe
740 userio_printf (io, user, " timeout='%g'\n", bvp->timeout); // safe
741 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
742 s_userio_xml_message_vprintf(io, user, fmt, ap);
743 userio_prints (io, user, ">\n");
744
745 IUUserIOBLOBContext(io, user, bvp);
746
747 userio_prints (io, user, "</setBLOBVector>\n");
748 indi_locale_C_numeric_pop(orig);
749}
750
752 const userio *io, void *user,
753 const INumberVectorProperty *nvp
754)
755{
756 locale_char_t *orig = indi_locale_C_numeric_push();
757 userio_prints (io, user, "<setNumberVector\n"
758 " device='");
759 userio_xml_escape(io, user, nvp->device);
760 userio_prints (io, user, "'\n"
761 " name='");
762 userio_xml_escape(io, user, nvp->name);
763 userio_prints (io, user, "'\n");
764 userio_printf (io, user, " state='%s'\n", pstateStr(nvp->s)); // safe
765 userio_printf (io, user, " timeout='%g'\n", nvp->timeout); // safe
766 userio_printf (io, user, " timestamp='%s'\n", indi_timestamp()); // safe
767 userio_prints (io, user, ">\n");
768
769 for (int i = 0; i < nvp->nnp; i++)
770 {
771 INumber *np = &nvp->np[i];
772 userio_prints (io, user, " <oneNumber name='");
773 userio_xml_escape(io, user, np->name);
774 userio_prints (io, user, "'\n");
775 userio_printf (io, user, " min='%g'\n", np->min); // safe
776 userio_printf (io, user, " max='%g'\n", np->max); // safe
777 userio_printf (io, user, " step='%g'\n", np->step); // safe
778 userio_prints (io, user, ">\n");
779 userio_printf (io, user, " %g\n", np->value); // safe
780 userio_prints (io, user, " </oneNumber>\n");
781 }
782
783 userio_prints (io, user, "</setNumberVector>\n");
784 indi_locale_C_numeric_pop(orig);
785}
786
787void IUUserIOPingRequest(const userio * io, void *user, const char * pingUid)
788{
789 userio_prints (io, user, "<pingRequest uid='");
790 userio_xml_escape(io, user, pingUid);
791 userio_prints (io, user, "' />\n");
792}
793
794void IUUserIOPingReply(const userio * io, void *user, const char * pingUid)
795{
796 userio_prints (io, user, "<pingReply uid='");
797 userio_xml_escape(io, user, pingUid);
798 userio_prints (io, user, "' />\n");
799}
std::string fmt(const char *fmt,...)
Definition Utils.cpp:241
int to64frombits_s(unsigned char *out, const unsigned char *in, int inlen, size_t outlen)
Convert bytes array to base64.
Definition base64.c:63
Constants and Data structure definitions for the interface to the reference INDI C API implementation...
#define MAXINDIMESSAGE
Definition indiapi.h:196
#define assert_mem(p)
Bails out if memory pointer is 0. Prints file and function.
Definition indiapi.h:503
@ ISR_1OFMANY
Definition indiapi.h:171
#define INDIV
Definition indiapi.h:134
const char * indi_timestamp()
Create an ISO 8601 formatted time stamp. The format is YYYY-MM-DDTHH:MM:SS.
Definition indicom.c:337
Implementations for common driver routines.
const char * ruleStr(ISRule r)
Definition indidevapi.c:877
const char * sstateStr(ISState s)
Definition indidevapi.c:863
const char * permStr(IPerm p)
Definition indidevapi.c:893
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *svp)
Returns the first ON switch it finds in the vector switch property.
Definition indidevapi.c:317
const char * pstateStr(IPState s)
Definition indidevapi.c:845
Interface to the reference INDI C API device implementation on the Device Driver side.
BLOBHandling
How drivers handle BLOBs incoming from snooping drivers.
Definition indidevapi.h:267
@ B_ONLY
Definition indidevapi.h:270
@ B_ALSO
Definition indidevapi.h:269
@ B_NEVER
Definition indidevapi.h:268
void IUUserIOBLOBContextOne(const userio *io, void *user, const char *name, unsigned int size, unsigned int bloblen, const void *blob, const char *format)
Definition indiuserio.c:101
void IUUserIOSwitchContext(const userio *io, void *user, const ISwitchVectorProperty *svp)
Definition indiuserio.c:91
void IUUserIOSetLightVA(const userio *io, void *user, const ILightVectorProperty *lvp, const char *fmt, va_list ap)
Definition indiuserio.c:704
void IUUserIONewBLOBFinish(const userio *io, void *user)
Definition indiuserio.c:281
void IUUserIODefLightVA(const userio *io, void *user, const ILightVectorProperty *lvp, const char *fmt, va_list ap)
Definition indiuserio.c:546
void IUUserIOLightContext(const userio *io, void *user, const ILightVectorProperty *lvp)
Definition indiuserio.c:184
void IUUserIONewBLOB(const userio *io, void *user, const IBLOBVectorProperty *bvp)
Definition indiuserio.c:251
void IUUserIOUpdateMinMax(const userio *io, void *user, const INumberVectorProperty *nvp)
Definition indiuserio.c:751
void IUUserIOTextContext(const userio *io, void *user, const ITextVectorProperty *tvp)
Definition indiuserio.c:55
void IUUserIODefBLOBVA(const userio *io, void *user, const IBLOBVectorProperty *b, const char *fmt, va_list ap)
Definition indiuserio.c:586
void IUUserIODeleteVA(const userio *io, void *user, const char *dev, const char *name, const char *fmt, va_list ap)
Definition indiuserio.c:286
void IUUserIOSetSwitchVA(const userio *io, void *user, const ISwitchVectorProperty *svp, const char *fmt, va_list ap)
Definition indiuserio.c:679
void IUUserIONewBLOBStart(const userio *io, void *user, const char *dev, const char *name, const char *timestamp)
Definition indiuserio.c:260
void IUUserIONewSwitchFull(const userio *io, void *user, const ISwitchVectorProperty *svp)
Definition indiuserio.c:229
void IUUserIODefTextVA(const userio *io, void *user, const ITextVectorProperty *tvp, const char *fmt, va_list ap)
Definition indiuserio.c:402
void IUUserIONumberContext(const userio *io, void *user, const INumberVectorProperty *nvp)
Definition indiuserio.c:42
void IDUserIOMessage(const userio *io, void *user, const char *dev, const char *fmt,...)
Definition indiuserio.c:375
void IUUserIONewText(const userio *io, void *user, const ITextVectorProperty *tvp)
Definition indiuserio.c:216
void IUUserIOSetNumberVA(const userio *io, void *user, const INumberVectorProperty *nvp, const char *fmt, va_list ap)
Definition indiuserio.c:654
void IUUserIODefSwitchVA(const userio *io, void *user, const ISwitchVectorProperty *s, const char *fmt, va_list ap)
Definition indiuserio.c:501
void IUUserIOSetBLOBVA(const userio *io, void *user, const IBLOBVectorProperty *bvp, const char *fmt, va_list ap)
Definition indiuserio.c:726
void IUUserIOEnableBLOB(const userio *io, void *user, const char *dev, const char *name, BLOBHandling blobH)
Definition indiuserio.c:341
void IUUserIOPingRequest(const userio *io, void *user, const char *pingUid)
Definition indiuserio.c:787
void IUUserIONewSwitch(const userio *io, void *user, const ISwitchVectorProperty *svp)
Definition indiuserio.c:240
void IDUserIOMessageVA(const userio *io, void *user, const char *dev, const char *fmt, va_list ap)
Definition indiuserio.c:358
void IUUserIOBLOBContext(const userio *io, void *user, const IBLOBVectorProperty *bvp)
Definition indiuserio.c:172
void IUUserIOSetTextVA(const userio *io, void *user, const ITextVectorProperty *tvp, const char *fmt, va_list ap)
Definition indiuserio.c:629
void IUUserIOConfigTag(const userio *io, void *user, int ctag)
Definition indiuserio.c:386
void IUUserIOSwitchContextFull(const userio *io, void *user, const ISwitchVectorProperty *svp)
Definition indiuserio.c:82
void IUUserIONewNumber(const userio *io, void *user, const INumberVectorProperty *nvp)
Definition indiuserio.c:199
void IUUserIOGetProperties(const userio *io, void *user, const char *dev, const char *name)
Definition indiuserio.c:307
void IUUserIOPingReply(const userio *io, void *user, const char *pingUid)
Definition indiuserio.c:794
void IUUserIOSwitchContextOne(const userio *io, void *user, const ISwitch *sp)
Definition indiuserio.c:71
void IUUserIODefNumberVA(const userio *io, void *user, const INumberVectorProperty *n, const char *fmt, va_list ap)
Definition indiuserio.c:449
char locale_char_t
One Blob (Binary Large Object) descriptor.
One light descriptor.
One number descriptor.
One switch descriptor.
One text descriptor.
BLOB (Binary Large Object) vector property descriptor.
Definition indiapi.h:469
char label[MAXINDILABEL]
Definition indiapi.h:475
char group[MAXINDIGROUP]
Definition indiapi.h:477
char name[MAXINDINAME]
Definition indiapi.h:473
char device[MAXINDIDEVICE]
Definition indiapi.h:471
Light vector property descriptor.
Definition indiapi.h:415
char label[MAXINDILABEL]
Definition indiapi.h:421
char name[MAXINDINAME]
Definition indiapi.h:419
char device[MAXINDIDEVICE]
Definition indiapi.h:417
char group[MAXINDIGROUP]
Definition indiapi.h:423
Number vector property descriptor.
Definition indiapi.h:317
char group[MAXINDIGROUP]
Definition indiapi.h:325
char device[MAXINDIDEVICE]
Definition indiapi.h:319
char name[MAXINDINAME]
Definition indiapi.h:321
char label[MAXINDILABEL]
Definition indiapi.h:323
Switch vector property descriptor.
Definition indiapi.h:365
char device[MAXINDIDEVICE]
Definition indiapi.h:367
char name[MAXINDINAME]
Definition indiapi.h:369
char label[MAXINDILABEL]
Definition indiapi.h:371
char group[MAXINDIGROUP]
Definition indiapi.h:373
Text vector property descriptor.
Definition indiapi.h:244
char label[MAXINDILABEL]
Definition indiapi.h:250
char device[MAXINDIDEVICE]
Definition indiapi.h:246
char name[MAXINDINAME]
Definition indiapi.h:248
char group[MAXINDIGROUP]
Definition indiapi.h:252
void(* joinbuff)(void *user, const char *xml, void *buffer, size_t bloblen)
Definition userio.h:34
ssize_t userio_prints(const struct userio *io, void *user, const char *str)
Definition userio.c:64
ssize_t userio_write(const struct userio *io, void *user, const void *ptr, size_t count)
Definition userio.c:59
ssize_t userio_printf(const struct userio *io, void *user, const char *format,...)
Definition userio.c:44
size_t userio_xml_escape(const struct userio *io, void *user, const char *src)
Definition userio.c:75
ssize_t userio_putc(const struct userio *io, void *user, int ch)
Definition userio.c:69