LivoxProto1: Implemented Device and getOrCreateDevice

Includes everything from sending heartbeat msgs to performing
the connection handshake. We also accept many params to
provider-params to customize and make things easier.
This commit is contained in:
2025-09-06 20:06:38 -04:00
parent 25234c4229
commit a0d577bf81
18 changed files with 1906 additions and 403 deletions
+136
View File
@@ -0,0 +1,136 @@
#include <algorithm>
#include <iostream>
#include <user/senseApiDesc.h>
#include "protocol.h"
#include "core.h"
namespace livoxProto1 {
static ProtoState protoState =
{
.isInitialized = false,
.componentThread = nullptr,
.deviceManager = nullptr
};
ProtoState& getProtoState()
{
return protoState;
}
DeviceManager::DeviceManager()
: broadcastListener(protoState.componentThread)
{
broadcastListener.setDeviceGoneAwayCb(deviceGoneAwayInd);
}
void DeviceManager::deviceGoneAwayInd(const comms::DiscoveredDevice &device)
{
std::cout << "Device gone away: " << device.stringify() << std::endl;
// Check if device exists in our collection
if (!protoState.deviceManager->getDevice(device)) {
return;
}
// Find and remove the device from the collection
auto it = std::find_if(
protoState.deviceManager->devices.begin(),
protoState.deviceManager->devices.end(),
[&device](const std::shared_ptr<Device> &d) {
return d->discoveredDevice == device;
}
);
if (it != protoState.deviceManager->devices.end()) {
protoState.deviceManager->devices.erase(it);
}
}
std::shared_ptr<Device> DeviceManager::getOrCreateDevice(
const std::string &deviceIdentifier,
const std::shared_ptr<smo::ComponentThread>& componentThread,
int handshakeTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort
)
{
// Validate smoIp format using Boost.Asio IPv4 validation
if (!smoIp.empty() && !comms::isValidIPv4(smoIp))
{
throw std::invalid_argument(
std::string(__func__) +
": Invalid IPv4 smoIp format: " + smoIp);
}
// Validate subnet nbits
if (smoSubnetNbits > 32)
{
throw std::invalid_argument(
std::string(__func__) +
": smoSubnetNbits must be between 0 and 32, got: " +
std::to_string(smoSubnetNbits));
}
// First try to get existing device
auto existingDevice = getDevice(deviceIdentifier);
if (existingDevice) {
return existingDevice;
}
// Device doesn't exist, create a new one
auto newDevice = std::make_shared<Device>(
deviceIdentifier, componentThread,
handshakeTimeoutMs, retryDelayMs,
smoIp, smoSubnetNbits,
dataPort, cmdPort, imuPort);
// Add to our collection
devices.push_back(newDevice);
return newDevice;
}
std::shared_ptr<Device> DeviceManager::getDevice(
const std::string &deviceIdentifier
)
{
for (auto& device : devices)
{
if (comms::deviceIdentifiersEqual(
device->discoveredDevice.deviceIdentifier, deviceIdentifier))
{
return device;
}
}
return nullptr;
}
bool DeviceManager::isDeviceKnown(const std::string& deviceIdentifier)
{
return broadcastListener.deviceExists(deviceIdentifier);
}
void main(const std::shared_ptr<smo::ComponentThread> &componentThread)
{
if (protoState.isInitialized) {
return;
}
protoState.isInitialized = true;
protoState.componentThread = componentThread;
protoState.deviceManager = std::make_unique<DeviceManager>();
protoState.deviceManager->broadcastListener.start();
}
void exit(void)
{
if (!protoState.isInitialized) {
return;
}
protoState.deviceManager->broadcastListener.stop();
protoState.deviceManager.reset();
protoState.componentThread.reset();
protoState.isInitialized = false;
}
} // namespace livoxProto1