#include #include #include #include #include #include #include #include #include #include #include #include #include namespace smo { namespace device { std::vector> DeviceManager::interoceptorDeviceSpecs; std::vector> DeviceManager::extrospectorDeviceSpecs; std::vector> DeviceManager::deviceAttachmentSpecs; std::vector> DeviceManager::devices; const std::string DeviceManager::stringifyDeviceSpecs(void) { std::ostringstream oss; for (const auto& spec : DeviceManager::interoceptorDeviceSpecs) { oss << "Interoceptor " << spec->stringify(); } for (const auto& spec : DeviceManager::extrospectorDeviceSpecs) { oss << "Extrospector " << spec->stringify(); } return oss.str(); } class DeviceManager::NewDeviceAttachmentSpecInd : public PostedAsynchronousContinuation { public: NewDeviceAttachmentSpecInd( std::shared_ptr s, const std::shared_ptr &caller, Callback cb) : PostedAsynchronousContinuation( caller, cb), spec(s) {} public: std::shared_ptr spec; public: void newDeviceAttachmentSpecInd1_posted( [[maybe_unused]] std::shared_ptr context ) { sense_api::SenseApiManager::getInstance().attachSenseDeviceReq( spec, {context, std::bind( &NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2, context.get(), context, std::placeholders::_1, std::placeholders::_2)}); } void newDeviceAttachmentSpecInd2( [[maybe_unused]] std::shared_ptr context, bool success, std::shared_ptr deviceSpec ) { if (!success) { std::cerr << __func__ << ": Attach failed for device spec " << deviceSpec->stringify() << std::endl; callOriginalCb(false, nullptr, deviceSpec); return; } try { /** EXPLANATION: * Remember that deviceAttachmentSpecs don't refer to devices, but * rather to roles that a device can enact when attached to in the * described manner. Therefore, it's possible for multiple DA specs * to refer to the same device. * * That's why we need to ensure that the device doesn't already * exist before trying to create a new device for it. */ std::shared_ptr device = nullptr; for (const auto& existingDevice : devices) { if (existingDevice->deviceIdentifier != spec->deviceIdentifier) { continue; } device = existingDevice; break; } // If device doesn't exist, create a new one and add it if (!device) { device = std::make_shared(spec->deviceIdentifier); devices.push_back(device); } // Add DeviceAttachmentSpec to device's list device->deviceAttachmentSpecs.push_back(spec); // Add DeviceAttachmentSpec to DeviceManager's list deviceAttachmentSpecs.push_back(spec); // Callback with success callOriginalCb(true, device, spec); } catch (const std::exception& e) { // Attach failed, callback with error callOriginalCb(false, nullptr, spec); } } }; void DeviceManager::newDeviceAttachmentSpecInd( std::shared_ptr spec, Callback callback) { // Check if a DeviceAttachmentSpec already matches for (const auto& existingSpec : deviceAttachmentSpecs) { if (!(*existingSpec == *spec)) { continue; } // Already exists, callback with error callback.callbackFn(false, nullptr, spec); return; } // Create async continuation const auto& caller = ComponentThread::getSelf(); auto continuation = std::make_shared( spec, caller, callback); mrntt::mrntt.thread->getIoService().post( std::bind( &NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd1_posted, continuation.get(), continuation)); } } // namespace device } // namespace smo