Line data Source code
1 : /** \file zaberStage.hpp
2 : * \brief A class with details of a single zaber stage
3 : *
4 : * \ingroup zaberLowLevel_files
5 : */
6 :
7 : #ifndef zaberStage_hpp
8 : #define zaberStage_hpp
9 :
10 : #include <iostream>
11 :
12 : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
13 :
14 : #include "za_serial.h"
15 :
16 : namespace MagAOX
17 : {
18 : namespace app
19 : {
20 :
21 : /// A class to manage the details of one stage in a Zaber system.
22 : /**
23 : * \ingroup zaberLowLevel
24 : */
25 : template <class parentT>
26 : class zaberStage
27 : {
28 : protected:
29 : parentT *m_parent{ nullptr }; // The parent MagAOXApp
30 :
31 : std::string m_name; ///< The stage's name.
32 :
33 : std::string m_serial; ///< The stage's serial number.
34 :
35 : int m_deviceAddress{ -1 }; ///< The device's address, a.k.a. its order in the chain
36 :
37 : int m_axisNumber{ 0 }; ///< The axis number at the address (normally 0 in MagAO-X)
38 :
39 : bool m_commandStatus{ true }; ///< The status of the last command sent. true = OK, false = RJ (rejected)
40 :
41 : char m_deviceStatus{
42 : 'U' }; ///< Current status. Either 'I' for IDLE or 'B' for BUSY. Intializes to 'U' for UNKOWN.
43 :
44 : bool m_homing{ false };
45 :
46 : timespec m_lastHomed{ 0, 0 }; ///< Time stamp of the last time the stage was homed
47 :
48 : bool m_parked{ false };
49 :
50 : long m_rawPos; ///< The raw position reported by the device, in microsteps.
51 :
52 : long m_tgtPos{ 0 }; ///< The tgt position last sent to the device, in microsteps.
53 :
54 : long m_maxPos; ///< The max position allowed for the device, set by config. Will be set to no larger m_maxPosHW.
55 :
56 : float m_temp{ -999 }; ///< The driver temperature, in C.
57 :
58 : bool m_knobEnabled{ false };
59 :
60 : bool m_ledEnabled{ false };
61 :
62 : bool m_warn{ false };
63 :
64 : bool m_warnFD{ false };
65 : bool m_warnFDreported{ false };
66 : bool m_warnFQ{ false };
67 : bool m_warnFQreported{ false };
68 : bool m_warnFS{ false };
69 : bool m_warnFSreported{ false };
70 : bool m_warnFT{ false };
71 : bool m_warnFTreported{ false };
72 : bool m_warnFB{ false };
73 : bool m_warnFBreported{ false };
74 : bool m_warnFP{ false };
75 : bool m_warnFPreported{ false };
76 : bool m_warnFE{ false };
77 : bool m_warnFEreported{ false };
78 : bool m_warnWH{ false };
79 : bool m_warnWHreported{ false };
80 : bool m_warnWL{ false };
81 : bool m_warnWLreported{ false };
82 : bool m_warnWP{ false };
83 : bool m_warnWPreported{ false };
84 : bool m_warnWV{ false };
85 : bool m_warnWVreported{ false };
86 : bool m_warnWT{ false };
87 : bool m_warnWTreported{ false };
88 : bool m_warnWM{ false };
89 : bool m_warnWMreported{ false };
90 : bool m_warnWR{ false };
91 : bool m_warnWRreported{ false };
92 : bool m_warnNC{ false };
93 : bool m_warnNCreported{ false };
94 : bool m_warnNI{ false };
95 : bool m_warnNIreported{ false };
96 : bool m_warnND{ false };
97 : bool m_warnNDreported{ false };
98 : bool m_warnNU{ false };
99 : bool m_warnNUreported{ false };
100 : bool m_warnNJ{ false };
101 : bool m_warnNJreported{ false };
102 : bool m_warnUNK{ false };
103 :
104 : public:
105 : zaberStage() = delete;
106 :
107 13 : zaberStage( parentT *parent )
108 13 : {
109 13 : if( parent == nullptr )
110 : {
111 0 : throw mx::exception( mx::error_t::invalidarg, "parent was null on construction of zaberState" );
112 : }
113 :
114 13 : m_parent = parent;
115 13 : }
116 :
117 : /// Get the device name
118 : /**
119 : * \returns the current value of m_name
120 : */
121 : std::string name();
122 :
123 : /// Set the device name
124 : /**
125 : * \returns 0 on success
126 : * \returns -1 on error
127 : */
128 : int name( const std::string &n /**< [in] the new device name*/ );
129 :
130 : /// Get the device serial number
131 : /**
132 : * \returns the current value of m_serial
133 : */
134 : std::string serial();
135 :
136 : /// Set the device serial
137 : /**
138 : * \returns 0 on success
139 : * \returns -1 on error
140 : */
141 : int serial( const std::string &s /**< [in] the new device serial*/ );
142 :
143 : /// Get the device address
144 : /**
145 : * \returns the current value of m_deviceAddress
146 : */
147 : int deviceAddress();
148 :
149 : /// Set the device address
150 : /**
151 : * \returns 0 on success
152 : * \returns -1 on error
153 : */
154 : int deviceAddress( const int &da /**< [in] the new device address*/ );
155 :
156 : /// Get the axis number
157 : /**
158 : * \returns the current value of m_axisNumber
159 : */
160 : int axisNumber();
161 :
162 : /// Set the axis number
163 : /**
164 : * \returns 0 on success
165 : * \returns -1 on error
166 : */
167 : int axisNumber( const int &an /**< [in] the new axis number */ );
168 :
169 : /// Get the command status
170 : /**
171 : * \returns the current value of m_commandStatus
172 : */
173 : bool commandStatus();
174 :
175 : /// Get the device status
176 : /**
177 : * \returns the current value of m_deviceStatus
178 : */
179 : char deviceStatus();
180 :
181 : /// Get the homing status
182 : /**
183 : * \returns the current value of m_homing
184 : */
185 : bool homing();
186 :
187 : /// Get the time of last homing
188 : /**
189 : * \returns the current value of m_lastHomed
190 : */
191 : time_t lastHomed();
192 :
193 : /// Get the parked status
194 : /**
195 : * \returns the current value of m_parked
196 : */
197 : int parked();
198 :
199 : /// Get the knob status
200 : /**
201 : * \returns the current value of m_knobEnabled
202 : */
203 : bool knobEnabled();
204 :
205 : /// Get the LED status
206 : /**
207 : * \returns the current value of m_ledEnabled
208 : */
209 : bool ledEnabled();
210 :
211 : /// Get the current raw position, in counts
212 : /**
213 : * \returns the current value of m_rawPos
214 : */
215 : long rawPos();
216 :
217 : /// Get the current tgt position, in counts
218 : /**
219 : * \returns the current value of m_tgtPos
220 : */
221 : long tgtPos();
222 :
223 : /// Get the max position, in counts
224 : /**
225 : * \returns the current value of m_maxPos
226 : */
227 : long maxPos();
228 :
229 : /// Get the status of the warning flag
230 : /**
231 : * \returns the current value of m_warn
232 : */
233 : bool warn();
234 :
235 : /// Get the temperature, in C
236 : /**
237 : * \returns the current value of m_temp
238 : */
239 : float temp();
240 :
241 : /// Get the warning state
242 : /**
243 : * \returns the true if any warning flags are set.
244 : */
245 : bool warningState();
246 :
247 : bool warnFD();
248 : bool warnFQ();
249 : bool warnFS();
250 : bool warnFT();
251 : bool warnFB();
252 : bool warnFP();
253 : bool warnFE();
254 : bool warnWH();
255 : bool warnWL();
256 : bool warnWP();
257 : bool warnWV();
258 : bool warnWT();
259 : bool warnWM();
260 : bool warnWR();
261 : bool warnNC();
262 : bool warnNI();
263 : bool warnND();
264 : bool warnNU();
265 : bool warnNJ();
266 : bool warnUNK();
267 :
268 : /// Get a response from the device, after a command has been sent.
269 : /** Parses the standard parts of the response in this stage's fields,
270 : * and extracts the response string.
271 : *
272 : * \returns 0 on success.
273 : * \returns -1 on error.
274 : */
275 : int getResponse( std::string &response, ///< [out] the text response
276 : const std::string &repBuff ///< [in] the reply buffer, not decoded.
277 : );
278 :
279 : /// Get a response from the device, after a command has been sent.
280 : /** Parses the standard parts of the response in this stages fields,
281 : * and extracts the response string.
282 : *
283 : * \overload
284 : *
285 : * \returns 0 on success.
286 : * \returns -1 on error.
287 : */
288 : int getResponse( std::string &response, ///< [out] the text response component
289 : const za_reply &rep ///< [in] the decodedstage reply
290 : );
291 :
292 : /// Determine whether a decoded message is the awaited command reply.
293 : bool isCommandReply( const za_reply &rep /**< [in] the decoded device message */ );
294 :
295 : /// Send a command and get the response
296 : int sendCommand( std::string &response, ///< [out] the response received from the stage
297 : z_port port, ///< [in] the port with which to communicate
298 : const std::string &command ///< [in] the command to send
299 : );
300 :
301 : /// Send a command for which no response is expected
302 : int sendCommand( z_port port, /**< [in] the port with which to communicate */
303 : const std::string &command /**< [in] the command to send */
304 : );
305 :
306 : /// Get a value for this device
307 : /** Sends the command specified and converts the response to the specified type.
308 : *
309 : * The command passed should include `get` if needed.
310 : *
311 : * \tparam valT is the value type to convert to.
312 : */
313 : template <typename valT>
314 : int getValue( valT &val, /**< [out] the value to update */
315 : z_port port, /**< [in] the port with which to communicate */
316 : const std::string command /**< [in] the command to send */
317 : );
318 :
319 : /// Get the maximum position from the stage
320 : int getMaxPos( z_port port /**< [in] the port with which to communicate */ );
321 :
322 : /// Get the parked state from the stage
323 : int getParked( z_port port /**< [in] the port with which to communicate */ );
324 :
325 : int getKnob( z_port port /**< [in] the port with which to communicate */ );
326 :
327 : int getLED( z_port port /**< [in] the port with which to communicate */ );
328 :
329 : /// Update the position of the stage
330 : int updatePos( z_port port /**< [in] the port with which to communicate */ );
331 :
332 : /// Update the stage temperature
333 : int updateTemp( z_port port /**< [in] the port with which to communicate */ );
334 :
335 : /// Enable/Disable the knob
336 : int enableKnob( z_port port, bool enable );
337 :
338 : // Enable/disable LED
339 : int enableLED( z_port port, bool enable );
340 :
341 : /// Stop the stage
342 : int stop( z_port port );
343 :
344 : /// Emergency stop the stage
345 : int estop( z_port port );
346 :
347 : /// Initiate homing
348 : int home( z_port port /**< [in] the port with which to communicate */ );
349 :
350 : /// Park the stage
351 : int park( z_port port /**< [in] the port with which to communicate */ );
352 :
353 : /// Unpark the stage
354 : int unpark( z_port port /**< [in] the port with which to communicate */ );
355 :
356 : /// Move to a new absolute position
357 : int moveAbs( z_port port, ///< [in] the port with which to communicate
358 : long rawPos ///< [in] the position to move to, in counts
359 : );
360 :
361 : /// Sets all warning flags to false
362 : /** This is not the same as clearing warnings on the device, this is just used for
363 : * bookkeeping.
364 : *
365 : * \returns 0 on success (always)
366 : */
367 : int unsetWarnings();
368 :
369 : /// Process a single warning from the device, setting the appropriate flag.
370 : /** Warnings are two ASCII characeters, e.g. "WR".
371 : *
372 : * \returns 0 if the warning is processed, including if it's not recognized.
373 : * \returns -1 on an error, currently not possible.
374 : */
375 : int processWarning( std::string &warn /**< [in] the two-character warning flag */ );
376 :
377 : /// Parse the warning response from the device.
378 : /** Sends each warning flag to processWarning.
379 : *
380 : * \returns 0 on success
381 : * \returns -1 on error
382 : */
383 : int parseWarnings( std::string &response /**< [in] the response from the warnings query*/ );
384 :
385 : /// Get warnings from the device
386 : /** Log entries will be made and flags will be set in this structure.
387 : *
388 : * \returns 0 on success
389 : * \returns -1 on error.
390 : */
391 : int getWarnings( z_port port /**< [in] the port with which to communicate */ );
392 :
393 : /// Clear all state so that when the system is powered back on we get the correct new state.
394 : int onPowerOff();
395 :
396 : int writeStateFile( std::ofstream &fout /**< [in] an open ofstream to write to */ );
397 :
398 : int readStateFile( std::ifstream &fin /**< [in] an open ofstream to write to */ );
399 : };
400 :
401 : template <class parentT>
402 0 : std::string zaberStage<parentT>::name()
403 : {
404 0 : return m_name;
405 : }
406 :
407 : template <class parentT>
408 1 : int zaberStage<parentT>::name( const std::string &n )
409 : {
410 1 : m_name = n;
411 1 : return 0;
412 : }
413 :
414 : template <class parentT>
415 0 : std::string zaberStage<parentT>::serial()
416 : {
417 0 : return m_serial;
418 : }
419 :
420 : template <class parentT>
421 1 : int zaberStage<parentT>::serial( const std::string &s )
422 : {
423 1 : m_serial = s;
424 1 : return 0;
425 : }
426 :
427 : template <class parentT>
428 0 : int zaberStage<parentT>::deviceAddress()
429 : {
430 0 : return m_deviceAddress;
431 : }
432 :
433 : template <class parentT>
434 4 : int zaberStage<parentT>::deviceAddress( const int &da )
435 : {
436 4 : m_deviceAddress = da;
437 4 : return 0;
438 : }
439 :
440 : template <class parentT>
441 : int zaberStage<parentT>::axisNumber()
442 : {
443 : return m_axisNumber;
444 : }
445 :
446 : template <class parentT>
447 : int zaberStage<parentT>::axisNumber( const int &an )
448 : {
449 : m_axisNumber = an;
450 : return 0;
451 : }
452 :
453 : template <class parentT>
454 : bool zaberStage<parentT>::commandStatus()
455 : {
456 : return m_commandStatus;
457 : }
458 :
459 : template <class parentT>
460 0 : char zaberStage<parentT>::deviceStatus()
461 : {
462 0 : return m_deviceStatus;
463 : }
464 :
465 : template <class parentT>
466 0 : bool zaberStage<parentT>::homing()
467 : {
468 0 : return m_homing;
469 : }
470 :
471 : template <class parentT>
472 0 : time_t zaberStage<parentT>::lastHomed()
473 : {
474 0 : return m_lastHomed.tv_sec;
475 : }
476 :
477 : template <class parentT>
478 0 : int zaberStage<parentT>::parked()
479 : {
480 0 : return m_parked;
481 : }
482 :
483 : template <class parentT>
484 0 : bool zaberStage<parentT>::knobEnabled()
485 : {
486 0 : return m_knobEnabled;
487 : }
488 :
489 : template <class parentT>
490 0 : bool zaberStage<parentT>::ledEnabled()
491 : {
492 0 : return m_ledEnabled;
493 : }
494 :
495 : template <class parentT>
496 0 : long zaberStage<parentT>::rawPos()
497 : {
498 0 : return m_rawPos;
499 : }
500 :
501 : template <class parentT>
502 0 : long zaberStage<parentT>::tgtPos()
503 : {
504 0 : return m_tgtPos;
505 : }
506 :
507 : template <class parentT>
508 0 : long zaberStage<parentT>::maxPos()
509 : {
510 0 : return m_maxPos;
511 : }
512 :
513 : template <class parentT>
514 0 : bool zaberStage<parentT>::warn()
515 : {
516 0 : return m_warn;
517 : }
518 :
519 : template <class parentT>
520 0 : float zaberStage<parentT>::temp()
521 : {
522 0 : return m_temp;
523 : }
524 :
525 : template <class parentT>
526 6 : bool zaberStage<parentT>::warningState()
527 : {
528 6 : return m_warn;
529 : }
530 :
531 : template <class parentT>
532 6 : bool zaberStage<parentT>::warnFD()
533 : {
534 6 : return m_warnFD;
535 : }
536 :
537 : template <class parentT>
538 6 : bool zaberStage<parentT>::warnFQ()
539 : {
540 6 : return m_warnFQ;
541 : }
542 :
543 : template <class parentT>
544 6 : bool zaberStage<parentT>::warnFS()
545 : {
546 6 : return m_warnFS;
547 : }
548 :
549 : template <class parentT>
550 6 : bool zaberStage<parentT>::warnFT()
551 : {
552 6 : return m_warnFT;
553 : }
554 :
555 : template <class parentT>
556 6 : bool zaberStage<parentT>::warnFB()
557 : {
558 6 : return m_warnFB;
559 : }
560 :
561 : template <class parentT>
562 6 : bool zaberStage<parentT>::warnFP()
563 : {
564 6 : return m_warnFP;
565 : }
566 :
567 : template <class parentT>
568 6 : bool zaberStage<parentT>::warnFE()
569 : {
570 6 : return m_warnFE;
571 : }
572 :
573 : template <class parentT>
574 6 : bool zaberStage<parentT>::warnWH()
575 : {
576 6 : return m_warnWH;
577 : }
578 :
579 : template <class parentT>
580 6 : bool zaberStage<parentT>::warnWL()
581 : {
582 6 : return m_warnWL;
583 : }
584 :
585 : template <class parentT>
586 6 : bool zaberStage<parentT>::warnWP()
587 : {
588 6 : return m_warnWP;
589 : }
590 :
591 : template <class parentT>
592 6 : bool zaberStage<parentT>::warnWV()
593 : {
594 6 : return m_warnWV;
595 : }
596 :
597 : template <class parentT>
598 6 : bool zaberStage<parentT>::warnWT()
599 : {
600 6 : return m_warnWT;
601 : }
602 :
603 : template <class parentT>
604 6 : bool zaberStage<parentT>::warnWM()
605 : {
606 6 : return m_warnWM;
607 : }
608 :
609 : template <class parentT>
610 7 : bool zaberStage<parentT>::warnWR()
611 : {
612 7 : return m_warnWR;
613 : }
614 :
615 : template <class parentT>
616 6 : bool zaberStage<parentT>::warnNC()
617 : {
618 6 : return m_warnNC;
619 : }
620 :
621 : template <class parentT>
622 6 : bool zaberStage<parentT>::warnNI()
623 : {
624 6 : return m_warnNI;
625 : }
626 :
627 : template <class parentT>
628 6 : bool zaberStage<parentT>::warnND()
629 : {
630 6 : return m_warnND;
631 : }
632 :
633 : template <class parentT>
634 6 : bool zaberStage<parentT>::warnNU()
635 : {
636 6 : return m_warnNU;
637 : }
638 :
639 : template <class parentT>
640 6 : bool zaberStage<parentT>::warnNJ()
641 : {
642 6 : return m_warnNJ;
643 : }
644 :
645 : template <class parentT>
646 8 : bool zaberStage<parentT>::warnUNK()
647 : {
648 8 : return m_warnUNK;
649 : }
650 :
651 : template <class parentT>
652 : int zaberStage<parentT>::getResponse( std::string &response, const std::string &repBuff )
653 : {
654 : za_reply rep;
655 : int rv = za_decode( &rep, repBuff.c_str(), repBuff.size() );
656 : if( rv != Z_SUCCESS )
657 : {
658 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
659 : {
660 : return rv; // don't log, but propagate error
661 : }
662 :
663 : MagAOXAppT::log<software_error>( { rv, "za_decode !=Z_SUCCESS" } );
664 : return rv;
665 : }
666 :
667 : return getResponse( response, rep );
668 : }
669 :
670 : template <class parentT>
671 0 : int zaberStage<parentT>::getResponse( std::string &response, const za_reply &rep )
672 : {
673 0 : if( rep.device_address == m_deviceAddress )
674 : {
675 0 : if( rep.reply_flags[0] == 'O' )
676 : {
677 0 : m_commandStatus = true;
678 : }
679 : else
680 : {
681 0 : m_commandStatus = false;
682 : }
683 :
684 0 : m_deviceStatus = rep.device_status[0];
685 :
686 0 : if( m_deviceStatus == 'I' && m_homing )
687 : {
688 0 : m_warnWR = false; // Clear preemptively
689 0 : m_homing = false;
690 0 : if( clock_gettime( CLOCK_ISIO, &m_lastHomed ) < 0 )
691 : {
692 0 : MagAOXAppT::log<software_error>( { errno, 0, "clock_gettime for last homed" } );
693 : }
694 : }
695 :
696 0 : if( rep.warning_flags[0] == '-' )
697 : {
698 0 : unsetWarnings();
699 : }
700 : else
701 : {
702 0 : m_warn = true;
703 : }
704 :
705 0 : response = rep.response_data;
706 :
707 0 : return 0;
708 : }
709 : else
710 : {
711 0 : MagAOXAppT::log<software_error>( "wrong device" );
712 0 : return -1;
713 : }
714 : }
715 :
716 : template <class parentT>
717 4 : bool zaberStage<parentT>::isCommandReply( const za_reply &rep )
718 : {
719 4 : return rep.message_type == '@' && rep.device_address == m_deviceAddress;
720 : }
721 :
722 : template <class parentT>
723 0 : int zaberStage<parentT>::sendCommand( std::string &response, z_port port, const std::string &command )
724 : {
725 0 : za_send( port, command.c_str(), command.size() );
726 :
727 : char buff[256];
728 :
729 0 : while( 1 )
730 : {
731 0 : int rv = za_receive( port, buff, sizeof( buff ) );
732 :
733 0 : if( rv == Z_ERROR_TIMEOUT )
734 : {
735 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
736 : {
737 0 : return rv; // don't log, but propagate error
738 : }
739 :
740 0 : MagAOXAppT::log<software_error>( "Z_ERROR_TIMEOUT" );
741 0 : break; // assume error and just get out.
742 : }
743 0 : else if( rv < 0 )
744 : {
745 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
746 : {
747 0 : return rv; // don't log, but propagate error
748 : }
749 :
750 0 : MagAOXAppT::log<software_error>( { 0, "za_receive !=Z_SUCCESS" } );
751 0 : break;
752 : }
753 : za_reply rep;
754 :
755 0 : rv = za_decode( &rep, buff, sizeof( buff ) );
756 0 : if( rv != Z_SUCCESS )
757 : {
758 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
759 : {
760 0 : return rv; // don't log, but propagate error
761 : }
762 :
763 0 : MagAOXAppT::log<software_error>( "za_decode !=Z_SUCCESS" );
764 0 : break;
765 : }
766 :
767 0 : if( isCommandReply( rep ) )
768 0 : return getResponse( response, rep );
769 : }
770 :
771 0 : response = "";
772 :
773 0 : return -1;
774 : }
775 :
776 : template <class parentT>
777 : template <typename valT>
778 0 : int zaberStage<parentT>::getValue( valT &val, z_port port, const std::string command )
779 : {
780 0 : if( m_deviceAddress < 1 )
781 : {
782 0 : return MagAOXAppT::log<software_error, -1>(
783 0 : { std::format( "stage {} with s/n {} not found in system.", m_name, m_serial ) } );
784 : }
785 :
786 0 : std::string response;
787 :
788 0 : int rv = sendCommand( response, port, std::format( "/{} {}", m_deviceAddress, command ) );
789 :
790 0 : if( rv == 0 )
791 : {
792 0 : if( m_commandStatus )
793 : {
794 : mx::error_t errc;
795 :
796 0 : val = mx::ioutils::stoT<valT>( response, &errc );
797 :
798 0 : if( !!errc )
799 : {
800 0 : return MagAOXAppT::log<software_error, -1>(
801 0 : std::format( "parsing [{}] response from {}: {}", command, m_name, mx::errorMessage( errc ) ) );
802 : }
803 :
804 0 : return 0;
805 : }
806 : else
807 : {
808 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
809 : {
810 0 : return -1; // don't log, but propagate error
811 : }
812 :
813 0 : MagAOXAppT::log<software_error>( { rv, command + "command Rejected" } );
814 0 : return -1;
815 : }
816 : }
817 : else
818 : {
819 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
820 : {
821 0 : return -1; // don't log, but propagate error
822 : }
823 :
824 0 : MagAOXAppT::log<software_error>();
825 :
826 0 : return -1;
827 : }
828 0 : }
829 :
830 : template <class parentT>
831 0 : int zaberStage<parentT>::getMaxPos( z_port port )
832 : {
833 0 : int rv = getValue( m_maxPos, port, "get limit.max" );
834 :
835 0 : if( rv < 0 )
836 : {
837 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
838 : {
839 0 : return -1; // don't log, but propagate error
840 : }
841 :
842 0 : return MagAOXAppT::log<software_error, -1>();
843 : }
844 :
845 0 : return 0;
846 : }
847 :
848 : template <class parentT>
849 0 : int zaberStage<parentT>::getParked( z_port port )
850 : {
851 0 : int rv = getValue( m_parked, port, "tools parking state" );
852 :
853 0 : if( rv < 0 )
854 : {
855 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
856 : {
857 0 : return -1; // don't log, but propagate error
858 : }
859 :
860 0 : return MagAOXAppT::log<software_error, -1>();
861 : }
862 :
863 0 : return 0;
864 : }
865 :
866 : template <class parentT>
867 0 : int zaberStage<parentT>::getKnob( z_port port )
868 : {
869 0 : int rv = getValue( m_knobEnabled, port, "get knob.enable" );
870 :
871 0 : if( rv < 0 )
872 : {
873 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
874 : {
875 0 : return -1; // don't log, but propagate error
876 : }
877 :
878 0 : return MagAOXAppT::log<software_error, -1>();
879 : }
880 :
881 0 : return 0;
882 : }
883 :
884 : template <class parentT>
885 0 : int zaberStage<parentT>::getLED( z_port port )
886 : {
887 0 : int rv = getValue( m_ledEnabled, port, "get system.led.enable" );
888 :
889 0 : if( rv < 0 )
890 : {
891 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
892 : {
893 0 : return -1; // don't log, but propagate error
894 : }
895 :
896 0 : return MagAOXAppT::log<software_error, -1>();
897 : }
898 :
899 0 : return 0;
900 : }
901 :
902 : template <class parentT>
903 0 : int zaberStage<parentT>::updatePos( z_port port )
904 : {
905 0 : int rv = getValue( m_rawPos, port, "get pos" );
906 :
907 0 : if( rv < 0 )
908 : {
909 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
910 : {
911 0 : return -1; // don't log, but propagate error
912 : }
913 :
914 0 : return MagAOXAppT::log<software_error, -1>();
915 : }
916 :
917 0 : return 0;
918 : }
919 :
920 : template <class parentT>
921 0 : int zaberStage<parentT>::updateTemp( z_port port )
922 : {
923 0 : int rv = getValue( m_temp, port, "get driver.temperature" );
924 :
925 0 : if( rv < 0 )
926 : {
927 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
928 : {
929 0 : return -1; // don't log, but propagate error
930 : }
931 :
932 0 : return MagAOXAppT::log<software_error, -1>();
933 : }
934 :
935 0 : return 0;
936 : }
937 :
938 : template <class parentT>
939 0 : int zaberStage<parentT>::sendCommand( z_port port, const std::string &command )
940 : {
941 0 : if( m_deviceAddress < 1 )
942 : {
943 0 : return MagAOXAppT::log<software_error, -1>(
944 0 : std::format( "stage {} with s/n {} not found in system.", m_name, m_serial ) );
945 : }
946 :
947 0 : std::string response;
948 :
949 0 : int rv = sendCommand( response, port, std::format( "/{} {}", m_deviceAddress, command ) );
950 :
951 0 : if( rv == 0 )
952 : {
953 0 : if( m_commandStatus )
954 : {
955 0 : return 0;
956 : }
957 : else
958 : {
959 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
960 : {
961 0 : return -1; // don't log, but propagate error
962 : }
963 :
964 0 : return MagAOXAppT::log<software_error, -1>(
965 0 : { rv, std::format( "{} {} commmand rejected", m_name, command ) } );
966 : }
967 : }
968 : else
969 : {
970 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
971 : {
972 0 : return -1; // don't log, but propagate error
973 : }
974 :
975 0 : MagAOXAppT::log<software_error>();
976 0 : return -1;
977 : }
978 0 : }
979 :
980 : template <class parentT>
981 0 : int zaberStage<parentT>::enableKnob( z_port port, bool enable )
982 : {
983 0 : std::string cmd = std::format( "set knob.enable {}", enable ? "1" : "0" );
984 :
985 0 : int rv = sendCommand( port, cmd );
986 :
987 0 : if( rv < 0 )
988 : {
989 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
990 : {
991 0 : return -1; // don't log, but propagate error
992 : }
993 :
994 0 : return MagAOXAppT::log<software_error, -1>();
995 : }
996 :
997 0 : return 0;
998 0 : }
999 :
1000 : template <class parentT>
1001 0 : int zaberStage<parentT>::enableLED( z_port port, bool enable )
1002 : {
1003 0 : std::string cmd = std::format( "set system.led.enable {}", enable ? "1" : "0" );
1004 :
1005 0 : int rv = sendCommand( port, cmd );
1006 :
1007 0 : if( rv < 0 )
1008 : {
1009 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1010 : {
1011 0 : return -1; // don't log, but propagate error
1012 : }
1013 :
1014 0 : return MagAOXAppT::log<software_error, -1>();
1015 : }
1016 :
1017 0 : return 0;
1018 0 : }
1019 :
1020 : template <class parentT>
1021 0 : int zaberStage<parentT>::stop( z_port port )
1022 : {
1023 0 : int rv = sendCommand( port, "stop" );
1024 :
1025 0 : if( rv < 0 )
1026 : {
1027 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1028 : {
1029 0 : return -1; // don't log, but propagate error
1030 : }
1031 :
1032 0 : return MagAOXAppT::log<software_error, -1>();
1033 : }
1034 :
1035 0 : return 0;
1036 : }
1037 :
1038 : template <class parentT>
1039 0 : int zaberStage<parentT>::estop( z_port port )
1040 : {
1041 0 : int rv = sendCommand( port, "estop" );
1042 :
1043 0 : if( rv < 0 )
1044 : {
1045 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1046 : {
1047 0 : return -1; // don't log, but propagate error
1048 : }
1049 :
1050 0 : return MagAOXAppT::log<software_error, -1>();
1051 : }
1052 :
1053 0 : return 0;
1054 : }
1055 :
1056 : template <class parentT>
1057 0 : int zaberStage<parentT>::home( z_port port )
1058 : {
1059 0 : int rv = sendCommand( port, "home" );
1060 :
1061 0 : if( rv < 0 )
1062 : {
1063 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1064 : {
1065 0 : return -1; // don't log, but propagate error
1066 : }
1067 :
1068 0 : return MagAOXAppT::log<software_error, -1>();
1069 : }
1070 :
1071 0 : m_homing = true;
1072 0 : m_tgtPos = 0;
1073 0 : return 0;
1074 : }
1075 :
1076 : template <class parentT>
1077 0 : int zaberStage<parentT>::park( z_port port )
1078 : {
1079 0 : int rv = sendCommand( port, "tools parking park" );
1080 :
1081 0 : if( rv < 0 )
1082 : {
1083 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1084 : {
1085 0 : return -1; // don't log, but propagate error
1086 : }
1087 :
1088 0 : return MagAOXAppT::log<software_error, -1>();
1089 : }
1090 :
1091 0 : m_parked = true;
1092 :
1093 0 : return 0;
1094 : }
1095 :
1096 : template <class parentT>
1097 0 : int zaberStage<parentT>::unpark( z_port port )
1098 : {
1099 0 : int rv = sendCommand( port, "tools parking unpark" );
1100 :
1101 0 : if( rv < 0 )
1102 : {
1103 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1104 : {
1105 0 : return -1; // don't log, but propagate error
1106 : }
1107 :
1108 0 : return MagAOXAppT::log<software_error, -1>();
1109 : }
1110 :
1111 0 : m_parked = false;
1112 0 : return 0;
1113 : }
1114 :
1115 : template <class parentT>
1116 0 : int zaberStage<parentT>::moveAbs( z_port port, long rawPos )
1117 : {
1118 0 : m_tgtPos = rawPos;
1119 :
1120 0 : if( m_parked )
1121 : {
1122 0 : if( unpark( port ) < 0 )
1123 : {
1124 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1125 : {
1126 0 : return -1; // don't log, but propagate error
1127 : }
1128 :
1129 0 : return MagAOXAppT::log<software_error, -1>();
1130 : }
1131 : }
1132 :
1133 0 : int rv = sendCommand( port, std::format( "move abs {}", rawPos ) );
1134 :
1135 0 : if( rv < 0 )
1136 : {
1137 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1138 : {
1139 0 : return -1; // don't log, but propagate error
1140 : }
1141 :
1142 0 : return MagAOXAppT::log<software_error, -1>();
1143 : }
1144 :
1145 0 : return 0;
1146 : }
1147 :
1148 : template <class parentT>
1149 0 : int zaberStage<parentT>::unsetWarnings()
1150 : {
1151 0 : m_warn = false;
1152 :
1153 0 : m_warnFD = false;
1154 0 : m_warnFQ = false;
1155 0 : m_warnFS = false;
1156 0 : m_warnFT = false;
1157 0 : m_warnFB = false;
1158 0 : m_warnFP = false;
1159 0 : m_warnFE = false;
1160 0 : m_warnWH = false;
1161 0 : m_warnWL = false;
1162 0 : m_warnWP = false;
1163 0 : m_warnWV = false;
1164 0 : m_warnWT = false;
1165 0 : m_warnWM = false;
1166 0 : m_warnWR = false;
1167 0 : m_warnNC = false;
1168 0 : m_warnNI = false;
1169 0 : m_warnND = false;
1170 0 : m_warnNU = false;
1171 0 : m_warnNJ = false;
1172 0 : m_warnUNK = false;
1173 :
1174 0 : return 0;
1175 : }
1176 :
1177 : template <class parentT>
1178 21 : int zaberStage<parentT>::processWarning( std::string &warn )
1179 : {
1180 21 : if( warn == "FD" )
1181 : {
1182 1 : if( !m_warnFDreported )
1183 : {
1184 1 : MagAOXAppT::log<text_log>( m_name +
1185 : " Driver Disabled (FD): The driver has disabled itself due to overheating.",
1186 : logPrio::LOG_EMERGENCY );
1187 1 : m_warnFDreported = true;
1188 : }
1189 :
1190 1 : m_warnFD = true;
1191 1 : return 0;
1192 : }
1193 20 : else if( warn == "FQ" )
1194 : {
1195 1 : if( !m_warnFQreported )
1196 : {
1197 1 : MagAOXAppT::log<text_log>( m_name + " warning FQ: you should probably check.", logPrio::LOG_EMERGENCY );
1198 1 : m_warnFQreported = true;
1199 : }
1200 :
1201 1 : m_warnFQ = true;
1202 1 : return 0;
1203 : }
1204 19 : else if( warn == "FS" )
1205 : {
1206 1 : if( !m_warnFSreported )
1207 : {
1208 1 : MagAOXAppT::log<text_log>(
1209 1 : m_name + " Stalled and Stopped (FS): Stalling was detected and the axis has stopped itself. ",
1210 : logPrio::LOG_WARNING );
1211 1 : m_warnFSreported = true;
1212 : }
1213 1 : m_warnFS = true;
1214 1 : return 0;
1215 : }
1216 18 : else if( warn == "FT" )
1217 : {
1218 1 : if( !m_warnFTreported )
1219 : {
1220 1 : MagAOXAppT::log<text_log>(
1221 1 : m_name + " Excessive Twist (FT): The lockstep group has exceeded allowable twist and has stopped. ",
1222 : logPrio::LOG_WARNING );
1223 1 : m_warnFTreported = true;
1224 : }
1225 :
1226 1 : m_warnFT = true;
1227 1 : return 0;
1228 : }
1229 17 : else if( warn == "FB" )
1230 : {
1231 1 : if( !m_warnFBreported )
1232 : {
1233 1 : MagAOXAppT::log<text_log>( m_name + " Stream Bounds Error (FB): A previous streamed motion could not be "
1234 : "executed because it failed a precondition",
1235 : logPrio::LOG_WARNING );
1236 1 : m_warnFBreported = true;
1237 : }
1238 :
1239 1 : m_warnFB = true;
1240 1 : return 0;
1241 : }
1242 16 : else if( warn == "FP" )
1243 : {
1244 1 : if( !m_warnFPreported )
1245 : {
1246 1 : MagAOXAppT::log<text_log>(
1247 1 : m_name + " Interpolated Path Deviation (FP): Streamed or sinusoidal motion was terminated because an "
1248 : "axis slipped and thus the device deviated from the requested path. ",
1249 : logPrio::LOG_WARNING );
1250 1 : m_warnFPreported = true;
1251 : }
1252 :
1253 1 : m_warnFP = true;
1254 1 : return 0;
1255 : }
1256 15 : else if( warn == "FE" )
1257 : {
1258 1 : if( !m_warnFEreported )
1259 : {
1260 1 : MagAOXAppT::log<text_log>(
1261 1 : m_name + " Limit Error (FE): The target limit sensor cannot be reached or is faulty. ",
1262 : logPrio::LOG_WARNING );
1263 1 : m_warnFEreported = true;
1264 : }
1265 :
1266 1 : m_warnFE = true;
1267 1 : return 0;
1268 : }
1269 14 : else if( warn == "WH" )
1270 : {
1271 1 : if( m_warnWHreported == false )
1272 : {
1273 1 : MagAOXAppT::log<text_log>(
1274 1 : m_name + " Device not homed (WH): The device has a position reference, but has not been homed.",
1275 : logPrio::LOG_WARNING );
1276 1 : m_warnWHreported = true;
1277 : }
1278 :
1279 1 : m_warnWH = true;
1280 1 : return 0;
1281 : }
1282 13 : else if( warn == "WL" )
1283 : {
1284 1 : if( !m_warnWLreported )
1285 : {
1286 1 : MagAOXAppT::log<text_log>( m_name + " Unexpected Limit Trigger warning (WL): A movement operation did not "
1287 : "complete due to a triggered limit sensor.",
1288 : logPrio::LOG_WARNING );
1289 1 : m_warnWLreported = true;
1290 : }
1291 :
1292 1 : m_warnWL = true;
1293 1 : return 0;
1294 : }
1295 12 : else if( warn == "WP" )
1296 : {
1297 1 : if( !m_warnWPreported )
1298 : {
1299 1 : MagAOXAppT::log<text_log>(
1300 1 : m_name + " Invalid calibration type (WP): The saved calibration data type is unsupported",
1301 : logPrio::LOG_WARNING );
1302 1 : m_warnWPreported = true;
1303 : }
1304 :
1305 1 : m_warnWP = true;
1306 1 : return 0;
1307 : }
1308 11 : else if( warn == "WV" )
1309 : {
1310 1 : if( !m_warnWVreported )
1311 : {
1312 1 : MagAOXAppT::log<text_log>( m_name + " Voltage Out of Range (WV): The supply voltage is outside the "
1313 : "recommended operating range of the device",
1314 : logPrio::LOG_WARNING );
1315 1 : m_warnWVreported = true;
1316 : }
1317 :
1318 1 : m_warnWV = true;
1319 1 : return 0;
1320 : }
1321 10 : else if( warn == "WT" )
1322 : {
1323 1 : if( !m_warnWTreported )
1324 : {
1325 1 : MagAOXAppT::log<text_log>( m_name + " Controller Temperature High (WT): The internal temperature of the "
1326 : "controller has exceeded the recommended limit for the device.",
1327 : logPrio::LOG_WARNING );
1328 1 : m_warnWTreported = true;
1329 : }
1330 :
1331 1 : m_warnWT = true;
1332 1 : return 0;
1333 : }
1334 9 : else if( warn == "WM" )
1335 : {
1336 1 : if( m_warnWMreported == false )
1337 : {
1338 1 : MagAOXAppT::log<text_log>( m_name + " Displaced when Stationary (WM): While not in motion, the axis has "
1339 : "been forced out of its position.",
1340 : logPrio::LOG_WARNING );
1341 1 : m_warnWMreported = true;
1342 : }
1343 :
1344 1 : m_warnWM = true;
1345 1 : return 0;
1346 : }
1347 8 : else if( warn == "WR" )
1348 : {
1349 2 : if( m_warnWRreported == false )
1350 : {
1351 2 : MagAOXAppT::log<text_log>(
1352 2 : m_name +
1353 : " No Reference Position (WR): Axis has not had a reference position established. [homing required]",
1354 : logPrio::LOG_WARNING );
1355 2 : m_warnWRreported = true;
1356 : }
1357 :
1358 2 : m_warnWR = true;
1359 2 : return 0;
1360 : }
1361 6 : else if( warn == "NC" )
1362 : {
1363 1 : if( !m_warnNCreported )
1364 : {
1365 1 : MagAOXAppT::log<text_log>( m_name +
1366 : " Manual Control (NC): Axis is busy due to manual control via the knob.",
1367 : logPrio::LOG_WARNING );
1368 1 : m_warnNCreported = true;
1369 : }
1370 :
1371 1 : m_warnNC = true;
1372 1 : return 0;
1373 : }
1374 5 : else if( warn == "NI" )
1375 : {
1376 1 : if( m_homing == true || warnWR() )
1377 : {
1378 0 : return 0; // ignore this during homing
1379 : }
1380 :
1381 1 : if( !m_warnNIreported )
1382 : {
1383 1 : MagAOXAppT::log<text_log>( m_name + " Command Interrupted (NI): A movement operation "
1384 : "(command or manual control) was requested "
1385 : "while the axis was executing another movement command.",
1386 : logPrio::LOG_WARNING );
1387 1 : m_warnNIreported = true;
1388 : }
1389 :
1390 1 : m_warnNI = true;
1391 1 : return 0;
1392 : }
1393 4 : else if( warn == "ND" )
1394 : {
1395 1 : if( !m_warnNDreported )
1396 : {
1397 1 : MagAOXAppT::log<text_log>( m_name + " Stream Discontinuity (ND): The device has slowed down while "
1398 : "following a "
1399 : "streamed motion path because it has run out of queued motions.",
1400 : logPrio::LOG_WARNING );
1401 1 : m_warnNDreported = true;
1402 : }
1403 :
1404 1 : m_warnND = true;
1405 1 : return 0;
1406 : }
1407 3 : else if( warn == "NU" )
1408 : {
1409 1 : if( !m_warnNUreported )
1410 : {
1411 1 : MagAOXAppT::log<text_log>( m_name + " Setting Update Pending (NU): A setting is pending to be "
1412 : "updated or a reset is pending.",
1413 : logPrio::LOG_WARNING );
1414 1 : m_warnNUreported = true;
1415 : }
1416 :
1417 1 : m_warnNU = true;
1418 1 : return 0;
1419 : }
1420 2 : else if( warn == "NJ" )
1421 : {
1422 1 : if( !m_warnNJreported )
1423 : {
1424 1 : MagAOXAppT::log<text_log>( m_name + " Joystick Calibrating (NJ): Joystick calibration is "
1425 : "in progress.",
1426 : logPrio::LOG_WARNING );
1427 1 : m_warnNJreported = true;
1428 : }
1429 :
1430 1 : m_warnNJ = true;
1431 1 : return 0;
1432 : }
1433 : else
1434 : {
1435 1 : MagAOXAppT::log<software_warning>( std::format( "{} unknown stage warning: {}", m_name, warn ) );
1436 :
1437 1 : m_warnUNK = true;
1438 :
1439 1 : return 0;
1440 : }
1441 :
1442 : return -1;
1443 : }
1444 :
1445 : template <class parentT>
1446 8 : int zaberStage<parentT>::parseWarnings( std::string &response )
1447 : {
1448 :
1449 : size_t nwarn;
1450 :
1451 : try
1452 : {
1453 8 : nwarn = std::stoi( response.substr( 0, 2 ) );
1454 : }
1455 0 : catch( ... )
1456 : {
1457 0 : return MagAOXAppT::log<software_error, -1>( { "exception while parsing warning" } );
1458 : }
1459 :
1460 8 : if( nwarn > 0 )
1461 : {
1462 7 : m_warn = true;
1463 : }
1464 :
1465 50 : for( size_t n = 0; n < nwarn; ++n )
1466 : {
1467 23 : if( response.size() < 5 + n * 3 )
1468 : {
1469 2 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1470 : {
1471 2 : return -1; // don't log, but propagate error
1472 : }
1473 :
1474 0 : return MagAOXAppT::log<software_error, -1>( { "parsing incomplete warning response" } );
1475 : }
1476 :
1477 21 : std::string warn = response.substr( 3 + n * 3, 2 );
1478 :
1479 21 : int rv = processWarning( warn );
1480 21 : if( rv < 0 )
1481 : {
1482 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1483 : {
1484 0 : return -1; // don't log, but propagate error
1485 : }
1486 :
1487 0 : MagAOXAppT::log<software_error>();
1488 0 : return -1;
1489 : }
1490 : }
1491 :
1492 6 : if( m_warnFDreported )
1493 : {
1494 1 : if( !m_warnFD )
1495 : {
1496 0 : m_warnFDreported = false;
1497 : }
1498 : }
1499 :
1500 6 : if( m_warnFQreported )
1501 : {
1502 1 : if( !m_warnFQ )
1503 : {
1504 0 : m_warnFQreported = false;
1505 : }
1506 : }
1507 :
1508 6 : if( m_warnFSreported )
1509 : {
1510 1 : if( !m_warnFS )
1511 : {
1512 0 : m_warnFSreported = false;
1513 : }
1514 : }
1515 :
1516 6 : if( m_warnFTreported )
1517 : {
1518 1 : if( !m_warnFT )
1519 : {
1520 0 : m_warnFTreported = false;
1521 : }
1522 : }
1523 :
1524 6 : if( m_warnFBreported )
1525 : {
1526 1 : if( !m_warnFB )
1527 : {
1528 0 : m_warnFBreported = false;
1529 : }
1530 : }
1531 :
1532 6 : if( m_warnFPreported )
1533 : {
1534 1 : if( !m_warnFP )
1535 : {
1536 0 : m_warnFPreported = false;
1537 : }
1538 : }
1539 :
1540 6 : if( m_warnFEreported )
1541 : {
1542 1 : if( !m_warnFE )
1543 : {
1544 0 : m_warnFEreported = false;
1545 : }
1546 : }
1547 :
1548 6 : if( m_warnWHreported )
1549 : {
1550 1 : if( !m_warnWH )
1551 : {
1552 0 : m_warnWHreported = false;
1553 : }
1554 : }
1555 :
1556 6 : if( m_warnWLreported )
1557 : {
1558 1 : if( !m_warnWL )
1559 : {
1560 0 : m_warnWLreported = false;
1561 : }
1562 : }
1563 :
1564 6 : if( m_warnWPreported )
1565 : {
1566 1 : if( !m_warnWP )
1567 : {
1568 0 : m_warnWPreported = false;
1569 : }
1570 : }
1571 :
1572 6 : if( m_warnWVreported )
1573 : {
1574 1 : if( !m_warnWV )
1575 : {
1576 0 : m_warnWVreported = false;
1577 : }
1578 : }
1579 :
1580 6 : if( m_warnWTreported )
1581 : {
1582 1 : if( !m_warnWT )
1583 : {
1584 0 : m_warnWTreported = false;
1585 : }
1586 : }
1587 :
1588 6 : if( m_warnWMreported )
1589 : {
1590 1 : if( !m_warnWM )
1591 : {
1592 0 : m_warnWMreported = false;
1593 : }
1594 : }
1595 :
1596 6 : if( m_warnWRreported )
1597 : {
1598 2 : if( !m_warnWR )
1599 : {
1600 0 : m_warnWRreported = false;
1601 : }
1602 : }
1603 :
1604 6 : if( m_warnNCreported )
1605 : {
1606 1 : if( !m_warnNC )
1607 : {
1608 0 : m_warnNCreported = false;
1609 : }
1610 : }
1611 :
1612 6 : if( m_warnNIreported )
1613 : {
1614 1 : if( !m_warnNI )
1615 : {
1616 0 : m_warnNIreported = false;
1617 : }
1618 : }
1619 :
1620 6 : if( m_warnNDreported )
1621 : {
1622 1 : if( !m_warnND )
1623 : {
1624 0 : m_warnNDreported = false;
1625 : }
1626 : }
1627 :
1628 6 : if( m_warnNUreported )
1629 : {
1630 1 : if( !m_warnNU )
1631 : {
1632 0 : m_warnNUreported = false;
1633 : }
1634 : }
1635 :
1636 6 : if( m_warnNJreported )
1637 : {
1638 1 : if( !m_warnNJ )
1639 : {
1640 0 : m_warnNJreported = false;
1641 : }
1642 : }
1643 :
1644 6 : return 0;
1645 : }
1646 :
1647 : template <class parentT>
1648 0 : int zaberStage<parentT>::getWarnings( z_port port )
1649 : {
1650 0 : if( m_deviceAddress < 1 )
1651 : {
1652 0 : return MagAOXAppT::log<software_error, -1>(
1653 0 : { "stage " + m_name + " with with s/n " + m_serial + " not found in system." } );
1654 : }
1655 :
1656 0 : std::string response;
1657 :
1658 0 : int rv = sendCommand( response, port, std::format( "/{} warnings", m_deviceAddress ) );
1659 :
1660 0 : if( rv == 0 )
1661 : {
1662 0 : if( m_commandStatus )
1663 : {
1664 0 : unsetWarnings(); // Clear all the flags before setting them to stay current.
1665 0 : return parseWarnings( response );
1666 : }
1667 : else
1668 : {
1669 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1670 : {
1671 0 : return -1; // don't log, but propagate error
1672 : }
1673 :
1674 0 : MagAOXAppT::log<software_error>( { rv, "warnings Command Rejected" } );
1675 0 : return -1;
1676 : }
1677 : }
1678 : else
1679 : {
1680 0 : if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
1681 : {
1682 0 : return -1; // don't log, but propagate error
1683 : }
1684 :
1685 0 : MagAOXAppT::log<software_error>();
1686 0 : return -1;
1687 : }
1688 0 : }
1689 :
1690 : template <class parentT>
1691 0 : int zaberStage<parentT>::onPowerOff()
1692 : {
1693 0 : m_commandStatus = true; ///< The status of the last command sent. true = OK, false = RJ (rejected)
1694 :
1695 0 : m_deviceStatus = 'U'; ///< Current status. Either 'I' for IDLE or 'B' for BUSY. Intializes to 'U' for UNKOWN.
1696 :
1697 0 : m_homing = false;
1698 :
1699 : // We don't 0 rawPos so it is retained
1700 :
1701 0 : m_temp = -999; ///< The driver temperature, in C.
1702 :
1703 0 : unsetWarnings();
1704 0 : m_warnWRreported = false;
1705 :
1706 0 : return 0;
1707 : }
1708 :
1709 : template <class parentT>
1710 0 : int zaberStage<parentT>::writeStateFile( std::ofstream &fout )
1711 : {
1712 0 : fout << m_rawPos << '\n';
1713 :
1714 0 : if( !fout )
1715 : {
1716 0 : return MagAOXAppT::log<software_error, -1>( { "error writing raw position" } );
1717 : }
1718 :
1719 0 : fout << m_parked << '\n';
1720 :
1721 0 : if( !fout )
1722 : {
1723 0 : return MagAOXAppT::log<software_error, -1>( { "error writing parked state" } );
1724 : }
1725 :
1726 0 : fout << m_maxPos << '\n';
1727 :
1728 0 : if( !fout )
1729 : {
1730 0 : return MagAOXAppT::log<software_error, -1>( { "error writing max position" } );
1731 : }
1732 :
1733 0 : fout << m_lastHomed.tv_sec << '\n';
1734 :
1735 0 : if( !fout )
1736 : {
1737 0 : return MagAOXAppT::log<software_error, -1>( { "error writing last home time" } );
1738 : }
1739 :
1740 0 : return 0;
1741 : }
1742 :
1743 : template <class parentT>
1744 0 : int zaberStage<parentT>::readStateFile( std::ifstream &fin )
1745 : {
1746 : long rawPos;
1747 : bool parked;
1748 : long maxPos;
1749 : time_t lastHomed;
1750 :
1751 0 : fin >> rawPos;
1752 :
1753 0 : if( !fin )
1754 : {
1755 0 : return MagAOXAppT::log<software_error, -1>( { "error reading raw position" } );
1756 : }
1757 :
1758 0 : fin >> parked;
1759 :
1760 0 : if( !fin )
1761 : {
1762 0 : return MagAOXAppT::log<software_error, -1>( { "error reading parked state" } );
1763 : }
1764 :
1765 0 : fin >> maxPos;
1766 :
1767 0 : if( !fin )
1768 : {
1769 0 : return MagAOXAppT::log<software_error, -1>( { "error reading max position" } );
1770 : }
1771 :
1772 0 : fin >> lastHomed;
1773 :
1774 0 : if( !fin )
1775 : {
1776 0 : return MagAOXAppT::log<software_error, -1>( { "error reading last home time" } );
1777 : }
1778 :
1779 0 : m_rawPos = rawPos;
1780 0 : m_tgtPos = rawPos;
1781 0 : m_parked = parked;
1782 0 : m_maxPos = maxPos;
1783 0 : m_lastHomed.tv_sec = lastHomed;
1784 0 : m_lastHomed.tv_nsec = 0;
1785 :
1786 0 : return 0;
1787 : }
1788 :
1789 : } // namespace app
1790 : } // namespace MagAOX
1791 :
1792 : #endif // zaberStage_hpp
|