1 /*!
2  * \file ClientAPIForAlignmentDatabase.cpp
3  *
4  * \author Roger James
5  * \date 13th November 2013
6  *
7  */
8 
9 #include "ClientAPIForAlignmentDatabase.h"
10 
11 #include "indicom.h"
12 
13 namespace INDI
14 {
15 namespace AlignmentSubsystem
16 {
ClientAPIForAlignmentDatabase()17 ClientAPIForAlignmentDatabase::ClientAPIForAlignmentDatabase()
18 {
19     pthread_cond_init(&DriverActionCompleteCondition, nullptr);
20     pthread_mutex_init(&DriverActionCompleteMutex, nullptr);
21 }
22 
~ClientAPIForAlignmentDatabase()23 ClientAPIForAlignmentDatabase::~ClientAPIForAlignmentDatabase()
24 {
25     pthread_cond_destroy(&DriverActionCompleteCondition);
26     pthread_mutex_destroy(&DriverActionCompleteMutex);
27 }
28 
AppendSyncPoint(const AlignmentDatabaseEntry & CurrentValues)29 bool ClientAPIForAlignmentDatabase::AppendSyncPoint(const AlignmentDatabaseEntry &CurrentValues)
30 {
31     // Wait for driver to initialise if neccessary
32     WaitForDriverCompletion();
33 
34     ISwitchVectorProperty *pAction = Action->getSwitch();
35     ISwitchVectorProperty *pCommit = Commit->getSwitch();
36 
37     if (APPEND != IUFindOnSwitchIndex(pAction))
38     {
39         // Request Append mode
40         IUResetSwitch(pAction);
41         pAction->sp[APPEND].s = ISS_ON;
42         SetDriverBusy();
43         BaseClient->sendNewSwitch(pAction);
44         WaitForDriverCompletion();
45         if (IPS_OK != pAction->s)
46         {
47             IDLog("AppendSyncPoint - Bad Action switch state %s\n", pstateStr(pAction->s));
48             return false;
49         }
50     }
51 
52     if (!SendEntryData(CurrentValues))
53         return false;
54 
55     // Commit the entry to the database
56     IUResetSwitch(pCommit);
57     pCommit->sp[0].s = ISS_ON;
58     SetDriverBusy();
59     BaseClient->sendNewSwitch(pCommit);
60     WaitForDriverCompletion();
61     if (IPS_OK != pCommit->s)
62     {
63         IDLog("AppendSyncPoint - Bad Commit switch state %s\n", pstateStr(pCommit->s));
64         return false;
65     }
66 
67     return true;
68 }
69 
ClearSyncPoints()70 bool ClientAPIForAlignmentDatabase::ClearSyncPoints()
71 {
72     // Wait for driver to initialise if neccessary
73     WaitForDriverCompletion();
74 
75     ISwitchVectorProperty *pAction = Action->getSwitch();
76     ISwitchVectorProperty *pCommit = Commit->getSwitch();
77 
78     // Select the required action
79     if (CLEAR != IUFindOnSwitchIndex(pAction))
80     {
81         // Request Clear mode
82         IUResetSwitch(pAction);
83         pAction->sp[CLEAR].s = ISS_ON;
84         SetDriverBusy();
85         BaseClient->sendNewSwitch(pAction);
86         WaitForDriverCompletion();
87         if (IPS_OK != pAction->s)
88         {
89             IDLog("ClearSyncPoints - Bad Action switch state %s\n", pstateStr(pAction->s));
90             return false;
91         }
92     }
93 
94     IUResetSwitch(pCommit);
95     pCommit->sp[0].s = ISS_ON;
96     SetDriverBusy();
97     BaseClient->sendNewSwitch(pCommit);
98     WaitForDriverCompletion();
99     if (IPS_OK != pCommit->s)
100     {
101         IDLog("ClearSyncPoints - Bad Commit switch state %s\n", pstateStr(pCommit->s));
102         return false;
103     }
104 
105     return true;
106 }
107 
DeleteSyncPoint(unsigned int Offset)108 bool ClientAPIForAlignmentDatabase::DeleteSyncPoint(unsigned int Offset)
109 {
110     // Wait for driver to initialise if neccessary
111     WaitForDriverCompletion();
112 
113     ISwitchVectorProperty *pAction       = Action->getSwitch();
114     INumberVectorProperty *pCurrentEntry = CurrentEntry->getNumber();
115     ISwitchVectorProperty *pCommit       = Commit->getSwitch();
116 
117     // Select the required action
118     if (DELETE != IUFindOnSwitchIndex(pAction))
119     {
120         // Request Delete mode
121         IUResetSwitch(pAction);
122         pAction->sp[DELETE].s = ISS_ON;
123         SetDriverBusy();
124         BaseClient->sendNewSwitch(pAction);
125         WaitForDriverCompletion();
126         if (IPS_OK != pAction->s)
127         {
128             IDLog("DeleteSyncPoint - Bad Action switch state %s\n", pstateStr(pAction->s));
129             return false;
130         }
131     }
132 
133     // Send the offset
134     pCurrentEntry->np[0].value = Offset;
135     SetDriverBusy();
136     BaseClient->sendNewNumber(pCurrentEntry);
137     WaitForDriverCompletion();
138     if (IPS_OK != pCurrentEntry->s)
139     {
140         IDLog("DeleteSyncPoint - Bad Current Entry state %s\n", pstateStr(pCurrentEntry->s));
141         return false;
142     }
143 
144     // Commit the entry to the database
145     IUResetSwitch(pCommit);
146     pCommit->sp[0].s = ISS_ON;
147     SetDriverBusy();
148     BaseClient->sendNewSwitch(pCommit);
149     WaitForDriverCompletion();
150     if (IPS_OK != pCommit->s)
151     {
152         IDLog("DeleteSyncPoint - Bad Commit switch state %s\n", pstateStr(pCommit->s));
153         return false;
154     }
155 
156     return true;
157 }
158 
EditSyncPoint(unsigned int Offset,const AlignmentDatabaseEntry & CurrentValues)159 bool ClientAPIForAlignmentDatabase::EditSyncPoint(unsigned int Offset, const AlignmentDatabaseEntry &CurrentValues)
160 {
161     // Wait for driver to initialise if neccessary
162     WaitForDriverCompletion();
163 
164     ISwitchVectorProperty *pAction           = Action->getSwitch();
165     INumberVectorProperty *pCurrentEntry     = CurrentEntry->getNumber();
166     ISwitchVectorProperty *pCommit           = Commit->getSwitch();
167 
168     // Select the required action
169     if (EDIT != IUFindOnSwitchIndex(pAction))
170     {
171         // Request Edit mode
172         IUResetSwitch(pAction);
173         pAction->sp[EDIT].s = ISS_ON;
174         SetDriverBusy();
175         BaseClient->sendNewSwitch(pAction);
176         WaitForDriverCompletion();
177         if (IPS_OK != pAction->s)
178         {
179             IDLog("EditSyncPoint - Bad Action switch state %s\n", pstateStr(pAction->s));
180             return false;
181         }
182     }
183 
184     // Send the offset
185     pCurrentEntry->np[0].value = Offset;
186     SetDriverBusy();
187     BaseClient->sendNewNumber(pCurrentEntry);
188     WaitForDriverCompletion();
189     if (IPS_OK != pCurrentEntry->s)
190     {
191         IDLog("EditSyncPoint - Bad Current Entry state %s\n", pstateStr(pCurrentEntry->s));
192         return false;
193     }
194 
195     if (!SendEntryData(CurrentValues))
196         return false;
197 
198     // Commit the entry to the database
199     IUResetSwitch(pCommit);
200     pCommit->sp[0].s = ISS_ON;
201     SetDriverBusy();
202     BaseClient->sendNewSwitch(pCommit);
203     WaitForDriverCompletion();
204     if (IPS_OK != pCommit->s)
205     {
206         IDLog("EditSyncPoint - Bad Commit switch state %s\n", pstateStr(pCommit->s));
207         return false;
208     }
209 
210     return true;
211 }
212 
GetDatabaseSize()213 int ClientAPIForAlignmentDatabase::GetDatabaseSize()
214 {
215     return 0;
216 }
217 
Initialise(INDI::BaseClient * BaseClient)218 void ClientAPIForAlignmentDatabase::Initialise(INDI::BaseClient *BaseClient)
219 {
220     ClientAPIForAlignmentDatabase::BaseClient = BaseClient;
221 }
222 
InsertSyncPoint(unsigned int Offset,const AlignmentDatabaseEntry & CurrentValues)223 bool ClientAPIForAlignmentDatabase::InsertSyncPoint(unsigned int Offset, const AlignmentDatabaseEntry &CurrentValues)
224 {
225     // Wait for driver to initialise if neccessary
226     WaitForDriverCompletion();
227 
228     ISwitchVectorProperty *pAction           = Action->getSwitch();
229     INumberVectorProperty *pCurrentEntry     = CurrentEntry->getNumber();
230     ISwitchVectorProperty *pCommit           = Commit->getSwitch();
231 
232     // Select the required action
233     if (INSERT != IUFindOnSwitchIndex(pAction))
234     {
235         // Request Insert mode
236         IUResetSwitch(pAction);
237         pAction->sp[INSERT].s = ISS_ON;
238         SetDriverBusy();
239         BaseClient->sendNewSwitch(pAction);
240         WaitForDriverCompletion();
241         if (IPS_OK != pAction->s)
242         {
243             IDLog("InsertSyncPoint - Bad Action switch state %s\n", pstateStr(pAction->s));
244             return false;
245         }
246     }
247 
248     // Send the offset
249     pCurrentEntry->np[0].value = Offset;
250     SetDriverBusy();
251     BaseClient->sendNewNumber(pCurrentEntry);
252     WaitForDriverCompletion();
253     if (IPS_OK != pCurrentEntry->s)
254     {
255         IDLog("InsertSyncPoint - Bad Current Entry state %s\n", pstateStr(pCurrentEntry->s));
256         return false;
257     }
258 
259     if (!SendEntryData(CurrentValues))
260         return false;
261 
262     // Commit the entry to the database
263     IUResetSwitch(pCommit);
264     pCommit->sp[0].s = ISS_ON;
265     SetDriverBusy();
266     BaseClient->sendNewSwitch(pCommit);
267     WaitForDriverCompletion();
268     if (IPS_OK != pCommit->s)
269     {
270         IDLog("InsertSyncPoint - Bad Commit switch state %s\n", pstateStr(pCommit->s));
271         return false;
272     }
273 
274     return true;
275 }
276 
LoadDatabase()277 bool ClientAPIForAlignmentDatabase::LoadDatabase()
278 {
279     // Wait for driver to initialise if neccessary
280     WaitForDriverCompletion();
281 
282     ISwitchVectorProperty *pAction = Action->getSwitch();
283     ISwitchVectorProperty *pCommit = Commit->getSwitch();
284 
285     // Select the required action
286     if (LOAD_DATABASE != IUFindOnSwitchIndex(pAction))
287     {
288         // Request Load Database mode
289         IUResetSwitch(pAction);
290         pAction->sp[LOAD_DATABASE].s = ISS_ON;
291         SetDriverBusy();
292         BaseClient->sendNewSwitch(pAction);
293         WaitForDriverCompletion();
294         if (IPS_OK != pAction->s)
295         {
296             IDLog("LoadDatabase - Bad Action switch state %s\n", pstateStr(pAction->s));
297             return false;
298         }
299     }
300 
301     // Commit the Load Database
302     IUResetSwitch(pCommit);
303     pCommit->sp[0].s = ISS_ON;
304     SetDriverBusy();
305     BaseClient->sendNewSwitch(pCommit);
306     WaitForDriverCompletion();
307     if (IPS_OK != pCommit->s)
308     {
309         IDLog("LoadDatabase - Bad Commit state %s\n", pstateStr(pCommit->s));
310         return false;
311     }
312 
313     return true;
314 }
315 
ProcessNewBLOB(IBLOB * BLOBPointer)316 void ClientAPIForAlignmentDatabase::ProcessNewBLOB(IBLOB *BLOBPointer)
317 {
318     if (strcmp(BLOBPointer->bvp->name, "ALIGNMENT_POINT_OPTIONAL_BINARY_BLOB") == 0)
319     {
320         if (IPS_BUSY != BLOBPointer->bvp->s)
321         {
322             ISwitchVectorProperty *pAction = Action->getSwitch();
323             int Index                      = IUFindOnSwitchIndex(pAction);
324             if ((READ != Index) && (READ_INCREMENT != Index))
325                 SignalDriverCompletion();
326         }
327     }
328 }
329 
ProcessNewDevice(INDI::BaseDevice * DevicePointer)330 void ClientAPIForAlignmentDatabase::ProcessNewDevice(INDI::BaseDevice *DevicePointer)
331 {
332     Device = DevicePointer;
333 }
334 
ProcessNewNumber(INumberVectorProperty * NumberVectorProperty)335 void ClientAPIForAlignmentDatabase::ProcessNewNumber(INumberVectorProperty *NumberVectorProperty)
336 {
337     if (strcmp(NumberVectorProperty->name, "ALIGNMENT_POINT_MANDATORY_NUMBERS") == 0)
338     {
339         if (IPS_BUSY != NumberVectorProperty->s)
340         {
341             ISwitchVectorProperty *pAction = Action->getSwitch();
342             int Index                      = IUFindOnSwitchIndex(pAction);
343             if ((READ != Index) && (READ_INCREMENT != Index))
344                 SignalDriverCompletion();
345         }
346     }
347     else if (strcmp(NumberVectorProperty->name, "ALIGNMENT_POINTSET_CURRENT_ENTRY") == 0)
348     {
349         if (IPS_BUSY != NumberVectorProperty->s)
350         {
351             ISwitchVectorProperty *pAction = Action->getSwitch();
352             int Index                      = IUFindOnSwitchIndex(pAction);
353             if (READ_INCREMENT != Index)
354                 SignalDriverCompletion();
355         }
356     }
357 }
358 
ProcessNewProperty(INDI::Property * PropertyPointer)359 void ClientAPIForAlignmentDatabase::ProcessNewProperty(INDI::Property *PropertyPointer)
360 {
361     bool GotOneOfMine = true;
362 
363     if (strcmp(PropertyPointer->getName(), "ALIGNMENT_POINT_MANDATORY_NUMBERS") == 0)
364         MandatoryNumbers = PropertyPointer;
365     else if (strcmp(PropertyPointer->getName(), "ALIGNMENT_POINT_OPTIONAL_BINARY_BLOB") == 0)
366     {
367         OptionalBinaryBlob = PropertyPointer;
368         // Make sure the format string is set up
369         strncpy(OptionalBinaryBlob->getBLOB()->bp->format, "alignmentPrivateData", MAXINDIBLOBFMT);
370     }
371     else if (strcmp(PropertyPointer->getName(), "ALIGNMENT_POINTSET_SIZE") == 0)
372         PointsetSize = PropertyPointer;
373     else if (strcmp(PropertyPointer->getName(), "ALIGNMENT_POINTSET_CURRENT_ENTRY") == 0)
374         CurrentEntry = PropertyPointer;
375     else if (strcmp(PropertyPointer->getName(), "ALIGNMENT_POINTSET_ACTION") == 0)
376         Action = PropertyPointer;
377     else if (strcmp(PropertyPointer->getName(), "ALIGNMENT_POINTSET_COMMIT") == 0)
378         Commit = PropertyPointer;
379     else
380         GotOneOfMine = false;
381 
382     // Tell the client when all the database proeprties have been set up
383     if (GotOneOfMine && (nullptr != MandatoryNumbers) && (nullptr != OptionalBinaryBlob) && (nullptr != PointsetSize) &&
384         (nullptr != CurrentEntry) && (nullptr != Action) && (nullptr != Commit))
385     {
386         // The DriverActionComplete state variable is initialised to false
387         // So I need to call this to set it to true and signal anyone
388         // waiting for the driver to initialise etc.
389         SignalDriverCompletion();
390     }
391 }
392 
ProcessNewSwitch(ISwitchVectorProperty * SwitchVectorProperty)393 void ClientAPIForAlignmentDatabase::ProcessNewSwitch(ISwitchVectorProperty *SwitchVectorProperty)
394 {
395     if (strcmp(SwitchVectorProperty->name, "ALIGNMENT_POINTSET_ACTION") == 0)
396     {
397         if (IPS_BUSY != SwitchVectorProperty->s)
398             SignalDriverCompletion();
399     }
400     else if (strcmp(SwitchVectorProperty->name, "ALIGNMENT_POINTSET_COMMIT") == 0)
401     {
402         if (IPS_BUSY != SwitchVectorProperty->s)
403             SignalDriverCompletion();
404     }
405 }
406 
ReadIncrementSyncPoint(AlignmentDatabaseEntry & CurrentValues)407 bool ClientAPIForAlignmentDatabase::ReadIncrementSyncPoint(AlignmentDatabaseEntry &CurrentValues)
408 {
409     // Wait for driver to initialise if neccessary
410     WaitForDriverCompletion();
411 
412     ISwitchVectorProperty *pAction           = Action->getSwitch();
413     INumberVectorProperty *pMandatoryNumbers = MandatoryNumbers->getNumber();
414     IBLOBVectorProperty *pBLOB               = OptionalBinaryBlob->getBLOB();
415     INumberVectorProperty *pCurrentEntry     = CurrentEntry->getNumber();
416     ISwitchVectorProperty *pCommit           = Commit->getSwitch();
417 
418     // Select the required action
419     if (READ_INCREMENT != IUFindOnSwitchIndex(pAction))
420     {
421         // Request Read Increment mode
422         IUResetSwitch(pAction);
423         pAction->sp[READ_INCREMENT].s = ISS_ON;
424         SetDriverBusy();
425         BaseClient->sendNewSwitch(pAction);
426         WaitForDriverCompletion();
427         if (IPS_OK != pAction->s)
428         {
429             IDLog("ReadIncrementSyncPoint - Bad Action switch state %s\n", pstateStr(pAction->s));
430             return false;
431         }
432     }
433 
434     // Commit the read increment
435     IUResetSwitch(pCommit);
436     pCommit->sp[0].s = ISS_ON;
437     SetDriverBusy();
438     BaseClient->sendNewSwitch(pCommit);
439     WaitForDriverCompletion();
440     if ((IPS_OK != pCommit->s) || (IPS_OK != pMandatoryNumbers->s) || (IPS_OK != pBLOB->s) ||
441         (IPS_OK != pCurrentEntry->s))
442     {
443         IDLog("ReadIncrementSyncPoint - Bad Commit/Mandatory numbers/Blob/Current entry state %s %s %s %s\n",
444               pstateStr(pCommit->s), pstateStr(pMandatoryNumbers->s), pstateStr(pBLOB->s), pstateStr(pCurrentEntry->s));
445         return false;
446     }
447 
448     // Read the entry data
449     CurrentValues.ObservationJulianDate = pMandatoryNumbers->np[ENTRY_OBSERVATION_JULIAN_DATE].value;
450     CurrentValues.RightAscension        = pMandatoryNumbers->np[ENTRY_RA].value;
451     CurrentValues.Declination           = pMandatoryNumbers->np[ENTRY_DEC].value;
452     CurrentValues.TelescopeDirection.x  = pMandatoryNumbers->np[ENTRY_VECTOR_X].value;
453     CurrentValues.TelescopeDirection.y  = pMandatoryNumbers->np[ENTRY_VECTOR_Y].value;
454     CurrentValues.TelescopeDirection.z  = pMandatoryNumbers->np[ENTRY_VECTOR_Z].value;
455 
456     return true;
457 }
458 
ReadSyncPoint(unsigned int Offset,AlignmentDatabaseEntry & CurrentValues)459 bool ClientAPIForAlignmentDatabase::ReadSyncPoint(unsigned int Offset, AlignmentDatabaseEntry &CurrentValues)
460 {
461     // Wait for driver to initialise if neccessary
462     WaitForDriverCompletion();
463 
464     ISwitchVectorProperty *pAction           = Action->getSwitch();
465     INumberVectorProperty *pMandatoryNumbers = MandatoryNumbers->getNumber();
466     IBLOBVectorProperty *pBLOB               = OptionalBinaryBlob->getBLOB();
467     INumberVectorProperty *pCurrentEntry     = CurrentEntry->getNumber();
468     ISwitchVectorProperty *pCommit           = Commit->getSwitch();
469 
470     // Select the required action
471     if (READ != IUFindOnSwitchIndex(pAction))
472     {
473         // Request Read mode
474         IUResetSwitch(pAction);
475         pAction->sp[READ].s = ISS_ON;
476         SetDriverBusy();
477         BaseClient->sendNewSwitch(pAction);
478         WaitForDriverCompletion();
479         if (IPS_OK != pAction->s)
480         {
481             IDLog("ReadSyncPoint - Bad Action switch state %s\n", pstateStr(pAction->s));
482             return false;
483         }
484     }
485 
486     // Send the offset
487     pCurrentEntry->np[0].value = Offset;
488     SetDriverBusy();
489     BaseClient->sendNewNumber(pCurrentEntry);
490     WaitForDriverCompletion();
491     if (IPS_OK != pCurrentEntry->s)
492     {
493         IDLog("ReadSyncPoint - Bad Current Entry state %s\n", pstateStr(pCurrentEntry->s));
494         return false;
495     }
496 
497     // Commit the read
498     IUResetSwitch(pCommit);
499     pCommit->sp[0].s = ISS_ON;
500     SetDriverBusy();
501     BaseClient->sendNewSwitch(pCommit);
502     WaitForDriverCompletion();
503     if ((IPS_OK != pCommit->s) || (IPS_OK != pMandatoryNumbers->s) || (IPS_OK != pBLOB->s))
504     {
505         IDLog("ReadSyncPoint - Bad Commit/Mandatory numbers/Blob state %s %s %s\n", pstateStr(pCommit->s),
506               pstateStr(pMandatoryNumbers->s), pstateStr(pBLOB->s));
507         return false;
508     }
509 
510     // Read the entry data
511     CurrentValues.ObservationJulianDate = pMandatoryNumbers->np[ENTRY_OBSERVATION_JULIAN_DATE].value;
512     CurrentValues.RightAscension        = pMandatoryNumbers->np[ENTRY_RA].value;
513     CurrentValues.Declination           = pMandatoryNumbers->np[ENTRY_DEC].value;
514     CurrentValues.TelescopeDirection.x  = pMandatoryNumbers->np[ENTRY_VECTOR_X].value;
515     CurrentValues.TelescopeDirection.y  = pMandatoryNumbers->np[ENTRY_VECTOR_Y].value;
516     CurrentValues.TelescopeDirection.z  = pMandatoryNumbers->np[ENTRY_VECTOR_Z].value;
517 
518     return true;
519 }
520 
SaveDatabase()521 bool ClientAPIForAlignmentDatabase::SaveDatabase()
522 {
523     // Wait for driver to initialise if neccessary
524     WaitForDriverCompletion();
525 
526     ISwitchVectorProperty *pAction = Action->getSwitch();
527     ISwitchVectorProperty *pCommit = Commit->getSwitch();
528 
529     // Select the required action
530     if (SAVE_DATABASE != IUFindOnSwitchIndex(pAction))
531     {
532         // Request Load Database mode
533         IUResetSwitch(pAction);
534         pAction->sp[SAVE_DATABASE].s = ISS_ON;
535         SetDriverBusy();
536         BaseClient->sendNewSwitch(pAction);
537         WaitForDriverCompletion();
538         if (IPS_OK != pAction->s)
539         {
540             IDLog("SaveDatabase - Bad Action switch state %s\n", pstateStr(pAction->s));
541             return false;
542         }
543     }
544 
545     // Commit the Save Database
546     IUResetSwitch(pCommit);
547     pCommit->sp[0].s = ISS_ON;
548     SetDriverBusy();
549     BaseClient->sendNewSwitch(pCommit);
550     WaitForDriverCompletion();
551     if (IPS_OK != pCommit->s)
552     {
553         IDLog("Save Database - Bad Commit state %s\n", pstateStr(pCommit->s));
554         return false;
555     }
556 
557     return true;
558 }
559 
560 // Private methods
561 
SendEntryData(const AlignmentDatabaseEntry & CurrentValues)562 bool ClientAPIForAlignmentDatabase::SendEntryData(const AlignmentDatabaseEntry &CurrentValues)
563 {
564     INumberVectorProperty *pMandatoryNumbers = MandatoryNumbers->getNumber();
565     IBLOBVectorProperty *pBLOB               = OptionalBinaryBlob->getBLOB();
566     // Send the entry data
567     pMandatoryNumbers->np[ENTRY_OBSERVATION_JULIAN_DATE].value = CurrentValues.ObservationJulianDate;
568     pMandatoryNumbers->np[ENTRY_RA].value                      = CurrentValues.RightAscension;
569     pMandatoryNumbers->np[ENTRY_DEC].value                     = CurrentValues.Declination;
570     pMandatoryNumbers->np[ENTRY_VECTOR_X].value                = CurrentValues.TelescopeDirection.x;
571     pMandatoryNumbers->np[ENTRY_VECTOR_Y].value                = CurrentValues.TelescopeDirection.y;
572     pMandatoryNumbers->np[ENTRY_VECTOR_Z].value                = CurrentValues.TelescopeDirection.z;
573     SetDriverBusy();
574     BaseClient->sendNewNumber(pMandatoryNumbers);
575     WaitForDriverCompletion();
576     if (IPS_OK != pMandatoryNumbers->s)
577     {
578         IDLog("SendEntryData - Bad mandatory numbers state %s\n", pstateStr(pMandatoryNumbers->s));
579         return false;
580     }
581 
582     if ((0 != CurrentValues.PrivateDataSize) && (nullptr != CurrentValues.PrivateData.get()))
583     {
584         // I have a BLOB to send
585         SetDriverBusy();
586         BaseClient->startBlob(Device->getDeviceName(), pBLOB->name, timestamp());
587         BaseClient->sendOneBlob(pBLOB->bp->name, CurrentValues.PrivateDataSize, pBLOB->bp->format,
588                                 CurrentValues.PrivateData.get());
589         BaseClient->finishBlob();
590         WaitForDriverCompletion();
591         if (IPS_OK != pBLOB->s)
592         {
593             IDLog("SendEntryData - Bad BLOB state %s\n", pstateStr(pBLOB->s));
594             return false;
595         }
596     }
597     return true;
598 }
599 
SetDriverBusy()600 bool ClientAPIForAlignmentDatabase::SetDriverBusy()
601 {
602     int ReturnCode = pthread_mutex_lock(&DriverActionCompleteMutex);
603 
604     if (ReturnCode != 0)
605         return false;
606     DriverActionComplete = false;
607     IDLog("SetDriverBusy\n");
608     ReturnCode = pthread_mutex_unlock(&DriverActionCompleteMutex);
609     return ReturnCode == 0;
610 }
611 
SignalDriverCompletion()612 bool ClientAPIForAlignmentDatabase::SignalDriverCompletion()
613 {
614     int ReturnCode = pthread_mutex_lock(&DriverActionCompleteMutex);
615 
616     if (ReturnCode != 0)
617         return false;
618     DriverActionComplete = true;
619     ReturnCode           = pthread_cond_signal(&DriverActionCompleteCondition);
620     if (ReturnCode != 0)
621     {
622         ReturnCode = pthread_mutex_unlock(&DriverActionCompleteMutex);
623         return false;
624     }
625     IDLog("SignalDriverCompletion\n");
626     ReturnCode = pthread_mutex_unlock(&DriverActionCompleteMutex);
627     return ReturnCode == 0;
628 }
629 
WaitForDriverCompletion()630 bool ClientAPIForAlignmentDatabase::WaitForDriverCompletion()
631 {
632     int ReturnCode = pthread_mutex_lock(&DriverActionCompleteMutex);
633 
634     while (!DriverActionComplete)
635     {
636         IDLog("WaitForDriverCompletion - Waiting\n");
637         ReturnCode = pthread_cond_wait(&DriverActionCompleteCondition, &DriverActionCompleteMutex);
638         IDLog("WaitForDriverCompletion - Back from wait ReturnCode = %d\n", ReturnCode);
639         if (ReturnCode != 0)
640         {
641             ReturnCode = pthread_mutex_unlock(&DriverActionCompleteMutex);
642             return false;
643         }
644     }
645     IDLog("WaitForDriverCompletion - Finished waiting\n");
646     ReturnCode = pthread_mutex_unlock(&DriverActionCompleteMutex);
647     return ReturnCode == 0;
648 }
649 
650 } // namespace AlignmentSubsystem
651 } // namespace INDI
652