7 #ifndef koolanceCtrl_hpp
8 #define koolanceCtrl_hpp
11 #include "../../libMagAOX/libMagAOX.hpp"
12 #include "../../magaox_git_version.h"
254 std::stringstream logs;
256 log<text_log>(logs.str());
262 std::stringstream logs;
264 log<text_log>(logs.str());
274 elevatedPrivileges ep(
this);
294 std::stringstream logs;
296 log<text_log>(logs.str());
322 log<text_log>(
"no response from device");
330 std::stringstream logs;
331 logs <<
"Connected to koolance system on " <<
m_deviceName;
332 log<text_log>(logs.str());
345 log<software_error>({__FILE__,__LINE__});
351 log<software_error>({__FILE__, __LINE__});
372 std::vector<unsigned char> com;
382 log<software_error>({__FILE__,__LINE__, errno,
"error from write"});
390 std::vector<unsigned char> resp;
393 mx::sys::milliSleep(1000);
399 log<software_error>({__FILE__,__LINE__, errno,
"error from read"});
409 log<text_log>(
"found protocol 1 device");
412 else if(readBytes == 51)
414 log<text_log>(
"found protocol 2 device");
434 createStandardIndiNumber<int>(
m_indiP_pumplvl,
"pump_level", 1, 10, 1,
"%d",
"Pump Level",
"Lab");
437 createStandardIndiNumber<int>(
m_indiP_fanlvl,
"fan_level", 0, 100, 1,
"%d",
"Fan Level",
"Lab");
451 std::vector<unsigned char> com;
461 log<software_error>({__FILE__,__LINE__, errno,
"error from write"});
475 log<software_error>({__FILE__,__LINE__, errno,
"error from read"});
485 m_liqTemp = ((float) (( (
unsigned char)resp[2] << 8) + (
unsigned char)resp[3]-2000)) / 10.0;
486 m_flowRate = ( (float) ((
unsigned char)resp[12] << 8) + (
unsigned char)resp[13]) / 10.0;
487 m_fanRPM = ((
unsigned char)resp[8] << 8) + (
unsigned char)resp[9];
488 m_pumpRPM = ((
unsigned char)resp[10] << 8) + (
unsigned char)resp[11];
512 log<software_error>({__FILE__,__LINE__, std::string(
"wrong response size (") + std::to_string(resp.size()) +
") returned"});
527 std::vector<unsigned char> com;
557 log<software_error>({__FILE__,__LINE__, errno,
"error from write"});
565 log<text_log>(
"set pump level to " + std::to_string(lvl));
576 std::vector<unsigned char> com;
606 log<software_error>({__FILE__,__LINE__, errno,
"error from write"});
614 log<text_log>(
"set fan level to " + std::to_string(lvl));
621 if(
ipRecv.getName() != m_indiP_pumplvl.getName())
623 log<software_error>({__FILE__,__LINE__,
"wrong INDI property received."});
629 if(
ipRecv.find(
"current") )
631 lvl =
ipRecv[
"current"].get<
int>();
634 if(
ipRecv.find(
"target") )
636 lvl =
ipRecv[
"target"].get<
int>();
639 if(lvl < 1 || lvl > 10)
641 log<software_error>({__FILE__,__LINE__,
"Pump level out of range"});
645 std::unique_lock<std::mutex>
lock(m_indiMutex);
647 return setPumpLvl(lvl);
654 if(
ipRecv.getName() != m_indiP_fanlvl.getName())
656 log<software_error>({__FILE__,__LINE__,
"wrong INDI property received."});
663 if(
ipRecv.find(
"current") )
665 lvl =
ipRecv[
"current"].get<
int>();
668 if(
ipRecv.find(
"target") )
670 lvl =
ipRecv[
"target"].get<
int>();
673 if(lvl < 0 || lvl > 100)
675 log<software_error>({__FILE__,__LINE__,
"Fan level out of range"});
679 std::unique_lock<std::mutex>
lock(m_indiMutex);
681 return setFanLvl(lvl);
701 static float last_liqTemp = std::numeric_limits<float>::max();
702 static float last_flowRate = std::numeric_limits<float>::max();
703 static int last_pumpLvl = std::numeric_limits<int>::max();
704 static int last_pumpRPM = std::numeric_limits<int>::max();
705 static int last_fanRPM = std::numeric_limits<int>::max();
706 static int last_fanLvl = std::numeric_limits<int>::max();
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.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
int m_powerState
Current power state, 1=On, 0=Off, -1=Unk.
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.
The MagAO-X Koolance Controller.
float m_liqTemp
The liquid temperature.
size_t m_protocolChars
Will be set to 43 if protocol 1, and set to 51 if protocol 2.
virtual void loadConfig()
INDI_NEWCALLBACK_DECL(koolanceCtrl, m_indiP_pumplvl)
~koolanceCtrl() noexcept
D'tor, declared and defined for noexcept.
virtual int appShutdown()
Shutdown the app.
pcf::IndiProperty m_indiP_fanlvl
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
pcf::IndiProperty m_indiP_pumplvl
int m_fanLvl
The fan power level, 0-100.
friend class koolanceCtrl_test
float m_flowRate
The flow rate.
int recordCooler(bool force=false)
virtual int appStartup()
Startup function.
int m_pumpLvl
The pump power level, 1-10.
virtual int appLogic()
Implementation of the FSM for koolanceCtrl.
int getStatus()
Get status from controller and updated INDI.
int m_pumpRPM
The pump RPM.
int initialConnect()
Initial connection to controller.
int setPumpLvl(int lvl)
Set the pump level.
int recordTelem(const telem_cooler *)
virtual void setupConfig()
int setFanLvl(int lvl)
Set the fan level.
pcf::IndiProperty m_indiP_status
koolanceCtrl()
Default c'tor.
INDI_NEWCALLBACK_DECL(koolanceCtrl, m_indiP_fanlvl)
bool m_indiSetup
Whether or not INDI has been set up after initial protocol determination.
#define REG_INDI_NEWPROP_NOCB(prop, propName, type)
Register a NEW INDI property with the class, with no callback.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
@ NODEVICE
No device exists for the application to control.
@ 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.
@ CONNECTED
The application has connected to the device or service.
@ UNINITIALIZED
The application is unitialized, the default.
@ NOTCONNECTED
The application is not connected to the device or service.
int ttyReadRaw(std::vector< unsigned char > &vecRead, int &readBytes, int fd, int timeoutRead)
Read from a tty console indicated by a file-descriptor, up to a given number of bytes.
std::string ttyErrorString(int ec)
Get a text explanation of a TTY_E_ error code.
int ttyRead(std::string &strRead, int bytes, int fd, int timeoutRead)
Read from a tty console indicated by a file-descriptor, until a given number of bytes are read.
const pcf::IndiProperty & ipRecv
updateIfChanged(m_indiP_angle, "target", m_angle)
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
std::unique_lock< std::mutex > lock(m_indiMutex)
constexpr static logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
A device base class which saves telemetry.
int appShutdown()
Perform telemeter application shutdown.
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int appLogic()
Perform telemeter application logic.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Log entry recording the build-time git state.
A USB device as a TTY device.
std::string m_deviceName
The device path name, e.g. /dev/ttyUSB0.
int m_fileDescrip
The file descriptor.
int connect()
Connect to the device.
int getDeviceName()
Get the device name from udev using the vendor, product, and serial number.
std::string m_idProduct
The product id 4-digit code.
int setupConfig(mx::app::appConfigurator &config)
Setup an application configurator for the USB section.
std::string m_serial
The serial number.
int loadConfig(mx::app::appConfigurator &config)
Load the USB section from an application configurator.
speed_t m_baudRate
The baud rate specification.
std::string m_idVendor
The vendor id 4-digit code.
#define TTY_E_DEVNOTFOUND