API
acronameUsbHub.hpp
Go to the documentation of this file.
1 /** \file acronameUsbHub.hpp
2  * \brief The MagAO-X Acroname USB Hub controller.
3  *
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  * \ingroup acronameUsbHub_files
7  */
8 
9 #ifndef acronameUsbHub_hpp
10 #define acronameUsbHub_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 #include "BrainStem2/BrainStem-all.h"
17 
18 namespace MagAOX
19 {
20 namespace app
21 {
22 
23 
24 /** \defgroup acronameUsbHub Acroname USB Hub Controller
25  * \brief Control of an Acroname USB 3.0 8-port hub
26  *
27  * <a href="../handbook/operating/software/apps/acronameUsbHub.html">Application Documentation</a>
28  *
29  * \ingroup apps
30  *
31  */
32 
33 /** \defgroup acronameUsbHub_files Acroname USB Hub controller Files
34  * \ingroup acronameUsbHub
35  */
36 
37 /** MagAO-X application to control an Acroname USB 3.0 8-port hub
38  *
39  * \todo add current, temperature, etc. monitoring
40  * \todo telemetry
41  *
42  * \ingroup acronameUsbHub
43  *
44  */
45 class acronameUsbHub : public MagAOXApp<>, public dev::outletController<acronameUsbHub>
46 {
47 
48 protected:
49 
50  /** \name configurable parameters
51  *@{
52  */
53 
54  uint32_t m_serialNumber {0}; ///< The Acroname device serial number.
55 
56  ///@}
57 
58 
59  aUSBHub3p m_hub; ///< BrainStem library handle
60 
61  bool m_connected {false}; ///< Whether or not the hub is currently connected
62 
63 public:
64 
65  ///Default c'tor
67 
68  ///Destructor
69  ~acronameUsbHub() noexcept;
70 
71  /// Setup the configuration system (called by MagAOXApp::setup())
72  virtual void setupConfig();
73 
74  /// load the configuration system results (called by MagAOXApp::setup())
75  virtual void loadConfig();
76 
77  /// Startup functions
78  /** Sets up the INDI vars.
79  *
80  */
81  virtual int appStartup();
82 
83  /// Implementation of the FSM for the Siglent SDG
84  virtual int appLogic();
85 
86  /// Implementation of the on-power-off FSM logic
87  virtual int onPowerOff();
88 
89  /// Implementation of the while-powered-off FSM
90  virtual int whilePowerOff();
91 
92  /// Do any needed shutdown tasks. Currently nothing in this app.
93  virtual int appShutdown();
94 
95  /// Get the state of the outlet from the device.
96  /** dev::outletController interface.
97  *
98  * \returns 0 on success.
99  * \returns -1 on error.
100  */
101  int updateOutletState( int outletNum /**< [in] the outlet number to update */);
102 
103  /// Turn an outlet on.
104  /** dev::outletController interface.
105  *
106  * \returns 0 on success.
107  * \returns -1 on error.
108  */
109  int turnOutletOn( int outletNum /**< [in] the outlet number to turn on */);
110 
111  /// Turn an outlet off.
112  /** dev::outletController interface.
113  *
114  * \returns 0 on success.
115  * \returns -1 on error.
116  */
117  int turnOutletOff( int outletNum /**< [in] the outlet number to turn off */);
118 
119 
120 };
121 
122 inline
123 acronameUsbHub::acronameUsbHub() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
124 {
125  m_powerMgtEnabled = false;
126 
128 
129  return;
130 }
131 
132 inline
134 {
135  // Disconnect
136 
137  m_hub.disconnect();
138 
139  return;
140 }
141 
142 inline
144 {
145  config.add("device.serialNumber", "", "device.serialNumber", argType::Required, "device", "serialNumber", false, "uint32", "The identifying serial number of the hub.");
146 
148 }
149 
150 
151 ///\todo mxlib loadConfig needs to return int to propagate errors!
152 
153 inline
155 {
156  config(m_serialNumber, "device.serialNumber");
158 }
159 
160 
161 
162 inline
164 {
165 
167  {
168  return log<text_log,-1>("Error setting up INDI for outlet control.", logPrio::LOG_CRITICAL);
169  }
170 
172 
173  return 0;
174 
175 }
176 
177 inline
179 {
180  if( state() == stateCodes::POWERON)
181  {
183  }
184 
186  {
187 
188  if(m_connected)
189  {
190  m_hub.disconnect();
191  m_connected = false;
192  }
193 
194  aErr err = aErrNone;
195 
196  elevatedPrivileges ep(this);
197 
198  //std::cerr << m_serialNumber << "\n";
199  //err = m_hub.discoverAndConnect(USB, m_serialNumber);
200  err = m_hub.connect(USB, m_serialNumber);
201  if (err != aErrNone)
202  {
203  if(!stateLogged())
204  {
205  log<text_log>("Failed to connect to usb hub", logPrio::LOG_ERROR);
206  }
207 
208  m_connected = false;
209  return 0;
210  }
211  else
212  {
214 
215  SystemClass sys;
216  sys.init(&m_hub,0);
217 
218  uint8_t model;
219  sys.getModel(&model);
220  std::string modelName = aDefs_GetModelName(model);
221 
222  uint32_t version;
223  sys.getVersion(&version);
224  char versionStr[256];
225  aVersion_ParseString(version, versionStr, sizeof(versionStr));
226 
227  uint32_t serial;
228  sys.getSerialNumber(&serial);
229 
230  log<text_log>("Connected to " + modelName + " #" + std::to_string(serial) + " w/fimrware version " + versionStr, logPrio::LOG_INFO);
231 
232  m_connected = true;
234  }
235  }
236 
237  if( state() == stateCodes::READY )
238  {
239  if(! m_hub.isConnected() )
240  {
241  m_hub.disconnect();
242  m_connected = false;
244  return 0;
245  }
246 
247 
249 
250  std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before doing INDI
252  }
253 
254  return 0;
255 
256 }
257 
258 inline
260 {
261  if(m_connected)
262  {
263  m_hub.disconnect();
264  m_connected = false;
265  }
266 
267  for(size_t n=0;n<m_outletStates.size();++n)
268  {
270  }
271 
272  std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before doing INDI
273  dev::outletController<acronameUsbHub>::updateINDI(); //Update the outlets and channel states
274 
275  //Update INDI targets to off.
276  for(auto it = m_channels.begin(); it != m_channels.end(); ++it)
277  {
278  updateIfChanged( it->second.m_indiP_prop, "target", "Off");
279  }
280 
281 
282 
283  return 0;
284 }
285 
286 inline
288 {
289  return 0;
290 }
291 
292 inline
294 {
295  return 0;
296 }
297 
298 inline
300 {
301  uint32_t state = 0;
302 
303  aErr err = m_hub.usb.getPortState(outletNum, &state);
304 
305  if(err != aErrNone)
306  {
307  if(err == aErrTimeout)
308  {
309  return log<software_error,-1>({__FILE__, __LINE__, "timeout enabling port"});
310  }
311  if(err == aErrConnection)
312  {
313  return log<software_error,-1>({__FILE__, __LINE__, "loss of connection detected when enabling port"});
314  }
315  }
316 
317  if(state & 1)
318  {
319  m_outletStates[outletNum] = OUTLET_STATE_ON;
320  }
321  else
322  {
323  m_outletStates[outletNum] = OUTLET_STATE_OFF;
324  }
325 
326  return 0;
327 }
328 
329 inline
330 int acronameUsbHub::turnOutletOn( int outletNum )
331 {
332  aErr err = m_hub.usb.setPortEnable(outletNum);
333 
334  if(err != aErrNone)
335  {
336  if(err == aErrTimeout)
337  {
338  return log<software_error,-1>({__FILE__, __LINE__, "timeout enabling port"});
339  }
340  if(err == aErrConnection)
341  {
342  return log<software_error,-1>({__FILE__, __LINE__, "loss of connection detected when enabling port"});
343  }
344  }
345 
346  return 0;
347 }
348 
349 inline
350 int acronameUsbHub::turnOutletOff( int outletNum )
351 {
352  aErr err = m_hub.usb.setPortDisable(outletNum);
353 
354  if(err != aErrNone)
355  {
356  if(err == aErrTimeout)
357  {
358  return log<software_error,-1>({__FILE__, __LINE__, "timeout disabling port"});
359  }
360  if(err == aErrConnection)
361  {
362  return log<software_error,-1>({__FILE__, __LINE__, "loss of connection detected when disabling port"});
363  }
364  }
365  return 0;
366 }
367 
368 
369 
370 
371 }//namespace app
372 } //namespace MagAOX
373 #endif
Internal class to manage setuid privilege escalation with RAII.
Definition: MagAOXApp.hpp:325
The base-class for MagAO-X applications.
Definition: MagAOXApp.hpp:75
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.
Definition: MagAOXApp.hpp:2877
stateCodes::stateCodeT state()
Get the current state code.
Definition: MagAOXApp.hpp:2082
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
Definition: MagAOXApp.hpp:2140
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
Definition: MagAOXApp.hpp:1590
std::mutex m_indiMutex
Mutex for locking INDI communications.
Definition: MagAOXApp.hpp:540
bool m_powerMgtEnabled
Flag controls whether power mgt is used. Set this in the constructor of a derived app....
Definition: MagAOXApp.hpp:981
virtual int onPowerOff()
Implementation of the on-power-off FSM logic.
int updateOutletState(int outletNum)
Get the state of the outlet from the device.
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
uint32_t m_serialNumber
The Acroname device serial number.
virtual int appLogic()
Implementation of the FSM for the Siglent SDG.
int turnOutletOn(int outletNum)
Turn an outlet on.
virtual int appStartup()
Startup functions.
bool m_connected
Whether or not the hub is currently connected.
int turnOutletOff(int outletNum)
Turn an outlet off.
virtual int whilePowerOff()
Implementation of the while-powered-off FSM.
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
~acronameUsbHub() noexcept
Destructor.
aUSBHub3p m_hub
BrainStem library handle.
@ READY
The device is ready for operation, but is not operating.
Definition: stateCodes.hpp:51
@ CONNECTED
The application has connected to the device or service.
Definition: stateCodes.hpp:45
@ NOTCONNECTED
The application is not connected to the device or service.
Definition: stateCodes.hpp:44
@ POWERON
The device power is on.
Definition: stateCodes.hpp:43
Definition: dm.hpp:24
constexpr static logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
Definition: logPriority.hpp:37
constexpr static logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
Definition: logPriority.hpp:40
constexpr static logPrioT LOG_INFO
Informational. The info log level is the lowest level recorded during normal operations.
Definition: logPriority.hpp:49
#define OUTLET_STATE_OFF
#define OUTLET_STATE_ON
A generic outlet controller.
int updateINDI()
Update the INDI properties for this device controller.
std::unordered_map< std::string, channelSpec > m_channels
The map of channel specifications, which can be accessed by their names.
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.
virtual int updateOutletStates()
Get the states of all outlets from the device.
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