7 #ifndef zaberLowLevel_hpp
8 #define zaberLowLevel_hpp
13 #include "../../libMagAOX/libMagAOX.hpp"
14 #include "../../magaox_git_version.h"
22 #define ZC_CONNECTED (0)
24 #define ZC_NOT_CONNECTED (10)
57 std::vector<zaberStage<zaberLowLevel>>
m_stages;
163 std::vector<std::string> sections;
165 config.unusedSections(sections);
167 if(sections.size() == 0)
169 log<software_error>({__FILE__, __LINE__,
"No stages found"});
173 for(
size_t n=0; n<sections.size(); ++n)
175 if(config.isSetUnused(mx::app::iniFile::makeKey(sections[n],
"serial" )))
185 std::string tmp =
m_stages[idx].serial();
186 config.configUnused( tmp , mx::app::iniFile::makeKey(sections[n],
"serial" ) );
214 elevatedPrivileges elPriv(
this);
228 log<software_error>({__FILE__, __LINE__,
"can not connect to zaber stage(s)"});
248 log<software_error>({__FILE__,__LINE__, rv,
"error from za_drain"});
257 std::string renum =
"/ renumber";
274 log<software_error>({__FILE__,__LINE__, rv,
"error from za_drain"});
281 std::string gss =
"/ get system.serial";
291 std::string serialRes;
319 std::vector<int> addresses;
320 std::vector<std::string> serials;
325 log<software_error>({__FILE__, __LINE__, errno, rv,
"error in parseSystemSerial"});
331 log<text_log>(
"Found " + std::to_string(addresses.size()) +
" stages.");
333 for(
size_t n=0;n<addresses.size(); ++n)
340 log<text_log>(
"stage @" + std::to_string(addresses[n]) +
" with s/n " + serials[n] +
" corresponds to " +
m_stages[
m_stageSerial[serials[n]]].name());
344 log<text_log>(
"Unkown stage @" + std::to_string(addresses[n]) +
" with s/n " + serials[n],
logPrio::LOG_WARNING);
348 for(
size_t n=0; n <
m_stages.size(); ++n)
377 for(
size_t n=0; n<
m_stages.size(); ++n)
383 for(
size_t n=0; n<
m_stages.size(); ++n)
390 for(
size_t n=0; n<
m_stages.size(); ++n)
396 for(
size_t n=0; n<
m_stages.size(); ++n)
403 for(
size_t n=0; n<
m_stages.size(); ++n)
410 for(
size_t n=0; n<
m_stages.size(); ++n)
417 for(
size_t n=0; n<
m_stages.size(); ++n)
424 for(
size_t n=0; n<
m_stages.size(); ++n)
431 for(
size_t n=0; n<
m_stages.size(); ++n)
438 for(
size_t n=0; n<
m_stages.size(); ++n)
457 for(
size_t i=0; i <
m_stages.size();++i)
484 std::stringstream logs;
486 log<text_log>(logs.str());
492 std::stringstream logs;
494 log<text_log>(logs.str());
498 for(
size_t i=0; i <
m_stages.size();++i)
500 if(
m_stages[i].deviceAddress() < 1)
continue;
518 for(
size_t i=0; i <
m_stages.size();++i)
520 if(
m_stages[i].deviceAddress() < 1)
continue;
526 log<text_log>(
"Connected to stage(s) on " +
m_deviceName);
541 for(
size_t i=0; i <
m_stages.size();++i)
558 log<software_error>({__FILE__, __LINE__});
573 for(
size_t i=0; i <
m_stages.size();++i)
575 if(
m_stages[i].deviceAddress() < 1)
continue;
593 if(
m_stages[i].deviceStatus() ==
'B')
604 else if(
m_stages[i].deviceStatus() ==
'I')
608 std::cerr << __FILE__ <<
" " << __LINE__ <<
"\n";
637 log<software_error>({__FILE__, __LINE__});
652 for(
size_t i=0; i <
m_stages.size();++i)
667 for(
size_t i=0; i <
m_stages.size();++i)
674 std::stringstream logs;
676 log<text_log>(logs.str());
683 for(
size_t i=0; i <
m_stages.size();++i)
688 log<software_critical>({__FILE__, __LINE__});
689 log<text_log>(
"Error NOT due to loss of USB connection. I can't fix it myself.",
logPrio::LOG_CRITICAL);
717 for(
size_t i=0; i <
m_stages.size();++i)
741 for(
size_t i=0; i <
m_stages.size();++i)
743 if(
m_stages[i].deviceAddress() < 1)
continue;
754 for(
size_t n=0; n < m_stages.size(); ++n)
756 if(
ipRecv.find(m_stages[n].name()) )
758 long tgt =
ipRecv[m_stages[n].name()].get<
long>();
761 if(m_stages[n].deviceAddress() < 1)
763 return log<
software_error,-1>({__FILE__, __LINE__,
"stage " + m_stages[n].name() +
" with with s/n " + m_stages[n].serial() +
" not found in system."});
766 std::lock_guard<std::mutex> guard(m_indiMutex);
767 updateIfChanged(m_indiP_curr_state, m_stages[n].name(), std::string(
"OPERATING"));
768 return m_stages[n].moveAbs(m_port, tgt);
780 for(
size_t n=0; n < m_stages.size(); ++n)
782 if(
ipRecv.find(m_stages[n].name()) )
784 long tgt =
ipRecv[m_stages[n].name()].get<
long>();
785 tgt += m_stages[n].rawPos();
788 if(m_stages[n].deviceAddress() < 1)
790 return log<
software_error,-1>({__FILE__, __LINE__,
"stage " + m_stages[n].name() +
" with with s/n " + m_stages[n].serial() +
" not found in system."});
792 std::lock_guard<std::mutex> guard(m_indiMutex);
794 updateIfChanged(m_indiP_curr_state, m_stages[n].name(), std::string(
"OPERATING"));
795 return m_stages[n].moveAbs(m_port, tgt);
807 for(
size_t n=0; n < m_stages.size(); ++n)
809 if(
ipRecv.find(m_stages[n].name()) )
811 int tgt =
ipRecv[m_stages[n].name()].get<
int>();
814 if(m_stages[n].deviceAddress() < 1)
816 return log<
software_error,-1>({__FILE__, __LINE__,
"stage " + m_stages[n].name() +
" with with s/n " + m_stages[n].serial() +
" not found in system."});
818 std::lock_guard<std::mutex> guard(m_indiMutex);
819 return m_stages[n].home(m_port);
832 for(
size_t n=0; n < m_stages.size(); ++n)
834 if(
ipRecv.find(m_stages[n].name()) )
836 int tgt =
ipRecv[m_stages[n].name()].get<
int>();
839 if(m_stages[n].deviceAddress() < 1)
841 return log<
software_error,-1>({__FILE__, __LINE__,
"stage " + m_stages[n].name() +
" with with s/n " + m_stages[n].serial() +
" not found in system."});
844 std::lock_guard<std::mutex> guard(m_indiMutex);
845 return m_stages[n].stop(m_port);
857 for(
size_t n=0; n < m_stages.size(); ++n)
859 if(
ipRecv.find(m_stages[n].name()) )
861 int tgt =
ipRecv[m_stages[n].name()].get<
int>();
864 if(m_stages[n].deviceAddress() < 1)
866 return log<
software_error,-1>({__FILE__, __LINE__,
"stage " + m_stages[n].name() +
" with with s/n " + m_stages[n].serial() +
" not found in system."});
869 std::lock_guard<std::mutex> guard(m_indiMutex);
870 return m_stages[n].estop(m_port);
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 powerState()
Returns the current power state.
int powerStateTarget()
Returns the target power state.
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
std::mutex m_indiMutex
Mutex for locking INDI communications.
zaberLowLevel()
Default c'tor.
INDI_NEWCALLBACK_DECL(zaberLowLevel, m_indiP_req_ehalt)
friend class zaberLowLevel_test
pcf::IndiProperty m_indiP_req_home
Command a stage to home.
pcf::IndiProperty m_indiP_warn
Current temperature of the stage.
INDI_NEWCALLBACK_DECL(zaberLowLevel, m_indiP_req_halt)
virtual int appLogic()
Implementation of the FSM for zaberLowLevel.
pcf::IndiProperty m_indiP_max_pos
Maximum raw position of the stage.
pcf::IndiProperty m_indiP_req_halt
Command a stage to safely halt.
virtual int onPowerOff()
Implementation of the on-power-off FSM logic.
pcf::IndiProperty m_indiP_tgt_pos
Target raw position of the stage.
pcf::IndiProperty m_indiP_temp
Current temperature of the stage.
std::unordered_map< std::string, size_t > m_stageSerial
INDI_NEWCALLBACK_DECL(zaberLowLevel, m_indiP_tgt_relpos)
std::unordered_map< int, size_t > m_stageAddress
pcf::IndiProperty m_indiP_curr_state
Current state of the stage.
int loadStages(std::string &serialRes)
virtual int whilePowerOff()
Implementation of the while-powered-off FSM.
virtual void loadConfig()
pcf::IndiProperty m_indiP_curr_pos
Current raw position of the stage.
INDI_NEWCALLBACK_DECL(zaberLowLevel, m_indiP_tgt_pos)
virtual int appStartup()
Startup functions.
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
std::vector< zaberStage< zaberLowLevel > > m_stages
pcf::IndiProperty m_indiP_tgt_relpos
Target relative position of the stage.
~zaberLowLevel() noexcept
D'tor, declared and defined for noexcept.
std::unordered_map< std::string, size_t > m_stageName
INDI_NEWCALLBACK_DECL(zaberLowLevel, m_indiP_req_home)
pcf::IndiProperty m_indiP_req_ehalt
Command a stage to safely immediately halt.
virtual void setupConfig()
A class to manage the details of one stage in a Zaber system.
#define REG_INDI_NEWPROP_NOCB(prop, propName, type)
Register a NEW INDI property with the class, with no callback.
#define REG_INDI_NEWPROP(prop, propName, type)
Register a NEW INDI property with the class, using the standard callback name.
@ 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.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ 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.
@ INITIALIZED
The application has been initialized, set just before calling appStartup().
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
std::string ttyErrorString(int ec)
Get a text explanation of a TTY_E_ error code.
int parseSystemSerial(std::vector< int > &address, std::vector< std::string > &serial, const std::string &response)
Parse the system.serial query.
INDI_VALIDATE_CALLBACK_PROPS(function, ipRecv)
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_DEBUG
Used for debugging.
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_WARNING
A condition has occurred which may become an error, but the process continues.
A USB device as a TTY device.
std::string m_deviceName
The device path name, e.g. /dev/ttyUSB0.
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
int za_connect(z_port *port, const char *port_name)
int za_receive(z_port port, char *destination, int length)
int za_send(z_port port, const char *command, size_t sMaxSz)
int za_drain(z_port port)
int za_disconnect(z_port port)
Provides a set of functions for interacting with Zaber devices in the ASCII protocol.
MagAOX::app::MagAOXApp< true > MagAOXAppT
A class with details of a single zaber stage.
utilties for working with zaber stages