2025-09-14 22:17:19 -04:00
|
|
|
#include <iostream>
|
|
|
|
|
#include <opts.h>
|
|
|
|
|
#include <asynchronousContinuation.h>
|
|
|
|
|
#include <asynchronousLoop.h>
|
2025-09-27 18:30:09 -04:00
|
|
|
#include <callback.h>
|
2025-09-14 22:17:19 -04:00
|
|
|
#include <body/body.h>
|
|
|
|
|
#include <componentThread.h>
|
|
|
|
|
#include <mind.h>
|
|
|
|
|
#include <senseApis/senseApiManager.h>
|
2025-09-27 23:16:46 -04:00
|
|
|
#include <deviceManager/deviceManager.h>
|
2025-09-14 22:17:19 -04:00
|
|
|
|
|
|
|
|
namespace smo {
|
|
|
|
|
namespace body {
|
|
|
|
|
|
|
|
|
|
Body::Body(Mind &parent, const std::shared_ptr<ComponentThread> &thread)
|
|
|
|
|
: MindComponent(parent, thread)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Body::InitializeReq
|
2025-09-17 16:32:20 -04:00
|
|
|
: public PostedAsynchronousContinuation<bodyLifetimeMgmtOpCbFn>
|
2025-09-14 22:17:19 -04:00
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
InitializeReq(
|
|
|
|
|
Mind &parent, const std::shared_ptr<ComponentThread> &caller,
|
2025-09-27 18:30:09 -04:00
|
|
|
Callback<bodyLifetimeMgmtOpCbFn> callback)
|
2025-09-17 16:32:20 -04:00
|
|
|
: PostedAsynchronousContinuation<bodyLifetimeMgmtOpCbFn>(caller, callback),
|
2025-09-14 22:17:19 -04:00
|
|
|
parent(parent)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Mind &parent;
|
|
|
|
|
|
|
|
|
|
public:
|
2025-09-15 08:33:49 -04:00
|
|
|
void initializeReq1_posted(
|
2025-09-14 22:17:19 -04:00
|
|
|
[[maybe_unused]] std::shared_ptr<InitializeReq> context
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
auto self = ComponentThread::getSelf();
|
|
|
|
|
if (self->id != ComponentThread::BODY)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error(std::string(__func__)
|
|
|
|
|
+ ": Must be executed on Body thread");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** EXPLANATION:
|
|
|
|
|
* The ComponentThread instance we pass in here is the one that will be
|
|
|
|
|
* used by Senseapi libs to perform device-independent background
|
|
|
|
|
* operations.
|
|
|
|
|
* For example, liblivoxProto1's BroadcastListener will use this thread
|
|
|
|
|
* to listen for UDP broadcast dgrams from Livox devices.
|
|
|
|
|
*
|
|
|
|
|
* Right now we use Marionette, but there's a strong argument for using
|
|
|
|
|
* Body instead since it's meant to handle device-management operations.
|
|
|
|
|
*/
|
|
|
|
|
sense_api::SenseApiManager::getInstance()
|
|
|
|
|
.loadAllSenseApiLibsFromOptions(caller);
|
|
|
|
|
|
2025-09-15 08:30:17 -04:00
|
|
|
/** EXPLANATION:
|
|
|
|
|
* Consider body::initializeReq to have been called if even one of its
|
|
|
|
|
* operations was executed at all, whether successfully or
|
|
|
|
|
* unsuccessfully.
|
|
|
|
|
*/
|
|
|
|
|
context->parent.bodyComponentInitialized = true;
|
|
|
|
|
|
2025-09-14 22:17:19 -04:00
|
|
|
std::cout << sense_api::SenseApiManager::getInstance().stringifyLibs()
|
|
|
|
|
<< std::endl;
|
|
|
|
|
|
|
|
|
|
if (OptionParser::getOptions().verbose)
|
|
|
|
|
{
|
|
|
|
|
std::cout << __func__ << ": About to initializeAllSenseApiLibs"
|
|
|
|
|
<< '\n';
|
|
|
|
|
}
|
|
|
|
|
sense_api::SenseApiManager::getInstance().initializeAllSenseApiLibs();
|
|
|
|
|
|
|
|
|
|
if (OptionParser::getOptions().verbose)
|
|
|
|
|
{
|
|
|
|
|
std::cout << __func__ << ": About to attachAllSenseDevicesFromSpecs"
|
|
|
|
|
<< '\n';
|
|
|
|
|
}
|
2025-09-28 12:52:59 -04:00
|
|
|
device::DeviceManager::getInstance()
|
|
|
|
|
.attachAllUnattachedDevicesFromCmdlineReq(
|
2025-09-27 18:30:09 -04:00
|
|
|
{context, std::bind(
|
2025-09-14 22:17:19 -04:00
|
|
|
&InitializeReq::initializeReq2,
|
|
|
|
|
context.get(), context,
|
2025-09-27 18:30:09 -04:00
|
|
|
std::placeholders::_1)});
|
2025-09-14 22:17:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void initializeReq2(
|
|
|
|
|
[[maybe_unused]] std::shared_ptr<InitializeReq> context,
|
|
|
|
|
smo::AsynchronousLoop &results
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
std::cout << "Mrntt: attached "
|
|
|
|
|
<< results.nSucceeded << " of " << results.nTotal
|
|
|
|
|
<< " sense devices." << "\n";
|
|
|
|
|
|
2025-09-17 16:32:20 -04:00
|
|
|
callOriginalCb(results.nSucceeded > 0);
|
2025-09-14 22:17:19 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Body::FinalizeReq
|
|
|
|
|
: public InitializeReq
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using InitializeReq::InitializeReq;
|
|
|
|
|
|
|
|
|
|
public:
|
2025-09-15 08:33:49 -04:00
|
|
|
void finalizeReq1_posted(
|
2025-09-14 22:17:19 -04:00
|
|
|
[[maybe_unused]] std::shared_ptr<FinalizeReq> context
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
auto self = ComponentThread::getSelf();
|
|
|
|
|
if (self->id != ComponentThread::BODY)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error(std::string(__func__)
|
|
|
|
|
+ ": Must be executed on Body thread");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::cout << "Mrntt: About to detach all sense devices." << "\n";
|
2025-09-28 12:19:56 -04:00
|
|
|
device::DeviceManager::getInstance().detachAllAttachedDeviceRoles(
|
2025-09-27 18:30:09 -04:00
|
|
|
{context, std::bind(
|
2025-09-14 22:17:19 -04:00
|
|
|
&FinalizeReq::finalizeReq2,
|
|
|
|
|
context.get(), context,
|
2025-09-27 18:30:09 -04:00
|
|
|
std::placeholders::_1)});
|
2025-09-14 22:17:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void finalizeReq2(
|
|
|
|
|
[[maybe_unused]] std::shared_ptr<FinalizeReq> context,
|
|
|
|
|
smo::AsynchronousLoop &results
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
std::cout << "Mrntt: Successfully detached "
|
|
|
|
|
<< results.nSucceeded << " of " << results.nTotal
|
|
|
|
|
<< " sense devices." << "\n";
|
|
|
|
|
|
2025-09-16 15:09:56 -04:00
|
|
|
std::cout << "Mrntt: About to finalize all sense api libs." << "\n";
|
|
|
|
|
sense_api::SenseApiManager::getInstance().finalizeAllSenseApiLibs();
|
|
|
|
|
|
2025-09-14 22:17:19 -04:00
|
|
|
std::cout << "Mrntt: About to unload all sense api libs." << "\n";
|
|
|
|
|
sense_api::SenseApiManager::getInstance().unloadAllSenseApiLibs();
|
2025-09-17 16:32:20 -04:00
|
|
|
callOriginalCb(results.nSucceeded == results.nTotal);
|
2025-09-14 22:17:19 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-27 18:30:09 -04:00
|
|
|
void Body::initializeReq(Callback<bodyLifetimeMgmtOpCbFn> callback)
|
2025-09-14 22:17:19 -04:00
|
|
|
{
|
|
|
|
|
auto mrntt = ComponentThread::getSelf();
|
|
|
|
|
|
|
|
|
|
if (mrntt->id != ComponentThread::MRNTT)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error(std::string(__func__)
|
|
|
|
|
+ ": Must be invoked by Mrntt thread");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto request = std::make_shared<InitializeReq>(
|
|
|
|
|
parent, mrntt, callback);
|
|
|
|
|
|
|
|
|
|
thread->getIoService().post(
|
|
|
|
|
std::bind(
|
2025-09-15 08:33:49 -04:00
|
|
|
&InitializeReq::initializeReq1_posted,
|
2025-09-14 22:17:19 -04:00
|
|
|
request.get(), request));
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-27 18:30:09 -04:00
|
|
|
void Body::finalizeReq(Callback<bodyLifetimeMgmtOpCbFn> callback)
|
2025-09-14 22:17:19 -04:00
|
|
|
{
|
|
|
|
|
auto mrntt = ComponentThread::getSelf();
|
|
|
|
|
|
|
|
|
|
if (mrntt->id != ComponentThread::MRNTT)
|
|
|
|
|
{
|
2025-09-16 15:10:28 -04:00
|
|
|
std::cerr << __func__ << ": Must be invoked by Mrntt thread"
|
|
|
|
|
<< std::endl;
|
2025-09-27 18:30:09 -04:00
|
|
|
callback.callbackFn(false);
|
2025-09-16 15:10:28 -04:00
|
|
|
return;
|
2025-09-14 22:17:19 -04:00
|
|
|
}
|
|
|
|
|
|
2025-09-15 08:30:17 -04:00
|
|
|
if (!parent.bodyComponentInitialized)
|
|
|
|
|
{
|
|
|
|
|
std::cout << "Mrntt: Body component not initialized. "
|
|
|
|
|
<< "Skipping finalization." << "\n";
|
2025-09-27 18:30:09 -04:00
|
|
|
callback.callbackFn(true);
|
2025-09-15 08:30:17 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-14 22:17:19 -04:00
|
|
|
auto request = std::make_shared<FinalizeReq>(
|
|
|
|
|
parent, mrntt, callback);
|
|
|
|
|
|
|
|
|
|
thread->getIoService().post(
|
|
|
|
|
std::bind(
|
2025-09-15 08:33:49 -04:00
|
|
|
&FinalizeReq::finalizeReq1_posted,
|
2025-09-14 22:17:19 -04:00
|
|
|
request.get(), request));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace body
|
|
|
|
|
} // namespace smo
|