Newer
Older
Martin Christoph Hierholzer
committed
/*
* VariableNetwork.h
*
* Created on: Jun 14, 2016
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_VARIABLE_NETWORK_H
#define CHIMERATK_VARIABLE_NETWORK_H
#include <list>
#include <string>
Martin Christoph Hierholzer
committed
#include <iostream>
Martin Christoph Hierholzer
committed
#include <typeinfo>
#include <boost/mpl/for_each.hpp>
Martin Christoph Hierholzer
committed
#include <ControlSystemAdapter/ProcessVariable.h>
Martin Christoph Hierholzer
committed
#include "Flags.h"
Martin Christoph Hierholzer
committed
namespace xmlpp {
class Element;
}
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
class AccessorBase;
/** This class describes a network of variables all connected to each other. */
class VariableNetwork {
Martin Christoph Hierholzer
committed
VariableNetwork( const VariableNetwork& other ) = delete; // non construction-copyable
VariableNetwork& operator=( const VariableNetwork& ) = delete; // non copyable
Martin Christoph Hierholzer
committed
public:
Martin Christoph Hierholzer
committed
VariableNetwork() {}
Martin Christoph Hierholzer
committed
/** Define accessor types */
Martin Christoph Hierholzer
committed
enum class NodeType {
Martin Christoph Hierholzer
committed
Device, ControlSystem, Application, TriggerReceiver, invalid
};
/** Define trigger types. The trigger decides when values are fed into the network and distributed to the consumers. */
enum class TriggerType {
feeder, ///< The feeder has an UpdateMode::push and thus decides when new values are fed
pollingConsumer, ///< If there is exacly one consumer with UpdateMode::poll, it will trigger the feeding
external, ///< another variable network can trigger the feeding of this network
none ///< no trigger has yet been selected
Martin Christoph Hierholzer
committed
};
Martin Christoph Hierholzer
committed
/** Structure describing a node of the network */
struct Node {
Martin Christoph Hierholzer
committed
NodeType type{NodeType::invalid};
Martin Christoph Hierholzer
committed
UpdateMode mode{UpdateMode::invalid};
Martin Christoph Hierholzer
committed
/** The network this node belongs to */
VariableNetwork *network{nullptr};
Martin Christoph Hierholzer
committed
/** Pointer to Accessor if type == Application */
AccessorBase *appNode{nullptr};
Martin Christoph Hierholzer
committed
/** Pointer to network which should be triggered by this node */
VariableNetwork *triggerReceiver{nullptr};
Martin Christoph Hierholzer
committed
/** Public name if type == ControlSystem */
std::string publicName;
/** Device information if type == Device */
Martin Christoph Hierholzer
committed
std::string deviceAlias;
std::string registerName;
Martin Christoph Hierholzer
committed
/** Function checking if the node requires a fixed implementation */
Martin Christoph Hierholzer
committed
bool hasImplementation() const;
/** Compare two nodes */
bool operator==(const Node& other) const;
bool operator!=(const Node& other) const;
Martin Christoph Hierholzer
committed
/** Print node information to std::cout */
Martin Christoph Hierholzer
committed
void dump() const;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Create an XML node describing this network node as seen by the control syste. If the type is not
* NodeType::ControlSystem, this function does nothing. Otherwise the correct directory hierarchy will be
* created (if not yet existing) and a variable tag will be created containing the externally visible
* properties of this variable. */
void createXML(xmlpp::Element *rootElement) const;
Martin Christoph Hierholzer
committed
};
Martin Christoph Hierholzer
committed
/** Add an application-side node (i.e. an Accessor) to the network. */
void addAppNode(AccessorBase &a);
Martin Christoph Hierholzer
committed
/** Add control-system-to-device publication. The given accessor will be used to derive the requred value type.
* The name will be the name of the process variable visible in the control system adapter. */
Martin Christoph Hierholzer
committed
void addFeedingPublication(AccessorBase &a, const std::string& name);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add control-system-to-device publication. The given accessor will be used to derive the requred value type.
* The name will be the name of the process variable visible in the control system adapter. */
Martin Christoph Hierholzer
committed
void addFeedingPublication(const std::type_info &typeInfo, const std::string& unit, const std::string& name);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add device-to-control-system publication. */
Martin Christoph Hierholzer
committed
void addConsumingPublication(const std::string& name);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add a device register as a consuming node (i.e. which will be written by this network) */
Martin Christoph Hierholzer
committed
void addConsumingDeviceRegister(const std::string &deviceAlias, const std::string ®isterName);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add a device register as a feeding node (i.e. which will be read from this network) */
void addFeedingDeviceRegister(AccessorBase &a, const std::string &deviceAlias, const std::string ®isterName,
Martin Christoph Hierholzer
committed
UpdateMode mode);
/** Add a device register as a feeding node (i.e. which will be read from this network) */
Martin Christoph Hierholzer
committed
void addFeedingDeviceRegister(const std::type_info &typeInfo, const std::string& unit,
const std::string &deviceAlias, const std::string ®isterName, UpdateMode mode);
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Add a trigger receiver node */
void addTriggerReceiver(VariableNetwork *network);
Martin Christoph Hierholzer
committed
/** Check if the network already has a feeding node connected to it. */
bool hasFeedingNode() const;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Count the number of consuming nodes in the network */
size_t countConsumingNodes() const;
/** Count the number of nodes requiring a fixed implementation */
size_t countFixedImplementations() const;
Martin Christoph Hierholzer
committed
/** Check if either of the given accessors is part of this network. If the second argument is omitted, only
* the first accessor will be checked. */
Martin Christoph Hierholzer
committed
bool hasAppNode(AccessorBase *a, AccessorBase *b=nullptr) const;
Martin Christoph Hierholzer
committed
/** Obtain the type info of the UserType. If the network type has not yet been determined (i.e. if no output
* accessor has been assigned yet), the typeid of void will be returned. */
const std::type_info& getValueType() const {
return *valueType;
}
Martin Christoph Hierholzer
committed
/** Return the feeding node */
const Node& getFeedingNode() const { return feeder; }
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** Return list of consuming nodes */
const std::list<Node>& getConsumingNodes() const { return consumerList; }
Martin Christoph Hierholzer
committed
/** Dump the network structure to std::cout */
void dump() const;
Martin Christoph Hierholzer
committed
/** Compare two networks */
bool operator==(const VariableNetwork &other) const {
if(other.feeder != feeder) return false;
if(other.valueType != valueType) return false;
if(other.consumerList != consumerList) return false;
return true;
}
bool operator!=(const VariableNetwork &other) const {
return !operator==(other);
}
Martin Christoph Hierholzer
committed
/** Return the trigger type. This function will also do some checking if the network confguration is valid under
* the aspect of the trigger type. */
TriggerType getTriggerType();
Martin Christoph Hierholzer
committed
/** Return the enginerring unit */
const std::string& getUnit() { return engineeringUnit; }
Martin Christoph Hierholzer
committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/** Return the network providing the external trigger to this network, if TriggerType::external. If the network
* has another trigger type, an exception will be thrown. */
VariableNetwork& getExternalTrigger();
/** Add an accessor belonging to another network as an external trigger to this network. Whenever the
* VariableNetwork of the given accessor will be fed with a new value, feeding of this network will be
* triggered as well. */
void addTrigger(AccessorBase &trigger);
/** Check if the network is legally configured */
void check();
/** Check the flag if the network connections has been created already */
bool isCreated() const { return flagIsCreated; }
/** Set the flag that the network connections are created */
void markCreated() { flagIsCreated = true; }
/** Assign a ProcessVariable as implementation for the external trigger */
void setExternalTriggerImpl(boost::shared_ptr< mtca4u::ProcessVariable > impl) {
externalTriggerImpl = impl;
}
/** */
boost::shared_ptr< mtca4u::ProcessVariable > getExternalTriggerImpl() const {
return externalTriggerImpl;
}
Martin Christoph Hierholzer
committed
protected:
Martin Christoph Hierholzer
committed
/** Feeding node (i.e. the node providing values to the network) */
Node feeder;
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/** List of consuming nodes (i.e. the nodes receiving values from the network) */
std::list<Node> consumerList;
Martin Christoph Hierholzer
committed
/** The network value type id. Since in C++, std::type_info is non-copyable and typeid() returns a reference to
* an object with static storage duration, we have to (and can safely) store a pointer here. */
const std::type_info* valueType{&typeid(void)};
Martin Christoph Hierholzer
committed
/** Engineering unit */
std::string engineeringUnit;
Martin Christoph Hierholzer
committed
/** Flag if an external trigger has been added to this network */
bool hasExternalTrigger{false};
/** Pointer to the network providing the external trigger */
VariableNetwork *externalTrigger{nullptr};
/** Pointer to ProcessVariable providing the trigger (if external trigger is enabled) */
boost::shared_ptr< mtca4u::ProcessVariable > externalTriggerImpl;
/** Flag if the network connections have been created already */
bool flagIsCreated{false};
Martin Christoph Hierholzer
committed
};
} /* namespace ChimeraTK */
#endif /* CHIMERATK_VARIABLE_NETWORK_H */