SkillManagerComponentPlugin.cpp
Go to the documentation of this file.
2 
3 #include <experimental/memory>
4 #include <list>
5 #include <memory>
6 #include <mutex>
7 #include <optional>
8 #include <shared_mutex>
9 #include <stdexcept>
10 #include <string>
11 #include <thread>
12 #include <tuple>
13 #include <utility>
14 #include <vector>
15 
16 #include <boost/locale.hpp>
17 #include <boost/uuid/name_generator.hpp>
18 #include <boost/uuid/nil_generator.hpp>
19 #include <boost/uuid/string_generator.hpp>
20 #include <boost/uuid/uuid.hpp>
21 #include <boost/uuid/uuid_generators.hpp>
22 #include <boost/uuid/uuid_io.hpp>
23 
24 #include <IceUtil/UUID.h>
25 
26 #include <SimoxUtility/algorithm/string/string_tools.h>
27 #include <SimoxUtility/json/json.hpp>
28 
34 
54 #include <RobotAPI/interface/aron/Aron.h>
55 #include <RobotAPI/interface/skills/SkillManagerInterface.h>
60 
61 namespace armarx::plugins
62 {
63  void
65  {
66  // Create mock root profile
68  root.id = "root";
69  root.name = "root";
70  root.description = "This is the root profile. It is the parent of all other profiles.";
71  root.parentPtr = nullptr;
72 
73  std::unique_lock profilesLock(fluxioDC.profilesMutex);
74  fluxioDC.profiles[root.id] = root;
75  profilesLock.unlock();
76 
77  // event parameter type
78  const auto& baseTypesPtr = std::make_shared<aron::type::Object>();
79  const std::string& keyName = "BaseTypesNamespace";
80  baseTypesPtr->setObjectName(keyName);
81  const auto& eventTypePtr = std::make_shared<aron::type::Object>();
82  eventTypePtr->setObjectName("Event");
83  baseTypesPtr->addMemberType("Event", eventTypePtr);
84 
85  std::unique_lock typesLock(fluxioDC.typesMutex);
86  fluxioDC.types[keyName] = baseTypesPtr;
87  typesLock.unlock();
88  }
89 
90  template <typename S, typename T>
91  std::vector<std::experimental::observer_ptr<const T>>
92  SkillManagerComponentPlugin::convertMapValuesToObserverVector(std::map<S, T>& map)
93  {
94  std::vector<std::experimental::observer_ptr<const T>> ret;
95  for (const auto& [k, v] : map)
96  {
98  }
99  return ret;
100  }
101 
102  void
104  {
105  auto& p = parent<SkillManagerComponentPluginUser>();
106  p.getProxy(myPrx, -1);
107  }
108 
109  void
111  {
112  }
113 
116  {
117  // NON LOCKING! WE ASSERT THAT THE CALLER HOLDS LOCK
118  for (const auto& [providerName, providerPrx] : skillProviderMap)
119  {
120  auto allSkills = providerPrx->getSkillDescriptions();
121  for (const auto& [currentSkillID, skillDesc] : allSkills)
122  {
123  if (currentSkillID.skillName == skillId.skillName)
124  {
125  return {providerName};
126  }
127  }
128  }
129  return {"INVALID PROVIDER NAME"};
130  }
131 
132  void
134  {
135  std::scoped_lock l(skillProviderMapMutex);
136  if (skillProviderMap.find(providerInfo.providerId) == skillProviderMap.end())
137  {
138  ARMARX_INFO << "Adding a provider with name '" << providerInfo.providerId.providerName
139  << "'.";
140  skillProviderMap.insert({providerInfo.providerId, providerInfo.providerInterface});
141  }
142  else
143  {
144  ARMARX_INFO << "Trying to add a provider with name '"
145  << providerInfo.providerId.providerName
146  << "' but the provider already exists. "
147  << "Overwriting the old provider info.";
148  skillProviderMap[providerInfo.providerId] = providerInfo.providerInterface;
149  }
150 
151  for (const auto& [skillID, skillDesc] : providerInfo.providedSkills)
152  {
153  descriptionIdToFluxioSkill(skillID, skillDesc);
154  ARMARX_INFO << "Adding skill '" << skillID.skillName << "' as FluxioSkill.";
155  }
156  }
157 
158  void
160  {
161  std::scoped_lock l(skillProviderMapMutex);
162  if (auto it = skillProviderMap.find(providerId); it != skillProviderMap.end())
163  {
164  ARMARX_INFO << "Removing a provider with name '" << providerId.providerName << "'.";
165  skillProviderMap.erase(it);
166  }
167  else
168  {
169  ARMARX_INFO << "Trying to remove a provider with name '" << providerId.providerName
170  << "' but it couldn't be found.";
171  }
172  }
173 
176  {
177  ARMARX_CHECK(executionRequest.skillId.isFullySpecified())
178  << "Got: " << executionRequest.skillId.toString();
179 
180  std::unique_lock l(skillProviderMapMutex);
181 
182  skills::ProviderID provderId(*executionRequest.skillId.providerId);
183 
184  // TODO: Really support regexes!
185  if (executionRequest.skillId.providerId->providerName == "*")
186  {
187  provderId = getFirstProviderNameThatHasSkill(executionRequest.skillId);
188  }
189 
190  if (auto it = skillProviderMap.find(provderId); it != skillProviderMap.end())
191  {
192  const auto& provider = it->second;
193 
194  if (!provider)
195  {
196  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
197  << provderId << "'. Removing it from skills.";
198  skillProviderMap.erase(it);
199 
201  __PRETTY_FUNCTION__,
202  "Skill execution failed. Could not execute a skill of provider '" +
203  provderId.toString() + "' because the provider does not exist.");
204  }
205 
206  try
207  {
208  skills::SkillExecutionRequest provider_executionRequest{
209  .skillId = executionRequest.skillId,
210  .executorName = executionRequest.executorName,
211  .parameters = executionRequest.parameters,
212  .callbackInterface = myPrx};
213 
214  auto async =
215  provider->begin_executeSkill(provider_executionRequest.toProviderIce());
216  l.unlock(); // allow parallel e.g. stopping. Otherwise the manager would lock himself in nested calls
217  auto provider_statusUpdate_ice = provider->end_executeSkill(async);
218 
219  // convert to manager view
220  auto statusUpdate =
221  skills::SkillStatusUpdate::FromIce(provider_statusUpdate_ice, provderId);
222  return statusUpdate;
223  }
224  catch (const std::exception& e)
225  {
226  l.lock();
227 
228  handleExceptionNonLockingThrow(__PRETTY_FUNCTION__, e, provderId);
229  }
230  }
231  else
232  {
234  __PRETTY_FUNCTION__,
235  "Skill execution failed. Could not execute a skill of provider '" +
236  provderId.toString() + "' because the provider does not exist.");
237  }
238  }
239 
242  const skills::SkillExecutionRequest& executionRequest)
243  {
244  ARMARX_CHECK(executionRequest.skillId.isFullySpecified())
245  << "Got: " << executionRequest.skillId.toString();
246 
247  std::unique_lock l(skillProviderMapMutex);
248 
249  skills::ProviderID provderId(*executionRequest.skillId.providerId);
250 
251  // TODO: Really support regexes!
252  if (executionRequest.skillId.providerId->providerName == "*")
253  {
254  provderId = getFirstProviderNameThatHasSkill(executionRequest.skillId);
255  }
256 
257  if (auto it = skillProviderMap.find(provderId); it != skillProviderMap.end())
258  {
259  const auto& provider = it->second;
260 
261  if (!provider)
262  {
263  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
264  << provderId << "'. Removing it from skills.";
265  skillProviderMap.erase(it);
266 
268  __PRETTY_FUNCTION__,
269  "Skill execution failed. Could not execute a skill of provider '" +
270  provderId.toString() + "' because the provider does not exist.");
271  }
272 
273  try
274  {
275  skills::SkillExecutionRequest provider_executionRequest{
276  .skillId = executionRequest.skillId,
277  .executorName = executionRequest.executorName,
278  .parameters = executionRequest.parameters,
279  .callbackInterface = myPrx};
280 
281  auto async =
282  provider->begin_executeSkillAsync(provider_executionRequest.toProviderIce());
283  l.unlock(); // allow parallel e.g. stopping. Otherwise the manager would lock himself in nested calls
284  auto provider_executionID_ice = provider->end_executeSkillAsync(async);
285 
286  // convert to manager view
287  auto executionId =
288  skills::SkillExecutionID::FromIce(provider_executionID_ice, provderId);
289  executionId.skillId.providerId = provderId;
290  return executionId;
291  }
292  catch (const std::exception& e)
293  {
294  l.lock();
295 
296  handleExceptionNonLockingThrow(__PRETTY_FUNCTION__, e, provderId);
297  }
298  }
299  else
300  {
302  __PRETTY_FUNCTION__,
303  "Skill execution failed. Could not execute a skill of provider '" +
304  provderId.toString() + "' because the provider does not exist.");
305  }
306  }
307 
308  bool
310  const aron::data::DictPtr& data)
311  {
312  ARMARX_DEBUG << "updateSkillParameters for skill " << executionId.skillId;
313 
314  ARMARX_CHECK(executionId.skillId.isFullySpecified())
315  << "Got: " << executionId.skillId.toString();
316 
317  std::unique_lock l(skillProviderMapMutex);
318  if (auto it = skillProviderMap.find(*executionId.skillId.providerId);
319  it != skillProviderMap.end())
320  {
321  const auto& providerId = it->first;
322  const auto& provider = it->second;
323 
324  if (!provider)
325  {
326  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
327  << providerId << "'. Removing it from skills.";
328  skillProviderMap.erase(it);
329  return false;
330  }
331 
332  try
333  {
334  auto async = provider->begin_updateSkillParameters(executionId.toProviderIce(),
335  data->toAronDictDTO());
336  l.unlock(); // allow parallel e.g. stopping. Otherwise the manager would lock himself in nested calls
337  auto r = provider->end_updateSkillParameters(async);
338  return r.success;
339  }
340  catch (const std::exception& e)
341  {
342  l.lock();
343 
344  handleExceptionNonLocking(__PRETTY_FUNCTION__, e, providerId);
345 
346  return false;
347  }
348  }
349  else
350  {
351  return false;
352  }
353  }
354 
355  bool
357  {
358  ARMARX_DEBUG << "abortSkill for skill " << executionId.skillId;
359 
360  ARMARX_CHECK(executionId.skillId.isFullySpecified())
361  << "Got: " << executionId.skillId.toString();
362 
363  std::unique_lock l(skillProviderMapMutex);
364  if (auto it = skillProviderMap.find(*executionId.skillId.providerId);
365  it != skillProviderMap.end())
366  {
367  const auto& providerId = it->first;
368  const auto& provider = it->second;
369 
370  if (!provider)
371  {
372  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
373  << providerId << "'. Removing it from skills.";
374  skillProviderMap.erase(it);
375  return false;
376  }
377 
378  try
379  {
380  auto async = provider->begin_abortSkill(executionId.toProviderIce());
381  l.unlock(); // allow parallel e.g. stopping. Otherwise the manager would lock himself in nested calls
382  auto r = provider->end_abortSkill(async);
383  return r.success;
384  }
385  catch (const std::exception& e)
386  {
387  l.lock();
388 
389  handleExceptionNonLocking(__PRETTY_FUNCTION__, e, providerId);
390 
391  return false;
392  }
393  }
394  else
395  {
396  return false;
397  }
398  }
399 
400  bool
402  {
403  ARMARX_CHECK(executionId.skillId.isFullySpecified())
404  << "Got: " << executionId.skillId.toString();
405 
406  std::unique_lock l(skillProviderMapMutex);
407  if (auto it = skillProviderMap.find(*executionId.skillId.providerId);
408  it != skillProviderMap.end())
409  {
410  const auto& providerId = it->first;
411  const auto& provider = it->second;
412 
413  if (!provider)
414  {
415  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
416  << providerId << "'. Removing it from skills.";
417  skillProviderMap.erase(it);
418  return false;
419  }
420 
421  try
422  {
423  auto async = provider->begin_abortSkillAsync(executionId.toProviderIce());
424  l.unlock(); // allow parallel e.g. stopping. Otherwise the manager would lock himself in nested calls
425  auto r = provider->end_abortSkillAsync(async);
426  return r.success;
427  }
428  catch (const std::exception& e)
429  {
430  l.lock();
431 
432  handleExceptionNonLocking(__PRETTY_FUNCTION__, e, providerId);
433 
434  return false;
435  }
436  }
437  else
438  {
439  return false;
440  }
441  }
442 
443  std::optional<skills::SkillDescription>
445  {
446  ARMARX_DEBUG << "getSkillDescription for skill " << skillId;
447 
448  ARMARX_CHECK(skillId.isFullySpecified()) << "Got: " << skillId.toString();
449 
450  std::unique_lock l(skillProviderMapMutex);
451  if (auto it = skillProviderMap.find(*skillId.providerId); it != skillProviderMap.end())
452  {
453  const auto& providerId = it->first;
454  const auto& provider = it->second;
455 
456  if (!provider)
457  {
458  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
459  << providerId << "'. Removing it from skills.";
460  skillProviderMap.erase(it);
461 
462  throw skills::error::SkillException(__PRETTY_FUNCTION__,
463  "Skill execution failed. Could not query a "
464  "status update of a skill of provider '" +
465  providerId.toString() +
466  "' because the provider does not exist.");
467  }
468 
469  try
470  {
471  auto async = provider->begin_getSkillDescription(skillId.toProviderIce());
472  l.unlock(); // allow parallel e.g. stopping. Otherwise the manager would lock himself in nested calls
473  auto provider_desc_ice = provider->end_getSkillDescription(async);
474 
475  if (not provider_desc_ice)
476  {
477  return std::nullopt;
478  }
479 
480  // convert to manager view
481  auto desc =
482  skills::SkillDescription::FromIce(provider_desc_ice.value(), providerId);
483  return desc;
484  }
485  catch (const std::exception& e)
486  {
487  l.lock();
488 
489  handleExceptionNonLockingThrow(__PRETTY_FUNCTION__, e, providerId);
490  }
491  }
492  else
493  {
494  return std::nullopt;
495  }
496  }
497 
498  std::map<skills::SkillID, skills::SkillDescription>
500  {
501  std::map<skills::SkillID, skills::SkillDescription> ret;
502 
503  std::unique_lock l(skillProviderMapMutex);
504  for (auto it = skillProviderMap.cbegin(); it != skillProviderMap.cend();)
505  {
506  const auto& providerId = it->first;
507  const auto& provider = it->second;
508 
509  if (!provider)
510  {
511  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
512  << providerId << "'. Removing it from skills.";
513  it = skillProviderMap.erase(it);
514  continue;
515  }
516 
517  try
518  {
519  auto async = provider->begin_getSkillDescriptions();
520  l.unlock();
521  auto m = provider->end_getSkillDescriptions(async);
522  l.lock();
523 
524  for (const auto& [provider_skillId_ice, skillDescription_ice] : m)
525  {
526  ret.insert(
527  {skills::SkillID::FromIce(provider_skillId_ice, providerId),
528  skills::SkillDescription::FromIce(skillDescription_ice, providerId)});
529  }
530 
531  ++it;
532  }
533  catch (const std::exception& e)
534  {
535  l.lock();
536 
537  if (auto _it = handleExceptionNonLocking(__PRETTY_FUNCTION__, e, providerId))
538  {
539  it = _it.value(); // next element
540  }
541  }
542  }
543  return ret;
544  }
545 
546  std::optional<skills::SkillStatusUpdate>
548  const skills::SkillExecutionID& executionId)
549  {
550  ARMARX_CHECK(executionId.skillId.isFullySpecified())
551  << "Got: " << executionId.skillId.toString();
552 
553  std::unique_lock l(skillProviderMapMutex);
554  if (auto it = skillProviderMap.find(*executionId.skillId.providerId);
555  it != skillProviderMap.end())
556  {
557  const auto& providerId = it->first;
558  const auto& provider = it->second;
559 
560  if (!provider)
561  {
562  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
563  << providerId << "'. Removing it from skills.";
564  skillProviderMap.erase(it);
565 
566  throw skills::error::SkillException(__PRETTY_FUNCTION__,
567  "Skill execution failed. Could not query a "
568  "status update of a skill of provider '" +
569  providerId.toString() +
570  "' because the provider does not exist.");
571  }
572 
573  try
574  {
575  auto async = provider->begin_getSkillExecutionStatus(executionId.toProviderIce());
576  l.unlock(); // allow parallel e.g. stopping. Otherwise the manager would lock himself in nested calls
577  auto provider_statusUpdate_ice = provider->end_getSkillExecutionStatus(async);
578 
579  if (not provider_statusUpdate_ice)
580  {
581  return std::nullopt;
582  }
583 
584  // convert to manager view
585  auto statusUpdate = skills::SkillStatusUpdate::FromIce(
586  provider_statusUpdate_ice.value(), providerId);
587 
588  // ARMARX_WARNING << "Status update: " << statusUpdate.result;
589  return statusUpdate;
590  }
591  catch (const std::exception& e)
592  {
593  l.lock();
594 
595  handleExceptionNonLockingThrow(__PRETTY_FUNCTION__, e, providerId);
596  }
597  }
598  else
599  {
600  return std::nullopt;
601  }
602  }
603 
604  std::map<skills::SkillExecutionID, skills::SkillStatusUpdate>
606  {
607  std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> ret;
608 
609  std::unique_lock l(skillProviderMapMutex);
610  for (auto it = skillProviderMap.cbegin(); it != skillProviderMap.cend();)
611  {
612  const auto& providerId = it->first;
613  const auto& provider = it->second;
614 
615  if (!provider)
616  {
617  ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
618  << providerId << "'. Removing it from skills.";
619  it = skillProviderMap.erase(it);
620  continue;
621  }
622 
623  try
624  {
625  auto async = provider->begin_getSkillExecutionStatuses();
626  l.unlock(); // allow parallel e.g. stopping. Otherwise the manager would lock himself in nested calls
627  auto m = provider->end_getSkillExecutionStatuses(async);
628  l.lock();
629 
630  for (const auto& [provider_executionId_ice, provider_statusUpdate_ice] : m)
631  {
632  ret.insert(
633  {skills::SkillExecutionID::FromIce(provider_executionId_ice, providerId),
634  skills::SkillStatusUpdate::FromIce(provider_statusUpdate_ice,
635  providerId)});
636  }
637  it++;
638  }
639  catch (const std::exception& e)
640  {
641  if (auto _it = handleExceptionNonLocking(__PRETTY_FUNCTION__, e, providerId))
642  {
643  it = _it.value(); // next element
644  }
645  }
646  }
647  return ret;
648  }
649 
650  std::optional<
651  std::map<skills::ProviderID, skills::provider::dti::SkillProviderInterfacePrx>::iterator>
652  SkillManagerComponentPlugin::handleExceptionNonLocking(const char* funcName,
653  const std::exception& e,
654  skills::ProviderID providerId,
655  bool eraseSkillProvider)
656  {
657  // NON LOCKING! WE ASSERT THAT THE CALLER HOLDS LOCK
658  if (auto it = skillProviderMap.find(providerId);
659  eraseSkillProvider and it != skillProviderMap.end())
660  {
661  ARMARX_WARNING << funcName << ": Found disconnected or buggy skill provider '"
662  << providerId << "' during execution. Removing it from skills. "
663  << "Error: " << e.what();
664  return skillProviderMap.erase(it);
665  }
666  else
667  {
668  ARMARX_WARNING << funcName << ": Found disconnected or buggy skill provider '"
669  << providerId
670  << "' during execution. However, it already got removed... "
671  << "Error: " << e.what();
672  return std::nullopt;
673  }
674  }
675 
676  void
677  SkillManagerComponentPlugin::handleExceptionNonLockingThrow(const char* funcName,
678  const std::exception& e,
679  skills::ProviderID providerId,
680  bool eraseSkillProvider)
681  {
682  // NON LOCKING! WE ASSERT THAT THE CALLER HOLDS LOCK
683  handleExceptionNonLocking(funcName, e, providerId, eraseSkillProvider);
684 
685  throw skills::error::SkillException(
686  funcName,
687  "Skill execution failed. Could not execute a skill of provider '" +
688  providerId.toString() + "' because the provider does not exist.");
689  }
690 
691  //****************************//
692  //** Fluxio related methods **//
693  //****************************//
694 
695  skills::Result<std::experimental::observer_ptr<skills::FluxioExecutor>,
696  skills::error::FluxioException>
698  const std::string& profileId,
699  const std::string& executorName,
700  armarx::aron::data::DictPtr parameters)
701  {
702  const auto& result = getSkill(skillId);
703  if (!result.isSuccess())
704  {
705  ARMARX_WARNING << "Skill with id '" << skillId << "' not found.";
708  {skillId}),
710  "SkillManagerComponentPlugin",
711  __FUNCTION__,
712  __LINE__)};
713  }
714 
715  const auto& skill = result.getResult();
716  if (skill == nullptr)
717  {
718  ARMARX_WARNING << "Unexpected nullptr for skill with id '" << skillId << "'.";
721  {skillId}),
723  "SkillManagerComponentPlugin",
724  __FUNCTION__,
725  __LINE__)};
726  }
727 
728  const std::string& executionId = IceUtil::generateUUID();
729  const bool isNative = skill->native;
731 
732  if (parameters == nullptr)
733  {
734  ARMARX_WARNING << "No parameters supplied for skill '" << skill->name << "(" << skillId
735  << ")'. Using profile values instead.";
736 
737  parameters = std::make_shared<aron::data::Dict>();
738  }
739 
741  << "Initializing skill execution with the following parameter values (overrides): "
743 
744  if (!isNative)
745  {
746  const auto& executeFluxioSkillFunc =
747  [this](const std::string& skillId,
748  const std::string& profileId,
749  const std::string& executorName,
750  const armarx::aron::data::DictPtr& parameters)
751  {
752  return this->executeFluxioSkill(skillId, profileId, executorName, parameters)
753  .getResult();
754  };
755 
756  const auto& abortFluxioSkill = [this](const std::string& executionId)
757  { this->abortFluxioSkill(executionId); };
758 
759  const auto& addMergerExecutorToDCFunc =
760  [this](const std::vector<std::string>& parameterIds)
761  {
762  const auto& executorId = IceUtil::generateUUID();
763  std::unique_lock l(this->fluxioDC.fluxioExecutorsMutex);
764 
765  this->fluxioDC.fluxioExecutors[executorId] =
766  std::make_unique<skills::FluxioMergerExecutor>(executorId, parameterIds);
767 
769  this->fluxioDC.fluxioExecutors[executorId].get());
770  l.unlock();
771  return ret;
772  };
773 
774  std::shared_lock skillLock(fluxioDC.skillsMutex);
775  const auto& skillRef = fluxioDC.skills[skillId];
776  skillLock.unlock();
777 
778  std::unique_lock l(fluxioDC.fluxioExecutorsMutex);
779  fluxioDC.fluxioExecutors[executionId] =
780  std::make_unique<skills::FluxioCompositeExecutor>(
781  executionId,
782  skillRef,
783  std::move(abortFluxioSkill),
784  std::move(executeFluxioSkillFunc),
785  std::move(addMergerExecutorToDCFunc));
786 
787  executorPtr =
788  std::experimental::make_observer(fluxioDC.fluxioExecutors[executionId].get());
789  l.unlock();
790 
791  const auto& profilePtr =
792  std::experimental::make_observer(&(fluxioDC.profiles[profileId]));
793 
794  std::thread([executorPtr, executorName, parameters, profilePtr]()
795  { executorPtr->run(executorName, parameters, profilePtr); })
796  .detach();
797  }
798  else
799  {
801  .providerId = skills::ProviderID{.providerName = skill->skillProviderPtr->name},
802  .skillName = skill->name};
803 
804  auto skillDescr = getSkillDescription(sID);
805  if (!skillDescr.has_value())
806  {
807  ARMARX_WARNING << "Skill description for skill with id '" << skillId
808  << "' not found. Aborting execution." << sID.toString();
809 
812  {skillId}),
814  "SkillManagerComponentPlugin",
815  __FUNCTION__,
816  __LINE__)};
817  }
818 
819  const auto& abortSkillFunc = [this](const skills::SkillExecutionID& executionId)
820  { return this->abortSkill(executionId); };
821 
822  const auto& executeSkillAsyncFunc = [this](const skills::SkillExecutionRequest& req)
823  { return this->executeSkillAsync(req); };
824 
825  const auto& getSkillExecutionStatusFunc =
826  [this](const skills::SkillExecutionID& executionId)
827  { return this->getSkillExecutionStatus(executionId); };
828 
829  std::unique_lock l(fluxioDC.fluxioExecutorsMutex);
830  fluxioDC.fluxioExecutors[executionId] = std::make_unique<skills::FluxioNativeExecutor>(
831  executionId,
832  sID,
833  *skill,
834  std::move(abortSkillFunc),
835  std::move(executeSkillAsyncFunc),
836  std::move(getSkillExecutionStatusFunc));
837 
838  executorPtr =
839  std::experimental::make_observer(fluxioDC.fluxioExecutors[executionId].get());
840  l.unlock();
841 
842  const auto& profilePtr =
843  std::experimental::make_observer(&(fluxioDC.profiles[profileId]));
844 
845  std::thread([executorPtr, executorName, parameters, profilePtr]()
846  { executorPtr->run(executorName, parameters, profilePtr); })
847  .detach();
848  }
849 
850  return {executorPtr};
851  }
852 
853  void
854  SkillManagerComponentPlugin::abortFluxioSkill(const std::string& executionId)
855  {
856  std::shared_lock l(fluxioDC.fluxioExecutorsMutex);
857  const auto& executorIt = fluxioDC.fluxioExecutors.find(executionId);
858  if (executorIt == fluxioDC.fluxioExecutors.end())
859  {
860  ARMARX_WARNING << "Execution with id '" << executionId << "' not found.";
861 
862  l.unlock();
865  {executionId}),
867  "SkillManagerComponentPlugin",
868  __FUNCTION__,
869  __LINE__)
870  .toManagerIce();
871  }
872  l.unlock();
873 
874  executorIt->second->abort();
875  }
876 
879  {
880  std::shared_lock l(fluxioDC.fluxioExecutorsMutex);
881  const auto& executorIt = fluxioDC.fluxioExecutors.find(executionId);
882  if (executorIt == fluxioDC.fluxioExecutors.end())
883  {
884  ARMARX_WARNING << "Execution with id '" << executionId << "' not found.";
885 
886  l.unlock();
889  {executionId}),
891  "SkillManagerComponentPlugin",
892  __FUNCTION__,
893  __LINE__)};
894  }
895  l.unlock();
896 
897  return {executorIt->second->getStatusUpdate().value()};
898  }
899 
900  /**
901  * @brief converts parametersType or resultType from skilldescription to fluxio parameters
902  * @param ret the map to insert the fluxio parameters into
903  * @param ptr the aron object ptr to convert (this is either skillDescription.parametersType or skillDescription.resultType)
904  * @param isInput value for the isInput field of the fluxio parameter(s)
905  */
906  void
907  SkillManagerComponentPlugin::convertAronObjectPtrToFluxioParameters(
908  std::map<std::string, skills::FluxioParameter>& ret,
909  const aron::type::ObjectPtr& ptr,
910  bool isInput,
911  const boost::uuids::uuid& skillId)
912  {
913  for (const auto& [name, typeInfo] : ptr->getMemberTypes())
914  {
916 
917  const auto& seed = name + (isInput ? "isInput" : "isOutput");
918  p.id = boost::uuids::to_string(createUuidWithString(seed, skillId));
919  p.name = name;
920  // Full type name may contain some extra info like dimensions etc.
921  p.description = typeInfo->getFullName();
922  p.type = typeInfo;
923  p.typeIdentificator = {boost::uuids::to_string(skillId), p.id};
924  p.required = (typeInfo->getMaybe() == 0);
925  p.isInput = isInput;
926 
927  ret[p.id] = p;
928  std::unique_lock l(fluxioDC.typesMutex);
929  fluxioDC.types[boost::uuids::to_string(skillId)]->addMemberType(p.id, typeInfo);
930 
931  l.unlock();
932  }
933  }
934 
935  boost::uuids::uuid
936  SkillManagerComponentPlugin::createUuidWithString(
937  const std::string& str,
938  std::optional<const boost::uuids::uuid> namespaceUUID)
939  {
940  boost::uuids::uuid nameS;
941  if (namespaceUUID.has_value())
942  {
943  nameS = namespaceUUID.value();
944  }
945  else
946  {
947  // use default null uuid
948  nameS = boost::uuids::nil_uuid();
949  }
950 
951  // initialise the name generator with the starting UUID
952  boost::uuids::name_generator generator(nameS);
953 
954  // generate a new UUID, seeded with the given string
955  return generator(str);
956  }
957 
958  /**
959  * @brief Converts the old skill structure to the new FluxioSkill structure.
960  * @param skillId The id of the skill.
961  * @param skillDescription The description of the skill.
962  */
963  void
964  SkillManagerComponentPlugin::descriptionIdToFluxioSkill(
965  skills::SkillID skillId,
966  skills::SkillDescription skillDescription)
967  {
968  {
969  // generate skill id (idempotent)
970  const auto& providerId = createUuidWithString(skillId.providerId->providerName);
971  const auto& id = createUuidWithString(skillId.skillName, providerId);
972 
973  std::unique_lock skillsLock(fluxioDC.skillsMutex);
974  auto skillsEntry = fluxioDC.skills.find(boost::uuids::to_string(id));
975  if (skillsEntry != fluxioDC.skills.end())
976  {
977  skillsLock.unlock();
978  return;
979  }
980 
981  skills::FluxioSkill s;
982 
983  s.id = boost::uuids::to_string(id);
984  s.name = skillId.skillName;
985  s.description = skillDescription.description;
986  s.timeout = skillDescription.timeout;
987  s.lastChanged = "";
988  s.executable = false;
989  s.native = true;
990 
991  std::unique_lock providersLock(fluxioDC.providersMutex);
992  const auto& providersEntry =
993  fluxioDC.providers.find(boost::uuids::to_string(providerId));
994  if (providersEntry != fluxioDC.providers.end())
995  {
996  s.skillProviderPtr = std::experimental::make_observer(&(providersEntry->second));
997  providersLock.unlock();
998  }
999  else
1000  {
1001  providersLock.unlock();
1002  const auto& res = addFluxioProvider(skillId.providerId->providerName);
1003  if (!res.isSuccess())
1004  {
1005  ARMARX_WARNING << "Failed to add provider with name '"
1006  << skillId.providerId->providerName << "'. Skill: '" << s.name
1007  << " with id: '" << s.id << "' will not be added.";
1008  skillsLock.unlock();
1009  return;
1010  }
1011  const auto p = res.getResult(); // TODO: nullptr check
1012  s.skillProviderPtr = p;
1013  }
1014  std::unique_lock typesLock(fluxioDC.typesMutex);
1015  const auto& eventTypeIt = fluxioDC.types.find("BaseTypesNamespace");
1016  if (eventTypeIt == fluxioDC.types.end())
1017  {
1018  ARMARX_WARNING << "Event type not found. Skill: '" << s.name << " with id: '"
1019  << s.id << "' will not be added.";
1020  typesLock.unlock();
1021  skillsLock.unlock();
1022  return;
1023  }
1024  typesLock.unlock();
1025  const auto& eventType = eventTypeIt->second->getMemberType("Event");
1026  const skills::FluxioTypeIdentificator& eventTypeIdent = {
1027  .skillId = "BaseTypesNamespace", .parameterId = "Event"};
1028  // add default control flow parameters
1029  skills::FluxioParameter start;
1030  start.name = "Start";
1031  start.type = eventType;
1032  start.typeIdentificator = eventTypeIdent;
1033  const auto& startIdStr = start.name + start.type->getFullName() + "isInput";
1034  start.id = boost::uuids::to_string(createUuidWithString(startIdStr, id));
1035  start.description = "Start the skill";
1036  start.required = true;
1037  start.isInput = true;
1038 
1039  skills::FluxioParameter succeeded;
1040  succeeded.name = "Succeeded";
1041  succeeded.type = eventType;
1042  succeeded.typeIdentificator = eventTypeIdent;
1043  const auto& successIdStr = succeeded.name + succeeded.type->getFullName() + "isOutput";
1044  succeeded.id = boost::uuids::to_string(createUuidWithString(successIdStr, id));
1045  succeeded.description = "Skill has been executed successfully";
1046  succeeded.required = false;
1047  succeeded.isInput = false;
1048 
1049  skills::FluxioParameter failed;
1050  failed.name = "Failed";
1051  failed.type = eventType;
1052  failed.typeIdentificator = eventTypeIdent;
1053  const auto& failedIdStr = failed.name + failed.type->getShortName() + "isOutput";
1054  failed.id = boost::uuids::to_string(createUuidWithString(failedIdStr, id));
1055  failed.description = "Skill has failed";
1056  failed.required = false;
1057  failed.isInput = false;
1058 
1059  skills::FluxioParameter aborted;
1060  aborted.name = "Aborted";
1061  aborted.type = eventType;
1062  aborted.typeIdentificator = eventTypeIdent;
1063  const auto& abortedIdStr = aborted.name + aborted.type->getShortName() + "isOutput";
1064  aborted.id = boost::uuids::to_string(createUuidWithString(abortedIdStr, id));
1065  aborted.description = "Skill has been aborted";
1066  aborted.required = false;
1067  aborted.isInput = false;
1068 
1069  s.parameters[start.id] = start;
1070  s.parameters[succeeded.id] = succeeded;
1071  s.parameters[failed.id] = failed;
1072  s.parameters[aborted.id] = aborted;
1073 
1074  const auto& parameters = std::make_shared<aron::type::Object>();
1075  typesLock.lock();
1076  if (fluxioDC.types.find(s.id) == fluxioDC.types.end())
1077  {
1078  fluxioDC.types[s.id] = parameters;
1079  }
1080  typesLock.unlock();
1081 
1082  if (skillDescription.parametersType != nullptr)
1083  {
1084  // input parameters
1085  convertAronObjectPtrToFluxioParameters(
1086  s.parameters, skillDescription.parametersType, true, id);
1087  }
1088 
1089  if (skillDescription.resultType != nullptr)
1090  {
1091  // output parameters
1092  convertAronObjectPtrToFluxioParameters(
1093  s.parameters, skillDescription.resultType, false, id);
1094  }
1095 
1096  if (skillDescription.rootProfileDefaults != nullptr)
1097  {
1098  auto rootProfilePtr = std::experimental::make_observer(&fluxioDC.profiles["root"]);
1099 
1100  for (const auto& [k, v] : skillDescription.rootProfileDefaults->getElements())
1101  {
1102  if (v == nullptr)
1103  {
1104  // nullptr values are not allowed (will lead to problems down the line)
1105  continue;
1106  }
1107 
1108  skills::FluxioValue val;
1109  val.profilePtr = rootProfilePtr;
1110  val.content = v;
1111 
1112  for (const auto& [pId, param] : s.parameters)
1113  {
1114  if (param.name == k && param.isInput)
1115  {
1116  s.parameters[pId].values.push_back(val);
1117  break;
1118  }
1119  }
1120  }
1121  }
1122  else
1123  {
1124  ARMARX_INFO << "No root profile defaults found for skill '" << s.name << "'.";
1125  }
1126 
1127  fluxioDC.skills.emplace(s.id, std::move(s));
1128  skillsLock.unlock();
1129  }
1130  }
1131 
1132  skills::Result<std::vector<std::experimental::observer_ptr<const skills::FluxioSkill>>,
1133  skills::error::FluxioException>
1135  {
1136  return {convertMapValuesToObserverVector(fluxioDC.skills)};
1137  }
1138 
1142  {
1143  std::shared_lock l(fluxioDC.skillsMutex);
1144  const auto& skillsEntry = fluxioDC.skills.find(id);
1145  if (skillsEntry == fluxioDC.skills.end())
1146  {
1147  ARMARX_WARNING << "Skill with id '" << id << "' not found.";
1148  l.unlock();
1152  "SkillManagerComponentPlugin",
1153  __FUNCTION__,
1154  __LINE__)};
1155  }
1156 
1157  l.unlock();
1158  return {std::experimental::make_observer(&skillsEntry->second)};
1159  }
1160 
1161  // TODO: Outsource to a helper function or a separate class
1162  std::optional<std::vector<std::experimental::observer_ptr<const skills::FluxioSkill>>>
1163  SkillManagerComponentPlugin::deleteSkill(const std::string& skillId,
1164  const std::string& userId,
1165  const bool dryRun)
1166  {
1167  std::shared_lock l(fluxioDC.skillsMutex);
1168  const auto& skillIt = fluxioDC.skills.find(skillId);
1169  if (skillIt == fluxioDC.skills.end())
1170  {
1171  ARMARX_WARNING << "Skill with id '" << skillId << "' not found.";
1172  l.unlock();
1173  return std::nullopt;
1174  }
1175  l.unlock();
1176 
1177  if (skillIt->second.native)
1178  {
1179  ARMARX_WARNING << "Skill with id '" << skillId
1180  << "' is a native skill and cannot be deleted.";
1181  return std::nullopt;
1182  }
1183 
1184  const auto& skillMutexResult = getSkillMutex(skillId, userId);
1185 
1186  if (!skillMutexResult.isSuccess())
1187  {
1188  ARMARX_WARNING << "User '" << userId << "' needs to acquire the mutex for skill '"
1189  << skillId << "' in order to delete it.";
1190  return std::nullopt;
1191  }
1192 
1193  if (!skillMutexResult.getResult())
1194  {
1195  ARMARX_WARNING << "User '" << userId << "' needs to acquire the mutex for skill '"
1196  << skillId << "' in order to delete it.";
1197  return std::nullopt;
1198  }
1199 
1200  std::vector<std::experimental::observer_ptr<skills::FluxioSkill>> affectedSkills;
1201  std::vector<std::experimental::observer_ptr<const skills::FluxioSkill>> ret;
1202  l.lock();
1203  for (auto& [id, s] : fluxioDC.skills)
1204  {
1205  if (s.native || s.id == skillId)
1206  {
1207  continue; // ignore native skills and the to-delete skill
1208  }
1209 
1210  for (const auto& [nodeId, node] : s.nodes)
1211  {
1212  if (node == nullptr)
1213  {
1214  ARMARX_WARNING << "Unexpected nullptr!";
1215  continue;
1216  }
1217 
1218  if (node->nodeType == skills::FluxioNodeType::SUBSKILL)
1219  {
1220  // cast to the right node type
1221  const auto& subSkillNodeptr =
1222  dynamic_cast<skills::FluxioSubSkillNode*>(node.get());
1223  if (subSkillNodeptr == nullptr)
1224  {
1225  ARMARX_WARNING << "Error while casting node to FluxioSubSkillNode.";
1226  continue;
1227  }
1228 
1229  if (subSkillNodeptr->skillPtr != nullptr &&
1230  subSkillNodeptr->skillPtr->id == skillId)
1231  {
1232  affectedSkills.emplace_back(std::experimental::make_observer(&s));
1233  ret.emplace_back(std::experimental::make_observer(&s));
1234  break;
1235  }
1236  }
1237  }
1238  }
1239  l.unlock();
1240 
1241  if (dryRun)
1242  {
1243  return ret;
1244  }
1245 
1246  // get mutex of all affected skills
1247  bool mutexesAquired = true;
1248  for (const auto& affectedSkill : affectedSkills)
1249  {
1250  const auto& affectedMutexResult = getSkillMutex(affectedSkill->id, userId);
1251 
1252  if (!affectedMutexResult.isSuccess() || !affectedMutexResult.getResult())
1253  {
1254  mutexesAquired = false;
1255  ARMARX_WARNING << "Someone else is editing the skill '" << affectedSkill->name
1256  << "(" << affectedSkill->id << ")' right now.";
1257  }
1258  }
1259 
1260  if (mutexesAquired)
1261  {
1262  ARMARX_WARNING << "Updating affected skills.";
1263  for (const auto& affectedSkill : affectedSkills)
1264  {
1265  affectedSkill->removeSubSkillNodesAndEdges(skillId);
1266  }
1267 
1268  ARMARX_WARNING << "Deleting skill '" << skillIt->second.name << "' (" << skillId
1269  << ").";
1270  std::unique_lock skillsLock(fluxioDC.skillsMutex);
1271  fluxioDC.skills.erase(skillId);
1272  skillsLock.unlock();
1273  }
1274  else
1275  {
1277  << "Not all Mutexes for affected skills could be aquired. Aborting deletion.";
1278  }
1279 
1280  //release mutexes
1281  for (const auto& affectedSkill : affectedSkills)
1282  {
1283  deleteSkillMutex(affectedSkill->id, userId);
1284  }
1285 
1286  if (mutexesAquired)
1287  {
1288  return ret;
1289  }
1290  return std::nullopt;
1291  }
1292 
1296  const std::string& parameterId,
1297  const std::string& userId,
1298  bool dryRun)
1299  {
1300  return updateFluxioParameter(skillId, parameterId, userId, dryRun, true);
1301  }
1302 
1306  const std::string& skillId,
1307  const skills::manager::dto::FluxioParameter& parameter,
1308  const std::string& userId,
1309  bool dryRun)
1310  {
1311  const auto& parameterId = parameter.id;
1312  return updateFluxioParameter(skillId, parameterId, userId, dryRun, false, parameter);
1313  }
1314 
1317  SkillManagerComponentPlugin::updateFluxioParameter(
1318  const std::string& skillId,
1319  const std::string& parameterId,
1320  const std::string& userId,
1321  bool dryRun,
1322  bool deleteParameter,
1323  const std::optional<skills::manager::dto::FluxioParameter>& parameterDT)
1324  {
1325  if (!deleteParameter && parameterDT == std::nullopt)
1326  {
1327  ARMARX_WARNING << "Required parameter data transfer object not provided.";
1330  {"parameter data transfer object"}),
1332  "SkillManagerComponentPlugin",
1333  __FUNCTION__,
1334  __LINE__)};
1335  }
1336 
1337  // check if skill exists
1338  const auto& res = getSkill(skillId);
1339  if (!res.isSuccess())
1340  {
1343  {skillId}),
1345  "SkillManagerComponentPlugin",
1346  __FUNCTION__,
1347  __LINE__)};
1348  }
1349  const auto& skill = res.getResult();
1350 
1351  // check if parameter exists
1352  const auto& parameterIt = skill->parameters.find(parameterId);
1353  if (parameterIt == skill->parameters.end())
1354  {
1357  {parameterId}),
1359  "SkillManagerComponentPlugin",
1360  __FUNCTION__,
1361  __LINE__)};
1362  }
1363  const auto& parameterOld = parameterIt->second;
1364 
1365  // check if user has mutex
1366  const auto& mutexResult = getSkillMutex(skillId, userId);
1367  if (!mutexResult.isSuccess())
1368  {
1369  return {mutexResult.getError()};
1370  }
1371 
1372  // find affected skills
1373  std::vector<std::experimental::observer_ptr<skills::FluxioSkill>> affectedSkills;
1374  std::vector<std::experimental::observer_ptr<const skills::FluxioSkill>> ret;
1375 
1376  // skip this part, if the parameter is updated and neither type nor isInput has changed
1377  if (deleteParameter ||
1378  parameterOld.typeIdentificator.toManagerIce() != parameterDT.value().type ||
1379  parameterOld.isInput != parameterDT.value().isInput)
1380  {
1381  std::shared_lock l(fluxioDC.skillsMutex);
1382  for (auto& [id, s] : fluxioDC.skills)
1383  {
1384  if (s.native || s.id == skillId)
1385  {
1386  continue; // ignore native skills and the skill with the parameter itself
1387  }
1388 
1389  for (const auto& e : s.edges)
1390  {
1391  if ((e.fromParameterPtr != nullptr && e.fromParameterPtr->id == parameterId) ||
1392  (e.toParameterPtr != nullptr && e.toParameterPtr->id == parameterId))
1393  {
1394  affectedSkills.emplace_back(std::experimental::make_observer(&s));
1395  ret.emplace_back(std::experimental::make_observer(&s));
1396  break;
1397  }
1398  }
1399  }
1400  l.unlock();
1401  }
1402 
1403  if (dryRun)
1404  {
1405  return {ret};
1406  }
1407 
1408  // get mutex of all affected skills
1409  bool mutexesAquired = true;
1410  for (const auto& affectedSkill : affectedSkills)
1411  {
1412  const auto& affectedMutexResult = getSkillMutex(affectedSkill->id, userId);
1413 
1414  if (!affectedMutexResult.isSuccess() || !affectedMutexResult.getResult())
1415  {
1416  mutexesAquired = false;
1417  ARMARX_WARNING << "Someone else is editing the skill '" << affectedSkill->name
1418  << "(" << affectedSkill->id << ")' right now.";
1419  }
1420  }
1421 
1422  // update or delete parameter
1423  if (mutexesAquired)
1424  {
1425  ARMARX_WARNING << "Updating affected skills.";
1426  for (const auto& affectedSkill : affectedSkills)
1427  {
1428  affectedSkill->removeEdgesConnectedToParameter(parameterId);
1429  }
1430 
1431  if (deleteParameter)
1432  {
1433  ARMARX_WARNING << "Deleting skill parameter'" << parameterOld.name << "' ("
1434  << parameterId << ").";
1435  std::unique_lock skillsLock(fluxioDC.skillsMutex);
1436  fluxioDC.skills[skillId].deleteParameter(parameterId);
1437  skillsLock.unlock();
1438  }
1439  else
1440  {
1441  ARMARX_WARNING << "Updating skill parameter'" << parameterOld.name << "' ("
1442  << parameterId << ").";
1443  std::scoped_lock l(fluxioDC.skillsMutex,
1444  fluxioDC.profilesMutex,
1445  fluxioDC.providersMutex,
1446  fluxioDC.typesMutex);
1447  auto& profilesMap = fluxioDC.profiles;
1448  auto& typesMap = fluxioDC.types;
1449  fluxioDC.skills[skillId].removeParameterNodesAndEdges(parameterId, true);
1450  fluxioDC.skills[skillId].parameters[parameterId].updateFromIce(
1451  *parameterDT, profilesMap, typesMap);
1452  }
1453  }
1454  else
1455  {
1456  ARMARX_WARNING << "Not all Mutexes for affected skills could be aquired. Aborting "
1457  << (deleteParameter ? "deletion" : "update") << " of parameter.";
1458  }
1459 
1460  //release mutexes
1461  for (const auto& affectedSkill : affectedSkills)
1462  {
1463  deleteSkillMutex(affectedSkill->id, userId);
1464  }
1465 
1466  if (mutexesAquired)
1467  {
1468  return ret;
1469  }
1470 
1473  {userId}),
1475  "SkillManagerComponentPlugin",
1476  __FUNCTION__,
1477  __LINE__)};
1478  }
1479 
1480  skills::Result<bool, skills::error::FluxioException>
1482  const std::string& userId)
1483  {
1484  return setEditFluxioSkillMutex(true, userId, skillId);
1485  }
1486 
1487  void
1489  const std::string& userId)
1490  {
1491  setEditFluxioSkillMutex(false, userId,
1492  skillId); // ignore return value for now
1493  }
1494 
1498  {
1499  std::shared_lock l(fluxioDC.profilesMutex);
1500  const auto& ret = convertMapValuesToObserverVector(fluxioDC.profiles);
1501  l.unlock();
1502  return {ret};
1503  }
1504 
1507  {
1508  std::shared_lock l(fluxioDC.profilesMutex);
1509  const auto& profilesEntry = fluxioDC.profiles.find(id);
1510 
1511  if (profilesEntry == fluxioDC.profiles.end())
1512  {
1513  l.unlock();
1517  "SkillManagerComponentPlugin",
1518  __FUNCTION__,
1519  __LINE__)};
1520  }
1521 
1522  l.unlock();
1523  return {profilesEntry->second};
1524  }
1525 
1528  {
1529  if (profile.parentPtr == nullptr)
1530  {
1531  ARMARX_WARNING << "Profile with name '" << profile.name << "' has no parent.";
1534  {profile.name}),
1536  "SkillManagerComponentPlugin",
1537  __FUNCTION__,
1538  __LINE__)};
1539  }
1540 
1541  const auto& parentId = profile.parentPtr->id;
1542  const auto& nameLowerCase = simox::alg::to_lower(profile.name);
1543 
1544  std::unique_lock l(fluxioDC.profilesMutex);
1545  auto it = std::find_if(
1546  fluxioDC.profiles.begin(),
1547  fluxioDC.profiles.end(),
1548  [&parentId, &nameLowerCase](const std::pair<std::string, skills::FluxioProfile>& p)
1549  {
1550  return p.second.parentPtr != nullptr && p.second.parentPtr->id == parentId &&
1551  simox::alg::to_lower(p.second.name) == nameLowerCase;
1552  });
1553 
1554  if (nameLowerCase == "root" || it != fluxioDC.profiles.end())
1555  {
1556  ARMARX_WARNING << "Profile with name '" << profile.name << "' already exists.";
1557  l.unlock();
1560  {profile.name}),
1562  "SkillManagerComponentPlugin",
1563  __FUNCTION__,
1564  __LINE__)};
1565  }
1566 
1567  std::string id = profile.id;
1568 
1569  bool validId = false;
1570  try
1571  {
1572  const auto& result = boost::uuids::string_generator()(id);
1573  validId = result.version() != boost::uuids::uuid::version_unknown;
1574  }
1575  catch (...)
1576  {
1577  validId = false;
1578  }
1579 
1580  if (!validId)
1581  {
1582  id = IceUtil::generateUUID();
1583  }
1584  else if (fluxioDC.profiles.find(profile.id) != fluxioDC.profiles.end())
1585  {
1586  ARMARX_INFO << "The id '" << profile.id
1587  << "' is already taken. A new uuid will be generated.";
1588  id = IceUtil::generateUUID();
1589  }
1590  else
1591  {
1592  id = profile.id;
1593  }
1594 
1595  fluxioDC.profiles[id] = profile; // a copy is created when the profile is added to the map
1596  fluxioDC.profiles[id].id = id; // this copy can then be modified
1597  const auto& ret = fluxioDC.profiles[id];
1598 
1599  l.unlock();
1600 
1601  return {ret};
1602  }
1603 
1604  void
1606  {
1607  auto oldProfile = getProfile(profile.id);
1608 
1609  if (oldProfile.isSuccess() && oldProfile.getResult().id == profile.id)
1610  {
1611  std::unique_lock l(fluxioDC.profilesMutex);
1612  fluxioDC.profiles[profile.id].name = profile.name;
1613  fluxioDC.profiles[profile.id].description = profile.description;
1614  fluxioDC.profiles[profile.id].parentPtr = profile.parentPtr;
1615  l.unlock();
1616  }
1617  else
1618  {
1619  //TODO: Do we throw the error here?
1620  }
1621  }
1622 
1626  {
1627  const std::string& providerId = boost::uuids::to_string(createUuidWithString(name));
1628 
1629  std::unique_lock l(fluxioDC.providersMutex);
1630  if (fluxioDC.providers.find(providerId) != fluxioDC.providers.end())
1631  {
1632  ARMARX_WARNING << "Provider with name '" << name << "' already exists.";
1633  l.unlock();
1634  return {std::experimental::make_observer(&fluxioDC.providers[providerId])};
1635  }
1636 
1638  p.id = providerId;
1639  p.name = name;
1640 
1641  fluxioDC.providers[p.id] = p;
1642  const auto& ret = std::experimental::make_observer(&fluxioDC.providers[p.id]);
1643  l.unlock();
1644 
1645  return {ret};
1646  }
1647 
1651  {
1652  for (const auto& [providerID, providerPrx] : skillProviderMap)
1653  {
1654  const auto& id = boost::uuids::to_string(createUuidWithString(providerID.providerName));
1655 
1656  std::shared_lock l(fluxioDC.providersMutex);
1657  const auto& providersEntry = fluxioDC.providers.find(id);
1658 
1659  if (providersEntry != fluxioDC.providers.end())
1660  {
1661  l.unlock();
1662  continue; // provider already exists
1663  }
1664 
1665  l.unlock();
1666  addFluxioProvider(providerID.providerName);
1667  }
1668 
1669  return {convertMapValuesToObserverVector(fluxioDC.providers)};
1670  }
1671 
1674  {
1675  getProviderList();
1676 
1677  std::shared_lock l(fluxioDC.providersMutex);
1678  const auto& providersEntry = fluxioDC.providers.find(id);
1679 
1680  if (providersEntry != fluxioDC.providers.end())
1681  {
1682  l.unlock();
1683  return {providersEntry->second};
1684  }
1685 
1686  l.unlock();
1690  "SkillManagerComponentPlugin",
1691  __FUNCTION__,
1692  __LINE__)};
1693  }
1694 
1698  {
1699  getProviderList();
1700 
1701  std::shared_lock l(fluxioDC.providersMutex);
1702  const auto& providersEntry = fluxioDC.providers.find(id);
1703 
1704  if (providersEntry == fluxioDC.providers.end())
1705  {
1706  l.unlock();
1710  "SkillManagerComponentPlugin",
1711  __FUNCTION__,
1712  __LINE__)};
1713  }
1714 
1715  l.unlock();
1716 
1717  auto res = getSkillList();
1718  if (!res.isSuccess())
1719  {
1720  auto e = res.getError();
1721  e.addToContext(std::nullopt, "SkillManagerComponentPlugin", __FUNCTION__, __LINE__);
1722  return {e};
1723  }
1724 
1725  auto allSkills = res.getResult();
1726 
1727  allSkills.erase(std::remove_if(allSkills.begin(),
1728  allSkills.end(),
1729  [id](const auto& skillPtr)
1730  { return skillPtr->skillProviderPtr->id != id; }),
1731  allSkills.end());
1732 
1733  return {allSkills};
1734  }
1735 
1739  const std::string& providerId,
1740  skills::FluxioSkill&& skill)
1741  {
1742  std::shared_lock l(fluxioDC.providersMutex);
1743  const auto& providerIt = fluxioDC.providers.find(providerId);
1744  if (providerIt == fluxioDC.providers.end())
1745  {
1746  ARMARX_WARNING << "Provider with id '" << providerId << "' not found.";
1747  l.unlock();
1750  {providerId}),
1752  "SkillManagerComponentPlugin",
1753  __FUNCTION__,
1754  __LINE__)};
1755  }
1756  l.unlock();
1757 
1758  if (skill.id.empty())
1759  {
1760  // its a new skill, its a new world, ...
1761  skill.id = IceUtil::generateUUID();
1762  }
1763  else
1764  {
1765  // TODO(me): check if a skill with the same id already exists
1766  }
1767 
1768  boost::uuids::uuid uuid;
1769  try
1770  {
1771  boost::uuids::string_generator gen;
1772  uuid = gen(skill.id);
1773  }
1774  catch (std::runtime_error& e)
1775  {
1776  ARMARX_WARNING << "Could not convert skill id to uuid: " << e.what();
1777  skill.id = IceUtil::generateUUID(); // fallback
1778  }
1779 
1780  std::unique_lock typesLock(fluxioDC.typesMutex);
1781  const auto& eventType = fluxioDC.types["BaseTypesNamespace"]->getMemberType("Event");
1782  typesLock.unlock();
1783  const skills::FluxioTypeIdentificator& eventTypeIdent = {.skillId = "BaseTypesNamespace",
1784  .parameterId = "Event"};
1785 
1786  // add default control flow parameters
1788  start.name = "Start";
1789  start.id = boost::uuids::to_string(createUuidWithString(start.name, uuid));
1790  start.description = "Start the skill";
1791  start.type = eventType;
1792  start.typeIdentificator = eventTypeIdent;
1793  start.required = true;
1794  start.isInput = true;
1795 
1796  skills::FluxioParameter succeeded;
1797  succeeded.name = "Succeeded";
1798  succeeded.id = boost::uuids::to_string(createUuidWithString(succeeded.name, uuid));
1799  succeeded.description = "Skill has been executed successfully";
1800  succeeded.type = eventType;
1801  succeeded.typeIdentificator = eventTypeIdent;
1802  succeeded.required = false;
1803  succeeded.isInput = false;
1804 
1805  skills::FluxioParameter failed;
1806  failed.name = "Failed";
1807  failed.id = boost::uuids::to_string(createUuidWithString(failed.name, uuid));
1808  failed.description = "Skill has failed";
1809  failed.type = eventType;
1810  failed.typeIdentificator = eventTypeIdent;
1811  failed.required = false;
1812  failed.isInput = false;
1813 
1814  skills::FluxioParameter aborted;
1815  aborted.name = "Aborted";
1816  aborted.id = boost::uuids::to_string(createUuidWithString(aborted.name, uuid));
1817  aborted.description = "Skill has been aborted";
1818  aborted.type = eventType;
1819  aborted.typeIdentificator = eventTypeIdent;
1820  aborted.required = false;
1821  aborted.isInput = false;
1822 
1823  skill.parameters[start.id] = start;
1824  skill.parameters[succeeded.id] = succeeded;
1825  skill.parameters[failed.id] = failed;
1826  skill.parameters[aborted.id] = aborted;
1827 
1828  skill.lastChanged = armarx::DateTime::Now().toDateTimeString();
1829 
1830  // store in data collector
1831  const auto skillId = skill.id;
1832  std::unique_lock skillsLock(fluxioDC.skillsMutex);
1833  fluxioDC.skills.emplace(skillId, std::move(skill));
1834  const auto& ret = std::experimental::make_observer(&(fluxioDC.skills[skillId]));
1835  skillsLock.unlock();
1836 
1837  // set mutex
1838  setEditFluxioSkillMutex(true, userId, skill.id);
1839  return {ret};
1840  }
1841 
1842  bool
1843  SkillManagerComponentPlugin::setEditFluxioSkillMutex(bool aquireMutex,
1844  const std::string& userId,
1845  const std::string& skillId)
1846  {
1847  std::scoped_lock l(fluxioDC.skillMutexMapMutex);
1848  const auto& skillMutexIt = fluxioDC.skillMutexMap.find(skillId);
1849 
1850  // aquire mutex
1851  if (aquireMutex)
1852  {
1853  if (skillMutexIt == fluxioDC.skillMutexMap.end())
1854  {
1855  // skill is free, set mutex
1856  fluxioDC.skillMutexMap[skillId] = std::make_tuple(userId, armarx::DateTime::Now());
1857  return true;
1858  }
1859 
1860  // skill is already locked
1861  if (std::get<0>(fluxioDC.skillMutexMap[skillId]) == userId)
1862  {
1863  // user already holds the mutex -> reset timestamp / prolong mutex
1864  std::get<1>(fluxioDC.skillMutexMap[skillId]) = armarx::DateTime::Now();
1865  return true;
1866  }
1867 
1868  // another user holds the mutex -> is it still valid ?
1869  armarx::Duration elapsedTime =
1870  armarx::DateTime::Now() - std::get<1>(fluxioDC.skillMutexMap[skillId]);
1871  if (elapsedTime.toMinutes() > fluxioDC.mutexTimeout)
1872  {
1873  // mutex invalid, requesting user gets the mutex instead
1874  fluxioDC.skillMutexMap[skillId] = std::make_tuple(userId, armarx::DateTime::Now());
1875  return true;
1876  }
1877 
1878  // mutex could not be aquired
1881  {skillId}),
1883  "SkillManagerComponentPlugin",
1884  __FUNCTION__,
1885  __LINE__)
1886  .toManagerIce();
1887  }
1888 
1889  // remove mutex
1890  if (skillMutexIt == fluxioDC.skillMutexMap.end())
1891  {
1892  // skill is already free
1893  return true;
1894  }
1895 
1896 
1897  // check if the user holds the mutex, as only the user that holds the mutex
1898  // can release it
1899  if (std::get<0>(fluxioDC.skillMutexMap[skillId]) == userId)
1900  {
1901  fluxioDC.skillMutexMap.erase(skillId);
1902  return true;
1903  }
1904 
1905  // mutex could not be removed
1908  {skillId}),
1910  "SkillManagerComponentPlugin",
1911  __FUNCTION__,
1912  __LINE__)
1913  .toManagerIce();
1914  }
1915 
1918  {
1919  auto ret = std::make_shared<aron::type::Object>();
1920  const skills::Result<
1921  std::vector<std::experimental::observer_ptr<const skills::FluxioSkill>>,
1923 
1924  if (!res.isSuccess())
1925  {
1926  ARMARX_WARNING << "Failed to get skill list.";
1927  return nullptr;
1928  }
1929 
1930  std::shared_lock l(fluxioDC.typesMutex);
1931  for (const auto& [skillId, skillTypes] : fluxioDC.types)
1932  {
1933  if (skillTypes == nullptr)
1934  {
1935  ARMARX_WARNING << "SkillTypes with id '" << skillId << "' not found.";
1936  continue;
1937  }
1938  ret->addMemberType(skillId, skillTypes);
1939  }
1940  l.unlock();
1941  ret->setObjectName("SkillTypes");
1942  return ret;
1943  }
1944 
1945 } // namespace armarx::plugins
armarx::skills::FluxioSkill
Definition: FluxioSkill.h:25
FluxioCompositeExecutor.h
armarx::skills::SkillExecutionID
Definition: SkillExecutionID.h:15
armarx::skills::FluxioParameter
Definition: FluxioParameter.h:23
armarx::skills::error::FluxioException::toManagerIce
skills::manager::dto::FluxioException toManagerIce() const
Definition: FluxioException.cpp:43
armarx::skills::ProviderID::toString
std::string toString() const
Definition: ProviderID.cpp:56
armarx::core::time::Duration::toMinutes
std::int64_t toMinutes() const
Returns the amount of minutes.
Definition: Duration.cpp:108
armarx::skills::SkillID::toString
std::string toString() const
Definition: SkillID.cpp:68
str
std::string str(const T &t)
Definition: UserAssistedSegmenterGuiWidgetController.cpp:43
armarx::aron::ret
ReaderT::InputType T & ret
Definition: rw.h:13
Exception.h
SkillStatusUpdate.h
armarx::skills::SkillStatusUpdate::FromIce
static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate &update, const std::optional< skills::ProviderID > &providerId=std::nullopt)
Definition: SkillStatusUpdate.cpp:369
armarx::skills::error::ErrorCode::ParameterNotFound
@ ParameterNotFound
armarx::skills::SkillExecutionRequest::skillId
skills::SkillID skillId
Definition: SkillExecutionRequest.h:25
SkillID.h
FluxioSkill.h
armarx::skills::error::FluxioException
A base class for skill exceptions.
Definition: FluxioException.h:24
armarx::skills::SkillID::skillName
std::string skillName
Definition: SkillID.h:41
armarx::skills::error::ErrorCode::UserHasNoMutexError
@ UserHasNoMutexError
armarx::skills::error::createErrorMessage
std::string createErrorMessage(ErrorCode code, const std::vector< std::string > &args)
Definition: FluxioErrorMessages.cpp:25
armarx::core::time::DateTime::Now
static DateTime Now()
Definition: DateTime.cpp:51
armarx::plugins::SkillManagerComponentPlugin::deleteSkillMutex
void deleteSkillMutex(const std::string &skillId, const std::string &userId)
Definition: SkillManagerComponentPlugin.cpp:1488
FluxioValue.h
FluxioResult.h
armarx::plugins::SkillManagerComponentPlugin::getSkillDescription
std::optional< skills::SkillDescription > getSkillDescription(const skills::SkillID &id)
Definition: SkillManagerComponentPlugin.cpp:444
armarx::aron::data::converter::AronNlohmannJSONConverter::ConvertToNlohmannJSON
static nlohmann::json ConvertToNlohmannJSON(const data::VariantPtr &)
Definition: NLohmannJSONConverter.cpp:10
armarx::skills::FluxioParameter::description
std::string description
Definition: FluxioParameter.h:27
DateTime.h
armarx::skills::FluxioTypeIdentificator
Definition: FluxioTypeIdentificator.h:10
armarx::skills::ProviderInfo::providedSkills
std::map< SkillID, SkillDescription > providedSkills
Definition: ProviderInfo.h:16
FluxioProvider.h
armarx::plugins::SkillManagerComponentPlugin::getFluxioSkillExecutionStatus
skills::Result< std::vector< skills::FluxioSkillStatusUpdate >, skills::error::FluxioException > getFluxioSkillExecutionStatus(const std::string &executionId)
Definition: SkillManagerComponentPlugin.cpp:878
armarx::skills::error::FluxioExceptionType::NOT_FOUND
@ NOT_FOUND
armarx::skills::ProviderID::providerName
std::string providerName
Definition: ProviderID.h:28
armarx::plugins::SkillManagerComponentPlugin::getSkillMutex
skills::Result< bool, skills::error::FluxioException > getSkillMutex(const std::string &skillId, const std::string &userId)
Definition: SkillManagerComponentPlugin.cpp:1481
std::experimental::fundamentals_v2::make_observer
observer_ptr< _Tp > make_observer(_Tp *__p) noexcept
Duration.h
armarx::skills::SkillID::providerId
std::optional< ProviderID > providerId
Definition: SkillID.h:40
armarx::plugins::SkillManagerComponentPlugin::getSkillDescriptions
std::map< skills::SkillID, skills::SkillDescription > getSkillDescriptions()
Definition: SkillManagerComponentPlugin.cpp:499
armarx::plugins::SkillManagerComponentPlugin::getProfileList
skills::Result< std::vector< std::experimental::observer_ptr< const skills::FluxioProfile > >, skills::error::FluxioException > getProfileList()
Definition: SkillManagerComponentPlugin.cpp:1497
FluxioProfile.h
ice_conversions.h
armarx::skills::error::ErrorCode::MissingRequired
@ MissingRequired
armarx::plugins::SkillManagerComponentPlugin::abortSkill
bool abortSkill(const skills::SkillExecutionID &id)
Definition: SkillManagerComponentPlugin.cpp:356
armarx::skills::FluxioProfile::name
std::string name
Definition: FluxioProfile.h:17
armarx::plugins::SkillManagerComponentPlugin::executeFluxioSkill
skills::Result< std::experimental::observer_ptr< skills::FluxioExecutor >, skills::error::FluxioException > executeFluxioSkill(const std::string &skillId, const std::string &profileId, const std::string &executorName, armarx::aron::data::DictPtr parameters=nullptr)
Definition: SkillManagerComponentPlugin.cpp:697
armarx::skills::error::FluxioException::create
static FluxioException create(const std::string &message, const FluxioExceptionType &type, const std::string &className, const char *function, int line)
Definition: FluxioException.cpp:31
std::experimental::fundamentals_v2::observer_ptr
Definition: ManagedIceObject.h:53
armarx::plugins::SkillManagerComponentPlugin::deleteSkill
std::optional< std::vector< std::experimental::observer_ptr< const skills::FluxioSkill > > > deleteSkill(const std::string &skillId, const std::string &userId, bool dryRun)
Definition: SkillManagerComponentPlugin.cpp:1163
Dict.h
armarx::skills::error::ErrorCode::ProfileHasNoParent
@ ProfileHasNoParent
armarx::plugins::SkillManagerComponentPlugin::getSkill
skills::Result< std::experimental::observer_ptr< const skills::FluxioSkill >, skills::error::FluxioException > getSkill(const std::string &id)
Definition: SkillManagerComponentPlugin.cpp:1141
armarx::skills::SkillExecutionID::toProviderIce
skills::provider::dto::SkillExecutionID toProviderIce() const
Definition: SkillExecutionID.cpp:21
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
SkillManagerComponentPlugin.h
armarx::skills::error::ErrorCode::SkillNotFound
@ SkillNotFound
NLohmannJSONConverter.h
armarx::plugins::SkillManagerComponentPlugin::executeSkill
skills::SkillStatusUpdate executeSkill(const skills::SkillExecutionRequest &req)
Definition: SkillManagerComponentPlugin.cpp:175
armarx::skills::FluxioParameter::name
std::string name
Definition: FluxioParameter.h:26
armarx::skills::FluxioParameter::typeIdentificator
FluxioTypeIdentificator typeIdentificator
Definition: FluxioParameter.h:28
armarx::skills::SkillExecutionRequest
Definition: SkillExecutionRequest.h:13
armarx::skills::ProviderInfo::providerInterface
provider::dti::SkillProviderInterfacePrx providerInterface
Definition: ProviderInfo.h:15
Object.h
armarx::plugins::SkillManagerComponentPlugin::removeProvider
void removeProvider(const skills::ProviderID &id)
Definition: SkillManagerComponentPlugin.cpp:159
armarx::skills::error::ErrorCode::GenericMutexError
@ GenericMutexError
armarx::skills::FluxioProvider
Definition: FluxioProvider.h:14
armarx::skills::error::FluxioExceptionType::FORBIDDEN
@ FORBIDDEN
armarx::skills::SkillStatusUpdate
Definition: SkillStatusUpdate.h:116
armarx::skills::ProviderID
Definition: ProviderID.h:12
armarx::plugins
This file is part of ArmarX.
Definition: DebugObserverComponentPlugin.cpp:27
FluxioParameter.h
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::skills::error::ErrorCode::ProviderNotFound
@ ProviderNotFound
armarx::skills::FluxioProfile::id
std::string id
Definition: FluxioProfile.h:16
FluxioException.h
armarx::plugins::SkillManagerComponentPlugin::preOnConnectComponent
void preOnConnectComponent() override
Definition: SkillManagerComponentPlugin.cpp:103
armarx::skills::error::ErrorCode::ExecutionNotFound
@ ExecutionNotFound
armarx::skills::FluxioProvider::name
std::string name
Definition: FluxioProvider.h:17
armarx::plugins::SkillManagerComponentPlugin::updateSkillParameters
bool updateSkillParameters(const skills::SkillExecutionID &id, const aron::data::DictPtr &data)
Definition: SkillManagerComponentPlugin.cpp:309
armarx::skills::error::SkillException
A base class for skill exceptions.
Definition: Exception.h:34
armarx::skills::SkillID::FromIce
static SkillID FromIce(const manager::dto::SkillID &)
Definition: SkillID.cpp:36
armarx::plugins::SkillManagerComponentPlugin::deleteSkillParameter
skills::Result< std::vector< std::experimental::observer_ptr< const skills::FluxioSkill > >, skills::error::FluxioException > deleteSkillParameter(const std::string &skillId, const std::string &parameterId, const std::string &userId, bool dryRun)
Definition: SkillManagerComponentPlugin.cpp:1295
armarx::plugins::SkillManagerComponentPlugin::addSkillToProvider
skills::Result< std::experimental::observer_ptr< const skills::FluxioSkill >, skills::error::FluxioException > addSkillToProvider(const std::string &userId, const std::string &providerId, skills::FluxioSkill &&skill)
Definition: SkillManagerComponentPlugin.cpp:1738
FluxioExecutor.h
armarx::plugins::SkillManagerComponentPlugin::getSkillsOfProvider
skills::Result< std::vector< std::experimental::observer_ptr< const skills::FluxioSkill > >, skills::error::FluxioException > getSkillsOfProvider(const std::string &id)
Definition: SkillManagerComponentPlugin.cpp:1697
armarx::plugins::SkillManagerComponentPlugin::updateProfile
void updateProfile(const skills::FluxioProfile &profile)
Definition: SkillManagerComponentPlugin.cpp:1605
armarx::skills::FluxioParameter::isInput
bool isInput
Definition: FluxioParameter.h:31
armarx::skills::FluxioParameter::id
std::string id
Definition: FluxioParameter.h:25
armarx::skills::FluxioTypeIdentificator::skillId
std::string skillId
Definition: FluxioTypeIdentificator.h:13
FluxioSubSkillNode.h
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
armarx::skills::FluxioProfile::description
std::string description
Definition: FluxioProfile.h:18
forward_declarations.h
Component.h
armarx::plugins::SkillManagerComponentPlugin::getSkillExecutionStatus
std::optional< skills::SkillStatusUpdate > getSkillExecutionStatus(const skills::SkillExecutionID &id)
Definition: SkillManagerComponentPlugin.cpp:547
armarx::skills::error::ErrorCode::ProfileNotFound
@ ProfileNotFound
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::plugins::SkillManagerComponentPlugin::getProviderList
skills::Result< std::vector< std::experimental::observer_ptr< const skills::FluxioProvider > >, skills::error::FluxioException > getProviderList()
Definition: SkillManagerComponentPlugin.cpp:1650
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
armarx::skills::error::ErrorCode::SkillDescNotFound
@ SkillDescNotFound
armarx::plugins::SkillManagerComponentPlugin::getProfile
skills::Result< skills::FluxioProfile, skills::error::FluxioException > getProfile(const std::string &id)
Definition: SkillManagerComponentPlugin.cpp:1506
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::skills::FluxioProfile
Definition: FluxioProfile.h:14
armarx::plugins::SkillManagerComponentPlugin::createProfile
skills::Result< skills::FluxioProfile, skills::error::FluxioException > createProfile(const skills::FluxioProfile &profile)
Definition: SkillManagerComponentPlugin.cpp:1527
armarx::skills::FluxioSubSkillNode
Definition: FluxioSubSkillNode.h:17
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::plugins::SkillManagerComponentPlugin::preOnInitComponent
void preOnInitComponent() override
Definition: SkillManagerComponentPlugin.cpp:64
armarx::skills::SkillExecutionID::skillId
SkillID skillId
Definition: SkillExecutionID.h:17
armarx::plugins::SkillManagerComponentPlugin::abortSkillAsync
bool abortSkillAsync(const skills::SkillExecutionID &id)
Definition: SkillManagerComponentPlugin.cpp:401
armarx::skills::SkillExecutionID::FromIce
static SkillExecutionID FromIce(const skills::manager::dto::SkillExecutionID &)
Definition: SkillExecutionID.cpp:31
armarx::core::time::Duration
Represents a duration.
Definition: Duration.h:16
armarx::plugins::SkillManagerComponentPlugin::getProvider
skills::Result< skills::FluxioProvider, skills::error::FluxioException > getProvider(const std::string &id)
Definition: SkillManagerComponentPlugin.cpp:1673
armarx::skills::SkillExecutionRequest::parameters
armarx::aron::data::DictPtr parameters
Definition: SkillExecutionRequest.h:27
armarx::skills::FluxioParameter::required
bool required
Definition: FluxioParameter.h:30
armarx::plugins::SkillManagerComponentPlugin::getTypes
aron::type::ObjectPtr getTypes()
Definition: SkillManagerComponentPlugin.cpp:1917
armarx::plugins::SkillManagerComponentPlugin::addFluxioProvider
skills::Result< std::experimental::observer_ptr< const skills::FluxioProvider >, skills::error::FluxioException > addFluxioProvider(const std::string &name)
Definition: SkillManagerComponentPlugin.cpp:1625
armarx::plugins::SkillManagerComponentPlugin::postCreatePropertyDefinitions
void postCreatePropertyDefinitions(PropertyDefinitionsPtr &properties) override
Definition: SkillManagerComponentPlugin.cpp:110
armarx::skills::SkillExecutionRequest::executorName
std::string executorName
Definition: SkillExecutionRequest.h:26
armarx::skills::FluxioParameter::type
aron::type::VariantPtr type
Definition: FluxioParameter.h:29
armarx::aron::type::ObjectPtr
std::shared_ptr< Object > ObjectPtr
Definition: Object.h:36
armarx::plugins::SkillManagerComponentPlugin::addProvider
void addProvider(const skills::ProviderInfo &info)
Definition: SkillManagerComponentPlugin.cpp:133
Logging.h
armarx::skills::ProviderInfo
Definition: ProviderInfo.h:11
armarx::plugins::SkillManagerComponentPlugin::executeSkillAsync
skills::SkillExecutionID executeSkillAsync(const skills::SkillExecutionRequest &req)
Definition: SkillManagerComponentPlugin.cpp:241
FluxioTypeIdentificator.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::plugins::SkillManagerComponentPlugin::updateSkillParameter
skills::Result< std::vector< std::experimental::observer_ptr< const skills::FluxioSkill > >, skills::error::FluxioException > updateSkillParameter(const std::string &skillId, const skills::manager::dto::FluxioParameter &parameter, const std::string &userId, bool dryRun)
Definition: SkillManagerComponentPlugin.cpp:1305
armarx::plugins::SkillManagerComponentPlugin::getSkillList
skills::Result< std::vector< std::experimental::observer_ptr< const skills::FluxioSkill > >, skills::error::FluxioException > getSkillList()
Definition: SkillManagerComponentPlugin.cpp:1134
armarx::skills::SkillDescription::FromIce
static SkillDescription FromIce(const provider::dto::SkillDescription &i, const std::optional< ProviderID > &=std::nullopt)
Definition: SkillDescription.cpp:39
armarx::skills::FluxioNodeType::SUBSKILL
@ SUBSKILL
armarx::skills::SkillID
Definition: SkillID.h:14
armarx::skills::SkillID::isFullySpecified
bool isFullySpecified() const
Definition: SkillID.cpp:78
armarx::skills::ProviderInfo::providerId
ProviderID providerId
Definition: ProviderInfo.h:14
armarx::plugins::SkillManagerComponentPlugin::getFirstProviderNameThatHasSkill
skills::ProviderID getFirstProviderNameThatHasSkill(const skills::SkillID &skillid)
Definition: SkillManagerComponentPlugin.cpp:115
FluxioMergerExecutor.h
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
FluxioNativeExecutor.h
armarx::core::time::DateTime::toDateTimeString
std::string toDateTimeString() const
Definition: DateTime.cpp:75
armarx::skills::Result
Definition: FluxioResult.h:12
FluxioNode.h
armarx::skills::FluxioProfile::parentPtr
std::experimental::observer_ptr< const FluxioProfile > parentPtr
Definition: FluxioProfile.h:19
armarx::skills::error::FluxioExceptionType::BAD_REQUEST
@ BAD_REQUEST
SkillDescription.h
FluxioErrorMessages.h
armarx::plugins::SkillManagerComponentPlugin::abortFluxioSkill
void abortFluxioSkill(const std::string &executionId)
Definition: SkillManagerComponentPlugin.cpp:854
armarx::skills::error::ErrorCode::ProfileAlreadyExists
@ ProfileAlreadyExists
armarx::skills::FluxioProvider::id
std::string id
Definition: FluxioProvider.h:16
armarx::plugins::SkillManagerComponentPlugin::getSkillExecutionStatuses
std::map< skills::SkillExecutionID, skills::SkillStatusUpdate > getSkillExecutionStatuses()
Definition: SkillManagerComponentPlugin.cpp:605