API
 
Loading...
Searching...
No Matches
trippLitePDU.hpp
Go to the documentation of this file.
1/** \file trippLitePDU.hpp
2 * \brief The MagAO-X Tripp Lite Power Distribution Unit controller.
3 *
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 * \ingroup trippLitePDU_files
7 */
8
9#ifndef trippLitePDU_hpp
10#define trippLitePDU_hpp
11
12
13#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
14#include "../../magaox_git_version.h"
15
16#ifdef XWC_SIM_MODE
17
19
20#endif
21
22/** \defgroup trippLitePDU Tripp Lite PDU
23 * \brief Control of MagAO-X Tripp Lite PDUs.
24 *
25 * <a href="../handbook/operating/software/apps/trippLitePDU.html">Application Documentation</a>
26 *
27 * \ingroup apps
28 *
29 */
30
31/** \defgroup trippLitePDU_files Tripp Lite PDU Files
32 * \ingroup trippLitePDU
33 */
34
35namespace MagAOX
36{
37namespace app
38{
39
40/// MagAO-X application to control a Tripp Lite power distribution unit (PDU).
41/** The device outlets are organized into channels. See \ref dev::outletController for details of configuring the channels.
42 *
43 * The line frequency and voltage, and the total load on the PDU, are monitored.
44 *
45 * \todo need username and secure password handling
46 * \todo need to recognize signals in tty polls and not return errors, etc.
47 * \todo begin logging freq/volt/amps telemetry
48 * \todo research load warnings
49 * \todo tests for parser
50 * \todo test for load warnings
51 * \todo load warnings/crit values can be logged on parse errors -- make this an issue
52 * \todo segfaults if device can not be reached on network -- make this an issue
53 *
54 * \ingroup trippLitePDU
55 */
56class trippLitePDU : public MagAOXApp<>, public dev::outletController<trippLitePDU>, public dev::ioDevice
57{
58
59protected:
60
61 std::string m_deviceAddr; ///< The device address
62 std::string m_devicePort; ///< The device port
63 std::string m_deviceUsername; ///< The login username for this device
64 std::string m_devicePassFile; ///< The login password for this device
65 int m_deviceVersion {0}; ///< Version 0 = the old PDUs, version 1 = new PDUMH15NET2LX, which is a new login procedure to get to the CLI.
66
67 float m_freqLowWarn {59}; ///< The low-frequency warning threshold
68 float m_freqHighWarn {61}; ///< The high-frequency warning threshold
69
70 float m_freqLowAlert {58}; ///< The low-frequency alert threshold
71 float m_freqHighAlert {62}; ///< The high-frequency alert threshold
72
73 float m_freqLowEmerg {57}; ///< The low-frequency emergency threshold
74 float m_freqHighEmerg {63}; ///< The high-frequency emergency threshold
75
76 float m_voltLowWarn {105}; ///< The low-voltage warning threshold
77 float m_voltHighWarn {125}; ///< The high-voltage warning threshold
78
79 float m_voltLowAlert {101}; ///< The low-voltage alert threshold
80 float m_voltHighAlert {126}; ///< The high-voltage alert threshold
81
82 float m_voltLowEmerg {99}; ///< The low-voltage emergency threshold
83 float m_voltHighEmerg {128}; ///< The high-voltage emergency threshold
84
85 float m_currWarn {15}; ///< The high-current warning threshold
86 float m_currAlert {16}; ///< The high-current alert threshold
87 float m_currEmerg {20}; ///< The high-current emergency threshold
88
89 #ifndef XWC_SIM_MODE
90 tty::telnetConn m_telnetConn; ///< The telnet connection manager
91 #endif
92
93 std::string m_status; ///< The device status
94 float m_frequency {0}; ///< The line frequency reported by the device.
95 float m_voltage {0}; ///< The line voltage reported by the device.
96 float m_current {0}; ///< The current being reported by the device.
97
98public:
99
100 /// Default c'tor.
101 trippLitePDU();
102
103 /// D'tor, declared and defined for noexcept.
106
107 /** \name MagAOXApp Interface
108 *
109 * @{
110 */
111
112 /// Setup the configuration system (called by MagAOXApp::setup())
113 virtual void setupConfig();
114
115 /// load the configuration system results (called by MagAOXApp::setup())
116 virtual void loadConfig();
117
118 /// Startup functions
119 /** Setsup the INDI vars.
120 * Checks if the device was found during loadConfig.
121 */
122 virtual int appStartup();
123
124 /// Implementation of the FSM for the tripp lite PDU.
125 virtual int appLogic();
126
127 /// Do any needed shutdown tasks. Currently nothing in this app.
128 virtual int appShutdown();
129
130 ///@}
131
132 /** \name outletController Interface
133 *
134 * @{
135 */
136
137 /// Update a single outlet state
138 /** For the trippLitePDU this isn't possible for a single outlet, so this calls updateOutletStates.
139 *
140 * \returns 0 on success
141 * \returns -1 on error
142 */
143 virtual int updateOutletState( int outletNum /**< [in] the outlet number to update */);
144
145 /// Queries the device to find the state of each outlet, as well as other parameters.
146 /** Sends `devstatus` to the device, and parses the result.
147 *
148 * \returns 0 on success
149 * \returns -1 on error
150 */
151 virtual int updateOutletStates();
152
153 /// Turn on an outlet.
154 /**
155 * \returns 0 on success
156 * \returns -1 on error
157 */
158 virtual int turnOutletOn( int outletNum /**< [in] the outlet number to turn on */);
159
160 /// Turn off an outlet.
161 /**
162 * \returns 0 on success
163 * \returns -1 on error
164 */
165 virtual int turnOutletOff( int outletNum /**< [in] the outlet number to turn off */);
166
167 ///@}
168
169 /** \name Device Interface
170 *
171 * These functions invoke the simulator code when enabled.
172 *
173 * @{
174 */
175 int devConnect();
176
177 int devLogin();
178
179 void devPostLogin();
180
181 int devStatus(std::string & strRead);
182
183 /// Parse the PDU devstatus response.
184 /**
185 * \returns 0 on success
186 * \returns <0 on error, with value indicating location of error.
187 */
188 int parsePDUStatus( std::string & strRead );
189
190 ///@}
191
193
194protected:
195
196 //declare our properties
197 pcf::IndiProperty m_indiP_status; ///< The device's status string
198 pcf::IndiProperty m_indiP_load; ///< The line and load characteristics
199
200
201#ifdef XWC_SIM_MODE
202
203public:
204
206
207#endif
208
209};
210
211trippLitePDU::trippLitePDU() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
212{
213 m_firstOne = true;
215 m_loopPause=2000000000;//Default to 2 sec loop pause to lessen the load on the PDUs.
216
217 return;
218}
219
221{
222 config.add("device.address", "a", "device.address", argType::Required, "device", "address", false, "string", "The device address.");
223 config.add("device.port", "p", "device.port", argType::Required, "device", "port", false, "string", "The device port.");
224 config.add("device.username", "u", "device.username", argType::Required, "device", "username", false, "string", "The device login username.");
225 config.add("device.passfile", "", "device.passfile", argType::Required, "device", "passfile", false, "string", "The device login password file (relative to secrets dir).");
226 config.add("device.powerAlertVersion", "", "device.powerAlertVersion", argType::Required, "device", "powerAlertVersion", false, "int", "The device network interface version. 0 is PDU..., 1 is newer LX platform.");
227
229
230 config.add("limits.freqLowWarn", "", "limits.freqLowWarn", argType::Required, "limits", "freqLowWarn", false, "int", "The low-frequency warning threshold");
231 config.add("limits.freqHighWarn", "", "limits.freqHighWarn", argType::Required, "limits", "freqHighWarn", false, "int", "The high-frequency warning threshold");
232 config.add("limits.freqLowAlert", "", "limits.freqLowAlert", argType::Required, "limits", "freqLowAlert", false, "int", "The low-frequency alert threshold");
233 config.add("limits.freqHighAlert", "", "limits.freqHighAlert", argType::Required, "limits", "freqHighAlert", false, "int", "The high-frequency alert threshold");
234 config.add("limits.freqLowEmerg", "", "limits.freqLowEmerg", argType::Required, "limits", "freqLowEmerg", false, "int", "The low-frequency emergency threshold");
235 config.add("limits.freqHighEmerg", "", "limits.freqHighEmerg", argType::Required, "limits", "freqHighEmerg", false, "int", "The high-frequency emergency threshold");
236
237 config.add("limits.voltLowWarn", "", "limits.voltLowWarn", argType::Required, "limits", "voltLowWarn", false, "int", "The low-voltage warning threshold");
238 config.add("limits.voltHighWarn", "", "limits.voltHighWarn", argType::Required, "limits", "voltHighWarn", false, "int", "The high-voltage warning threshold");
239 config.add("limits.voltLowAlert", "", "limits.voltLowAlert", argType::Required, "limits", "voltLowAlert", false, "int", "The low-voltage alert threshold");
240 config.add("limits.voltHighAlert", "", "limits.voltHighAlert", argType::Required, "limits", "voltHighAlert", false, "int", "The high-voltage alert threshold");
241 config.add("limits.voltLowEmerg", "", "limits.voltLowEmerg", argType::Required, "limits", "voltLowEmerg", false, "int", "The low-voltage emergency threshold");
242 config.add("limits.voltHighEmerg", "", "limits.voltHighEmerg", argType::Required, "limits", "voltHighEmerg", false, "int", "The high-voltage emergency threshold");
243
244 config.add("limits.currWarn", "", "limits.currWarn", argType::Required, "limits", "currWarn", false, "int", "The high-current warning threshold");
245 config.add("limits.currAlert", "", "limits.currAlert", argType::Required, "limits", "currAlert", false, "int", "The high-current alert threshold");
246 config.add("limits.currEmerg", "", "limits.currEmerg", argType::Required, "limits", "currEmerg", false, "int", "The high-current emergency threshold");
247
249
250}
251
252
254{
255 config(m_deviceAddr, "device.address");
256 config(m_devicePort, "device.port");
257 config(m_deviceUsername, "device.username");
258 config(m_devicePassFile, "device.passfile");
259 config(m_deviceVersion, "device.powerAlertVersion");
260
262
263 config(m_freqLowWarn, "limits.freqLowWarn");
264 config(m_freqHighWarn, "limits.freqHighWarn");
265 config(m_freqLowAlert, "limits.freqLowAlert");
266 config(m_freqHighAlert, "limits.freqHighAlert");
267 config(m_freqLowEmerg, "limits.freqLowEmerg");
268 config(m_freqHighEmerg, "limits.freqHighEmerg");
269
270 config(m_voltLowWarn, "limits.voltLowWarn");
271 config(m_voltHighWarn, "limits.voltHighWarn");
272 config(m_voltLowAlert, "limits.voltLowAlert");
273 config(m_voltHighAlert, "limits.voltHighAlert");
274 config(m_voltLowEmerg, "limits.voltLowEmerg");
275 config(m_voltHighEmerg, "limits.voltHighEmerg");
276
277 config(m_currWarn, "limits.currWarn");
278 config(m_currAlert, "limits.currAlert");
279 config(m_currEmerg, "limits.currEmerg");
280
282
283
284}
285
287{
288 #ifdef XWC_SIM_MODE
289 log<text_log>("XWC_SIM_MODE active");
290 #endif
291
292 // set up the INDI properties
293 REG_INDI_NEWPROP_NOCB(m_indiP_status, "status", pcf::IndiProperty::Text);
294 m_indiP_status.add (pcf::IndiElement("value"));
295
296 REG_INDI_NEWPROP_NOCB(m_indiP_load, "load", pcf::IndiProperty::Number);
297 m_indiP_load.add (pcf::IndiElement("frequency"));
298 m_indiP_load.add (pcf::IndiElement("voltage"));
299 m_indiP_load.add (pcf::IndiElement("current"));
300
302 {
303 return log<text_log,-1>("Error setting up INDI for outlet control.", logPrio::LOG_CRITICAL);
304 }
305
307
308 return 0;
309}
310
312{
314 {
315 static int lastrv = 0; //Used to handle a change in error within the same state. Make general?
316 static int lasterrno = 0;
317
318 int rv = devConnect();
319
320 if(rv == 0)
321 {
323
324 if(!stateLogged())
325 {
326 std::string logs = "Connected to " + m_deviceAddr + ":" + m_devicePort;
328 }
329 lastrv = rv;
331 }
332 else
333 {
334 if(!stateLogged())
335 {
336 log<text_log>({"Failed to connect to " + m_deviceAddr + ":" + m_devicePort}, logPrio::LOG_ERROR);
337 }
338 if( rv != lastrv )
339 {
341 lastrv = rv;
342 }
343 if( errno != lasterrno )
344 {
347 }
348 return 0;
349 }
350 }
351
353 {
354 int rv = devLogin();
355
356 if(rv == 0)
357 {
359 }
360 else
361 {
363 {
365 log<text_log>("login timedout", logPrio::LOG_ERROR);
366 return 0;
367 }
368
370 log<text_log>("login failure", logPrio::LOG_CRITICAL);
371 return -1;
372 }
373 }
374
376 {
377 devPostLogin();
378
380 }
381
382 if(state() == stateCodes::READY)
383 {
384 std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
385
386 if( !lock.owns_lock())
387 {
388 return 0;
389 }
390
391 int rv = updateOutletStates();
392
393 if(rv < 0) return log<software_error,-1>({__FILE__, __LINE__});
394
396
397 return 0;
398 }
399
401 log<text_log>("appLogic fell through", logPrio::LOG_CRITICAL);
402 return -1;
403
404}
405
407{
408 //don't bother
409 return 0;
410}
411
413{
414 static_cast<void>(outletNum);
415
416 return updateOutletStates(); //We can't do just one.
417}
418
419
421{
422 int rv;
423 std::string strRead;
424
426
427 if(rv < 0 )
428 {
429 log<software_error>({__FILE__, __LINE__, "error getting device status"});
431 return 0;
432 }
433
434 if(rv > 0)
435 {
436 return 0; //this means the re-read was successful, but we don't want to parse this time.
437 }
438
440
441 if(rv == 0)
442 {
444
446
448
450
452 }
453 else
454 {
455 log<software_error>({__FILE__, __LINE__, 0, rv, "parse error"});
456 }
457
458 return 0;
459}
460
461int trippLitePDU::turnOutletOn( int outletNum )
462{
463 std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before doing anything
464
465 #ifndef XWC_SIM_MODE
466 std::string cmd = "loadctl on -o ";
467 cmd += mx::ioutils::convertToString<int>(outletNum+1); //Internally 0 counted, device starts at 1.
468 cmd += " --force\r";
469
471
472 #else
473
474 int rv = m_simulator.turnOutletOn(outletNum);
475
476 #endif
477
478 if(rv < 0) return log<software_error, -1>({__FILE__, __LINE__, 0, rv, "telnet error"});
479
480 return 0;
481}
482
483int trippLitePDU::turnOutletOff( int outletNum )
484{
485 std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before doing anything
486
487 #ifndef XWC_SIM_MODE
488 std::string cmd = "loadctl off -o ";
489 cmd += mx::ioutils::convertToString<int>(outletNum+1); //Internally 0 counted, device starts at 1.
490 cmd += " --force\r";
491
493
494 #else
495
496 int rv = m_simulator.turnOutletOff(outletNum);
497
498 #endif
499
500 if(rv < 0) return log<software_error, -1>({__FILE__, __LINE__, 0, rv, "telnet error"});
501
502 return 0;
503}
504
506{
507 #ifndef XWC_SIM_MODE
508
510
511 #else
512
513 return m_simulator.connect(m_deviceAddr, m_devicePort);
514
515 #endif
516}
517
519{
520 #ifndef XWC_SIM_MODE
521
522 //Newer version of power alert changed login (at least the first one)
523 if(m_deviceVersion > 0)
524 {
526 m_telnetConn.m_prompt = ">>";
527 }
528
529 return m_telnetConn.login("localadmin", "localadmin");
530
531 #else
532
533 return m_simulator.login("localadmin", "localadmin");
534
535 #endif
536}
537
539{
540
541 #ifndef XWC_SIM_MODE
542
543 //For newer version of power alert we need to select C.L.I.
544 if(m_deviceVersion > 0)
545 {
547 m_telnetConn.m_prompt = "$> ";
548 }
549
550 #else
551
552 m_simulator.postLogin();
553
554 #endif
555}
556
557int trippLitePDU::devStatus(std::string & strRead)
558{
559 #ifndef XWC_SIM_MODE
560
561 int rv = m_telnetConn.writeRead("devstatus\n", true, m_writeTimeout, m_readTimeout);
562
564
566 {
568
569 if( rv < 0 )
570 {
571 log<software_error>({__FILE__, __LINE__, 0, rv, "devstatus timeout, timed out on re-read: " + tty::ttyErrorString(rv)});
572 return -1;
573 }
574
575 log<text_log>("devstatus timeout, re-read successful");
576
577 return 1;
578 }
579 else if(rv < 0 )
580 {
582 return -1;
583 }
584
585 return 0;
586
587 #else
588
589 return m_simulator.devStatus(strRead);
590
591 #endif
592}
593
594int trippLitePDU::parsePDUStatus( std::string & strRead )
595{
596 size_t curpos = 0;
597
598 curpos = strRead.find_first_of("\r\n", curpos);
599
600 std::string sstr;
601
602 while(curpos < strRead.size())
603 {
604 size_t eol = strRead.find_first_of("\r\n", curpos);
605
606 if(eol == std::string::npos) eol = strRead.size();
607
608 if(eol == curpos)
609 {
610 curpos = eol + 1;
611 continue;
612 }
613
614 sstr = strRead.substr(curpos, eol-curpos);
615 curpos = eol + 1;
616
617 if(sstr[0] == '-' || sstr[0] == '0' || sstr[0] == 'L' || sstr[0] == ' ' || sstr[0] == 'D' || sstr[0] == '$') continue;
618
619 if(sstr[0] == 'I')
620 {
621 if(sstr[6] == 'V')
622 {
623 size_t begin = sstr.find(' ',6);
624 if(begin == std::string::npos)
625 {
626 return -1;
627 }
628
629 begin = sstr.find_first_not_of(' ', begin);
630 if(begin == std::string::npos)
631 {
632 return -2;
633 }
634
635 size_t end = sstr.find('V', begin);
636 if(end == std::string::npos)
637 {
638 return -3;
639 }
640
641 float V = mx::ioutils::convertFromString<float>( sstr.substr(begin, end-begin) );
642
643 m_voltage = V;
644 }
645
646 else if(sstr[6] == 'F')
647 {
648 size_t begin = sstr.find(' ',6);
649 if(begin == std::string::npos)
650 {
651 return -4;
652 }
653
654 begin = sstr.find_first_not_of(' ', begin);
655 if(begin == std::string::npos)
656 {
657 return -5;
658 }
659
660 size_t end = sstr.find('H', begin);
661 if(end == std::string::npos)
662 {
663 return -6;
664 }
665
666 float F = mx::ioutils::convertFromString<float>( sstr.substr(begin, end-begin) );
667
668 m_frequency = F;
669 }
670 else return -1;
671 }
672 else if(sstr[0] == 'O')
673 {
674 if(sstr[7] == 'C')
675 {
676 size_t begin = sstr.find(' ',7);
677 if(begin == std::string::npos)
678 {
679 return -7;
680 }
681
682 begin = sstr.find_first_not_of(' ', begin);
683 if(begin == std::string::npos)
684 {
685 return -8;
686 }
687
688 size_t end = sstr.find('A', begin);
689 if(end == std::string::npos)
690 {
691 return -9;
692 }
693
694 float C = mx::ioutils::convertFromString<float>( sstr.substr(begin, end-begin) );
695
696 m_current = C;
697 }
698 else if(sstr[8] == 'O')
699 {
700 std::vector<int> outletStates(m_outletStates.size(),OUTLET_STATE_OFF);
701
702 size_t begin = sstr.find(' ',8);
703 if(begin == std::string::npos)
704 {
705 return -10;
706 }
707
708 begin = sstr.find_first_not_of(' ', begin);
709
710 if(begin == std::string::npos)
711 {
712 return -11;
713 }
714
715 while(begin < sstr.size())
716 {
717 size_t end = sstr.find(' ', begin);
718 if(end == std::string::npos)
719 {
720 end = sstr.size();
721 }
722
723 int onum = atoi(sstr.substr(begin, end-begin).c_str());
724
725 if(onum > 0 && onum < 9)
726 {
727 outletStates[onum-1] = OUTLET_STATE_ON; //this outlet is on.
728 }
729 begin = sstr.find_first_not_of(' ', end+1);
730 }
731
732 for(size_t i=0;i<m_outletStates.size();++i)
733 {
735 }
736 }
737 else if( sstr[7] == 'V' || sstr[7] == 'F')
738 {
739 continue;
740 }
741 else
742 {
743 return -12;
744 }
745 }
746 else
747 {
748 return -13;
749 }
750 }
751
752 return 0;
753}
754
756{
758 {
759 log<text_log>("Frequency is " + std::to_string(m_frequency) + " Hz, below " +
760 std::to_string(m_freqLowEmerg) + " Hz.", logPrio::LOG_EMERGENCY);
761 }
762 else if (m_frequency >= m_freqHighEmerg)
763 {
764 log<text_log>("Frequency is " + std::to_string(m_frequency) + " Hz, above " +
765 std::to_string(m_freqHighEmerg) + " Hz.", logPrio::LOG_EMERGENCY);
766 }
767 else if (m_frequency <= m_freqLowAlert)
768 {
769 log<text_log>("Frequency is " + std::to_string(m_frequency) + " Hz, below " +
770 std::to_string(m_freqLowAlert) + " Hz.", logPrio::LOG_ALERT);
771 }
772 else if (m_frequency >= m_freqHighAlert)
773 {
774 log<text_log>("Frequency is " + std::to_string(m_frequency) + " Hz, above " +
775 std::to_string(m_freqHighAlert) + " Hz.", logPrio::LOG_ALERT);
776 }
777 else if(m_frequency <= m_freqLowWarn)
778 {
779 log<text_log>("Frequency is " + std::to_string(m_frequency) + " Hz, below " +
780 std::to_string(m_freqLowWarn) + " Hz.", logPrio::LOG_WARNING);
781 }
782 else if (m_frequency >= m_freqHighWarn)
783 {
784 log<text_log>("Frequency is " + std::to_string(m_frequency) + " Hz, above " +
785 std::to_string(m_freqHighWarn) + " Hz.", logPrio::LOG_WARNING);
786 }
787
789 {
790 log<text_log>("Voltage is " + std::to_string(m_voltage) + " V, below " +
791 std::to_string(m_voltLowEmerg) + " V.", logPrio::LOG_EMERGENCY);
792 }
793 else if (m_voltage >= m_voltHighEmerg)
794 {
795 log<text_log>("Voltage is " + std::to_string(m_voltage) + " V, above " +
796 std::to_string(m_voltHighEmerg) + " V.", logPrio::LOG_EMERGENCY);
797 }
798 else if (m_voltage <= m_voltLowAlert)
799 {
800 log<text_log>("Voltage is " + std::to_string(m_voltage) + " V, below " +
801 std::to_string(m_voltLowAlert) + " V.", logPrio::LOG_ALERT);
802 }
803 else if (m_voltage >= m_voltHighAlert)
804 {
805 log<text_log>("Voltage is " + std::to_string(m_voltage) + " V, above " +
806 std::to_string(m_voltHighAlert) + " V.", logPrio::LOG_ALERT);
807 }
808 else if(m_voltage <= m_voltLowWarn)
809 {
810 log<text_log>("Voltage is " + std::to_string(m_voltage) + " V, below " +
811 std::to_string(m_voltLowWarn) + " V.", logPrio::LOG_WARNING);
812 }
813 else if (m_voltage >= m_voltHighWarn)
814 {
815 log<text_log>("Voltage is " + std::to_string(m_voltage) + " V, above " +
816 std::to_string(m_voltHighWarn) + " V.", logPrio::LOG_WARNING);
817 }
818
819 if (m_current >= m_currEmerg)
820 {
821 log<text_log>("Current is " + std::to_string(m_current) + " A, above " +
822 std::to_string(m_currEmerg) + " A.", logPrio::LOG_EMERGENCY);
823 }
824 else if (m_current >= m_currAlert)
825 {
826 log<text_log>("Current is " + std::to_string(m_current) + " A, above " +
827 std::to_string(m_currAlert) + " A.", logPrio::LOG_ALERT);
828 }
829 else if (m_current >= m_currWarn)
830 {
831 log<text_log>("Current is " + std::to_string(m_current) + " A, above " +
832 std::to_string(m_currWarn) + " A.", logPrio::LOG_WARNING);
833 }
834}
835
836} //namespace app
837} //namespace MagAOX
838
839#endif //trippLitePDU_hpp
The base-class for MagAO-X applications.
Definition MagAOXApp.hpp:73
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
stateCodes::stateCodeT state()
Get the current state code.
unsigned long m_loopPause
Definition MagAOXApp.hpp:95
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
std::mutex m_indiMutex
Mutex for locking INDI communications.
MagAO-X application to control a Tripp Lite power distribution unit (PDU).
float m_voltage
The line voltage reported by the device.
float m_currWarn
The high-current warning threshold.
std::string m_status
The device status.
std::string m_deviceUsername
The login username for this device.
int devStatus(std::string &strRead)
float m_currAlert
The high-current alert threshold.
float m_voltHighAlert
The high-voltage alert threshold.
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
pcf::IndiProperty m_indiP_status
The device's status string.
pcf::IndiProperty m_indiP_load
The line and load characteristics.
virtual int turnOutletOn(int outletNum)
Turn on an outlet.
virtual int updateOutletStates()
Queries the device to find the state of each outlet, as well as other parameters.
virtual int appLogic()
Implementation of the FSM for the tripp lite PDU.
float m_freqLowAlert
The low-frequency alert threshold.
float m_freqHighEmerg
The high-frequency emergency threshold.
float m_frequency
The line frequency reported by the device.
float m_voltLowWarn
The low-voltage warning threshold.
float m_voltLowAlert
The low-voltage alert threshold.
int m_deviceVersion
Version 0 = the old PDUs, version 1 = new PDUMH15NET2LX, which is a new login procedure to get to the...
std::string m_devicePassFile
The login password for this device.
float m_voltHighEmerg
The high-voltage emergency threshold.
std::string m_deviceAddr
The device address.
virtual int appStartup()
Startup functions.
float m_currEmerg
The high-current emergency threshold.
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
~trippLitePDU() noexcept
D'tor, declared and defined for noexcept.
float m_freqHighWarn
The high-frequency warning threshold.
float m_freqLowWarn
The low-frequency warning threshold.
float m_voltHighWarn
The high-voltage warning threshold.
float m_voltLowEmerg
The low-voltage emergency threshold.
virtual int turnOutletOff(int outletNum)
Turn off an outlet.
virtual int updateOutletState(int outletNum)
Update a single outlet state.
tty::telnetConn m_telnetConn
The telnet connection manager.
float m_current
The current being reported by the device.
float m_freqLowEmerg
The low-frequency emergency threshold.
std::string m_devicePort
The device port.
float m_freqHighAlert
The high-frequency alert threshold.
int parsePDUStatus(std::string &strRead)
Parse the PDU devstatus response.
#define REG_INDI_NEWPROP_NOCB(prop, propName, type)
Register a NEW INDI property with the class, with no callback.
@ FAILURE
The application has failed, should be used when m_shutdown is set for an error.
@ READY
The device is ready for operation, but is not operating.
@ LOGGEDIN
The application has logged into the device or service.
@ CONNECTED
The application has connected to the device or service.
@ NOTCONNECTED
The application is not connected to the device or service.
std::string ttyErrorString(int ec)
Get a text explanation of a TTY_E_ error code.
Definition ttyErrors.cpp:15
std::unique_lock< std::mutex > lock(m_indiMutex)
Definition dm.hpp:24
static constexpr logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
static constexpr logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
static constexpr logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
static constexpr logPrioT LOG_EMERGENCY
Normal operations of the entire system should be shut down immediately.
static constexpr logPrioT LOG_ALERT
This should only be used if some action is required by operators to keep the system safe.
#define OUTLET_STATE_OFF
#define OUTLET_STATE_ON
An input/output capable device.
Definition ioDevice.hpp:27
unsigned m_writeTimeout
The write timeout [msec].
Definition ioDevice.hpp:29
int loadConfig(mx::app::appConfigurator &config)
Load the device section from an application configurator.
Definition ioDevice.cpp:28
int setupConfig(mx::app::appConfigurator &config)
Setup an application configurator for the device section.
Definition ioDevice.cpp:20
unsigned m_readTimeout
The read timeout [msec].
Definition ioDevice.hpp:28
A generic outlet controller.
int updateINDI()
Update the INDI properties for this device controller.
bool m_firstOne
Flag is true if the first outlet is numbered 1, otherwise assumes starting at 0.
int loadConfig(mx::app::appConfigurator &config)
Load the [channel] sections from an application configurator.
int setupConfig(mx::app::appConfigurator &config)
Setup an application configurator for an outletController.
int setNumberOfOutlets(int numOuts)
Sets the number of outlets. This should be called by the derived class constructor.
std::vector< int > m_outletStates
The current states of each outlet. These MUST be updated by derived classes in the overridden updated...
Software ERR log entry.
A simple text log, a string-type log.
Definition text_log.hpp:24
A Telnet connection manager, wrapping libtelnet.
int login(const std::string &username, const std::string &password)
Manage the login process on this device.
std::string m_usernamePrompt
The device's username entry prompt, used for managing login.
std::string m_strRead
The accumulated string read from the device.
std::string m_prompt
The device's prompt, used for detecting end of transmission.
int writeRead(const std::string &strWrite, bool swallowEcho, int timeoutWrite, int timeoutRead)
Write to a telnet connection, then get the reply.
int read(const std::string &eot, int timeoutRead, bool clear=true)
Read from a telnet connection, until end-of-transmission string is read.
int connect(const std::string &host, const std::string &port)
Connect to the device.
The MagAO-X Tripp Lite Power Distribution Unit ontroller Simulator.
#define TTY_E_TIMEOUTONREAD
Definition ttyErrors.hpp:27
#define TTY_E_TIMEOUTONREADPOLL
Definition ttyErrors.hpp:24
#define TELNET_E_LOGINTIMEOUT
Definition ttyErrors.hpp:40