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 |
|
---|