Instrument Neutral Distributed Interface INDI  2.0.2
indiuserio.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 2021 by Pawel Soja <kernel32.pl@gmail.com>
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 
28 static 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 
42 void 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 
55 void 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 
71 void 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 
82 void 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 
91 void 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 
172 void 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 
184 void 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 
199 void 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 
216 void 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 
229 void 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 
240 void 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 
251 void 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 
281 void 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
330 static 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 
787 void 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 
794 void 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 }
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:198
#define assert_mem(p)
Bails out if memory pointer is 0. Prints file and function.
Definition: indiapi.h:505
@ ISR_1OFMANY
Definition: indiapi.h:173
#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:348
Implementations for common driver routines.
const char * ruleStr(ISRule r)
Definition: indidevapi.c:660
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *svp)
Returns the first ON switch it finds in the vector switch property.
Definition: indidevapi.c:108
const char * pstateStr(IPState s)
Definition: indidevapi.c:628
const char * sstateStr(ISState s)
Definition: indidevapi.c:646
const char * permStr(IPerm p)
Definition: indidevapi.c:676
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:266
@ B_ONLY
Definition: indidevapi.h:269
@ B_ALSO
Definition: indidevapi.h:268
@ B_NEVER
Definition: indidevapi.h:267
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
Definition: locale_compat.h:62
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:471
char label[MAXINDILABEL]
Definition: indiapi.h:477
char group[MAXINDIGROUP]
Definition: indiapi.h:479
char name[MAXINDINAME]
Definition: indiapi.h:475
char device[MAXINDIDEVICE]
Definition: indiapi.h:473
Light vector property descriptor.
Definition: indiapi.h:417
char label[MAXINDILABEL]
Definition: indiapi.h:423
char name[MAXINDINAME]
Definition: indiapi.h:421
char device[MAXINDIDEVICE]
Definition: indiapi.h:419
char group[MAXINDIGROUP]
Definition: indiapi.h:425
Number vector property descriptor.
Definition: indiapi.h:319
char group[MAXINDIGROUP]
Definition: indiapi.h:327
char device[MAXINDIDEVICE]
Definition: indiapi.h:321
char name[MAXINDINAME]
Definition: indiapi.h:323
char label[MAXINDILABEL]
Definition: indiapi.h:325
Switch vector property descriptor.
Definition: indiapi.h:367
char device[MAXINDIDEVICE]
Definition: indiapi.h:369
char name[MAXINDINAME]
Definition: indiapi.h:371
char label[MAXINDILABEL]
Definition: indiapi.h:373
char group[MAXINDIGROUP]
Definition: indiapi.h:375
Text vector property descriptor.
Definition: indiapi.h:246
char label[MAXINDILABEL]
Definition: indiapi.h:252
char device[MAXINDIDEVICE]
Definition: indiapi.h:248
char name[MAXINDINAME]
Definition: indiapi.h:250
char group[MAXINDIGROUP]
Definition: indiapi.h:254
Definition: userio.h:29
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