RTC Toolkit  0.1.0-alpha
rtcComponent.hpp
Go to the documentation of this file.
1 
9 #ifndef RTCTK_COMPONENTFRAMEWORK_RTCCOMPONENT_HPP
10 #define RTCTK_COMPONENTFRAMEWORK_RTCCOMPONENT_HPP
11 
22 
23 #include <mal/Cii.hpp>
24 #include <string>
25 #include <memory>
26 
27 #include <type_traits>
28 
29 namespace rtctk::componentFramework {
30 
32 
38 template <class BusinessLogic>
39 class RtcComponent {
40 
41 public:
42  template<typename BusinessLogicFactory>
43  RtcComponent(Args const& args, BusinessLogicFactory factory)
44  {
45  m_component_name = args.GetComponentName();
46  LOG4CPLUS_INFO(GetLogger(), "RtcComponent '" << m_component_name << "' started.");
47  LOG4CPLUS_DEBUG(GetLogger(), "BusinessLogic is '" << detail::GetTypeName(typeid(BusinessLogic)) << "'");
48 
49  auto svc_disc_endpoint = args.GetServiceDiscEndpoint();
50  m_services.Add<ServiceDiscovery>(std::make_unique<ServiceDiscovery>(svc_disc_endpoint, m_component_name));
51 
52  ServiceDiscovery& svc_disc = m_services.Get<ServiceDiscovery>();
53 
54  auto rtr_endpoint = svc_disc.Get(ServiceDiscovery::RUNTIME_REPO_ENDPOINT);
55  m_services.Add<RuntimeRepoApiIf>(std::make_unique<FakeRuntimeRepoAdapter>(rtr_endpoint));
56 
57  auto oldb_endpoint = svc_disc.Get(ServiceDiscovery::OLDB_ENDPOINT);
58  m_services.Add<OldbApiIf>(std::make_unique<FakeOldbAdapter>(oldb_endpoint));
59 
60  auto req_rep_endpoint = svc_disc.Get(ServiceDiscovery::REQ_REP_ENDPOINT);
61  m_replier = std::make_unique<CommandReplier>(req_rep_endpoint);
62 
63  auto pub_sub_endpoint = svc_disc.Get(ServiceDiscovery::PUB_SUB_ENDPOINT);
64  m_publisher = std::make_unique<StatePublisher>(pub_sub_endpoint, m_component_name);
65 
66  // TODO: currently only one sm is supported, later solve this with traits and constexpr if
67  static_assert(std::is_base_of_v<RunnableStateMachineLogicIf, BusinessLogic>,
68  "BusinessLogic must implement RunnableStateMachineLogicIf");
69 
70  static_assert(std::is_invocable_v<BusinessLogicFactory, std::string const&, ServiceContainer&>,
71  "Factory must be invocable with 'std::string const&' and 'ServiceContainer&'");
72 
73  static_assert(std::is_same_v<std::invoke_result_t<BusinessLogicFactory, std::string const&, ServiceContainer&>, std::unique_ptr<BusinessLogic>>,
74  "Factory must return type 'std::unique_ptr<BusinessLogic>'");
75 
76  m_business_logic = std::invoke(factory, m_component_name, m_services);
77  m_state_machine = std::make_unique<RunnableStateMachine>(*m_business_logic, [this](std::string const& state){OnStateChanged(state);});
78  m_command_handler = std::make_unique<CommandHandler>(*m_replier, *m_state_machine);
79  }
80 
81  RtcComponent(int argc, char *argv[])
82  : RtcComponent(argc, argv, std::make_unique<BusinessLogic, std::string const&, ServiceContainer&>)
83  {
84  static_assert(std::is_constructible_v<BusinessLogic, std::string const&, ServiceContainer&>,
85  "BusinessLogic must be constructible with 'std::string const&' and 'ServiceContainer&'");
86  }
87 
88  RtcComponent(const RtcComponent& other) = delete;
89  RtcComponent& operator= (const RtcComponent& other) = delete;
90  RtcComponent(RtcComponent&& other) = delete;
91  RtcComponent& operator= (const RtcComponent&& other) = delete;
92 
94  {
95  LOG4CPLUS_INFO(GetLogger(), "RtcComponent '" << m_component_name << "' terminated.");
96  }
97 
98  void Run()
99  {
100  m_command_handler->Start();
101  m_state_machine->Work();
102  }
103 
104 private:
105 
106  void OnStateChanged(const std::string& state) {
107  m_publisher->PublishState(state);
108 
109  OldbApiIf& oldb = m_services.Get<OldbApiIf>();
110  DataPointPath dp_name = DataPointPath("/" + m_component_name + "/state");
111  if(not oldb.DataPointExists(dp_name)) {
112  oldb.CreateDataPoint(dp_name, "RtcString");
113  }
114  oldb.SetDataPoint(dp_name, state);
115  }
116 
117  std::string m_component_name;
118  ServiceContainer m_services;
119  std::unique_ptr<CommandReplier> m_replier;
120  std::unique_ptr<StatePublisher> m_publisher;
121  std::unique_ptr<BusinessLogic> m_business_logic;
122  std::unique_ptr<RunnableStateMachine> m_state_machine;
123  std::unique_ptr<CommandHandler> m_command_handler;
124 };
125 
139 template <class BusinessLogic, class BusinessLogicFactory>
140 void RunAsRtcComponent(Args const& args, BusinessLogicFactory factory)
141 {
142  RtcComponent<BusinessLogic> component{args, factory};
143 
144  component.Run();
145 }
146 
156 template <class BusinessLogic>
157 void RunAsRtcComponent(Args const& args)
158 {
159  static_assert(std::is_constructible_v<BusinessLogic, std::string const&, ServiceContainer&>,
160  "BusinessLogic must be constructible with 'std::string const&' and 'ServiceContainer&'");
161  RunAsRtcComponent<BusinessLogic>(args, std::make_unique<BusinessLogic, std::string const&, ServiceContainer&>);
162 }
163 
164 } // closing namespace
165 
174 
175 
179 #ifndef RTCTK_NOMAIN
180 int main(int argc, char *argv[])
181 {
182  using namespace rtctk::componentFramework;
183 
184  LogInitializer initializer;
185 
186  try {
187 
188  Args args{argc, argv};
189 
190  auto component_name = args.GetComponentName();
191  auto log_props_file = args.GetLogPropsFile();
192 
193  if(log_props_file.has_value()) {
194  auto props_file = log_props_file.value().path().to_string();
195  LogConfigure(props_file);
196  SetDefaultLogger(component_name);
197  LOG4CPLUS_INFO(GetLogger(), "Custom log properties file loaded: '" << props_file);
198  }else {
199  LogConfigure();
200  MakeLogger(component_name, log4cplus::INFO_LOG_LEVEL);
201  SetDefaultLogger(component_name);
202  }
203 
204  RtcComponentMain(args);
205 
206  return EXIT_SUCCESS;
207 
208  }catch(detail::HelpOnly& e) {
209  std::cout << e.what() << std::endl;
210  return EXIT_SUCCESS;
211  }catch(detail::ArgNotSet& e) {
212  std::cout << e.what() << std::endl;
213  }catch(std::exception& e) {
214  LOG4CPLUS_FATAL(GetLogger(), e.what());
215  }catch(...) {
216  LOG4CPLUS_FATAL(GetLogger(), "Unknown exception occured!");
217  }
218  return EXIT_FAILURE;
219 }
220 #endif
221 
222 #endif
serviceContainer.hpp
A container that can hold any type of service.
rtctk::componentFramework::detail::GetTypeName
std::string GetTypeName(const std::type_info &tid)
Definition: rtcComponent.hpp:105
commandReplier.hpp
Receive commands via MAL.
rtctk::componentFramework::RepositoryIf::SetDataPoint
void SetDataPoint(const DataPointPath &path, const T value)
Sets a datapoint in the repository.
Definition: repositoryIf.hpp:407
RtcComponentMain
void RtcComponentMain(rtctk::componentFramework::Args const &args)
Definition: main.cpp:18
rtctk::componentFramework::RtcComponent
Definition: rtcComponent.hpp:39
rtctk::componentFramework::detail::HelpOnly
Definition: rtcComponent.hpp:20
rtctk::componentFramework::MakeLogger
void MakeLogger(const std::string &name, log4cplus::LogLevel ll, bool log_to_file=true, bool additive=false)
rtctk::componentFramework::ServiceContainer::Get
Service & Get(const std::string &name="")
Definition: serviceContainer.hpp:82
rtctk::componentFramework::detail::ArgNotSet
Definition: rtcComponent.hpp:27
rtctk::componentFramework::LogConfigure
void LogConfigure(const std::string &cfg_file_name="")
rtctk::componentFramework::ServiceContainer::Add
void Add(Service &&service, const std::string &name="")
Definition: serviceContainer.hpp:45
statePublisher.hpp
Publishes the stdif state topic via MAL.
rtctk::componentFramework::Args
detail::Args Args
Definition: rtcComponent.hpp:31
rtctk::componentFramework
Definition: rtcComponent.hpp:17
serviceDiscovery.hpp
Class that implements a very basic service discover mechanism.
rtctk::componentFramework::ServiceDiscovery::RUNTIME_REPO_ENDPOINT
static const DataPointPath RUNTIME_REPO_ENDPOINT
Definition: serviceDiscovery.hpp:32
rtctk::componentFramework::RepositoryIf::DataPointExists
virtual bool DataPointExists(const DataPointPath &path) const =0
Checks for the existence of a datapoint in the repository.
rtctk::componentFramework::ServiceDiscovery
Definition: serviceDiscovery.hpp:25
rtctk::componentFramework::detail::Args
Definition: rtcComponent.hpp:34
rtcComponent.hpp
Provides details for core functionality of an RTC Component.
rtctk::componentFramework::RtcComponent::RtcComponent
RtcComponent(RtcComponent &&other)=delete
rtctk::componentFramework::ServiceDiscovery::Get
::elt::mal::Uri Get(const std::string &service_name)
rtctk::componentFramework::RepositoryIf::CreateDataPoint
virtual void CreateDataPoint(const DataPointPath &path, const std::string &type)=0
Creates a new datapoint in the repository with a specified type.
main
int main(int argc, char *argv[])
Definition: rtcComponent.hpp:180
fakeRuntimeRepoAdapter.hpp
Header file needed to instantiate FakeRuntimeRepoAdapter in test components.
commandHandler.hpp
Receive commands via MAL and inject events to state machine.
rtctk::componentFramework::LogInitializer
Definition: logger.hpp:20
rtctk::componentFramework::GetLogger
log4cplus::Logger & GetLogger(const std::string &name="")
rtctk::componentFramework::RtcComponent::~RtcComponent
~RtcComponent()
Definition: rtcComponent.hpp:93
rtctk::componentFramework::ServiceDiscovery::REQ_REP_ENDPOINT
static const DataPointPath REQ_REP_ENDPOINT
Definition: serviceDiscovery.hpp:30
rtctk::componentFramework::OldbApiIf
Definition: oldbApiIf.hpp:18
rtctk::componentFramework::ServiceContainer
Definition: serviceContainer.hpp:31
rtctk::componentFramework::RtcComponent::RtcComponent
RtcComponent(int argc, char *argv[])
Definition: rtcComponent.hpp:81
rtctk::componentFramework::RtcComponent::RtcComponent
RtcComponent(Args const &args, BusinessLogicFactory factory)
Definition: rtcComponent.hpp:43
rtctk::componentFramework::RuntimeRepoApiIf
Definition: runtimeRepoApiIf.hpp:59
rtctk::componentFramework::detail::Args::GetComponentName
std::string GetComponentName() const
Definition: rtcComponent.hpp:43
rtctk::componentFramework::RtcComponent::Run
void Run()
Definition: rtcComponent.hpp:98
rtctk::componentFramework::detail::Args::GetServiceDiscEndpoint
elt::mal::Uri GetServiceDiscEndpoint() const
Definition: rtcComponent.hpp:47
fakeOldbAdapter.hpp
Header file needed to instantiate FakeOldbAdapter in test components.
std
Definition: mudpiProcessingError.hpp:109
rtctk::componentFramework::RtcComponent::RtcComponent
RtcComponent(const RtcComponent &other)=delete
logger.hpp
Logging Support Library based on log4cplus.
rtctk::componentFramework::SetDefaultLogger
void SetDefaultLogger(const std::string &name)
Definition: logger.cpp:32
rtctk::componentFramework::DataPointPath
Definition: dataPointPath.hpp:30
rtctk::componentFramework::ServiceDiscovery::PUB_SUB_ENDPOINT
static const DataPointPath PUB_SUB_ENDPOINT
Definition: serviceDiscovery.hpp:31
rtctk::componentFramework::RunAsRtcComponent
void RunAsRtcComponent(Args const &args, BusinessLogicFactory factory)
Definition: rtcComponent.hpp:140
rtctk::componentFramework::ServiceDiscovery::OLDB_ENDPOINT
static const DataPointPath OLDB_ENDPOINT
Definition: serviceDiscovery.hpp:34
rtctk::componentFramework::RtcComponent::operator=
RtcComponent & operator=(const RtcComponent &other)=delete
runnableStateMachine.hpp
The Runnable Statemachine.