LivoxProto1: port to sscl::co framework
Code now actually looks a lot cleaner, tbh.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
- Aggressively isolate, split off, deduplicate and reuse code which can be made into common library code. Do the same with UI elements. Do this both when implementing new features and opportunistically while refactoring or changing old code/UI elements.
|
||||
- Names of files, functions, classes, abstractions, database fields, etc should be aimed at disambiguating purpose and function, rather than at brevity.
|
||||
- Any source or header file that includes a Boost header must include `<boostAsioLinkageFix.h>` first (at the top of the file, or immediately after the include guard in headers), before all other includes, so Boost.Asio is used as a non-header-only library correctly.
|
||||
- When refactoring code, moving code around or splitting code into new files, don't omit or remove source code comments. Preserve source code comments across refactors.
|
||||
|
||||
## Style:
|
||||
|
||||
@@ -18,7 +19,8 @@
|
||||
* UpperCamelCase for class/struct names, lowerCamelCase for var and member var
|
||||
names; underscores_between_words for namespace names. No hungarian notation.
|
||||
* Differentiate overshadowing local arg var names from class member var names
|
||||
by prefixing local arg var names with underscore (_).
|
||||
by prefixing local arg var names with underscore (_). Don't do things like
|
||||
postfixing the local arg var name with "In", etc.
|
||||
* Single-line blocks after a selection/iteration statement must always be
|
||||
enclosed in braces, but you can choose whether opening brace is on same line,
|
||||
versus whether you put both braces on same line. I.e:
|
||||
|
||||
@@ -17,10 +17,17 @@ if(ENABLE_LIB_livoxProto1)
|
||||
|
||||
# Set config define for header generation
|
||||
add_compile_definitions(CONFIG_LIB_LIVOXPROTO1_ENABLED)
|
||||
target_include_directories(livoxProto1 PUBLIC ${Boost_INCLUDE_DIRS})
|
||||
target_include_directories(livoxProto1 PUBLIC
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/smocore/include
|
||||
${CMAKE_SOURCE_DIR}/commonLibs
|
||||
)
|
||||
target_link_libraries(livoxProto1 PUBLIC
|
||||
Boost::system Boost::log
|
||||
attachmentSupport)
|
||||
attachmentSupport
|
||||
spinscale
|
||||
)
|
||||
|
||||
# Verify Boost dynamic dependencies after build
|
||||
add_custom_command(TARGET livoxProto1 POST_BUILD
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <boostAsioLinkageFix.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
+41
-125
@@ -1,10 +1,10 @@
|
||||
#include <boostAsioLinkageFix.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <opts.h>
|
||||
#include <spinscale/cps/asynchronousContinuation.h>
|
||||
#include <spinscale/cps/callback.h>
|
||||
#include <user/senseApiDesc.h>
|
||||
#include "protocol.h"
|
||||
#include "core.h"
|
||||
@@ -72,68 +72,16 @@ std::optional<std::shared_ptr<Device>> DeviceManager::getDevice(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// GetOrCreateDeviceReq nested class implementation
|
||||
class DeviceManager::GetOrCreateDeviceReq
|
||||
: public sscl::cps::NonPostedAsynchronousContinuation<
|
||||
livoxProto1_getOrCreateDeviceReqCbFn>
|
||||
{
|
||||
public:
|
||||
DeviceManager& deviceManager;
|
||||
// The device we're trying to connect (holds all connection parameters)
|
||||
std::shared_ptr<Device> pendingDevice;
|
||||
|
||||
public:
|
||||
GetOrCreateDeviceReq(
|
||||
DeviceManager& mgr,
|
||||
std::shared_ptr<Device> device,
|
||||
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> cb)
|
||||
: sscl::cps::NonPostedAsynchronousContinuation<
|
||||
livoxProto1_getOrCreateDeviceReqCbFn>(std::move(cb)),
|
||||
deviceManager(mgr), pendingDevice(device)
|
||||
{}
|
||||
|
||||
// Public accessor for the original callback
|
||||
void callOriginalCallback(bool success, std::shared_ptr<Device> device)
|
||||
{ callOriginalCb(success, device); }
|
||||
|
||||
void callOriginalCallbackWithFailure()
|
||||
{ callOriginalCallback(false, nullptr); }
|
||||
|
||||
void getOrCreateDeviceReq1(
|
||||
std::shared_ptr<GetOrCreateDeviceReq> context, bool connectSuccess
|
||||
)
|
||||
{
|
||||
if (!connectSuccess)
|
||||
{
|
||||
std::cerr << __func__ << ": Connection failed for device "
|
||||
<< context->pendingDevice->discoveredDevice.deviceIdentifier
|
||||
<< std::endl;
|
||||
context->callOriginalCallbackWithFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
// Connection successful, add device to collection
|
||||
context->deviceManager.devices.push_back(context->pendingDevice);
|
||||
if (getProtoState().smoCallbacks.OptionParser_getOptions().verbose)
|
||||
{
|
||||
std::cout << __func__ << ": Successfully connected and added device "
|
||||
<< context->pendingDevice->discoveredDevice.deviceIdentifier
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// Return success with the connected device
|
||||
context->callOriginalCallback(true, context->pendingDevice);
|
||||
}
|
||||
};
|
||||
|
||||
void DeviceManager::getOrCreateDeviceReq(
|
||||
sscl::co::ViralNonPostingInvoker<LivoxProto1GetOrCreateDeviceResult>
|
||||
DeviceManager::getOrCreateDeviceCReq(
|
||||
const std::string &deviceIdentifier,
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread,
|
||||
int commandTimeoutMs, int retryDelayMs,
|
||||
const std::string& smoIp, uint8_t smoSubnetNbits,
|
||||
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
|
||||
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback)
|
||||
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort)
|
||||
{
|
||||
LivoxProto1GetOrCreateDeviceResult result;
|
||||
|
||||
// Validate smoIp format using Boost.Asio IPv4 validation
|
||||
if (!smoIp.empty() && !comms::isValidIPv4(smoIp))
|
||||
{
|
||||
@@ -155,9 +103,9 @@ void DeviceManager::getOrCreateDeviceReq(
|
||||
auto existingDevice = getDevice(deviceIdentifier);
|
||||
if (existingDevice)
|
||||
{
|
||||
// Device already exists and is connected, return it
|
||||
callback.callbackFn(true, existingDevice.value());
|
||||
return;
|
||||
result.success = true;
|
||||
result.device = existingDevice.value();
|
||||
co_return result;
|
||||
}
|
||||
|
||||
// Device doesn't exist, create a new one but don't add it to collection yet
|
||||
@@ -167,82 +115,50 @@ void DeviceManager::getOrCreateDeviceReq(
|
||||
smoIp, smoSubnetNbits,
|
||||
dataPort, cmdPort, imuPort);
|
||||
|
||||
// Create the continuation request object to hold state and callbacks
|
||||
auto request = std::make_shared<GetOrCreateDeviceReq>(
|
||||
*this, newDevice, std::move(callback));
|
||||
|
||||
// Start the connection process - only add to collection on success
|
||||
request->pendingDevice->connectReq(
|
||||
{request, std::bind(
|
||||
&DeviceManager::GetOrCreateDeviceReq::getOrCreateDeviceReq1,
|
||||
request.get(), request, std::placeholders::_1)});
|
||||
const bool connectSuccess = co_await newDevice->connectCReq();
|
||||
if (!connectSuccess)
|
||||
{
|
||||
std::cerr << __func__ << ": Connection failed for device "
|
||||
<< newDevice->discoveredDevice.deviceIdentifier
|
||||
<< std::endl;
|
||||
co_return result;
|
||||
}
|
||||
|
||||
devices.push_back(newDevice);
|
||||
if (getProtoState().smoCallbacks.OptionParser_getOptions().verbose)
|
||||
{
|
||||
std::cout << __func__ << ": Successfully connected and added device "
|
||||
<< newDevice->discoveredDevice.deviceIdentifier
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
result.success = true;
|
||||
result.device = newDevice;
|
||||
co_return result;
|
||||
}
|
||||
|
||||
class DeviceManager::DestroyDeviceReq
|
||||
: public sscl::cps::NonPostedAsynchronousContinuation<
|
||||
livoxProto1_destroyDeviceReqCbFn>
|
||||
{
|
||||
public:
|
||||
DeviceManager& deviceManager;
|
||||
std::shared_ptr<Device> pendingDevice;
|
||||
|
||||
public:
|
||||
DestroyDeviceReq(
|
||||
DeviceManager& mgr,
|
||||
std::shared_ptr<Device> device,
|
||||
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> cb)
|
||||
: sscl::cps::NonPostedAsynchronousContinuation<
|
||||
livoxProto1_destroyDeviceReqCbFn>(std::move(cb)),
|
||||
deviceManager(mgr), pendingDevice(device)
|
||||
{}
|
||||
|
||||
// Public accessor for the original callback
|
||||
void callOriginalCallback(bool success)
|
||||
{ callOriginalCb(success); }
|
||||
|
||||
void callOriginalCallbackWithFailure()
|
||||
{ callOriginalCallback(false); }
|
||||
|
||||
void destroyDeviceReq1(
|
||||
std::shared_ptr<DestroyDeviceReq> context, bool success
|
||||
)
|
||||
{
|
||||
context->deviceManager.devices.erase(
|
||||
std::remove(
|
||||
context->deviceManager.devices.begin(),
|
||||
context->deviceManager.devices.end(),
|
||||
context->pendingDevice),
|
||||
context->deviceManager.devices.end());
|
||||
|
||||
context->callOriginalCallback(success);
|
||||
}
|
||||
};
|
||||
|
||||
void DeviceManager::destroyDeviceReq(
|
||||
std::shared_ptr<Device> dev,
|
||||
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> callback
|
||||
)
|
||||
sscl::co::ViralNonPostingInvoker<bool> DeviceManager::destroyDeviceCReq(
|
||||
std::shared_ptr<Device> dev)
|
||||
{
|
||||
/** EXPLANATION:
|
||||
* Check to see if the device is in our collection. If so, call
|
||||
* disconnectReq and then remove it.
|
||||
* disconnectCReq and then remove it.
|
||||
*/
|
||||
std::shared_ptr<Device> device = getDevice(dev->discoveredDevice).
|
||||
value_or(nullptr);
|
||||
|
||||
if (!device || device->nAttachedStimulusProducers > 0)
|
||||
{
|
||||
callback.callbackFn(false);
|
||||
return;
|
||||
if (!device || device->nAttachedStimulusProducers > 0) {
|
||||
co_return false;
|
||||
}
|
||||
|
||||
auto request = std::make_shared<DestroyDeviceReq>(
|
||||
*this, device, std::move(callback));
|
||||
const bool success = co_await device->disconnectCReq();
|
||||
|
||||
device->disconnectReq(
|
||||
{request, std::bind(
|
||||
&DeviceManager::DestroyDeviceReq::destroyDeviceReq1,
|
||||
request.get(), request, std::placeholders::_1)});
|
||||
devices.erase(
|
||||
std::remove(devices.begin(), devices.end(), device),
|
||||
devices.end());
|
||||
|
||||
co_return success;
|
||||
}
|
||||
|
||||
void main(const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "broadcastListener.h"
|
||||
#include "udpCommandDemuxer.h"
|
||||
#include "livoxProto1.h"
|
||||
#include <spinscale/cps/callback.h>
|
||||
#include <spinscale/co/invokers.h>
|
||||
|
||||
namespace livoxProto1 {
|
||||
|
||||
@@ -23,17 +23,16 @@ public:
|
||||
|
||||
static void deviceGoneAwayInd(const comms::DiscoveredDevice &device);
|
||||
|
||||
void getOrCreateDeviceReq(
|
||||
sscl::co::ViralNonPostingInvoker<LivoxProto1GetOrCreateDeviceResult>
|
||||
getOrCreateDeviceCReq(
|
||||
const std::string &deviceIdentifier,
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread,
|
||||
int commandTimeoutMs, int retryDelayMs,
|
||||
const std::string& smoIp, uint8_t smoSubnetNbits,
|
||||
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
|
||||
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback);
|
||||
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort);
|
||||
|
||||
void destroyDeviceReq(
|
||||
std::shared_ptr<Device> device,
|
||||
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> callback);
|
||||
sscl::co::ViralNonPostingInvoker<bool> destroyDeviceCReq(
|
||||
std::shared_ptr<Device> device);
|
||||
|
||||
std::optional<std::shared_ptr<Device>> getDevice(
|
||||
const std::string &deviceIdentifier);
|
||||
@@ -52,10 +51,6 @@ public:
|
||||
std::vector<std::shared_ptr<Device>> devices;
|
||||
comms::BroadcastListener broadcastListener;
|
||||
comms::UdpCommandDemuxer udpCommandDemuxer;
|
||||
|
||||
// Nested continuation class for async device creation
|
||||
class GetOrCreateDeviceReq;
|
||||
class DestroyDeviceReq;
|
||||
};
|
||||
|
||||
void main(
|
||||
|
||||
+670
-1575
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/posix/stream_descriptor.hpp>
|
||||
#include "protocol.h"
|
||||
#include <spinscale/cps/callback.h>
|
||||
#include <spinscale/co/invokers.h>
|
||||
#include <spinscale/spinLock.h>
|
||||
|
||||
// Custom hash function for std::pair<uint8_t, uint8_t>
|
||||
@@ -96,16 +96,6 @@ private:
|
||||
std::optional<std::string> detectSmoIp(const std::string& deviceIP);
|
||||
uint32_t getSubnetMaskFor(uint8_t nbits);
|
||||
|
||||
class ConnectReq;
|
||||
class ConnectToKnownDeviceReq;
|
||||
class ConnectByDeviceIdentifierReq;
|
||||
class ExecuteHandshakeReq;
|
||||
class DisconnectReq;
|
||||
class EnablePcloudDataReq;
|
||||
class DisablePcloudDataReq;
|
||||
class SetReturnModeReq;
|
||||
class GetReturnModeReq;
|
||||
|
||||
public:
|
||||
enum class ReturnMode : uint8_t
|
||||
{
|
||||
@@ -146,37 +136,30 @@ public:
|
||||
// Utility methods
|
||||
std::optional<std::string> getSmoIp(const std::string& deviceIP);
|
||||
|
||||
// Callback function type definitions for async methods
|
||||
typedef std::function<void(bool success)> connectReqCbFn;
|
||||
typedef std::function<
|
||||
void(bool success, const std::string& ipAddr)>
|
||||
connectToKnownDeviceReqCbFn;
|
||||
typedef std::function<
|
||||
void(bool success, const std::string& ipAddr)>
|
||||
connectByDeviceIdentifierReqCbFn;
|
||||
typedef std::function<void(bool success)> executeHandshakeReqCbFn;
|
||||
typedef std::function<void(bool success)> disconnectReqCbFn;
|
||||
typedef std::function<void(bool success)> enablePcloudDataReqCbFn;
|
||||
typedef std::function<void(bool success)> disablePcloudDataReqCbFn;
|
||||
typedef std::function<void(bool success)> setReturnModeReqCbFn;
|
||||
typedef std::function<void(bool success, uint8_t returnMode)>
|
||||
getReturnModeReqCbFn;
|
||||
struct ConnectIpResult
|
||||
{
|
||||
bool success = false;
|
||||
std::string ipAddr;
|
||||
};
|
||||
|
||||
// Async connection methods
|
||||
void connectReq(sscl::cps::Callback<connectReqCbFn> callback);
|
||||
void connectToKnownDeviceReq(
|
||||
sscl::cps::Callback<connectToKnownDeviceReqCbFn> callback);
|
||||
void connectByDeviceIdentifierReq(
|
||||
sscl::cps::Callback<connectByDeviceIdentifierReqCbFn> callback);
|
||||
void executeHandshakeReq(
|
||||
const std::string& deviceIP,
|
||||
sscl::cps::Callback<executeHandshakeReqCbFn> callback);
|
||||
void disconnectReq(sscl::cps::Callback<disconnectReqCbFn> callback);
|
||||
void enablePcloudDataReq(sscl::cps::Callback<enablePcloudDataReqCbFn> callback);
|
||||
void disablePcloudDataReq(sscl::cps::Callback<disablePcloudDataReqCbFn> callback);
|
||||
void setReturnModeReq(
|
||||
uint8_t returnMode, sscl::cps::Callback<setReturnModeReqCbFn> callback);
|
||||
void getReturnModeReq(sscl::cps::Callback<getReturnModeReqCbFn> callback);
|
||||
sscl::co::ViralNonPostingInvoker<bool> connectCReq();
|
||||
sscl::co::ViralNonPostingInvoker<ConnectIpResult> connectToKnownDeviceCReq();
|
||||
sscl::co::ViralNonPostingInvoker<ConnectIpResult> connectByDeviceIdentifierCReq();
|
||||
sscl::co::ViralNonPostingInvoker<bool> executeHandshakeCReq(
|
||||
const std::string& deviceIP);
|
||||
sscl::co::ViralNonPostingInvoker<bool> disconnectCReq();
|
||||
sscl::co::ViralNonPostingInvoker<bool> enablePcloudDataCReq();
|
||||
sscl::co::ViralNonPostingInvoker<bool> disablePcloudDataCReq();
|
||||
|
||||
struct GetReturnModeResult
|
||||
{
|
||||
bool success = false;
|
||||
uint8_t returnMode = 0;
|
||||
};
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<bool> setReturnModeCReq(uint8_t returnMode);
|
||||
sscl::co::ViralNonPostingInvoker<GetReturnModeResult> getReturnModeCReq();
|
||||
|
||||
public:
|
||||
comms::DiscoveredDevice discoveredDevice;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <boostAsioLinkageFix.h>
|
||||
#include <stdexcept>
|
||||
#include <spinscale/cps/callback.h>
|
||||
#include <boost/asio/posix/stream_descriptor.hpp>
|
||||
#include "livoxProto1.h"
|
||||
#include "device.h"
|
||||
@@ -10,14 +9,13 @@
|
||||
|
||||
extern "C" {
|
||||
|
||||
void livoxProto1_getOrCreateDeviceReq(
|
||||
sscl::co::ViralNonPostingInvoker<LivoxProto1GetOrCreateDeviceResult>
|
||||
livoxProto1_getOrCreateDeviceCReq(
|
||||
const std::string& deviceIdentifier,
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread,
|
||||
int commandTimeoutMs, int retryDelayMs,
|
||||
const std::string& smoIp, uint8_t smoSubnetNbits,
|
||||
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
|
||||
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback
|
||||
)
|
||||
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort)
|
||||
{
|
||||
// Get the global DeviceManager instance
|
||||
auto& protoState = livoxProto1::getProtoState();
|
||||
@@ -28,19 +26,16 @@ void livoxProto1_getOrCreateDeviceReq(
|
||||
"livoxProto1_main first");
|
||||
}
|
||||
|
||||
// Delegate to DeviceManager
|
||||
protoState.deviceManager->getOrCreateDeviceReq(
|
||||
// Delegate to the DeviceManager to create the device
|
||||
co_return co_await protoState.deviceManager->getOrCreateDeviceCReq(
|
||||
deviceIdentifier, componentThread,
|
||||
commandTimeoutMs, retryDelayMs,
|
||||
smoIp, smoSubnetNbits,
|
||||
dataPort, cmdPort, imuPort,
|
||||
callback);
|
||||
dataPort, cmdPort, imuPort);
|
||||
}
|
||||
|
||||
void livoxProto1_destroyDeviceReq(
|
||||
std::shared_ptr<livoxProto1::Device> device,
|
||||
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> callback
|
||||
)
|
||||
sscl::co::ViralNonPostingInvoker<bool> livoxProto1_destroyDeviceCReq(
|
||||
std::shared_ptr<livoxProto1::Device> device)
|
||||
{
|
||||
auto& protoState = livoxProto1::getProtoState();
|
||||
if (!protoState.deviceManager)
|
||||
@@ -49,8 +44,7 @@ void livoxProto1_destroyDeviceReq(
|
||||
+ ": DeviceManager not initialized");
|
||||
}
|
||||
|
||||
protoState.deviceManager->destroyDeviceReq(
|
||||
device, callback);
|
||||
co_return co_await protoState.deviceManager->destroyDeviceCReq(device);
|
||||
}
|
||||
|
||||
void livoxProto1_main(
|
||||
@@ -65,10 +59,8 @@ void livoxProto1_exit(void)
|
||||
livoxProto1::exit();
|
||||
}
|
||||
|
||||
void livoxProto1_device_enablePcloudDataReq(
|
||||
std::shared_ptr<livoxProto1::Device> device,
|
||||
sscl::cps::Callback<livoxProto1_device_enablePcloudDataReqCbFn> callback
|
||||
)
|
||||
sscl::co::ViralNonPostingInvoker<bool> livoxProto1_device_enablePcloudDataCReq(
|
||||
std::shared_ptr<livoxProto1::Device> device)
|
||||
{
|
||||
if (!device)
|
||||
{
|
||||
@@ -76,13 +68,11 @@ void livoxProto1_device_enablePcloudDataReq(
|
||||
+ ": Device pointer is null");
|
||||
}
|
||||
|
||||
device->enablePcloudDataReq(callback);
|
||||
co_return co_await device->enablePcloudDataCReq();
|
||||
}
|
||||
|
||||
void livoxProto1_device_disablePcloudDataReq(
|
||||
std::shared_ptr<livoxProto1::Device> device,
|
||||
sscl::cps::Callback<livoxProto1_device_disablePcloudDataReqCbFn> callback
|
||||
)
|
||||
sscl::co::ViralNonPostingInvoker<bool> livoxProto1_device_disablePcloudDataCReq(
|
||||
std::shared_ptr<livoxProto1::Device> device)
|
||||
{
|
||||
if (!device)
|
||||
{
|
||||
@@ -90,13 +80,12 @@ void livoxProto1_device_disablePcloudDataReq(
|
||||
+ ": Device pointer is null");
|
||||
}
|
||||
|
||||
device->disablePcloudDataReq(callback);
|
||||
co_return co_await device->disablePcloudDataCReq();
|
||||
}
|
||||
|
||||
void livoxProto1_device_getReturnModeReq(
|
||||
std::shared_ptr<livoxProto1::Device> device,
|
||||
sscl::cps::Callback<livoxProto1_device_getReturnModeReqCbFn> callback
|
||||
)
|
||||
sscl::co::ViralNonPostingInvoker<LivoxProto1GetReturnModeResult>
|
||||
livoxProto1_device_getReturnModeCReq(
|
||||
std::shared_ptr<livoxProto1::Device> device)
|
||||
{
|
||||
if (!device)
|
||||
{
|
||||
@@ -104,7 +93,12 @@ void livoxProto1_device_getReturnModeReq(
|
||||
+ ": Device pointer is null");
|
||||
}
|
||||
|
||||
device->getReturnModeReq(callback);
|
||||
livoxProto1::Device::GetReturnModeResult deviceResult =
|
||||
co_await device->getReturnModeCReq();
|
||||
LivoxProto1GetReturnModeResult result;
|
||||
result.success = deviceResult.success;
|
||||
result.returnMode = deviceResult.returnMode;
|
||||
co_return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<boost::asio::posix::stream_descriptor>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <spinscale/cps/callback.h>
|
||||
#include <spinscale/co/invokers.h>
|
||||
#include <boost/asio/posix/stream_descriptor.hpp>
|
||||
|
||||
// Forward declarations
|
||||
@@ -23,6 +23,18 @@ namespace livoxProto1 {
|
||||
class Device;
|
||||
}
|
||||
|
||||
struct LivoxProto1GetOrCreateDeviceResult
|
||||
{
|
||||
bool success = false;
|
||||
std::shared_ptr<livoxProto1::Device> device;
|
||||
};
|
||||
|
||||
struct LivoxProto1GetReturnModeResult
|
||||
{
|
||||
bool success = false;
|
||||
uint8_t returnMode = 0;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -52,54 +64,43 @@ typedef void livoxProto1_exitFn(void);
|
||||
* @param dataPort Data port for point cloud (default: 56000)
|
||||
* @param cmdPort Command port (default: 56001)
|
||||
* @param imuPort IMU port (default: 56002)
|
||||
* @return Device pointer on success, nullptr on failure
|
||||
* @return LivoxProto1GetOrCreateDeviceResult (success + device on success,
|
||||
* null device on failure)
|
||||
*/
|
||||
typedef std::function<
|
||||
void(bool success, std::shared_ptr<livoxProto1::Device> device)>
|
||||
livoxProto1_getOrCreateDeviceReqCbFn;
|
||||
|
||||
typedef void livoxProto1_getOrCreateDeviceReqFn(
|
||||
typedef sscl::co::ViralNonPostingInvoker<LivoxProto1GetOrCreateDeviceResult>
|
||||
livoxProto1_getOrCreateDeviceCReqFn(
|
||||
const std::string& deviceIdentifier,
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread,
|
||||
int commandTimeoutMs, int retryDelayMs,
|
||||
const std::string& smoIp, uint8_t smoSubnetNbits,
|
||||
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
|
||||
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback);
|
||||
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort);
|
||||
|
||||
typedef std::function<void(bool success)> livoxProto1_destroyDeviceReqCbFn;
|
||||
typedef void livoxProto1_destroyDeviceReqFn(
|
||||
std::shared_ptr<livoxProto1::Device> device,
|
||||
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> callback);
|
||||
typedef sscl::co::ViralNonPostingInvoker<bool> livoxProto1_destroyDeviceCReqFn(
|
||||
std::shared_ptr<livoxProto1::Device> device);
|
||||
|
||||
typedef std::function<void(bool success)>
|
||||
livoxProto1_device_enablePcloudDataReqCbFn;
|
||||
typedef void livoxProto1_device_enablePcloudDataReqFn(
|
||||
std::shared_ptr<livoxProto1::Device> device,
|
||||
sscl::cps::Callback<livoxProto1_device_enablePcloudDataReqCbFn> callback);
|
||||
typedef sscl::co::ViralNonPostingInvoker<bool>
|
||||
livoxProto1_device_enablePcloudDataCReqFn(
|
||||
std::shared_ptr<livoxProto1::Device> device);
|
||||
|
||||
typedef std::function<void(bool success)>
|
||||
livoxProto1_device_disablePcloudDataReqCbFn;
|
||||
typedef void livoxProto1_device_disablePcloudDataReqFn(
|
||||
std::shared_ptr<livoxProto1::Device> device,
|
||||
sscl::cps::Callback<livoxProto1_device_disablePcloudDataReqCbFn> callback);
|
||||
typedef sscl::co::ViralNonPostingInvoker<bool>
|
||||
livoxProto1_device_disablePcloudDataCReqFn(
|
||||
std::shared_ptr<livoxProto1::Device> device);
|
||||
|
||||
typedef std::function<void(bool success, uint8_t returnMode)>
|
||||
livoxProto1_device_getReturnModeReqCbFn;
|
||||
typedef void livoxProto1_device_getReturnModeReqFn(
|
||||
std::shared_ptr<livoxProto1::Device> device,
|
||||
sscl::cps::Callback<livoxProto1_device_getReturnModeReqCbFn> callback);
|
||||
typedef sscl::co::ViralNonPostingInvoker<LivoxProto1GetReturnModeResult>
|
||||
livoxProto1_device_getReturnModeCReqFn(
|
||||
std::shared_ptr<livoxProto1::Device> device);
|
||||
|
||||
typedef std::shared_ptr<boost::asio::posix::stream_descriptor>
|
||||
livoxProto1_getPcloudDataFdDescFn(void);
|
||||
|
||||
livoxProto1_mainFn livoxProto1_main;
|
||||
livoxProto1_exitFn livoxProto1_exit;
|
||||
livoxProto1_getOrCreateDeviceReqFn livoxProto1_getOrCreateDeviceReq;
|
||||
livoxProto1_destroyDeviceReqFn livoxProto1_destroyDeviceReq;
|
||||
livoxProto1_device_enablePcloudDataReqFn livoxProto1_device_enablePcloudDataReq;
|
||||
livoxProto1_device_disablePcloudDataReqFn
|
||||
livoxProto1_device_disablePcloudDataReq;
|
||||
livoxProto1_device_getReturnModeReqFn livoxProto1_device_getReturnModeReq;
|
||||
livoxProto1_getOrCreateDeviceCReqFn livoxProto1_getOrCreateDeviceCReq;
|
||||
livoxProto1_destroyDeviceCReqFn livoxProto1_destroyDeviceCReq;
|
||||
livoxProto1_device_enablePcloudDataCReqFn livoxProto1_device_enablePcloudDataCReq;
|
||||
livoxProto1_device_disablePcloudDataCReqFn
|
||||
livoxProto1_device_disablePcloudDataCReq;
|
||||
livoxProto1_device_getReturnModeCReqFn livoxProto1_device_getReturnModeCReq;
|
||||
livoxProto1_getPcloudDataFdDescFn livoxProto1_getPcloudDataFdDesc;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include <boostAsioLinkageFix.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <coroutine>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -8,7 +12,11 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <adapters/boostAsio/deadlineTimerAReq.h>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <spinscale/co/group.h>
|
||||
#include "udpCommandDemuxer.h"
|
||||
#include "protocol.h"
|
||||
#include "core.h"
|
||||
#include "device.h"
|
||||
|
||||
@@ -330,6 +338,19 @@ void UdpCommandDemuxer::processIncomingData()
|
||||
char sourceIP[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &senderAddr.sin_addr, sourceIP, INET_ADDRSTRLEN);
|
||||
|
||||
if (bytesReceived >= static_cast<ssize_t>(
|
||||
sizeof(Header) + sizeof(Command)))
|
||||
{
|
||||
const uint8_t cmdSet = receiveBuffer[sizeof(Header)];
|
||||
const uint8_t cmdId = receiveBuffer[sizeof(Header) + 1];
|
||||
|
||||
if (tryCompletePendingCommandWait(
|
||||
sourceIP, cmdSet, cmdId, receiveBuffer, bytesReceived))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// First, find device with matching IP address in DeviceManager collection
|
||||
for (const auto &device : deviceManager.devices)
|
||||
{
|
||||
@@ -395,5 +416,208 @@ void UdpCommandDemuxer::processIncomingData()
|
||||
<< sourceIP << ", discarding datagram" << std::endl;
|
||||
}
|
||||
|
||||
struct UdpCommandDemuxer::PendingCommandWaitDesc
|
||||
{
|
||||
CommandWaitKey key;
|
||||
boost::asio::io_service &resumeIoService;
|
||||
std::atomic<bool> settled{false};
|
||||
UdpCommandResponseResult result{};
|
||||
std::coroutine_handle<> callerSchedHandle;
|
||||
|
||||
PendingCommandWaitDesc(
|
||||
CommandWaitKey keyIn,
|
||||
boost::asio::io_service &resumeIoServiceIn)
|
||||
: key(std::move(keyIn)),
|
||||
resumeIoService(resumeIoServiceIn)
|
||||
{}
|
||||
};
|
||||
|
||||
void UdpCommandDemuxer::settlePendingCommandWait(
|
||||
const std::shared_ptr<PendingCommandWaitDesc> &wait,
|
||||
UdpCommandResponseResult::Outcome outcome,
|
||||
const uint8_t *data, ssize_t bytesReceived)
|
||||
{
|
||||
if (wait->settled.exchange(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
wait->result.outcome = outcome;
|
||||
wait->result.bytesReceived = bytesReceived;
|
||||
|
||||
if (outcome == UdpCommandResponseResult::Outcome::Response
|
||||
&& data != nullptr
|
||||
&& bytesReceived > 0
|
||||
&& bytesReceived
|
||||
<= static_cast<ssize_t>(sizeof(wait->result.buffer)))
|
||||
{
|
||||
memcpy(wait->result.buffer, data, bytesReceived);
|
||||
}
|
||||
|
||||
std::coroutine_handle<> handle = wait->callerSchedHandle;
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::asio::post(wait->resumeIoService, handle);
|
||||
}
|
||||
|
||||
std::shared_ptr<UdpCommandDemuxer::PendingCommandWaitDesc>
|
||||
UdpCommandDemuxer::findAndRemovePendingCommandWait(const CommandWaitKey &key)
|
||||
{
|
||||
sscl::SpinLock::Guard guard(pendingWaits.lock);
|
||||
const auto iterator = pendingWaits.rsrc.pendingWaits.find(key);
|
||||
if (iterator == pendingWaits.rsrc.pendingWaits.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<PendingCommandWaitDesc> wait = iterator->second;
|
||||
pendingWaits.rsrc.pendingWaits.erase(iterator);
|
||||
return wait;
|
||||
}
|
||||
|
||||
void UdpCommandDemuxer::cancelPendingCommandWait(
|
||||
uint8_t cmdSet, uint8_t cmdId,
|
||||
const std::string &deviceIp)
|
||||
{
|
||||
std::shared_ptr<PendingCommandWaitDesc> wait = findAndRemovePendingCommandWait(
|
||||
{deviceIp, cmdSet, cmdId});
|
||||
|
||||
if (!wait) { return; }
|
||||
|
||||
settlePendingCommandWait(
|
||||
wait,
|
||||
UdpCommandResponseResult::Outcome::Timeout,
|
||||
nullptr, -1);
|
||||
}
|
||||
|
||||
bool UdpCommandDemuxer::tryCompletePendingCommandWait(
|
||||
const char *sourceIp,
|
||||
uint8_t cmdSet, uint8_t cmdId,
|
||||
const uint8_t *data, ssize_t bytesReceived)
|
||||
{
|
||||
std::shared_ptr<PendingCommandWaitDesc> wait = findAndRemovePendingCommandWait(
|
||||
{sourceIp, cmdSet, cmdId});
|
||||
|
||||
if (!wait) { return false; }
|
||||
|
||||
const UdpCommandResponseResult::Outcome outcome =
|
||||
(bytesReceived > 0
|
||||
&& bytesReceived
|
||||
<= static_cast<ssize_t>(sizeof(wait->result.buffer)))
|
||||
? UdpCommandResponseResult::Outcome::Response
|
||||
: UdpCommandResponseResult::Outcome::RecvError;
|
||||
|
||||
settlePendingCommandWait(wait, outcome, data, bytesReceived);
|
||||
return true;
|
||||
}
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<UdpCommandResponseResult>
|
||||
UdpCommandDemuxer::waitForCommandResponseCReq(
|
||||
uint8_t cmdSet, uint8_t cmdId,
|
||||
const std::string &deviceIp)
|
||||
{
|
||||
const CommandWaitKey key{deviceIp, cmdSet, cmdId};
|
||||
auto wait = std::make_shared<PendingCommandWaitDesc>(
|
||||
key, componentThread->getIoService());
|
||||
|
||||
{
|
||||
sscl::SpinLock::Guard guard(pendingWaits.lock);
|
||||
pendingWaits.rsrc.pendingWaits[key] = wait;
|
||||
}
|
||||
|
||||
struct PendingCommandWaitDescAwaiter
|
||||
{
|
||||
std::shared_ptr<PendingCommandWaitDesc> wait;
|
||||
|
||||
bool await_ready() const noexcept
|
||||
{
|
||||
return wait->settled.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
bool await_suspend(std::coroutine_handle<> caller) noexcept
|
||||
{
|
||||
if (wait->settled.load(std::memory_order_acquire)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wait->callerSchedHandle = caller;
|
||||
return true;
|
||||
}
|
||||
|
||||
UdpCommandResponseResult await_resume() const noexcept
|
||||
{
|
||||
return wait->result;
|
||||
}
|
||||
};
|
||||
|
||||
const UdpCommandResponseResult result =
|
||||
co_await PendingCommandWaitDescAwaiter{wait};
|
||||
|
||||
if (findAndRemovePendingCommandWait(key))
|
||||
{
|
||||
std::cerr << __func__ << ": pending wait still registered after "
|
||||
"settle for device " << deviceIp << " (cmd_set="
|
||||
<< static_cast<int>(cmdSet) << ", cmd_id="
|
||||
<< static_cast<int>(cmdId) << "); program error"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
co_return result;
|
||||
}
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<UdpCommandResponseResult>
|
||||
UdpCommandDemuxer::waitForCommandResponseCReq(
|
||||
uint8_t cmdSet, uint8_t cmdId,
|
||||
const std::string &deviceIp,
|
||||
int timeoutMs)
|
||||
{
|
||||
/** EXPLANATION:
|
||||
* We setup an async timer event to detect timeout, and register a UDP
|
||||
* command handler to wait for the device to respond to the incoming command
|
||||
* request. If the device does not respond within the timeout period,
|
||||
* we will consider the command to have failed.
|
||||
*/
|
||||
boost::asio::io_service &ioService = componentThread->getIoService();
|
||||
std::optional<std::shared_ptr<boost::asio::deadline_timer>> raceTimer;
|
||||
auto timerAwaiter = adapters::boostAsio::getDeadlineTimerAReqAwaiter(
|
||||
ioService,
|
||||
boost::posix_time::milliseconds(timeoutMs),
|
||||
raceTimer);
|
||||
auto responseInvoker = waitForCommandResponseCReq(cmdSet, cmdId, deviceIp);
|
||||
|
||||
static constexpr int timerMemberSettlementIndex = 0;
|
||||
|
||||
sscl::co::Group group;
|
||||
group.add(timerAwaiter);
|
||||
group.add(responseInvoker);
|
||||
|
||||
co_await group.getAwaitFirstSettlementInvoker();
|
||||
group.checkForAndReThrowGroupExceptions();
|
||||
|
||||
const bool timerWonFirst =
|
||||
group.s.rsrc.firstSettledInvokerIdx == timerMemberSettlementIndex;
|
||||
|
||||
if (timerWonFirst) {
|
||||
cancelPendingCommandWait(cmdSet, cmdId, deviceIp);
|
||||
} else if (raceTimer) {
|
||||
(*raceTimer)->cancel();
|
||||
}
|
||||
|
||||
/** Group member adapter coros are fire-and-forget; keep group alive until
|
||||
* both members settle so the loser adapter does not touch freed state.
|
||||
*/
|
||||
co_await group.getAwaitAllSettlementsInvoker();
|
||||
group.checkForAndReThrowGroupExceptions();
|
||||
|
||||
if (timerWonFirst)
|
||||
{
|
||||
UdpCommandResponseResult timeoutResult;
|
||||
timeoutResult.outcome = UdpCommandResponseResult::Outcome::Timeout;
|
||||
co_return timeoutResult;
|
||||
}
|
||||
|
||||
co_return responseInvoker.completedReturnValues().myReturnValue;
|
||||
}
|
||||
|
||||
} // namespace comms
|
||||
} // namespace livoxProto1
|
||||
|
||||
@@ -3,10 +3,16 @@
|
||||
|
||||
#include <boostAsioLinkageFix.h>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <boost/asio/posix/stream_descriptor.hpp>
|
||||
#include <componentThread.h>
|
||||
#include <spinscale/spinLock.h>
|
||||
#include <spinscale/sharedResourceGroup.h>
|
||||
#include <spinscale/co/invokers.h>
|
||||
|
||||
namespace livoxProto1 {
|
||||
|
||||
@@ -15,6 +21,45 @@ class DeviceManager;
|
||||
|
||||
namespace comms {
|
||||
|
||||
struct UdpCommandResponseResult
|
||||
{
|
||||
enum class Outcome
|
||||
{
|
||||
Timeout,
|
||||
Response,
|
||||
RecvError
|
||||
};
|
||||
|
||||
Outcome outcome = Outcome::Timeout;
|
||||
uint8_t buffer[1024]{};
|
||||
ssize_t bytesReceived = -1;
|
||||
};
|
||||
|
||||
struct CommandWaitKey
|
||||
{
|
||||
std::string deviceIp;
|
||||
uint8_t cmdSet;
|
||||
uint8_t cmdId;
|
||||
|
||||
bool operator==(const CommandWaitKey &other) const
|
||||
{
|
||||
return deviceIp == other.deviceIp
|
||||
&& cmdSet == other.cmdSet
|
||||
&& cmdId == other.cmdId;
|
||||
}
|
||||
};
|
||||
|
||||
struct CommandWaitKeyHash
|
||||
{
|
||||
std::size_t operator()(const CommandWaitKey &key) const
|
||||
{
|
||||
std::size_t hash = std::hash<std::string>{}(key.deviceIp);
|
||||
hash ^= (static_cast<std::size_t>(key.cmdSet) << 8)
|
||||
| static_cast<std::size_t>(key.cmdId);
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* UdpCommandDemuxer - Routes UDP command datagrams to appropriate devices
|
||||
*
|
||||
@@ -62,13 +107,20 @@ public:
|
||||
return pcloudDataFdDesc;
|
||||
}
|
||||
|
||||
private:
|
||||
// Socket and async objects
|
||||
std::shared_ptr<boost::asio::posix::stream_descriptor> pcloudDataFdDesc;
|
||||
// Socket and async objects
|
||||
std::shared_ptr<boost::asio::posix::stream_descriptor> cmdEndpointFdDesc;
|
||||
sscl::co::ViralNonPostingInvoker<UdpCommandResponseResult>
|
||||
waitForCommandResponseCReq(
|
||||
uint8_t cmdSet, uint8_t cmdId,
|
||||
const std::string &deviceIp,
|
||||
int timeoutMs);
|
||||
|
||||
private:
|
||||
struct PendingCommandWaitDesc;
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<UdpCommandResponseResult>
|
||||
waitForCommandResponseCReq(
|
||||
uint8_t cmdSet, uint8_t cmdId,
|
||||
const std::string &deviceIp);
|
||||
|
||||
void setupSockets();
|
||||
void setupCommandSocket();
|
||||
void setupPcloudDataSocket();
|
||||
@@ -76,6 +128,23 @@ private:
|
||||
void onDataReady(const boost::system::error_code& error);
|
||||
void processIncomingData();
|
||||
|
||||
bool tryCompletePendingCommandWait(
|
||||
const char *sourceIp,
|
||||
uint8_t cmdSet, uint8_t cmdId,
|
||||
const uint8_t *data, ssize_t bytesReceived);
|
||||
|
||||
void cancelPendingCommandWait(
|
||||
uint8_t cmdSet, uint8_t cmdId,
|
||||
const std::string &deviceIp);
|
||||
|
||||
std::shared_ptr<PendingCommandWaitDesc> findAndRemovePendingCommandWait(
|
||||
const CommandWaitKey &key);
|
||||
|
||||
void settlePendingCommandWait(
|
||||
const std::shared_ptr<PendingCommandWaitDesc> &wait,
|
||||
UdpCommandResponseResult::Outcome outcome,
|
||||
const uint8_t *data, ssize_t bytesReceived);
|
||||
|
||||
std::shared_ptr<sscl::ComponentThread> componentThread;
|
||||
DeviceManager& deviceManager;
|
||||
uint16_t commandPort;
|
||||
@@ -86,7 +155,21 @@ private:
|
||||
std::atomic<bool> isActive{false};
|
||||
std::atomic<bool> shouldStop{false};
|
||||
|
||||
// Receive buffer
|
||||
struct PendingWaitsResources
|
||||
{
|
||||
std::unordered_map<
|
||||
CommandWaitKey,
|
||||
std::shared_ptr<PendingCommandWaitDesc>,
|
||||
CommandWaitKeyHash>
|
||||
pendingWaits;
|
||||
};
|
||||
|
||||
sscl::SharedResourceGroup<sscl::SpinLock, PendingWaitsResources>
|
||||
pendingWaits;
|
||||
|
||||
std::shared_ptr<boost::asio::posix::stream_descriptor> pcloudDataFdDesc;
|
||||
std::shared_ptr<boost::asio::posix::stream_descriptor> cmdEndpointFdDesc;
|
||||
|
||||
uint8_t receiveBuffer[1024];
|
||||
struct sockaddr_in senderAddr;
|
||||
socklen_t senderAddrLen;
|
||||
|
||||
@@ -18,12 +18,11 @@ or event-driven APIs.
|
||||
include/adapters/
|
||||
README.md
|
||||
boostAsio/
|
||||
<boost asio adapter awaiters>
|
||||
deadlineTimerAReq.h
|
||||
opencl/
|
||||
<OpenCL adapter awaiters>
|
||||
smo/
|
||||
cpsCallbackAReq.h
|
||||
livoxProto1CpsAwaiters.h
|
||||
<other SMO/internal callback adapters>
|
||||
```
|
||||
|
||||
@@ -32,7 +31,7 @@ include/adapters/
|
||||
- Name adapter awaiter wrapper functions `get<fnName>AReqAwaiter()`, where
|
||||
`<fnName>` is the wrapped CPS/API request symbol with its library prefix
|
||||
removed and each `_`-delimited segment Pascal-cased (e.g.
|
||||
`livoxProto1_getOrCreateDeviceReq` → `getGetOrCreateDeviceReqAReqAwaiter()`).
|
||||
`someLib_someOperationReq` → `getSomeOperationReqAReqAwaiter()`).
|
||||
- Keep adapters small and single-purpose; but unify where possible to reduce
|
||||
code duplication.
|
||||
- Make result types explicit for multi-argument callbacks.
|
||||
|
||||
@@ -2,31 +2,110 @@
|
||||
#define ADAPTERS_BOOST_ASIO_DEADLINE_TIMER_AREQ_H
|
||||
|
||||
#include <boostAsioLinkageFix.h>
|
||||
#include <functional>
|
||||
|
||||
#include <atomic>
|
||||
#include <coroutine>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <adapters/smo/cpsCallbackAReq.h>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
namespace adapters::boostAsio {
|
||||
|
||||
using TimerWaitCbFn = std::function<void(bool success)>;
|
||||
/** Coroutine awaiter: true if the delay elapsed, false if cancelled/aborted. */
|
||||
class DeadlineTimerAReq
|
||||
{
|
||||
public:
|
||||
struct AsyncState
|
||||
{
|
||||
std::atomic<bool> settled{false};
|
||||
bool timerExpiredNormally = false;
|
||||
std::coroutine_handle<> callerSchedHandle;
|
||||
std::shared_ptr<boost::asio::deadline_timer> timer;
|
||||
};
|
||||
|
||||
inline auto deadlineTimerWaitAReq(
|
||||
DeadlineTimerAReq(
|
||||
boost::asio::io_service &resumeIoService,
|
||||
const boost::posix_time::milliseconds delay,
|
||||
std::optional<std::shared_ptr<boost::asio::deadline_timer>> &timerOut)
|
||||
: asyncState(std::make_shared<AsyncState>()),
|
||||
resumeIoService(resumeIoService)
|
||||
{
|
||||
asyncState->timer =
|
||||
std::make_shared<boost::asio::deadline_timer>(resumeIoService);
|
||||
timerOut = asyncState->timer;
|
||||
|
||||
asyncState->timer->expires_from_now(delay);
|
||||
asyncState->timer->async_wait(
|
||||
[this](const boost::system::error_code &error)
|
||||
{
|
||||
onTimer(error);
|
||||
});
|
||||
}
|
||||
|
||||
bool await_ready() const noexcept
|
||||
{
|
||||
return asyncState->settled.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
bool await_suspend(std::coroutine_handle<> caller) noexcept
|
||||
{
|
||||
if (asyncState->settled.load(std::memory_order_acquire)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
asyncState->callerSchedHandle = caller;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool await_resume() const noexcept
|
||||
{
|
||||
return asyncState->timerExpiredNormally;
|
||||
}
|
||||
|
||||
private:
|
||||
void onTimer(const boost::system::error_code &error)
|
||||
{
|
||||
if (asyncState->settled.exchange(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
asyncState->timerExpiredNormally = !error;
|
||||
signalSettledAndResumeCaller();
|
||||
}
|
||||
|
||||
void signalSettledAndResumeCaller()
|
||||
{
|
||||
std::coroutine_handle<> handle = asyncState->callerSchedHandle;
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::asio::post(resumeIoService, handle);
|
||||
}
|
||||
|
||||
std::shared_ptr<AsyncState> asyncState;
|
||||
boost::asio::io_service &resumeIoService;
|
||||
};
|
||||
|
||||
inline auto getDeadlineTimerAReqAwaiter(
|
||||
boost::asio::io_service &ioService,
|
||||
const boost::posix_time::milliseconds delay)
|
||||
{
|
||||
return smo::cpsBoundary::CpsCallbackAReq<bool, TimerWaitCbFn, std::function<void(sscl::cps::Callback<TimerWaitCbFn>)>>(
|
||||
ioService,
|
||||
[&ioService, delay](sscl::cps::Callback<TimerWaitCbFn> cb)
|
||||
{
|
||||
auto timer = std::make_shared<boost::asio::deadline_timer>(ioService);
|
||||
timer->expires_from_now(delay);
|
||||
timer->async_wait(
|
||||
[timer, cb](const boost::system::error_code &error) mutable
|
||||
{
|
||||
cb.callbackFn(!error);
|
||||
});
|
||||
});
|
||||
std::optional<std::shared_ptr<boost::asio::deadline_timer>> timerOut;
|
||||
return DeadlineTimerAReq(ioService, delay, timerOut);
|
||||
}
|
||||
|
||||
inline auto getDeadlineTimerAReqAwaiter(
|
||||
boost::asio::io_service &ioService,
|
||||
const boost::posix_time::milliseconds delay,
|
||||
std::optional<std::shared_ptr<boost::asio::deadline_timer>> &timerOut)
|
||||
{
|
||||
return DeadlineTimerAReq(ioService, delay, timerOut);
|
||||
}
|
||||
|
||||
} // namespace adapters::boostAsio
|
||||
|
||||
@@ -80,9 +80,7 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
boost::asio::post(
|
||||
resumeIoService,
|
||||
[handle]() { handle.resume(); });
|
||||
boost::asio::post(resumeIoService, handle);
|
||||
}
|
||||
|
||||
std::shared_ptr<AsyncState> asyncState;
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
#ifndef ADAPTERS_SMO_LIVOX_PROTO1_CPS_AWAITERS_H
|
||||
#define ADAPTERS_SMO_LIVOX_PROTO1_CPS_AWAITERS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include <adapters/smo/cpsCallbackAReq.h>
|
||||
#include <livoxProto1/livoxProto1.h>
|
||||
#include <spinscale/componentThread.h>
|
||||
|
||||
namespace adapters::smo {
|
||||
|
||||
struct GetOrCreateDeviceResult
|
||||
{
|
||||
bool success = false;
|
||||
std::shared_ptr<livoxProto1::Device> device;
|
||||
};
|
||||
|
||||
struct GetReturnModeResult
|
||||
{
|
||||
bool success = false;
|
||||
uint8_t returnMode = 0;
|
||||
};
|
||||
|
||||
inline auto getGetOrCreateDeviceReqAReqAwaiter(
|
||||
boost::asio::io_service &resumeIoService,
|
||||
livoxProto1_getOrCreateDeviceReqFn *fn,
|
||||
const std::string &deviceIdentifier,
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
int commandTimeoutMs,
|
||||
int retryDelayMs,
|
||||
const std::string &smoIp,
|
||||
uint8_t smoSubnetNbits,
|
||||
uint16_t dataPort,
|
||||
uint16_t cmdPort,
|
||||
uint16_t imuPort)
|
||||
{
|
||||
return ::smo::cpsBoundary::CpsCallbackAReq<
|
||||
GetOrCreateDeviceResult,
|
||||
livoxProto1_getOrCreateDeviceReqCbFn,
|
||||
std::function<void(sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn>)>>(
|
||||
resumeIoService,
|
||||
[=](sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> cb)
|
||||
{
|
||||
(*fn)(
|
||||
deviceIdentifier,
|
||||
componentThread,
|
||||
commandTimeoutMs, retryDelayMs,
|
||||
smoIp, smoSubnetNbits,
|
||||
dataPort, cmdPort, imuPort,
|
||||
std::move(cb));
|
||||
});
|
||||
}
|
||||
|
||||
inline auto getDeviceGetReturnModeReqAReqAwaiter(
|
||||
boost::asio::io_service &resumeIoService,
|
||||
livoxProto1_device_getReturnModeReqFn *fn,
|
||||
std::shared_ptr<livoxProto1::Device> device)
|
||||
{
|
||||
return ::smo::cpsBoundary::CpsCallbackAReq<
|
||||
GetReturnModeResult,
|
||||
livoxProto1_device_getReturnModeReqCbFn,
|
||||
std::function<void(sscl::cps::Callback<livoxProto1_device_getReturnModeReqCbFn>)>>(
|
||||
resumeIoService,
|
||||
[=](sscl::cps::Callback<livoxProto1_device_getReturnModeReqCbFn> cb)
|
||||
{
|
||||
(*fn)(device, std::move(cb));
|
||||
});
|
||||
}
|
||||
|
||||
inline auto getDeviceEnablePcloudDataReqAReqAwaiter(
|
||||
boost::asio::io_service &resumeIoService,
|
||||
livoxProto1_device_enablePcloudDataReqFn *fn,
|
||||
std::shared_ptr<livoxProto1::Device> device)
|
||||
{
|
||||
return ::smo::cpsBoundary::CpsCallbackAReq<
|
||||
bool,
|
||||
livoxProto1_device_enablePcloudDataReqCbFn,
|
||||
std::function<void(sscl::cps::Callback<livoxProto1_device_enablePcloudDataReqCbFn>)>>(
|
||||
resumeIoService,
|
||||
[=](sscl::cps::Callback<livoxProto1_device_enablePcloudDataReqCbFn> cb)
|
||||
{
|
||||
(*fn)(device, std::move(cb));
|
||||
});
|
||||
}
|
||||
|
||||
inline auto getDeviceDisablePcloudDataReqAReqAwaiter(
|
||||
boost::asio::io_service &resumeIoService,
|
||||
livoxProto1_device_disablePcloudDataReqFn *fn,
|
||||
std::shared_ptr<livoxProto1::Device> device)
|
||||
{
|
||||
return ::smo::cpsBoundary::CpsCallbackAReq<
|
||||
bool,
|
||||
livoxProto1_device_disablePcloudDataReqCbFn,
|
||||
std::function<void(sscl::cps::Callback<livoxProto1_device_disablePcloudDataReqCbFn>)>>(
|
||||
resumeIoService,
|
||||
[=](sscl::cps::Callback<livoxProto1_device_disablePcloudDataReqCbFn> cb)
|
||||
{
|
||||
(*fn)(device, std::move(cb));
|
||||
});
|
||||
}
|
||||
|
||||
inline auto getDestroyDeviceReqAReqAwaiter(
|
||||
boost::asio::io_service &resumeIoService,
|
||||
livoxProto1_destroyDeviceReqFn *fn,
|
||||
std::shared_ptr<livoxProto1::Device> device)
|
||||
{
|
||||
return ::smo::cpsBoundary::CpsCallbackAReq<
|
||||
bool,
|
||||
livoxProto1_destroyDeviceReqCbFn,
|
||||
std::function<void(sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn>)>>(
|
||||
resumeIoService,
|
||||
[=](sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> cb)
|
||||
{
|
||||
(*fn)(device, std::move(cb));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace adapters::smo
|
||||
|
||||
#endif // ADAPTERS_SMO_LIVOX_PROTO1_CPS_AWAITERS_H
|
||||
@@ -14,7 +14,6 @@ if(ENABLE_STIMBUFFAPI_livoxGen1)
|
||||
|
||||
add_library(livoxGen1 SHARED
|
||||
livoxGen1.cpp
|
||||
livoxGen1Proto1CpsBridge.cpp
|
||||
pcloudStimulusProducer.cpp
|
||||
livoxPcloudFrameDumper.cpp
|
||||
ioUringAssemblyEngine.cpp
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <user/senseApiDesc.h>
|
||||
|
||||
#include "livoxGen1Internal.h"
|
||||
#include "livoxGen1Proto1CpsBridge.h"
|
||||
|
||||
namespace smo::stim_buff {
|
||||
|
||||
@@ -28,11 +27,11 @@ LivoxProto1DllState::LivoxProto1DllState()
|
||||
: dlopenHandle(nullptr, DlCloser),
|
||||
livoxProto1_main(nullptr),
|
||||
livoxProto1_exit(nullptr),
|
||||
livoxProto1_getOrCreateDeviceReq(nullptr),
|
||||
livoxProto1_destroyDeviceReq(nullptr),
|
||||
livoxProto1_device_enablePcloudDataReq(nullptr),
|
||||
livoxProto1_device_disablePcloudDataReq(nullptr),
|
||||
livoxProto1_device_getReturnModeReq(nullptr),
|
||||
livoxProto1_getOrCreateDeviceCReq(nullptr),
|
||||
livoxProto1_destroyDeviceCReq(nullptr),
|
||||
livoxProto1_device_enablePcloudDataCReq(nullptr),
|
||||
livoxProto1_device_disablePcloudDataCReq(nullptr),
|
||||
livoxProto1_device_getReturnModeCReq(nullptr),
|
||||
livoxProto1_getPcloudDataFdDesc(nullptr)
|
||||
{}
|
||||
|
||||
@@ -221,14 +220,14 @@ bool validateAttachRequest(
|
||||
sscl::co::ViralNonPostingInvoker<StimBuffDeviceOpResult>
|
||||
enablePcloudDataForAttach(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec> &desc,
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<sscl::ComponentThread> &/*componentThread*/,
|
||||
const std::shared_ptr<livoxProto1::Device> &device)
|
||||
{
|
||||
/* Enable pcloud data. Don't need delay since no commands were
|
||||
* sent to device prior to us reaching here (or delay already handled).
|
||||
*/
|
||||
const bool enabled = co_await coAwaitEnablePcloudData(
|
||||
componentThread, device);
|
||||
const bool enabled = co_await (*livoxProto1.livoxProto1_device_enablePcloudDataCReq)(
|
||||
device);
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
@@ -329,10 +328,13 @@ attachByCreatingProducer(
|
||||
* Generally, it will resume sending them within 1-2 seconds.
|
||||
*/
|
||||
const LivoxProviderParams params = parseLivoxProviderParams(desc);
|
||||
adapters::smo::GetOrCreateDeviceResult deviceResult =
|
||||
co_await coAwaitGetOrCreateDevice(
|
||||
componentThread, desc->deviceSelector,
|
||||
params);
|
||||
LivoxProto1GetOrCreateDeviceResult deviceResult =
|
||||
co_await (*livoxProto1.livoxProto1_getOrCreateDeviceCReq)(
|
||||
desc->deviceSelector,
|
||||
componentThread,
|
||||
params.commandTimeoutMs, params.retryDelayMs,
|
||||
params.smoIp, params.smoSubnetNbits,
|
||||
params.dataPort, params.cmdPort, params.imuPort);
|
||||
|
||||
if (!deviceResult.success || !deviceResult.device)
|
||||
{
|
||||
@@ -354,7 +356,7 @@ attachByCreatingProducer(
|
||||
* may not yet be ready for another command.
|
||||
*/
|
||||
// Initialize timer with LivoxGen1 metadata io_service
|
||||
const bool delayOk = co_await adapters::boostAsio::deadlineTimerWaitAReq(
|
||||
const bool delayOk = co_await adapters::boostAsio::getDeadlineTimerAReqAwaiter(
|
||||
componentThread->getIoService(),
|
||||
boost::posix_time::milliseconds(LIVOX_GEN1_DEVICE_COMMAND_DELAY_MS));
|
||||
|
||||
@@ -364,8 +366,9 @@ attachByCreatingProducer(
|
||||
co_return StimBuffDeviceOpResult{false, desc};
|
||||
}
|
||||
|
||||
auto returnModeResult = co_await coAwaitGetReturnMode(
|
||||
componentThread, deviceResult.device);
|
||||
LivoxProto1GetReturnModeResult returnModeResult =
|
||||
co_await (*livoxProto1.livoxProto1_device_getReturnModeCReq)(
|
||||
deviceResult.device);
|
||||
|
||||
if (!returnModeResult.success)
|
||||
{
|
||||
@@ -455,7 +458,7 @@ livoxGen1_attachDeviceCReq(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec> &desc,
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread)
|
||||
{
|
||||
if (!livoxProto1.livoxProto1_getOrCreateDeviceReq)
|
||||
if (!livoxProto1.livoxProto1_getOrCreateDeviceCReq)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": LivoxProto1 getOrCreateDevice function "
|
||||
@@ -522,8 +525,8 @@ livoxGen1_detachDeviceCReq(
|
||||
|
||||
// Last buffer on producer: disable pcloud before tearing down device
|
||||
// Disable point cloud data first
|
||||
const bool disabled = co_await coAwaitDisablePcloudData(
|
||||
requestComponentThread, stimProducer->device);
|
||||
const bool disabled = co_await (*livoxProto1.livoxProto1_device_disablePcloudDataCReq)(
|
||||
stimProducer->device);
|
||||
|
||||
if (!disabled)
|
||||
{
|
||||
@@ -536,7 +539,7 @@ livoxGen1_detachDeviceCReq(
|
||||
|
||||
// Helper method to delay and then call destroyDeviceReq
|
||||
// Initialize timer with LivoxGen1 metadata io_service
|
||||
co_await adapters::boostAsio::deadlineTimerWaitAReq(
|
||||
co_await adapters::boostAsio::getDeadlineTimerAReqAwaiter(
|
||||
requestComponentThread->getIoService(),
|
||||
boost::posix_time::milliseconds(LIVOX_GEN1_DEVICE_COMMAND_DELAY_MS));
|
||||
|
||||
@@ -563,8 +566,7 @@ livoxGen1_detachDeviceCReq(
|
||||
attachedStimulusProducers.erase(it);
|
||||
}
|
||||
|
||||
const bool destroyed = co_await coAwaitDestroyDevice(
|
||||
requestComponentThread,
|
||||
const bool destroyed = co_await (*livoxProto1.livoxProto1_destroyDeviceCReq)(
|
||||
stimProducer->device);
|
||||
if (!destroyed) {
|
||||
std::cerr << __func__ << ": Failed to destroy dev "
|
||||
@@ -611,31 +613,31 @@ sscl::co::ViralNonPostingInvoker<int> livoxGen1_initializeCInd()
|
||||
dlsym(livoxProto1.dlopenHandle.get(), "livoxProto1_main"));
|
||||
livoxProto1.livoxProto1_exit = reinterpret_cast<livoxProto1_exitFn *>(
|
||||
dlsym(livoxProto1.dlopenHandle.get(), "livoxProto1_exit"));
|
||||
livoxProto1.livoxProto1_getOrCreateDeviceReq = reinterpret_cast<
|
||||
livoxProto1_getOrCreateDeviceReqFn *>(
|
||||
livoxProto1.livoxProto1_getOrCreateDeviceCReq = reinterpret_cast<
|
||||
livoxProto1_getOrCreateDeviceCReqFn *>(
|
||||
dlsym(
|
||||
livoxProto1.dlopenHandle.get(),
|
||||
"livoxProto1_getOrCreateDeviceReq"));
|
||||
livoxProto1.livoxProto1_destroyDeviceReq = reinterpret_cast<
|
||||
livoxProto1_destroyDeviceReqFn *>(
|
||||
"livoxProto1_getOrCreateDeviceCReq"));
|
||||
livoxProto1.livoxProto1_destroyDeviceCReq = reinterpret_cast<
|
||||
livoxProto1_destroyDeviceCReqFn *>(
|
||||
dlsym(
|
||||
livoxProto1.dlopenHandle.get(),
|
||||
"livoxProto1_destroyDeviceReq"));
|
||||
livoxProto1.livoxProto1_device_enablePcloudDataReq = reinterpret_cast<
|
||||
livoxProto1_device_enablePcloudDataReqFn *>(
|
||||
"livoxProto1_destroyDeviceCReq"));
|
||||
livoxProto1.livoxProto1_device_enablePcloudDataCReq = reinterpret_cast<
|
||||
livoxProto1_device_enablePcloudDataCReqFn *>(
|
||||
dlsym(
|
||||
livoxProto1.dlopenHandle.get(),
|
||||
"livoxProto1_device_enablePcloudDataReq"));
|
||||
livoxProto1.livoxProto1_device_disablePcloudDataReq = reinterpret_cast<
|
||||
livoxProto1_device_disablePcloudDataReqFn *>(
|
||||
"livoxProto1_device_enablePcloudDataCReq"));
|
||||
livoxProto1.livoxProto1_device_disablePcloudDataCReq = reinterpret_cast<
|
||||
livoxProto1_device_disablePcloudDataCReqFn *>(
|
||||
dlsym(
|
||||
livoxProto1.dlopenHandle.get(),
|
||||
"livoxProto1_device_disablePcloudDataReq"));
|
||||
livoxProto1.livoxProto1_device_getReturnModeReq = reinterpret_cast<
|
||||
livoxProto1_device_getReturnModeReqFn *>(
|
||||
"livoxProto1_device_disablePcloudDataCReq"));
|
||||
livoxProto1.livoxProto1_device_getReturnModeCReq = reinterpret_cast<
|
||||
livoxProto1_device_getReturnModeCReqFn *>(
|
||||
dlsym(
|
||||
livoxProto1.dlopenHandle.get(),
|
||||
"livoxProto1_device_getReturnModeReq"));
|
||||
"livoxProto1_device_getReturnModeCReq"));
|
||||
livoxProto1.livoxProto1_getPcloudDataFdDesc = reinterpret_cast<
|
||||
livoxProto1_getPcloudDataFdDescFn *>(
|
||||
dlsym(
|
||||
@@ -644,11 +646,11 @@ sscl::co::ViralNonPostingInvoker<int> livoxGen1_initializeCInd()
|
||||
|
||||
if (!livoxProto1.livoxProto1_main
|
||||
|| !livoxProto1.livoxProto1_exit
|
||||
|| !livoxProto1.livoxProto1_getOrCreateDeviceReq
|
||||
|| !livoxProto1.livoxProto1_destroyDeviceReq
|
||||
|| !livoxProto1.livoxProto1_device_enablePcloudDataReq
|
||||
|| !livoxProto1.livoxProto1_device_disablePcloudDataReq
|
||||
|| !livoxProto1.livoxProto1_device_getReturnModeReq
|
||||
|| !livoxProto1.livoxProto1_getOrCreateDeviceCReq
|
||||
|| !livoxProto1.livoxProto1_destroyDeviceCReq
|
||||
|| !livoxProto1.livoxProto1_device_enablePcloudDataCReq
|
||||
|| !livoxProto1.livoxProto1_device_disablePcloudDataCReq
|
||||
|| !livoxProto1.livoxProto1_device_getReturnModeCReq
|
||||
|| !livoxProto1.livoxProto1_getPcloudDataFdDesc)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
|
||||
@@ -18,13 +18,13 @@ struct LivoxProto1DllState
|
||||
std::unique_ptr<void, void(*)(void*)> dlopenHandle;
|
||||
livoxProto1_mainFn *livoxProto1_main;
|
||||
livoxProto1_exitFn *livoxProto1_exit;
|
||||
livoxProto1_getOrCreateDeviceReqFn *livoxProto1_getOrCreateDeviceReq;
|
||||
livoxProto1_destroyDeviceReqFn *livoxProto1_destroyDeviceReq;
|
||||
livoxProto1_device_enablePcloudDataReqFn
|
||||
*livoxProto1_device_enablePcloudDataReq;
|
||||
livoxProto1_device_disablePcloudDataReqFn
|
||||
*livoxProto1_device_disablePcloudDataReq;
|
||||
livoxProto1_device_getReturnModeReqFn *livoxProto1_device_getReturnModeReq;
|
||||
livoxProto1_getOrCreateDeviceCReqFn *livoxProto1_getOrCreateDeviceCReq;
|
||||
livoxProto1_destroyDeviceCReqFn *livoxProto1_destroyDeviceCReq;
|
||||
livoxProto1_device_enablePcloudDataCReqFn
|
||||
*livoxProto1_device_enablePcloudDataCReq;
|
||||
livoxProto1_device_disablePcloudDataCReqFn
|
||||
*livoxProto1_device_disablePcloudDataCReq;
|
||||
livoxProto1_device_getReturnModeCReqFn *livoxProto1_device_getReturnModeCReq;
|
||||
livoxProto1_getPcloudDataFdDescFn *livoxProto1_getPcloudDataFdDesc;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
#include "livoxGen1Proto1CpsBridge.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace smo::stim_buff {
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<adapters::smo::GetOrCreateDeviceResult>
|
||||
coAwaitGetOrCreateDevice(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::string &deviceIdentifier,
|
||||
const LivoxProviderParams ¶ms)
|
||||
{
|
||||
if (!livoxProto1.livoxProto1_getOrCreateDeviceReq) {
|
||||
throw std::runtime_error("coAwaitGetOrCreateDevice: proto1 function missing");
|
||||
}
|
||||
|
||||
auto result = co_await adapters::smo::getGetOrCreateDeviceReqAReqAwaiter(
|
||||
componentThread->getIoService(),
|
||||
livoxProto1.livoxProto1_getOrCreateDeviceReq,
|
||||
deviceIdentifier,
|
||||
componentThread,
|
||||
params.commandTimeoutMs,
|
||||
params.retryDelayMs,
|
||||
params.smoIp,
|
||||
params.smoSubnetNbits,
|
||||
params.dataPort,
|
||||
params.cmdPort,
|
||||
params.imuPort);
|
||||
co_return result;
|
||||
}
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<adapters::smo::GetReturnModeResult>
|
||||
coAwaitGetReturnMode(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<livoxProto1::Device> &device)
|
||||
{
|
||||
if (!livoxProto1.livoxProto1_device_getReturnModeReq) {
|
||||
throw std::runtime_error("coAwaitGetReturnMode: proto1 function missing");
|
||||
}
|
||||
|
||||
co_return co_await adapters::smo::getDeviceGetReturnModeReqAReqAwaiter(
|
||||
componentThread->getIoService(),
|
||||
livoxProto1.livoxProto1_device_getReturnModeReq,
|
||||
device);
|
||||
}
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<bool> coAwaitEnablePcloudData(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<livoxProto1::Device> &device)
|
||||
{
|
||||
if (!livoxProto1.livoxProto1_device_enablePcloudDataReq) {
|
||||
throw std::runtime_error("coAwaitEnablePcloudData: proto1 function missing");
|
||||
}
|
||||
|
||||
co_return co_await adapters::smo::getDeviceEnablePcloudDataReqAReqAwaiter(
|
||||
componentThread->getIoService(),
|
||||
livoxProto1.livoxProto1_device_enablePcloudDataReq,
|
||||
device);
|
||||
}
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<bool> coAwaitDisablePcloudData(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<livoxProto1::Device> &device)
|
||||
{
|
||||
if (!livoxProto1.livoxProto1_device_disablePcloudDataReq) {
|
||||
throw std::runtime_error("coAwaitDisablePcloudData: proto1 function missing");
|
||||
}
|
||||
|
||||
co_return co_await adapters::smo::getDeviceDisablePcloudDataReqAReqAwaiter(
|
||||
componentThread->getIoService(),
|
||||
livoxProto1.livoxProto1_device_disablePcloudDataReq,
|
||||
device);
|
||||
}
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<bool> coAwaitDestroyDevice(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<livoxProto1::Device> &device)
|
||||
{
|
||||
if (!livoxProto1.livoxProto1_destroyDeviceReq) {
|
||||
throw std::runtime_error("coAwaitDestroyDevice: proto1 function missing");
|
||||
}
|
||||
|
||||
co_return co_await adapters::smo::getDestroyDeviceReqAReqAwaiter(
|
||||
componentThread->getIoService(),
|
||||
livoxProto1.livoxProto1_destroyDeviceReq,
|
||||
device);
|
||||
}
|
||||
|
||||
} // namespace smo::stim_buff
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef LIVOX_GEN1_PROTO1_CPS_BRIDGE_H
|
||||
#define LIVOX_GEN1_PROTO1_CPS_BRIDGE_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <adapters/smo/livoxProto1CpsAwaiters.h>
|
||||
#include <spinscale/co/invokers.h>
|
||||
#include <spinscale/componentThread.h>
|
||||
|
||||
#include "livoxGen1Internal.h"
|
||||
|
||||
namespace smo::stim_buff {
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<adapters::smo::GetOrCreateDeviceResult>
|
||||
coAwaitGetOrCreateDevice(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::string &deviceIdentifier,
|
||||
const LivoxProviderParams ¶ms);
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<adapters::smo::GetReturnModeResult>
|
||||
coAwaitGetReturnMode(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<livoxProto1::Device> &device);
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<bool> coAwaitEnablePcloudData(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<livoxProto1::Device> &device);
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<bool> coAwaitDisablePcloudData(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<livoxProto1::Device> &device);
|
||||
|
||||
sscl::co::ViralNonPostingInvoker<bool> coAwaitDestroyDevice(
|
||||
const std::shared_ptr<sscl::ComponentThread> &componentThread,
|
||||
const std::shared_ptr<livoxProto1::Device> &device);
|
||||
|
||||
} // namespace smo::stim_buff
|
||||
|
||||
#endif // LIVOX_GEN1_PROTO1_CPS_BRIDGE_H
|
||||
Reference in New Issue
Block a user