1 /*
2 * stepguider_sxao_indi.cpp
3 * PHD Guiding
4 *
5 * Created by Hans Lambermont
6 * Copyright (c) 2016 Hans Lambermont
7 * All rights reserved.
8 *
9 * This source code is distributed under the following "BSD" license
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * Neither the name Craig Stark, Stark Labs nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35 #include "phd.h"
36
37 #ifdef STEPGUIDER_SXAO_INDI
38
39 #include "stepguider_sxao_indi.h"
40 #include "phdindiclient.h"
41 #include "config_indi.h"
42
43 #include <libindi/basedevice.h>
44 #include <libindi/indiproperty.h>
45
46 class StepGuiderSxAoINDI : public StepGuider, public PhdIndiClient
47 {
48 private:
49 // INDI parts
50 static const int MaxDeviceInitWaitMilliSeconds = 2000;
51 static const int MaxDevicePropertiesWaitMilliSeconds = 5000;
52 long INDIport;
53 wxString INDIhost;
54 wxString INDIaoDeviceName;
55 bool modal;
56 bool ready;
57 void ClearStatus();
58 void CheckState();
59
60 INumberVectorProperty *pulseGuideNS_prop;
61 INumber *pulseN_prop;
62 INumber *pulseS_prop;
63 INumberVectorProperty *pulseGuideWE_prop;
64 INumber *pulseW_prop;
65 INumber *pulseE_prop;
66 INumberVectorProperty *aoNS_prop;
67 INumber *aoN_prop;
68 INumber *aoS_prop;
69 INumberVectorProperty *aoWE_prop;
70 INumber *aoW_prop;
71 INumber *aoE_prop;
72 ISwitchVectorProperty *aoCenterUnjam_prop;
73 ISwitch *aoCenter_prop;
74 ISwitch *aoUnjam_prop;
75 INDI::BaseDevice *ao_device;
76 ITextVectorProperty *ao_port;
77 ITextVectorProperty *ao_driverInfo;
78 IText *ao_driverName;
79 IText *ao_driverExec;
80 IText *ao_driverVersion;
81 IText *ao_driverInterface;
82 ITextVectorProperty *ao_info;
83 IText *ao_firmware;
84 ILightVectorProperty *ao_limit;
85 ILight *ao_limit_north;
86 ILight *ao_limit_south;
87 ILight *ao_limit_east;
88 ILight *ao_limit_west;
89
90 // StepGuider parts
91 static const int DefaultMaxSteps = 45;
92 wxString m_Name;
93 int m_maxSteps;
94 int SxAoVersion;
95
96 bool Center() override;
97 STEP_RESULT Step(GUIDE_DIRECTION direction, int steps) override;
98 int MaxPosition(GUIDE_DIRECTION direction) const override;
99 bool SetMaxPosition(int steps) override;
100 bool IsAtLimit(GUIDE_DIRECTION direction, bool *isAtLimit) override;
101
102 bool FirmwareVersion(int *version);
103
104 bool ST4HasGuideOutput() override;
105 bool ST4HostConnected() override;
106 bool ST4HasNonGuiMove() override;
107 bool ST4PulseGuideScope(int direction, int duration) override;
108
109 protected:
110 // INDI parts
111 void newDevice(INDI::BaseDevice *dp) override;
112 #ifndef INDI_PRE_1_0_0
113 void removeDevice(INDI::BaseDevice *dp) override;
114 #endif
115 void newProperty(INDI::Property *property) override;
removeProperty(INDI::Property * property)116 void removeProperty(INDI::Property *property) override {};
newBLOB(IBLOB * bp)117 void newBLOB(IBLOB *bp) override {};
newSwitch(ISwitchVectorProperty * svp)118 void newSwitch(ISwitchVectorProperty *svp) override {};
119 void newNumber(INumberVectorProperty *nvp) override;
120 void newMessage(INDI::BaseDevice *dp, int messageID) override;
newText(ITextVectorProperty * tvp)121 void newText(ITextVectorProperty *tvp) override {};
newLight(ILightVectorProperty * lvp)122 void newLight(ILightVectorProperty *lvp) override {};
123 void serverConnected() override;
124 void IndiServerDisconnected(int exit_code) override;
125
126 public:
127 StepGuiderSxAoINDI();
128 ~StepGuiderSxAoINDI();
129
130 // StepGuider parts
131 bool Connect() override;
132 bool Disconnect() override;
133 bool HasNonGuiMove() override;
134 bool HasSetupDialog() const override;
135 void SetupDialog() override;
136
137 private:
138 void ShowPropertyDialog() override;
139 };
140
StepGuiderSxAoINDI()141 StepGuiderSxAoINDI::StepGuiderSxAoINDI()
142 {
143 ClearStatus();
144
145 // load the values from the current profile
146 INDIhost = pConfig->Profile.GetString("/indi/INDIhost", _T("localhost"));
147 INDIport = pConfig->Profile.GetLong("/indi/INDIport", 7624);
148 INDIaoDeviceName = pConfig->Profile.GetString("/indi/INDIao", _T("INDI SXV-AO-LF"));
149
150 m_Name = INDIaoDeviceName;
151 m_maxSteps = pConfig->Profile.GetInt("/stepguider/sxao/MaxSteps", DefaultMaxSteps);
152 }
153
~StepGuiderSxAoINDI()154 StepGuiderSxAoINDI::~StepGuiderSxAoINDI()
155 {
156 DisconnectIndiServer();
157 }
158
ClearStatus()159 void StepGuiderSxAoINDI::ClearStatus()
160 {
161 // reset properties
162 pulseGuideNS_prop = nullptr;
163 pulseN_prop = nullptr;
164 pulseS_prop = nullptr;
165 pulseGuideWE_prop = nullptr;
166 pulseW_prop = nullptr;
167 pulseE_prop = nullptr;
168 aoNS_prop = nullptr;
169 aoN_prop = nullptr;
170 aoS_prop = nullptr;
171 aoWE_prop = nullptr;
172 aoW_prop = nullptr;
173 aoE_prop = nullptr;
174 aoCenterUnjam_prop = nullptr;
175 aoCenter_prop = nullptr;
176 aoUnjam_prop = nullptr;
177 ao_device = nullptr;
178 ao_port = nullptr;
179 ao_driverInfo = nullptr;
180 ao_driverName = nullptr;
181 ao_driverExec = nullptr;
182 ao_driverVersion = nullptr;
183 ao_driverInterface = nullptr;
184 ao_info = nullptr;
185 ao_firmware = nullptr;
186 ao_limit = nullptr;
187 ao_limit_north = nullptr;
188 ao_limit_south = nullptr;
189 ao_limit_east = nullptr;
190 ao_limit_west = nullptr;
191 SxAoVersion = -1;
192
193 // reset connection status
194 ready = false;
195 }
196
CheckState()197 void StepGuiderSxAoINDI::CheckState()
198 {
199 // Check if the device has all the required properties for our usage.
200 if (IsConnected() && (ao_driverVersion && aoN_prop && aoS_prop && aoW_prop && aoE_prop && aoCenter_prop)) {
201 if (atof(ao_driverVersion->text) < 1.12) {
202 wxMessageBox(wxString::Format(
203 _("We need at least INDI driver %s version 1.12 to get the Firmware version and the Limit switch states."),
204 ao_driverExec->text), _("Error"));
205 } else if (ao_firmware) {
206 if (! ready) {
207 if (FirmwareVersion(&SxAoVersion)) {
208 throw ERROR_INFO("StepGuiderSxAoINDI::CheckState: unable to get firmware version");
209 }
210 if (SxAoVersion == 0) {
211 wxMessageBox(wxString::Format(
212 _("This AO device has firmware version %03u which means it needs to be flashed.\n"
213 "The SXV-AO Utility v104 or newer, available at http://www.sxccd.com/drivers-downloads,\n"
214 "contains the firmware."), SxAoVersion),
215 _("Error"));
216 throw ERROR_INFO("StepGuiderSxAoINDI::CheckState: V000 means AO device needs a flash");
217 }
218 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::CheckState is ready, firmware %03u", SxAoVersion));
219 ready = true;
220 if (modal) {
221 modal = false;
222 }
223 }
224 }
225 }
226 }
227
newDevice(INDI::BaseDevice * dp)228 void StepGuiderSxAoINDI::newDevice(INDI::BaseDevice *dp)
229 {
230 if (strcmp(dp->getDeviceName(), INDIaoDeviceName.mb_str(wxConvUTF8)) == 0) {
231 ao_device = dp;
232 }
233 }
234
newProperty(INDI::Property * property)235 void StepGuiderSxAoINDI::newProperty(INDI::Property *property)
236 {
237 const char* PropName = property->getName();
238 #ifdef INDI_PRE_1_1_0
239 INDI_TYPE Proptype = property->getType();
240 #else
241 INDI_PROPERTY_TYPE Proptype = property->getType();
242 #endif
243
244 /*
245 printf("SXAO PropName: %s Proptype: %d\n", PropName, Proptype);
246 fflush(stdout);
247 * 0 INDI_NUMBER, < INumberVectorProperty.
248 * 1 INDI_SWITCH, < ISwitchVectorProperty.
249 * 2 INDI_TEXT, < ITextVectorProperty.
250 * 3 INDI_LIGHT, < ILightVectorProperty.
251 * 4 INDI_BLOB, < IBLOBVectorProperty.
252 * 5 INDI_UNKNOWN
253 SXAO PropName: CONNECTION Proptype: 1
254 SXAO PropName: DRIVER_INFO Proptype: 2
255 SXAO PropName: DEBUG Proptype: 1
256 SXAO PropName: SIMULATION Proptype: 1
257 SXAO PropName: DEVICE_PORT Proptype: 2
258 SXAO PropName: CONFIG_PROCESS Proptype: 1
259 SXAO PropName: TELESCOPE_TIMED_GUIDE_NS Proptype: 0
260 SXAO PropName: TELESCOPE_TIMED_GUIDE_WE Proptype: 0
261 SXAO PropName: AO_NS Proptype: 0
262 SXAO PropName: AO_WE Proptype: 0
263 SXAO PropName: AO_CENTER Proptype: 1
264 SXAO PropName: INFO Proptype: 2
265 SXAO PropName: AT_LIMIT Proptype: 3
266 */
267
268 if (strcmp(PropName, "CONNECTION") == 0 && Proptype == INDI_SWITCH) {
269 ISwitch *connectswitch = IUFindSwitch(property->getSwitch(),"CONNECT");
270 if (connectswitch->s == ISS_ON) {
271 StepGuider::Connect();
272 }
273 } else if (strcmp(PropName, "DRIVER_INFO") == 0 && Proptype == INDI_TEXT) {
274 ao_driverInfo = property->getText();
275 ao_driverName = IUFindText(ao_driverInfo, "DRIVER_NAME");
276 ao_driverExec = IUFindText(ao_driverInfo, "DRIVER_EXEC");
277 ao_driverVersion = IUFindText(ao_driverInfo, "DRIVER_VERSION"); // we need >=1.12 for Firmware version and AT_LIMIT
278 ao_driverInterface = IUFindText(ao_driverInfo, "DRIVER_INTERFACE");
279 } else if (strcmp(PropName, "DEVICE_PORT") == 0 && Proptype == INDI_TEXT) {
280 ao_port = property->getText();
281 } else if ((strcmp(PropName, "TELESCOPE_TIMED_GUIDE_NS") == 0) && Proptype == INDI_NUMBER){
282 pulseGuideNS_prop = property->getNumber();
283 pulseN_prop = IUFindNumber(pulseGuideNS_prop,"TIMED_GUIDE_N");
284 pulseS_prop = IUFindNumber(pulseGuideNS_prop,"TIMED_GUIDE_S");
285 } else if ((strcmp(PropName, "TELESCOPE_TIMED_GUIDE_WE") == 0) && Proptype == INDI_NUMBER){
286 pulseGuideWE_prop = property->getNumber();
287 pulseW_prop = IUFindNumber(pulseGuideWE_prop,"TIMED_GUIDE_W");
288 pulseE_prop = IUFindNumber(pulseGuideWE_prop,"TIMED_GUIDE_E");
289 } else if ((strcmp(PropName, "AO_NS") == 0) && Proptype == INDI_NUMBER){
290 aoNS_prop = property->getNumber();
291 aoN_prop = IUFindNumber(aoNS_prop,"AO_N");
292 aoS_prop = IUFindNumber(aoNS_prop,"AO_S");
293 } else if ((strcmp(PropName, "AO_WE") == 0) && Proptype == INDI_NUMBER){
294 aoWE_prop = property->getNumber();
295 aoW_prop = IUFindNumber(aoWE_prop,"AO_W");
296 aoE_prop = IUFindNumber(aoWE_prop,"AO_E");
297 } else if (strcmp(PropName, "AO_CENTER") == 0 && Proptype == INDI_SWITCH) {
298 aoCenterUnjam_prop = property->getSwitch();
299 aoCenter_prop = IUFindSwitch(aoCenterUnjam_prop,"CENTER");
300 aoUnjam_prop = IUFindSwitch(aoCenterUnjam_prop,"UNJAM");
301 } else if (strcmp(PropName, "INFO") == 0 && Proptype == INDI_TEXT) {
302 ao_info = property->getText();
303 ao_firmware = IUFindText(ao_info, "FIRMWARE");
304 } else if (strcmp(PropName, "AT_LIMIT") == 0 && Proptype == INDI_LIGHT) {
305 ao_limit = property->getLight();
306 ao_limit_north = IUFindLight(ao_limit, "AT_LIMIT_N");
307 ao_limit_south = IUFindLight(ao_limit, "AT_LIMIT_S");
308 ao_limit_east = IUFindLight(ao_limit, "AT_LIMIT_E");
309 ao_limit_west = IUFindLight(ao_limit, "AT_LIMIT_W");
310 }
311
312 CheckState();
313 }
314
newNumber(INumberVectorProperty * nvp)315 void StepGuiderSxAoINDI::newNumber(INumberVectorProperty *nvp) {}
newMessage(INDI::BaseDevice * dp,int messageID)316 void StepGuiderSxAoINDI::newMessage(INDI::BaseDevice *dp, int messageID) {}
317
318
Connect()319 bool StepGuiderSxAoINDI::Connect()
320 {
321 if (INDIaoDeviceName == wxT("INDI SXV-AO-LF")) {
322 SetupDialog(); // If not configured open the setup dialog
323 }
324 setServer(INDIhost.mb_str(wxConvUTF8), INDIport); // define server to connect to.
325 watchDevice(INDIaoDeviceName.mb_str(wxConvUTF8)); // Receive messages only for our device.
326 Debug.AddLine(wxString::Format("Connecting to INDI server %s on port %d, device %s", INDIhost.mb_str(wxConvUTF8), INDIport, INDIaoDeviceName.mb_str(wxConvUTF8)));
327 if (connectServer() ) { // Connect to INDI server.
328 return false; // and wait for serverConnected event
329 }
330 return true;
331 }
332
Disconnect()333 bool StepGuiderSxAoINDI::Disconnect()
334 {
335 Debug.Write("StepGuiderSxAoINDI::Disconnect\n");
336 DisconnectIndiServer();
337 ClearStatus();
338 StepGuider::Disconnect();
339 return false;
340 }
341
HasSetupDialog() const342 bool StepGuiderSxAoINDI::HasSetupDialog() const
343 {
344 return true;
345 }
346
SetupDialog()347 void StepGuiderSxAoINDI::SetupDialog()
348 {
349 // show the server and device configuration
350 INDIConfig indiDlg(wxGetApp().GetTopWindow(), _("INDI AO Selection"), INDI_TYPE_AO);
351 indiDlg.INDIhost = INDIhost;
352 indiDlg.INDIport = INDIport;
353 indiDlg.INDIDevName = INDIaoDeviceName;
354 // initialize with actual values
355 indiDlg.SetSettings();
356 // try to connect to server
357 indiDlg.Connect();
358 if (indiDlg.ShowModal() == wxID_OK)
359 {
360 // if OK save the values to the current profile
361 indiDlg.SaveSettings();
362 INDIhost = indiDlg.INDIhost;
363 INDIport = indiDlg.INDIport;
364 INDIaoDeviceName = indiDlg.INDIDevName;
365 pConfig->Profile.SetString("/indi/INDIhost", INDIhost);
366 pConfig->Profile.SetLong("/indi/INDIport", INDIport);
367 pConfig->Profile.SetString("/indi/INDIao", INDIaoDeviceName);
368 m_Name = INDIaoDeviceName;
369 }
370
371 indiDlg.Disconnect();
372 }
373
ShowPropertyDialog()374 void StepGuiderSxAoINDI::ShowPropertyDialog()
375 {
376 SetupDialog();
377 }
378
serverConnected()379 void StepGuiderSxAoINDI::serverConnected()
380 {
381 // wait for the DEVICE_PORT property
382 modal = true;
383 wxLongLong msec;
384 msec = wxGetUTCTimeMillis();
385 while (!ao_port && wxGetUTCTimeMillis() - msec < MaxDeviceInitWaitMilliSeconds)
386 {
387 wxMilliSleep(20);
388 ::wxSafeYield();
389 }
390 // connect to the device
391 connectDevice(INDIaoDeviceName.mb_str(wxConvUTF8));
392
393 // wait for all defined properties in CheckState
394 msec = wxGetUTCTimeMillis();
395 while (modal && wxGetUTCTimeMillis() - msec < MaxDevicePropertiesWaitMilliSeconds)
396 {
397 wxMilliSleep(20);
398 ::wxSafeYield();
399 }
400 modal = false; // even if CheckState still says no
401
402 if (ready) {
403 try {
404 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::serverConnected connecting StepGuider"));
405 StepGuider::Connect();
406 } catch (const wxString& Msg) {
407 POSSIBLY_UNUSED(Msg);
408 }
409 } else {
410 Disconnect();
411 }
412 }
413
IndiServerDisconnected(int exit_code)414 void StepGuiderSxAoINDI::IndiServerDisconnected(int exit_code)
415 {
416 // after disconnection we reset the connection status and the properties pointers
417 ClearStatus();
418 if (exit_code==-1) {
419 // in case the connection is lost we must reset the client socket
420 Disconnect();
421 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::serverDisconnected disconnecting StepGuider"));
422 StepGuider::Disconnect();
423 }
424 }
425
426 #ifndef INDI_PRE_1_0_0
removeDevice(INDI::BaseDevice * dp)427 void StepGuiderSxAoINDI::removeDevice(INDI::BaseDevice *dp)
428 {
429 ClearStatus();
430 Disconnect();
431 StepGuider::Disconnect();
432 }
433 #endif
434
Step(GUIDE_DIRECTION direction,int steps)435 StepGuider::STEP_RESULT StepGuiderSxAoINDI::Step(GUIDE_DIRECTION direction, int steps)
436 {
437 STEP_RESULT result = STEP_OK;
438
439 try
440 {
441 if (!aoNS_prop || !aoWE_prop)
442 throw ERROR_INFO("StepGuiderSxAO::step: missing ns or we property");
443
444 switch (direction) {
445 case NORTH:
446 aoN_prop->value = steps;
447 aoS_prop->value = 0;
448 sendNewNumber(aoNS_prop);
449 break;
450 case SOUTH:
451 aoN_prop->value = 0;
452 aoS_prop->value = steps;
453 sendNewNumber(aoNS_prop);
454 break;
455 case EAST:
456 aoW_prop->value = 0;
457 aoE_prop->value = steps;
458 sendNewNumber(aoWE_prop);
459 break;
460 case WEST:
461 aoW_prop->value = steps;
462 aoE_prop->value = 0;
463 sendNewNumber(aoWE_prop);
464 break;
465 default:
466 throw ERROR_INFO("StepGuiderSxAO::step: invalid direction");
467 break;
468 }
469 }
470 catch (const wxString& Msg)
471 {
472 POSSIBLY_UNUSED(Msg);
473 result = STEP_ERROR;
474 }
475
476 return result;
477 }
478
MaxPosition(GUIDE_DIRECTION direction) const479 int StepGuiderSxAoINDI::MaxPosition(GUIDE_DIRECTION direction) const
480 {
481 return m_maxSteps;
482 }
483
SetMaxPosition(int steps)484 bool StepGuiderSxAoINDI::SetMaxPosition(int steps)
485 {
486 Debug.Write(wxString::Format("StepGuiderSxAoINDI: setting max steps = %d\n", steps));
487 m_maxSteps = steps;
488 pConfig->Profile.SetInt("/stepguider/sxao/MaxSteps", m_maxSteps);
489 return false;
490 }
491
IsAtLimit(GUIDE_DIRECTION direction,bool * isAtLimit)492 bool StepGuiderSxAoINDI::IsAtLimit(GUIDE_DIRECTION direction, bool *isAtLimit)
493 {
494 bool bError = false;
495 if (ao_limit) {
496 try {
497 switch (direction) {
498 case NORTH:
499 *isAtLimit = ao_limit_north->s == IPS_ALERT;
500 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::IsAtLimit North"));
501 break;
502 case SOUTH:
503 *isAtLimit = ao_limit_south->s == IPS_ALERT;
504 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::IsAtLimit South"));
505 break;
506 case EAST:
507 *isAtLimit = ao_limit_east->s == IPS_ALERT;
508 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::IsAtLimit East"));
509 break;
510 case WEST:
511 *isAtLimit = ao_limit_west->s == IPS_ALERT;
512 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::IsAtLimit West"));
513 break;
514 default:
515 throw ERROR_INFO("StepGuiderSxAoINDI::IsAtLimit: invalid direction");
516 break;
517 }
518 } catch (const wxString& Msg) {
519 POSSIBLY_UNUSED(Msg);
520 bError = true;
521 }
522 } else {
523 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::IsAtLimit called before we received any ao_limit"));
524 bError = true;
525 }
526
527 return bError;
528 }
529
FirmwareVersion(int * version)530 bool StepGuiderSxAoINDI::FirmwareVersion(int *version)
531 {
532 bool bError = false;
533 if (ao_firmware) {
534 try {
535 *version = 0;
536 for (int i=0; i<3; i++) {
537 unsigned char ch = (ao_firmware->text)[1+i];
538 if (ch < '0' || ch > '9') {
539 throw ERROR_INFO("StepGuiderSxAO::firmwareVersion: invalid character");
540 }
541 *version *= 10;
542 *version += ch - '0';
543 }
544 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::Firmwareversion %u", *version));
545 } catch (const wxString& Msg) {
546 *version = -1;
547 POSSIBLY_UNUSED(Msg);
548 bError = true;
549 }
550 } else {
551 bError = true;
552 }
553 return bError;
554 }
555
Center()556 bool StepGuiderSxAoINDI::Center()
557 {
558 Debug.AddLine(wxString::Format("StepGuiderSxAoINDI::Center"));
559 if (aoCenterUnjam_prop) {
560 aoCenter_prop->s = ISS_ON;
561 aoUnjam_prop->s = ISS_OFF;
562 sendNewSwitch(aoCenterUnjam_prop);
563 // TODO: detect failure of center and try Unjam
564 ZeroCurrentPosition();
565 return false;
566 }
567 return true;
568 }
569
ST4HasGuideOutput()570 bool StepGuiderSxAoINDI::ST4HasGuideOutput()
571 {
572 return true;
573 }
574
ST4HostConnected()575 bool StepGuiderSxAoINDI::ST4HostConnected()
576 {
577 return IsConnected();
578 }
579
ST4HasNonGuiMove()580 bool StepGuiderSxAoINDI::ST4HasNonGuiMove()
581 {
582 return true;
583 }
584
ST4PulseGuideScope(int direction,int duration)585 bool StepGuiderSxAoINDI::ST4PulseGuideScope(int direction, int duration)
586 {
587 bool bError = true;
588 if (pulseGuideNS_prop && pulseGuideWE_prop) {
589 bError = false;
590 try {
591 switch (direction) {
592 case NORTH:
593 pulseN_prop->value = duration;
594 pulseS_prop->value = 0;
595 sendNewNumber(pulseGuideNS_prop);
596 break;
597 case SOUTH:
598 pulseN_prop->value = 0;
599 pulseS_prop->value = duration;
600 sendNewNumber(pulseGuideNS_prop);
601 break;
602 case EAST:
603 pulseW_prop->value = 0;
604 pulseE_prop->value = duration;
605 sendNewNumber(pulseGuideWE_prop);
606 break;
607 case WEST:
608 pulseW_prop->value = duration;
609 pulseE_prop->value = 0;
610 sendNewNumber(pulseGuideWE_prop);
611 break;
612 default:
613 throw ERROR_INFO("StepGuiderSxAO::ST4PulseGuideScope: invalid direction");
614 break;
615 }
616 } catch (const wxString& Msg) {
617 POSSIBLY_UNUSED(Msg);
618 bError = true;
619 }
620 }
621
622 return bError;
623 }
624
HasNonGuiMove()625 bool StepGuiderSxAoINDI::HasNonGuiMove()
626 {
627 return true;
628 }
629
MakeStepGuiderSxAoIndi()630 StepGuider *StepGuiderSxAoIndiFactory::MakeStepGuiderSxAoIndi()
631 {
632 return new StepGuiderSxAoINDI();
633 }
634
635 #endif // #ifdef STEPGUIDER_SXAO_INDI
636