1 | #include <stdlib.h> |
---|
2 | #include <string.h> |
---|
3 | #include <errno.h> |
---|
4 | #include <zlib.h> |
---|
5 | |
---|
6 | #include "basedriver.h" |
---|
7 | #include "baseclient.h" |
---|
8 | #include "indicom.h" |
---|
9 | #include "base64.h" |
---|
10 | |
---|
11 | INDI::BaseDriver::BaseDriver() |
---|
12 | { |
---|
13 | mediator = NULL; |
---|
14 | lp = newLilXML(); |
---|
15 | } |
---|
16 | |
---|
17 | |
---|
18 | INDI::BaseDriver::~BaseDriver() |
---|
19 | { |
---|
20 | std::vector<INumberVectorProperty *>::const_iterator numi; |
---|
21 | std::vector<ISwitchVectorProperty *>::const_iterator switchi; |
---|
22 | std::vector<ITextVectorProperty *>::const_iterator texti; |
---|
23 | std::vector<ILightVectorProperty *>::const_iterator lighti; |
---|
24 | std::vector<IBLOBVectorProperty *>::const_iterator blobi; |
---|
25 | |
---|
26 | delLilXML (lp); |
---|
27 | pAll.clear(); |
---|
28 | |
---|
29 | for ( numi = pNumbers.begin(); numi != pNumbers.end(); numi++) |
---|
30 | delete (*numi); |
---|
31 | |
---|
32 | for ( switchi = pSwitches.begin(); switchi != pSwitches.end(); switchi++) |
---|
33 | delete (*switchi); |
---|
34 | |
---|
35 | for ( texti = pTexts.begin(); texti != pTexts.end(); texti++) |
---|
36 | delete (*texti); |
---|
37 | |
---|
38 | for ( lighti = pLights.begin(); lighti != pLights.end(); lighti++) |
---|
39 | delete (*lighti); |
---|
40 | |
---|
41 | for ( blobi = pBlobs.begin(); blobi != pBlobs.end(); blobi++) |
---|
42 | delete (*blobi); |
---|
43 | } |
---|
44 | |
---|
45 | INumberVectorProperty * INDI::BaseDriver::getNumber(const char *name) |
---|
46 | { |
---|
47 | std::vector<INumberVectorProperty *>::const_iterator numi; |
---|
48 | |
---|
49 | for ( numi = pNumbers.begin(); numi != pNumbers.end(); numi++) |
---|
50 | if (!strcmp(name, (*numi)->name)) |
---|
51 | return *numi; |
---|
52 | |
---|
53 | return NULL; |
---|
54 | |
---|
55 | } |
---|
56 | |
---|
57 | ITextVectorProperty * INDI::BaseDriver::getText(const char *name) |
---|
58 | { |
---|
59 | std::vector<ITextVectorProperty *>::const_iterator texti; |
---|
60 | |
---|
61 | for ( texti = pTexts.begin(); texti != pTexts.end(); texti++) |
---|
62 | if (!strcmp(name, (*texti)->name)) |
---|
63 | return *texti; |
---|
64 | |
---|
65 | return NULL; |
---|
66 | } |
---|
67 | |
---|
68 | ISwitchVectorProperty * INDI::BaseDriver::getSwitch(const char *name) |
---|
69 | { |
---|
70 | std::vector<ISwitchVectorProperty *>::const_iterator switchi; |
---|
71 | |
---|
72 | for ( switchi = pSwitches.begin(); switchi != pSwitches.end(); switchi++) |
---|
73 | if (!strcmp(name, (*switchi)->name)) |
---|
74 | return *switchi; |
---|
75 | |
---|
76 | return NULL; |
---|
77 | |
---|
78 | } |
---|
79 | |
---|
80 | ILightVectorProperty * INDI::BaseDriver::getLight(const char *name) |
---|
81 | { |
---|
82 | std::vector<ILightVectorProperty *>::const_iterator lighti; |
---|
83 | |
---|
84 | for ( lighti = pLights.begin(); lighti != pLights.end(); lighti++) |
---|
85 | if (!strcmp(name, (*lighti)->name)) |
---|
86 | return *lighti; |
---|
87 | |
---|
88 | return NULL; |
---|
89 | |
---|
90 | } |
---|
91 | |
---|
92 | IBLOBVectorProperty * INDI::BaseDriver::getBLOB(const char *name) |
---|
93 | { |
---|
94 | std::vector<IBLOBVectorProperty *>::const_iterator blobi; |
---|
95 | |
---|
96 | for ( blobi = pBlobs.begin(); blobi != pBlobs.end(); blobi++) |
---|
97 | if (!strcmp(name, (*blobi)->name)) |
---|
98 | return *blobi; |
---|
99 | |
---|
100 | return NULL; |
---|
101 | } |
---|
102 | |
---|
103 | void * INDI::BaseDriver::getProperty(const char *name, INDI_TYPE & type) |
---|
104 | { |
---|
105 | std::vector<pOrder>::const_iterator orderi; |
---|
106 | |
---|
107 | INumberVectorProperty *nvp; |
---|
108 | ITextVectorProperty *tvp; |
---|
109 | ISwitchVectorProperty *svp; |
---|
110 | ILightVectorProperty *lvp; |
---|
111 | IBLOBVectorProperty *bvp; |
---|
112 | int i=0; |
---|
113 | |
---|
114 | for (i=0, orderi = pAll.begin(); orderi != pAll.end(); orderi++, i++) |
---|
115 | { |
---|
116 | switch ( (*orderi).type) |
---|
117 | { |
---|
118 | case INDI_NUMBER: |
---|
119 | nvp = static_cast<INumberVectorProperty *>((*orderi).p); |
---|
120 | if (!strcmp(name, nvp->name)) |
---|
121 | { |
---|
122 | type = INDI_NUMBER; |
---|
123 | return (*orderi).p; |
---|
124 | } |
---|
125 | |
---|
126 | break; |
---|
127 | case INDI_TEXT: |
---|
128 | tvp = static_cast<ITextVectorProperty *>((*orderi).p); |
---|
129 | if (!strcmp(name, tvp->name)) |
---|
130 | { |
---|
131 | type = INDI_TEXT; |
---|
132 | return (*orderi).p; |
---|
133 | } |
---|
134 | break; |
---|
135 | case INDI_SWITCH: |
---|
136 | svp = static_cast<ISwitchVectorProperty *>((*orderi).p); |
---|
137 | if (!strcmp(name, svp->name)) |
---|
138 | { |
---|
139 | type = INDI_SWITCH; |
---|
140 | return (*orderi).p; |
---|
141 | } |
---|
142 | break; |
---|
143 | case INDI_LIGHT: |
---|
144 | lvp = static_cast<ILightVectorProperty *>((*orderi).p); |
---|
145 | if (!strcmp(name, lvp->name)) |
---|
146 | { |
---|
147 | type = INDI_LIGHT; |
---|
148 | return (*orderi).p; |
---|
149 | } |
---|
150 | break; |
---|
151 | case INDI_BLOB: |
---|
152 | bvp = static_cast<IBLOBVectorProperty *>((*orderi).p); |
---|
153 | if (!strcmp(name, bvp->name)) |
---|
154 | { |
---|
155 | type = INDI_BLOB; |
---|
156 | return (*orderi).p; |
---|
157 | } |
---|
158 | break; |
---|
159 | } |
---|
160 | } |
---|
161 | |
---|
162 | return NULL; |
---|
163 | } |
---|
164 | |
---|
165 | int INDI::BaseDriver::removeProperty(const char *name) |
---|
166 | { |
---|
167 | std::vector<pOrder>::iterator orderi; |
---|
168 | |
---|
169 | INumberVectorProperty *nvp; |
---|
170 | ITextVectorProperty *tvp; |
---|
171 | ISwitchVectorProperty *svp; |
---|
172 | ILightVectorProperty *lvp; |
---|
173 | IBLOBVectorProperty *bvp; |
---|
174 | |
---|
175 | for (orderi = pAll.begin(); orderi != pAll.end(); orderi++) |
---|
176 | { |
---|
177 | switch ( (*orderi).type) |
---|
178 | { |
---|
179 | case INDI_NUMBER: |
---|
180 | nvp = static_cast<INumberVectorProperty *>((*orderi).p); |
---|
181 | if (!strcmp(name, nvp->name)) |
---|
182 | { |
---|
183 | pAll.erase(orderi); |
---|
184 | delete (nvp); |
---|
185 | return 0; |
---|
186 | } |
---|
187 | break; |
---|
188 | case INDI_TEXT: |
---|
189 | tvp = static_cast<ITextVectorProperty *>((*orderi).p); |
---|
190 | if (!strcmp(name, tvp->name)) |
---|
191 | { |
---|
192 | pAll.erase(orderi); |
---|
193 | delete (tvp); |
---|
194 | return 0; |
---|
195 | } |
---|
196 | break; |
---|
197 | case INDI_SWITCH: |
---|
198 | svp = static_cast<ISwitchVectorProperty *>((*orderi).p); |
---|
199 | if (!strcmp(name, svp->name)) |
---|
200 | { |
---|
201 | pAll.erase(orderi); |
---|
202 | delete (svp); |
---|
203 | return 0; |
---|
204 | } |
---|
205 | break; |
---|
206 | case INDI_LIGHT: |
---|
207 | lvp = static_cast<ILightVectorProperty *>((*orderi).p); |
---|
208 | if (!strcmp(name, lvp->name)) |
---|
209 | { |
---|
210 | pAll.erase(orderi); |
---|
211 | delete (lvp); |
---|
212 | return 0; |
---|
213 | } |
---|
214 | break; |
---|
215 | case INDI_BLOB: |
---|
216 | bvp = static_cast<IBLOBVectorProperty *>((*orderi).p); |
---|
217 | if (!strcmp(name, bvp->name)) |
---|
218 | { |
---|
219 | pAll.erase(orderi); |
---|
220 | delete (bvp); |
---|
221 | return 0; |
---|
222 | } |
---|
223 | break; |
---|
224 | } |
---|
225 | } |
---|
226 | |
---|
227 | return INDI_PROPERTY_INVALID; |
---|
228 | } |
---|
229 | |
---|
230 | void INDI::BaseDriver::buildSkeleton(const char *filename) |
---|
231 | { |
---|
232 | char errmsg[MAXRBUF]; |
---|
233 | FILE *fp = NULL; |
---|
234 | XMLEle *root = NULL, *fproot = NULL; |
---|
235 | |
---|
236 | fp = fopen(filename, "r"); |
---|
237 | |
---|
238 | if (fp == NULL) |
---|
239 | { |
---|
240 | IDLog("Unable to build skeleton. Error loading file %s: %s\n", filename, strerror(errno)); |
---|
241 | return; |
---|
242 | } |
---|
243 | |
---|
244 | fproot = readXMLFile(fp, lp, errmsg); |
---|
245 | |
---|
246 | if (fproot == NULL) |
---|
247 | { |
---|
248 | IDLog("Unable to parse skeleton XML: %s", errmsg); |
---|
249 | return; |
---|
250 | } |
---|
251 | |
---|
252 | //prXMLEle(stderr, fproot, 0); |
---|
253 | |
---|
254 | for (root = nextXMLEle (fproot, 1); root != NULL; root = nextXMLEle (fproot, 0)) |
---|
255 | buildProp(root, errmsg); |
---|
256 | |
---|
257 | |
---|
258 | |
---|
259 | /**************************************************************************/ |
---|
260 | |
---|
261 | } |
---|
262 | |
---|
263 | int INDI::BaseDriver::buildProp(XMLEle *root, char *errmsg) |
---|
264 | { |
---|
265 | IPerm perm; |
---|
266 | IPState state; |
---|
267 | ISRule rule; |
---|
268 | XMLEle *ep = NULL; |
---|
269 | char *rtag, *rname, *rdev; |
---|
270 | INDI_TYPE type; |
---|
271 | double timeout=0; |
---|
272 | |
---|
273 | rtag = tagXMLEle(root); |
---|
274 | |
---|
275 | /* pull out device and name */ |
---|
276 | if (crackDN (root, &rdev, &rname, errmsg) < 0) |
---|
277 | return -1; |
---|
278 | |
---|
279 | if (!deviceID[0]) |
---|
280 | { |
---|
281 | if (getenv("INDIDEV")) |
---|
282 | strncpy(deviceID, getenv("INDIDEV"), MAXINDINAME); |
---|
283 | else |
---|
284 | strncpy(deviceID, rdev, MAXINDINAME); |
---|
285 | } |
---|
286 | |
---|
287 | if (getProperty(rname, type) != NULL) |
---|
288 | return INDI::BaseClient::INDI_PROPERTY_DUPLICATED; |
---|
289 | |
---|
290 | if (crackIPerm(findXMLAttValu(root, "perm"), &perm) < 0) |
---|
291 | { |
---|
292 | IDLog("Error extracting %s permission (%s)", rname, findXMLAttValu(root, "perm")); |
---|
293 | return -1; |
---|
294 | } |
---|
295 | |
---|
296 | timeout = atoi(findXMLAttValu(root, "timeout")); |
---|
297 | |
---|
298 | if (crackIPState (findXMLAttValu(root, "state"), &state) < 0) |
---|
299 | { |
---|
300 | IDLog("Error extracting %s state (%s)", rname, findXMLAttValu(root, "state")); |
---|
301 | return -1; |
---|
302 | } |
---|
303 | |
---|
304 | if (!strcmp (rtag, "defNumberVector")) |
---|
305 | { |
---|
306 | |
---|
307 | INumberVectorProperty *nvp = new INumberVectorProperty; |
---|
308 | INumber *np = NULL; |
---|
309 | int n=0; |
---|
310 | |
---|
311 | strncpy(nvp->device, deviceID, MAXINDIDEVICE); |
---|
312 | strncpy(nvp->name, rname, MAXINDINAME); |
---|
313 | strncpy(nvp->label, findXMLAttValu(root, "label"), MAXINDILABEL); |
---|
314 | strncpy(nvp->group, findXMLAttValu(root, "group"), MAXINDIGROUP); |
---|
315 | |
---|
316 | nvp->p = perm; |
---|
317 | nvp->s = state; |
---|
318 | nvp->timeout = timeout; |
---|
319 | |
---|
320 | /* pull out each name/value pair */ |
---|
321 | for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++) |
---|
322 | { |
---|
323 | if (!strcmp (tagXMLEle(ep), "defNumber")) |
---|
324 | { |
---|
325 | np = (INumber *) realloc(np, (n+1) * sizeof(INumber)); |
---|
326 | |
---|
327 | np[n].nvp = nvp; |
---|
328 | |
---|
329 | XMLAtt *na = findXMLAtt (ep, "name"); |
---|
330 | |
---|
331 | if (na) |
---|
332 | { |
---|
333 | if (f_scansexa (pcdataXMLEle(ep), &(np[n].value)) < 0) |
---|
334 | IDLog("%s: Bad format %s\n", rname, pcdataXMLEle(ep)); |
---|
335 | else |
---|
336 | { |
---|
337 | |
---|
338 | strncpy(np[n].name, valuXMLAtt(na), MAXINDINAME); |
---|
339 | |
---|
340 | na = findXMLAtt (ep, "label"); |
---|
341 | if (na) |
---|
342 | strncpy(np[n].label, valuXMLAtt(na),MAXINDILABEL); |
---|
343 | na = findXMLAtt (ep, "format"); |
---|
344 | if (na) |
---|
345 | strncpy(np[n].format, valuXMLAtt(na), MAXINDIFORMAT); |
---|
346 | |
---|
347 | na = findXMLAtt (ep, "min"); |
---|
348 | if (na) |
---|
349 | np[n].min = atof(valuXMLAtt(na)); |
---|
350 | na = findXMLAtt (ep, "max"); |
---|
351 | if (na) |
---|
352 | np[n].max = atof(valuXMLAtt(na)); |
---|
353 | na = findXMLAtt (ep, "step"); |
---|
354 | if (na) |
---|
355 | np[n].step = atof(valuXMLAtt(na)); |
---|
356 | |
---|
357 | } |
---|
358 | } |
---|
359 | } |
---|
360 | } |
---|
361 | |
---|
362 | if (n > 0) |
---|
363 | { |
---|
364 | nvp->nnp = n; |
---|
365 | nvp->np = np; |
---|
366 | pNumbers.push_back(nvp); |
---|
367 | pOrder o = { INDI_NUMBER, nvp }; |
---|
368 | pAll.push_back(o); |
---|
369 | IDLog("Adding number property %s to list.\n", nvp->name); |
---|
370 | } |
---|
371 | else |
---|
372 | IDLog("%s: newNumberVector with no valid members\n",rname); |
---|
373 | } |
---|
374 | else if (!strcmp (rtag, "defSwitchVector")) |
---|
375 | { |
---|
376 | ISwitchVectorProperty *svp = new ISwitchVectorProperty; |
---|
377 | ISwitch *sp = NULL; |
---|
378 | int n=0; |
---|
379 | |
---|
380 | strncpy(svp->device, deviceID, MAXINDIDEVICE); |
---|
381 | strncpy(svp->name, rname, MAXINDINAME); |
---|
382 | strncpy(svp->label, findXMLAttValu(root, "label"), MAXINDILABEL); |
---|
383 | strncpy(svp->group, findXMLAttValu(root, "group"), MAXINDIGROUP); |
---|
384 | |
---|
385 | if (crackISRule(findXMLAttValu(root, "rule"), (&svp->r)) < 0) |
---|
386 | svp->r = ISR_1OFMANY; |
---|
387 | |
---|
388 | svp->p = perm; |
---|
389 | svp->s = state; |
---|
390 | svp->timeout = timeout; |
---|
391 | |
---|
392 | |
---|
393 | /* pull out each name/value pair */ |
---|
394 | for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++) |
---|
395 | { |
---|
396 | if (!strcmp (tagXMLEle(ep), "defSwitch")) |
---|
397 | { |
---|
398 | sp = (ISwitch *) realloc(sp, (n+1) * sizeof(ISwitch)); |
---|
399 | |
---|
400 | sp[n].svp = svp; |
---|
401 | |
---|
402 | XMLAtt *na = findXMLAtt (ep, "name"); |
---|
403 | |
---|
404 | if (na) |
---|
405 | { |
---|
406 | crackISState(pcdataXMLEle(ep), &(sp[n].s)); |
---|
407 | strncpy(sp[n].name, valuXMLAtt(na), MAXINDINAME); |
---|
408 | |
---|
409 | na = findXMLAtt (ep, "label"); |
---|
410 | if (na) |
---|
411 | strncpy(sp[n].label, valuXMLAtt(na),MAXINDILABEL); |
---|
412 | } |
---|
413 | } |
---|
414 | } |
---|
415 | |
---|
416 | if (n > 0) |
---|
417 | { |
---|
418 | svp->nsp = n; |
---|
419 | svp->sp = sp; |
---|
420 | pSwitches.push_back(svp); |
---|
421 | pOrder o = { INDI_SWITCH, svp }; |
---|
422 | pAll.push_back(o); |
---|
423 | IDLog("Adding Switch property %s to list.\n", svp->name); |
---|
424 | } |
---|
425 | else |
---|
426 | IDLog("%s: newSwitchVector with no valid members\n",rname); |
---|
427 | } |
---|
428 | |
---|
429 | else if (!strcmp (rtag, "defTextVector")) |
---|
430 | { |
---|
431 | |
---|
432 | ITextVectorProperty *tvp = new ITextVectorProperty; |
---|
433 | IText *tp = NULL; |
---|
434 | int n=0; |
---|
435 | |
---|
436 | strncpy(tvp->device, deviceID, MAXINDIDEVICE); |
---|
437 | strncpy(tvp->name, rname, MAXINDINAME); |
---|
438 | strncpy(tvp->label, findXMLAttValu(root, "label"), MAXINDILABEL); |
---|
439 | strncpy(tvp->group, findXMLAttValu(root, "group"), MAXINDIGROUP); |
---|
440 | |
---|
441 | tvp->p = perm; |
---|
442 | tvp->s = state; |
---|
443 | tvp->timeout = timeout; |
---|
444 | |
---|
445 | /* pull out each name/value pair */ |
---|
446 | for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++) |
---|
447 | { |
---|
448 | if (!strcmp (tagXMLEle(ep), "defText")) |
---|
449 | { |
---|
450 | tp = (IText *) realloc(tp, (n+1) * sizeof(IText)); |
---|
451 | |
---|
452 | tp[n].tvp = tvp; |
---|
453 | |
---|
454 | XMLAtt *na = findXMLAtt (ep, "name"); |
---|
455 | |
---|
456 | if (na) |
---|
457 | { |
---|
458 | tp[n].text = (char *) malloc(pcdatalenXMLEle(ep)*sizeof(char)); |
---|
459 | strncpy(tp[n].text, pcdataXMLEle(ep), pcdatalenXMLEle(ep)); |
---|
460 | strncpy(tp[n].name, valuXMLAtt(na), MAXINDINAME); |
---|
461 | |
---|
462 | na = findXMLAtt (ep, "label"); |
---|
463 | if (na) |
---|
464 | strncpy(tp[n].label, valuXMLAtt(na),MAXINDILABEL); |
---|
465 | } |
---|
466 | } |
---|
467 | } |
---|
468 | |
---|
469 | if (n > 0) |
---|
470 | { |
---|
471 | tvp->ntp = n; |
---|
472 | tvp->tp = tp; |
---|
473 | pTexts.push_back(tvp); |
---|
474 | pOrder o = { INDI_TEXT, tvp }; |
---|
475 | pAll.push_back(o); |
---|
476 | IDLog("Adding Text property %s to list.\n", tvp->name); |
---|
477 | } |
---|
478 | else |
---|
479 | IDLog("%s: newTextVector with no valid members\n",rname); |
---|
480 | } |
---|
481 | else if (!strcmp (rtag, "defLightVector")) |
---|
482 | { |
---|
483 | |
---|
484 | ILightVectorProperty *lvp = new ILightVectorProperty; |
---|
485 | ILight *lp = NULL; |
---|
486 | int n=0; |
---|
487 | |
---|
488 | strncpy(lvp->device, deviceID, MAXINDIDEVICE); |
---|
489 | strncpy(lvp->name, rname, MAXINDINAME); |
---|
490 | strncpy(lvp->label, findXMLAttValu(root, "label"), MAXINDILABEL); |
---|
491 | strncpy(lvp->group, findXMLAttValu(root, "group"), MAXINDIGROUP); |
---|
492 | |
---|
493 | lvp->s = state; |
---|
494 | |
---|
495 | /* pull out each name/value pair */ |
---|
496 | for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++) |
---|
497 | { |
---|
498 | if (!strcmp (tagXMLEle(ep), "defLight")) |
---|
499 | { |
---|
500 | lp = (ILight *) realloc(lp, (n+1) * sizeof(ILight)); |
---|
501 | |
---|
502 | lp[n].lvp = lvp; |
---|
503 | |
---|
504 | XMLAtt *na = findXMLAtt (ep, "name"); |
---|
505 | |
---|
506 | if (na) |
---|
507 | { |
---|
508 | crackIPState(pcdataXMLEle(ep), &(lp[n].s)); |
---|
509 | strncpy(lp[n].name, valuXMLAtt(na), MAXINDINAME); |
---|
510 | |
---|
511 | na = findXMLAtt (ep, "label"); |
---|
512 | if (na) |
---|
513 | strncpy(lp[n].label, valuXMLAtt(na),MAXINDILABEL); |
---|
514 | |
---|
515 | } |
---|
516 | } |
---|
517 | } |
---|
518 | |
---|
519 | if (n > 0) |
---|
520 | { |
---|
521 | lvp->nlp = n; |
---|
522 | lvp->lp = lp; |
---|
523 | pLights.push_back(lvp); |
---|
524 | pOrder o = { INDI_LIGHT, lvp }; |
---|
525 | pAll.push_back(o); |
---|
526 | IDLog("Adding Light property %s to list.\n", lvp->name); |
---|
527 | } |
---|
528 | else |
---|
529 | IDLog("%s: newLightVector with no valid members\n",rname); |
---|
530 | } |
---|
531 | else if (!strcmp (rtag, "defBLOBVector")) |
---|
532 | { |
---|
533 | |
---|
534 | IBLOBVectorProperty *bvp = new IBLOBVectorProperty; |
---|
535 | IBLOB *bp = NULL; |
---|
536 | int n=0; |
---|
537 | |
---|
538 | strncpy(bvp->device, deviceID, MAXINDIDEVICE); |
---|
539 | strncpy(bvp->name, rname, MAXINDINAME); |
---|
540 | strncpy(bvp->label, findXMLAttValu(root, "label"), MAXINDILABEL); |
---|
541 | strncpy(bvp->group, findXMLAttValu(root, "group"), MAXINDIGROUP); |
---|
542 | |
---|
543 | bvp->s = state; |
---|
544 | |
---|
545 | /* pull out each name/value pair */ |
---|
546 | for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++) |
---|
547 | { |
---|
548 | if (!strcmp (tagXMLEle(ep), "defBLOB")) |
---|
549 | { |
---|
550 | bp = (IBLOB *) realloc(bp, (n+1) * sizeof(IBLOB)); |
---|
551 | |
---|
552 | bp[n].bvp = bvp; |
---|
553 | |
---|
554 | XMLAtt *na = findXMLAtt (ep, "name"); |
---|
555 | |
---|
556 | if (na) |
---|
557 | { |
---|
558 | strncpy(bp[n].name, valuXMLAtt(na), MAXINDINAME); |
---|
559 | |
---|
560 | na = findXMLAtt (ep, "label"); |
---|
561 | if (na) |
---|
562 | strncpy(bp[n].label, valuXMLAtt(na),MAXINDILABEL); |
---|
563 | |
---|
564 | na = findXMLAtt (ep, "format"); |
---|
565 | if (na) |
---|
566 | strncpy(bp[n].label, valuXMLAtt(na),MAXINDIBLOBFMT); |
---|
567 | |
---|
568 | // Initialize everything to zero |
---|
569 | |
---|
570 | bp[n].blob = NULL; |
---|
571 | bp[n].size = 0; |
---|
572 | bp[n].bloblen = 0; |
---|
573 | } |
---|
574 | |
---|
575 | } |
---|
576 | } |
---|
577 | |
---|
578 | if (n > 0) |
---|
579 | { |
---|
580 | bvp->nbp = n; |
---|
581 | bvp->bp = bp; |
---|
582 | pBlobs.push_back(bvp); |
---|
583 | pOrder o = { INDI_BLOB, bvp }; |
---|
584 | pAll.push_back(o); |
---|
585 | IDLog("Adding BLOB property %s to list.\n", bvp->name); |
---|
586 | } |
---|
587 | else |
---|
588 | IDLog("%s: newBLOBVector with no valid members\n",rname); |
---|
589 | } |
---|
590 | |
---|
591 | return (0); |
---|
592 | |
---|
593 | } |
---|
594 | |
---|
595 | bool INDI::BaseDriver::isConnected() |
---|
596 | { |
---|
597 | ISwitchVectorProperty *svp = getSwitch("CONNECTION"); |
---|
598 | if (!svp) |
---|
599 | return false; |
---|
600 | |
---|
601 | ISwitch * sp = IUFindSwitch(svp, "CONNECT"); |
---|
602 | |
---|
603 | if (!sp) |
---|
604 | return false; |
---|
605 | |
---|
606 | if (sp->s == ISS_ON) |
---|
607 | return true; |
---|
608 | else |
---|
609 | return false; |
---|
610 | |
---|
611 | } |
---|
612 | |
---|
613 | void INDI::BaseDriver::setConnected(bool status) |
---|
614 | { |
---|
615 | ISwitch *sp = NULL; |
---|
616 | ISwitchVectorProperty *svp = getSwitch("CONNECTION"); |
---|
617 | if (!svp) |
---|
618 | return; |
---|
619 | |
---|
620 | IUResetSwitch(svp); |
---|
621 | |
---|
622 | // Connect |
---|
623 | if (status) |
---|
624 | { |
---|
625 | sp = IUFindSwitch(svp, "CONNECT"); |
---|
626 | if (!sp) |
---|
627 | return; |
---|
628 | sp->s = ISS_ON; |
---|
629 | } |
---|
630 | // Disconnect |
---|
631 | else |
---|
632 | { |
---|
633 | sp = IUFindSwitch(svp, "DISCONNECT"); |
---|
634 | if (!sp) |
---|
635 | return; |
---|
636 | sp->s = ISS_ON; |
---|
637 | } |
---|
638 | |
---|
639 | svp->s = IPS_OK; |
---|
640 | } |
---|
641 | |
---|
642 | /* |
---|
643 | * return 0 if ok else -1 with reason in errmsg |
---|
644 | */ |
---|
645 | int INDI::BaseDriver::setValue (XMLEle *root, char * errmsg) |
---|
646 | { |
---|
647 | XMLAtt *ap; |
---|
648 | XMLEle *ep; |
---|
649 | char *rtag, *name; |
---|
650 | double timeout; |
---|
651 | IPState state; |
---|
652 | bool stateSet=false, timeoutSet=false; |
---|
653 | |
---|
654 | rtag = tagXMLEle(root); |
---|
655 | |
---|
656 | ap = findXMLAtt (root, "name"); |
---|
657 | if (!ap) |
---|
658 | { |
---|
659 | snprintf(errmsg, MAXRBUF, "INDI: <%s> unable to find name attribute", tagXMLEle(root)); |
---|
660 | return (-1); |
---|
661 | } |
---|
662 | |
---|
663 | name = valuXMLAtt(ap); |
---|
664 | |
---|
665 | /* set overall property state, if any */ |
---|
666 | ap = findXMLAtt (root, "state"); |
---|
667 | if (ap) |
---|
668 | { |
---|
669 | if (crackIPState(valuXMLAtt(ap), &state) != 0) |
---|
670 | { |
---|
671 | snprintf(errmsg, MAXRBUF, "INDI: <%s> bogus state %s for %s", tagXMLEle(root), |
---|
672 | valuXMLAtt(ap), name); |
---|
673 | return (-1); |
---|
674 | } |
---|
675 | |
---|
676 | stateSet = true; |
---|
677 | } |
---|
678 | |
---|
679 | /* allow changing the timeout */ |
---|
680 | ap = findXMLAtt (root, "timeout"); |
---|
681 | if (ap) |
---|
682 | { |
---|
683 | timeout = atof(valuXMLAtt(ap)); |
---|
684 | timeoutSet = true; |
---|
685 | } |
---|
686 | |
---|
687 | if (!strcmp(rtag, "setNumberVector")) |
---|
688 | { |
---|
689 | INumberVectorProperty *nvp = getNumber(name); |
---|
690 | if (nvp == NULL) |
---|
691 | { |
---|
692 | snprintf(errmsg, MAXRBUF, "INDI: Could not find property %s in %s", name, deviceID); |
---|
693 | return -1; |
---|
694 | } |
---|
695 | |
---|
696 | if (stateSet) |
---|
697 | nvp->s = state; |
---|
698 | |
---|
699 | if (timeoutSet) |
---|
700 | nvp->timeout = timeout; |
---|
701 | |
---|
702 | for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0)) |
---|
703 | { |
---|
704 | INumber *np = IUFindNumber(nvp, findXMLAttValu(ep, "name")); |
---|
705 | if (!np) |
---|
706 | continue; |
---|
707 | |
---|
708 | np->value = atof(pcdataXMLEle(ep)); |
---|
709 | |
---|
710 | // Permit changing of min/max |
---|
711 | if (findXMLAtt(ep, "min")) |
---|
712 | np->min = atof(findXMLAttValu(ep, "min")); |
---|
713 | if (findXMLAtt(ep, "max")) |
---|
714 | np->max = atof(findXMLAttValu(ep, "max")); |
---|
715 | } |
---|
716 | |
---|
717 | if (mediator) |
---|
718 | mediator->newNumber(nvp); |
---|
719 | |
---|
720 | return 0; |
---|
721 | } |
---|
722 | else if (!strcmp(rtag, "setTextVector")) |
---|
723 | { |
---|
724 | ITextVectorProperty *tvp = getText(name); |
---|
725 | if (tvp == NULL) |
---|
726 | return -1; |
---|
727 | |
---|
728 | if (stateSet) |
---|
729 | tvp->s = state; |
---|
730 | |
---|
731 | if (timeoutSet) |
---|
732 | tvp->timeout = timeout; |
---|
733 | |
---|
734 | for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0)) |
---|
735 | { |
---|
736 | IText *tp = IUFindText(tvp, findXMLAttValu(ep, "name")); |
---|
737 | if (!tp) |
---|
738 | continue; |
---|
739 | |
---|
740 | IUSaveText(tp, pcdataXMLEle(ep)); |
---|
741 | } |
---|
742 | |
---|
743 | if (mediator) |
---|
744 | mediator->newText(tvp); |
---|
745 | |
---|
746 | return 0; |
---|
747 | } |
---|
748 | else if (!strcmp(rtag, "setSwitchVector")) |
---|
749 | { |
---|
750 | ISState swState; |
---|
751 | ISwitchVectorProperty *svp = getSwitch(name); |
---|
752 | if (svp == NULL) |
---|
753 | return -1; |
---|
754 | |
---|
755 | if (stateSet) |
---|
756 | svp->s = state; |
---|
757 | |
---|
758 | if (timeoutSet) |
---|
759 | svp->timeout = timeout; |
---|
760 | |
---|
761 | for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0)) |
---|
762 | { |
---|
763 | ISwitch *sp = IUFindSwitch(svp, findXMLAttValu(ep, "name")); |
---|
764 | if (!sp) |
---|
765 | continue; |
---|
766 | |
---|
767 | if (crackISState(pcdataXMLEle(ep), &swState) == 0) |
---|
768 | sp->s = swState; |
---|
769 | } |
---|
770 | |
---|
771 | if (mediator) |
---|
772 | mediator->newSwitch(svp); |
---|
773 | |
---|
774 | return 0; |
---|
775 | } |
---|
776 | else if (!strcmp(rtag, "setLightVector")) |
---|
777 | { |
---|
778 | IPState lState; |
---|
779 | ILightVectorProperty *lvp = getLight(name); |
---|
780 | if (lvp == NULL) |
---|
781 | return -1; |
---|
782 | |
---|
783 | if (stateSet) |
---|
784 | lvp->s = state; |
---|
785 | |
---|
786 | for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0)) |
---|
787 | { |
---|
788 | ILight *lp = IUFindLight(lvp, findXMLAttValu(ep, "name")); |
---|
789 | if (!lp) |
---|
790 | continue; |
---|
791 | |
---|
792 | if (crackIPState(pcdataXMLEle(ep), &lState) == 0) |
---|
793 | lp->s = lState; |
---|
794 | } |
---|
795 | |
---|
796 | if (mediator) |
---|
797 | mediator->newLight(lvp); |
---|
798 | |
---|
799 | return 0; |
---|
800 | |
---|
801 | } |
---|
802 | else if (!strcmp(rtag, "setBLOBVector")) |
---|
803 | { |
---|
804 | IBLOBVectorProperty *bvp = getBLOB(name); |
---|
805 | if (bvp == NULL) |
---|
806 | return -1; |
---|
807 | |
---|
808 | if (stateSet) |
---|
809 | bvp->s = state; |
---|
810 | |
---|
811 | if (timeoutSet) |
---|
812 | bvp->timeout = timeout; |
---|
813 | |
---|
814 | return setBLOB(bvp, root, errmsg); |
---|
815 | } |
---|
816 | |
---|
817 | snprintf(errmsg, MAXRBUF, "INDI: <%s> Unable to process tag", tagXMLEle(root)); |
---|
818 | return -1; |
---|
819 | } |
---|
820 | |
---|
821 | /* Set BLOB vector. Process incoming data stream |
---|
822 | * Return 0 if okay, -1 if error |
---|
823 | */ |
---|
824 | int INDI::BaseDriver::setBLOB(IBLOBVectorProperty *bvp, XMLEle * root, char * errmsg) |
---|
825 | { |
---|
826 | |
---|
827 | XMLEle *ep; |
---|
828 | IBLOB *blobEL; |
---|
829 | |
---|
830 | for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) |
---|
831 | { |
---|
832 | if (strcmp(tagXMLEle(ep), "oneBLOB") == 0) |
---|
833 | { |
---|
834 | blobEL = IUFindBLOB(bvp, findXMLAttValu (ep, "name")); |
---|
835 | |
---|
836 | if (blobEL) |
---|
837 | return processBLOB(blobEL, ep, errmsg); |
---|
838 | else |
---|
839 | { |
---|
840 | snprintf(errmsg, MAXRBUF, "INDI: set %s.%s.%s not found", bvp->device, bvp->name, |
---|
841 | findXMLAttValu (ep, "name")); |
---|
842 | return (-1); |
---|
843 | } |
---|
844 | } |
---|
845 | } |
---|
846 | |
---|
847 | return -1; |
---|
848 | } |
---|
849 | |
---|
850 | /* Process incoming data stream |
---|
851 | * Return 0 if okay, -1 if error |
---|
852 | */ |
---|
853 | int INDI::BaseDriver::processBLOB(IBLOB *blobEL, XMLEle *ep, char * errmsg) |
---|
854 | { |
---|
855 | XMLAtt *ap = NULL; |
---|
856 | int blobSize=0, r=0; |
---|
857 | uLongf dataSize=0; |
---|
858 | char *baseBuffer=NULL, *dataFormat; |
---|
859 | unsigned char *blobBuffer(NULL), *dataBuffer(NULL); |
---|
860 | bool iscomp(false); |
---|
861 | |
---|
862 | ap = findXMLAtt(ep, "size"); |
---|
863 | if (!ap) |
---|
864 | { |
---|
865 | snprintf(errmsg, MAXRBUF, "INDI: set %s size not found", blobEL->name); |
---|
866 | return (-1); |
---|
867 | } |
---|
868 | |
---|
869 | dataSize = atoi(valuXMLAtt(ap)); |
---|
870 | |
---|
871 | ap = findXMLAtt(ep, "format"); |
---|
872 | if (!ap) |
---|
873 | { |
---|
874 | snprintf(errmsg, MAXRBUF, "INDI: set %s format not found",blobEL->name); |
---|
875 | return (-1); |
---|
876 | } |
---|
877 | |
---|
878 | dataFormat = valuXMLAtt(ap); |
---|
879 | |
---|
880 | strncpy(blobEL->format, dataFormat, MAXINDIFORMAT); |
---|
881 | |
---|
882 | baseBuffer = (char *) malloc ( (3*pcdatalenXMLEle(ep)/4) * sizeof (char)); |
---|
883 | |
---|
884 | if (baseBuffer == NULL) |
---|
885 | { |
---|
886 | strncpy(errmsg, "Unable to allocate memory for base buffer", MAXRBUF); |
---|
887 | return (-1); |
---|
888 | } |
---|
889 | |
---|
890 | blobSize = from64tobits (baseBuffer, pcdataXMLEle(ep)); |
---|
891 | blobBuffer = (unsigned char *) baseBuffer; |
---|
892 | |
---|
893 | /* Blob size = 0 when only state changes */ |
---|
894 | if (dataSize == 0) |
---|
895 | { |
---|
896 | free (blobBuffer); |
---|
897 | return (0); |
---|
898 | } |
---|
899 | else if (blobSize < 0) |
---|
900 | { |
---|
901 | free (blobBuffer); |
---|
902 | snprintf(errmsg, MAXRBUF, "INDI: %s.%s.%s bad base64", blobEL->bvp->device, blobEL->bvp->name, blobEL->name); |
---|
903 | return (-1); |
---|
904 | } |
---|
905 | |
---|
906 | if (strstr(dataFormat, ".z")) |
---|
907 | { |
---|
908 | dataFormat[strlen(dataFormat)-2] = '\0'; |
---|
909 | dataBuffer = (unsigned char *) realloc (dataBuffer, (dataSize * sizeof(unsigned char))); |
---|
910 | |
---|
911 | if (baseBuffer == NULL) |
---|
912 | { |
---|
913 | free (blobBuffer); |
---|
914 | strncpy(errmsg, "Unable to allocate memory for data buffer", MAXRBUF); |
---|
915 | return (-1); |
---|
916 | } |
---|
917 | |
---|
918 | r = uncompress(dataBuffer, &dataSize, blobBuffer, (uLong) blobSize); |
---|
919 | if (r != Z_OK) |
---|
920 | { |
---|
921 | snprintf(errmsg, MAXRBUF, "INDI: %s.%s.%s compression error: %d", blobEL->bvp->device, blobEL->bvp->name, blobEL->name, r); |
---|
922 | free (blobBuffer); |
---|
923 | return -1; |
---|
924 | } |
---|
925 | blobEL->size = dataSize; |
---|
926 | } |
---|
927 | else |
---|
928 | { |
---|
929 | dataBuffer = (unsigned char *) realloc (dataBuffer, (dataSize * sizeof(unsigned char))); |
---|
930 | memcpy(dataBuffer, blobBuffer, dataSize); |
---|
931 | blobEL->size = dataSize; |
---|
932 | } |
---|
933 | |
---|
934 | blobEL->blob = dataBuffer; |
---|
935 | |
---|
936 | if (mediator) |
---|
937 | mediator->newBLOB(blobEL); |
---|
938 | |
---|
939 | // newBLOB(dataBuffer, dataSize, dataFormat); |
---|
940 | |
---|
941 | free (blobBuffer); |
---|
942 | return (0); |
---|
943 | } |
---|
944 | |
---|
945 | void INDI::BaseDriver::setDeviceName(const char *dev) |
---|
946 | { |
---|
947 | strncpy(deviceID, dev, MAXINDINAME); |
---|
948 | } |
---|
949 | |
---|
950 | const char * INDI::BaseDriver::deviceName() |
---|
951 | { |
---|
952 | return deviceID; |
---|
953 | } |
---|
954 | |
---|
955 | void INDI::BaseDriver::addMessage(const char *msg) |
---|
956 | { |
---|
957 | messageQueue.append(msg); |
---|
958 | } |
---|
959 | |
---|