Newer
Older
Martin Christoph Hierholzer
committed
/*
* DeviceModule.h
*
* Created on: Jun 27, 2016
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_DEVICE_MODULE_H
#define CHIMERATK_DEVICE_MODULE_H
#include <ChimeraTK/ForwardDeclarations.h>
#include <ChimeraTK/RegisterPath.h>
Martin Christoph Hierholzer
committed
#include "VariableNetworkNode.h"
#include "Module.h"
Martin Christoph Hierholzer
committed
#include "VirtualModule.h"
#include "VariableGroup.h"
#include "ScalarAccessor.h"
#include "ControlSystemModule.h"
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
class Application;
class DeviceModule : public Module {
Martin Christoph Hierholzer
committed
public:
/** Constructor: The device represented by this DeviceModule is identified by either the device alias found
Martin Christoph Hierholzer
committed
* in the DMAP file or directly an URI. The given optional prefix will be prepended to all register names
* (separated by a slash). */
DeviceModule(Application *application, const std::string& deviceAliasOrURI, const std::string& registerNamePrefix="");
Martin Christoph Hierholzer
committed
DeviceModule(const std::string& deviceAliasOrURI, const std::string& registerNamePrefix="");
Martin Christoph Hierholzer
committed
/** Default constructor: create dysfunctional device module */
DeviceModule() {}
/** Destructor */
virtual ~DeviceModule();
Martin Christoph Hierholzer
committed
/** Move operation with the move constructor */
Martin Christoph Hierholzer
committed
DeviceModule(DeviceModule &&other) { operator=(std::move(other)); }
Martin Christoph Hierholzer
committed
/** Move assignment */
DeviceModule& operator=(DeviceModule &&other) {
Module::operator=(std::move(other));
deviceAliasOrURI = std::move(other.deviceAliasOrURI);
registerNamePrefix = std::move(other.registerNamePrefix);
subModules = std::move(other.subModules);
deviceError = std::move(other.deviceError);
Martin Christoph Hierholzer
committed
return *this;
}
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** The subscript operator returns a VariableNetworkNode which can be used in the Application::initialise()
* function to connect the register with another variable. */
Martin Christoph Hierholzer
committed
VariableNetworkNode operator()(const std::string& registerName, UpdateMode mode,
Martin Christoph Hierholzer
committed
const std::type_info &valueType=typeid(AnyType), size_t nElements=0) const;
Martin Christoph Hierholzer
committed
VariableNetworkNode operator()(const std::string& registerName, const std::type_info &valueType,
Martin Christoph Hierholzer
committed
size_t nElements=0, UpdateMode mode=UpdateMode::poll) const {
Martin Christoph Hierholzer
committed
return operator()(registerName, mode, valueType, nElements);
Martin Christoph Hierholzer
committed
}
Martin Christoph Hierholzer
committed
VariableNetworkNode operator()(const std::string& variableName) const override {
Martin Christoph Hierholzer
committed
return operator()(variableName, UpdateMode::poll);
}
Martin Christoph Hierholzer
committed
Module& operator[](const std::string& moduleName) const override;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
const Module& virtualise() const override;
Martin Christoph Hierholzer
committed
void connectTo(const Module &target, VariableNetworkNode trigger={}) const override;
Martin Christoph Hierholzer
committed
ModuleType getModuleType() const override { return ModuleType::Device; }
void reportException(std::string errMsg);
void run() override;
void terminate() override;
VersionNumber getCurrentVersionNumber() const override { return currentVersionNumber; }
void setCurrentVersionNumber(VersionNumber versionNumber) override {
if(versionNumber > currentVersionNumber) currentVersionNumber = versionNumber;
}
VersionNumber currentVersionNumber;
/*This function connects DeviceError Variable Group to cs*/
void defineConnections() override;
Martin Christoph Hierholzer
committed
protected:
Martin Christoph Hierholzer
committed
// populate virtualisedModuleFromCatalog based on the information in the device's catalogue
VirtualModule& virtualiseFromCatalog() const;
mutable VirtualModule virtualisedModuleFromCatalog{"INVALID", "", ModuleType::Invalid};
mutable bool virtualisedModuleFromCatalog_isValid{false};
Martin Christoph Hierholzer
committed
std::string deviceAliasOrURI;
ChimeraTK::RegisterPath registerNamePrefix;
Martin Christoph Hierholzer
committed
// List of sub modules accessed through the operator[]. This is mutable since it is little more than a cache and
// thus does not change the logical state of this module
Martin Christoph Hierholzer
committed
mutable std::map<std::string, DeviceModule> subModules;
/* A VariableGroup for exception status and message*/
public:
struct DeviceError : public VariableGroup {
using VariableGroup::VariableGroup;
ScalarOutput<int> status{this,"status","",""};
ScalarOutput<std::string> message{this,"message","",""};
DeviceError deviceError{this, "deviceError", "Error"};
private:
/** The thread executing reportException() */
boost::thread moduleThread;
cppext::future_queue<std::string> errorQueue{5};
std::mutex errorMutex;
std::condition_variable errorCondVar;
/** This functions tries to open the device and set the deviceError.
* Once done it notifies the waiting thread(s) */
void handleException();
Martin Christoph Hierholzer
committed
};
} /* namespace ChimeraTK */
#endif /* CHIMERATK_DEVICE_MODULE_H */