DynExp
Highly flexible laboratory automation for dynamically changing experiments.
HardwareAdaptergRPC.h
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
9 #pragma once
10 
11 #include "stdafx.h"
13 
14 namespace DynExpHardware
15 {
16  template <typename gRPCStub>
17  class gRPCHardwareAdapter;
18 
24  {
28  static constexpr auto UNIMPLEMENTED_ErrorMsg = "The connected gRPC server does not implement the called gRPC stub function. Check the server configuration.";
29 
30  public:
36  gRPCException(const grpc::Status Result, const std::source_location Location = std::source_location::current()) noexcept;
37  };
38 
43  template <typename gRPCStub>
44  class gRPCHardwareAdapterParams : public DynExp::HardwareAdapterParamsBase
45  {
46  public:
52  : HardwareAdapterParamsBase(ID, Core), NetworkParams(*this) {}
53 
54  virtual ~gRPCHardwareAdapterParams() = default;
55 
56  virtual const char* GetParamClassTag() const noexcept override { return "gRPCHardwareAdapterParams"; }
57 
59 
60  private:
63  };
64 
68  template <typename gRPCStub>
70  {
71  public:
74 
76  virtual ~gRPCHardwareAdapterConfigurator() = default;
77 
78  private:
79  virtual DynExp::ParamsBasePtrType MakeParams(DynExp::ItemIDType ID, const DynExp::DynExpCore& Core) const override { return DynExp::MakeParams<gRPCHardwareAdapterConfigurator>(ID, Core); }
80  };
81 
88  template <typename gRPCStub>
90  {
91  public:
94  using gRPCStubType = gRPCStub;
95 
96  constexpr static auto Name() noexcept { return "gRPC Hardware Adapter"; }
97  constexpr static auto Category() noexcept { return "Communication"; }
98 
99  gRPCHardwareAdapter(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
100  : HardwareAdapterBase(OwnerThreadID, std::move(Params)) {}
102 
103  virtual std::string GetName() const override { return Name(); }
104  virtual std::string GetCategory() const override { return Category(); }
105 
106  protected:
111 
116  typename gRPCStub::Stub& GetStubUnsafe() const;
117 
124  void CheckError(const grpc::Status Result, const std::source_location Location = std::source_location::current()) const;
125 
130  bool IsOpenedUnsafe() const noexcept { return StubPtr.get(); }
132 
133  private:
136 
137  void EnsureReadyStateChild() override final;
138  bool IsReadyChild() const override final;
139  bool IsConnectedChild() const noexcept override final;
140 
145 
150  void OpenUnsafe();
151 
155  void CloseUnsafe();
157 
162 
165  virtual void OpenUnsafeChild() {}
166 
170  virtual void CloseUnsafeChild() {}
172 
173  std::unique_ptr<typename gRPCStub::Stub> StubPtr;
174  };
175 
176  template <typename gRPCStub>
178  {
179  // Not locking, since the object is being destroyed. This should be inherently thread-safe.
180  CloseUnsafe();
181  }
182 
183  template <typename gRPCStub>
184  typename gRPCStub::Stub& gRPCHardwareAdapter<gRPCStub>::GetStubUnsafe() const
185  {
186  if (!IsOpenedUnsafe())
187  ThrowExceptionUnsafe(std::make_exception_ptr(Util::NotAvailableException("The gRPC stub is not connected yet.", Util::ErrorType::Error)));
188 
189  return *StubPtr;
190  }
191 
192  template <typename gRPCStub>
193  void gRPCHardwareAdapter<gRPCStub>::CheckError(const grpc::Status Result, const std::source_location Location) const
194  {
195  if (Result.ok())
196  return;
197 
198  // AcquireLock() has already been called by an (in)direct caller of this function.
199  ThrowExceptionUnsafe(std::make_exception_ptr(gRPCException(Result, Location)));
200  }
201 
202  template <typename gRPCStub>
204  {
205  // auto lock = AcquireLock(); not necessary here, since DynExp ensures that Object::Reset() can only
206  // be called if respective object is not in use.
207 
208  CloseUnsafe();
209 
211  }
212 
213  template <typename gRPCStub>
215  {
216  auto lock = AcquireLock(HardwareOperationTimeout);
217 
218  OpenUnsafe();
219  }
220 
221  template <typename gRPCStub>
223  {
224  auto lock = AcquireLock(HardwareOperationTimeout);
225 
226  auto Exception = GetExceptionUnsafe();
228 
229  return IsOpenedUnsafe();
230  }
231 
232  template <typename gRPCStub>
234  {
235  try
236  {
237  auto lock = AcquireLock(HardwareOperationTimeout);
238 
239  return IsOpenedUnsafe();
240  }
241  catch (...)
242  {
243  return false;
244  }
245  }
246 
247  template <typename gRPCStub>
249  {
250  if (IsOpenedUnsafe())
251  return;
252 
253  auto DerivedParams = dynamic_Params_cast<gRPCHardwareAdapter>(GetParams());
254 
255  // TODO: Offer SSL credentials.
256  StubPtr = gRPCStub::NewStub(grpc::CreateChannel(DerivedParams->NetworkParams.MakeAddress(), grpc::InsecureChannelCredentials()));
257 
258  OpenUnsafeChild();
259  }
260 
261  template <typename gRPCStub>
263  {
264  CloseUnsafeChild();
265 
266  StubPtr.reset();
267  }
268 }
Implementation of a hardware adapter to communicate text-based commands over TCP sockets.
Defines an exception caused by an operation involving the gRPC library and communication over a TCP s...
static constexpr auto UNIMPLEMENTED_ErrorMsg
Message used for the grpc::StatusCode::UNIMPLEMENTED status code.
gRPCException(const grpc::Status Result, const std::source_location Location=std::source_location::current()) noexcept
Constructs a gRPCException instance.
Configurator class for gRPCHardwareAdapter.
virtual DynExp::ParamsBasePtrType MakeParams(DynExp::ItemIDType ID, const DynExp::DynExpCore &Core) const override
Override to make derived classes call DynExp::MakeParams with the correct configurator type derived f...
Parameter class for gRPCHardwareAdapter.
gRPCHardwareAdapterParams(DynExp::ItemIDType ID, const DynExp::DynExpCore &Core)
Constructs the parameters for a gRPCHardwareAdapter instance.
virtual const char * GetParamClassTag() const noexcept override
This function is intended to be overridden once in each derived class returning the name of the respe...
DynExp::NetworkParamsExtension NetworkParams
Bundles several parameters to describe a network connection. Use in parameter classes.
void ConfigureParamsImpl(dispatch_tag< HardwareAdapterParamsBase >) override final
virtual void ConfigureParamsImpl(dispatch_tag< gRPCHardwareAdapterParams >)
This template class provides basic functionality to design hardware adapters for instruments which co...
void EnsureReadyStateChild() override final
Ensures that this Object instance is ready by possibly starting its worker thread or by opening conne...
void OpenUnsafe()
Establishes the connection to a gRPC server creating a new gRPC stub, which is stored in StubPtr.
void CheckError(const grpc::Status Result, const std::source_location Location=std::source_location::current()) const
Checks whether Result denotes an error state. If this is the case, a respective gRPCException is cons...
virtual void ResetImpl(dispatch_tag< gRPCHardwareAdapter >)
void ResetImpl(dispatch_tag< HardwareAdapterBase >) override final
gRPCStub gRPCStubType
gRPCStub gRPC stub class which is used to transfer data.
bool IsConnectedChild() const noexcept override final
Determines the connection status of the hardware interface.
gRPCStub::Stub & GetStubUnsafe() const
Getter for the gRPC stub.
constexpr static auto Name() noexcept
Every derived class has to redefine this function.
void CloseUnsafe()
Closes the connection to a gRPC server. StubPtr becomes nullptr.
bool IsOpenedUnsafe() const noexcept
Checks whether the gRPCHardwareAdapter is connected to a server.
std::unique_ptr< typename gRPCStub::Stub > StubPtr
Pointer to the gRPC stub.
virtual std::string GetName() const override
Returns the name of this Object type.
bool IsReadyChild() const override final
Returns wheter this Object instance is ready (e.g. it is running or connected to a hardware device) a...
virtual void CloseUnsafeChild()
Override to add additional termination steps. Gets executed before the gRPC connection is disconnecte...
constexpr static auto Category() noexcept
Every derived class has to redefine this function.
virtual std::string GetCategory() const override
Returns the category of this Object type.
gRPCHardwareAdapter(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
DynExp's core class acts as the interface between the user interface and DynExp's internal data like ...
Definition: DynExpCore.h:127
Defines the base class for a hardware adapter object. Hardware adapters describe interfaces/connectio...
Configurator class for HardwareAdapterBase.
Parameter class for HardwareAdapterBase.
Bundles several parameters to describe a network connection. Use in parameter classes.
Refer to ParamsBase::dispatch_tag.
Definition: Object.h:2018
Tag for function dispatching mechanism within this class used when derived classes are not intended t...
Definition: Object.h:349
DynExp exceptions are derived from this class. It contains basic information about the cause of the e...
Definition: Exception.h:51
Exception(std::string Description, const ErrorType Type=ErrorType::Error, const int ErrorCode=-1, const std::source_location Location=std::source_location::current()) noexcept
Constructs an exception. Constructor is noexcept, although std::runtime_error() might throw std::bad_...
Definition: Exception.cpp:8
Thrown when some operation or feature is temporarily or permanently not available.
Definition: Exception.h:286
DynExp's hardware namespace contains the implementation of DynExp hardware adapters which extend DynE...
DynExp's main namespace contains the implementation of DynExp including classes to manage resources (...
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition: Object.h:1807
size_t ItemIDType
ID type of objects/items managed by DynExp.
void ForwardException(std::exception_ptr e)
Wraps the exception passed to the function in a ForwardedException and throws the ForwardedException....
Definition: Exception.cpp:30
Accumulates include statements to provide a precompiled header.