9 #ifndef trippLitePDU_hpp
10 #define trippLitePDU_hpp
13 #include "../../libMagAOX/libMagAOX.hpp"
14 #include "../../magaox_git_version.h"
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.");
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");
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");
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");
289 log<text_log>(
"XWC_SIM_MODE active");
315 static int lastrv = 0;
316 static int lasterrno = 0;
343 if( errno != lasterrno )
345 log<software_error>( {__FILE__,__LINE__, errno});
386 if( !
lock.owns_lock())
414 static_cast<void>(outletNum);
429 log<software_error>({__FILE__, __LINE__,
"error getting device status"});
455 log<software_error>({__FILE__, __LINE__, 0, rv,
"parse error"});
466 std::string cmd =
"loadctl on -o ";
467 cmd += mx::ioutils::convertToString<int>(outletNum+1);
474 int rv = m_simulator.turnOutletOn(outletNum);
478 if(rv < 0)
return log<
software_error, -1>({__FILE__, __LINE__, 0, rv,
"telnet error"});
488 std::string cmd =
"loadctl off -o ";
489 cmd += mx::ioutils::convertToString<int>(outletNum+1);
496 int rv = m_simulator.turnOutletOff(outletNum);
500 if(rv < 0)
return log<
software_error, -1>({__FILE__, __LINE__, 0, rv,
"telnet error"});
533 return m_simulator.login(
"localadmin",
"localadmin");
552 m_simulator.postLogin();
571 log<software_error>({__FILE__, __LINE__, 0, rv,
"devstatus timeout, timed out on re-read: " +
tty::ttyErrorString(rv)});
575 log<text_log>(
"devstatus timeout, re-read successful");
589 return m_simulator.devStatus(strRead);
598 curpos = strRead.find_first_of(
"\r\n", curpos);
602 while(curpos < strRead.size())
604 size_t eol = strRead.find_first_of(
"\r\n", curpos);
606 if(eol == std::string::npos) eol = strRead.size();
614 sstr = strRead.substr(curpos, eol-curpos);
617 if(sstr[0] ==
'-' || sstr[0] ==
'0' || sstr[0] ==
'L' || sstr[0] ==
' ' || sstr[0] ==
'D' || sstr[0] ==
'$')
continue;
623 size_t begin = sstr.find(
' ',6);
624 if(begin == std::string::npos)
629 begin = sstr.find_first_not_of(
' ', begin);
630 if(begin == std::string::npos)
635 size_t end = sstr.find(
'V', begin);
636 if(end == std::string::npos)
641 float V = mx::ioutils::convertFromString<float>( sstr.substr(begin, end-begin) );
646 else if(sstr[6] ==
'F')
648 size_t begin = sstr.find(
' ',6);
649 if(begin == std::string::npos)
654 begin = sstr.find_first_not_of(
' ', begin);
655 if(begin == std::string::npos)
660 size_t end = sstr.find(
'H', begin);
661 if(end == std::string::npos)
666 float F = mx::ioutils::convertFromString<float>( sstr.substr(begin, end-begin) );
672 else if(sstr[0] ==
'O')
676 size_t begin = sstr.find(
' ',7);
677 if(begin == std::string::npos)
682 begin = sstr.find_first_not_of(
' ', begin);
683 if(begin == std::string::npos)
688 size_t end = sstr.find(
'A', begin);
689 if(end == std::string::npos)
694 float C = mx::ioutils::convertFromString<float>( sstr.substr(begin, end-begin) );
698 else if(sstr[8] ==
'O')
702 size_t begin = sstr.find(
' ',8);
703 if(begin == std::string::npos)
708 begin = sstr.find_first_not_of(
' ', begin);
710 if(begin == std::string::npos)
715 while(begin < sstr.size())
717 size_t end = sstr.find(
' ', begin);
718 if(end == std::string::npos)
723 int onum = atoi(sstr.substr(begin, end-begin).c_str());
725 if(onum > 0 && onum < 9)
729 begin = sstr.find_first_not_of(
' ', end+1);
737 else if( sstr[7] ==
'V' || sstr[7] ==
'F')
759 log<text_log>(
"Frequency is " + std::to_string(
m_frequency) +
" Hz, below " +
764 log<text_log>(
"Frequency is " + std::to_string(
m_frequency) +
" Hz, above " +
769 log<text_log>(
"Frequency is " + std::to_string(
m_frequency) +
" Hz, below " +
774 log<text_log>(
"Frequency is " + std::to_string(
m_frequency) +
" Hz, above " +
779 log<text_log>(
"Frequency is " + std::to_string(
m_frequency) +
" Hz, below " +
784 log<text_log>(
"Frequency is " + std::to_string(
m_frequency) +
" Hz, above " +
790 log<text_log>(
"Voltage is " + std::to_string(
m_voltage) +
" V, below " +
795 log<text_log>(
"Voltage is " + std::to_string(
m_voltage) +
" V, above " +
800 log<text_log>(
"Voltage is " + std::to_string(
m_voltage) +
" V, below " +
805 log<text_log>(
"Voltage is " + std::to_string(
m_voltage) +
" V, above " +
810 log<text_log>(
"Voltage is " + std::to_string(
m_voltage) +
" V, below " +
815 log<text_log>(
"Voltage is " + std::to_string(
m_voltage) +
" V, above " +
821 log<text_log>(
"Current is " + std::to_string(
m_current) +
" A, above " +
826 log<text_log>(
"Current is " + std::to_string(
m_current) +
" A, above " +
831 log<text_log>(
"Current is " + std::to_string(
m_current) +
" A, above " +
The base-class for MagAO-X applications.
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
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.
void updateAlarmsAndWarnings()
float m_freqHighWarn
The high-frequency warning threshold.
float m_freqLowWarn
The low-frequency warning threshold.
trippLitePDU()
Default c'tor.
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.
std::unique_lock< std::mutex > lock(m_indiMutex)
constexpr static logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
constexpr static logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
constexpr static logPrioT LOG_ALERT
This should only be used if some action is required by operators to keep the system safe.
constexpr static logPrioT LOG_EMERGENCY
Normal operations of the entire system should be shut down immediately.
constexpr static logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
An input/output capable device.
unsigned m_writeTimeout
The write timeout [msec].
int loadConfig(mx::app::appConfigurator &config)
Load the device section from an application configurator.
int setupConfig(mx::app::appConfigurator &config)
Setup an application configurator for the device section.
unsigned m_readTimeout
The read timeout [msec].
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...
A simple text log, a string-type log.
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
#define TTY_E_TIMEOUTONREADPOLL
#define TELNET_E_LOGINTIMEOUT