Comments and formatting
This commit is contained in:
@@ -17,7 +17,6 @@
|
|||||||
namespace livoxProto1 {
|
namespace livoxProto1 {
|
||||||
namespace comms {
|
namespace comms {
|
||||||
|
|
||||||
// DiscoveredDevice constructors
|
|
||||||
DiscoveredDevice::DiscoveredDevice(
|
DiscoveredDevice::DiscoveredDevice(
|
||||||
const std::string &deviceIdentifier,
|
const std::string &deviceIdentifier,
|
||||||
DeviceType deviceType,
|
DeviceType deviceType,
|
||||||
@@ -65,7 +64,6 @@ std::string DiscoveredDevice::getDeviceTypeName(void) const
|
|||||||
|
|
||||||
} // namespace comms
|
} // namespace comms
|
||||||
|
|
||||||
// Device implementation
|
|
||||||
Device::Device(const std::string &deviceIdentifier,
|
Device::Device(const std::string &deviceIdentifier,
|
||||||
const std::shared_ptr<smo::ComponentThread>& componentThread,
|
const std::shared_ptr<smo::ComponentThread>& componentThread,
|
||||||
int handshakeTimeoutMs, int retryDelayMs,
|
int handshakeTimeoutMs, int retryDelayMs,
|
||||||
@@ -86,7 +84,6 @@ heartbeatActive(false)
|
|||||||
|
|
||||||
Device::~Device()
|
Device::~Device()
|
||||||
{
|
{
|
||||||
// Stop heartbeat if active
|
|
||||||
if (heartbeatActive.load()) {
|
if (heartbeatActive.load()) {
|
||||||
heartbeatActive.store(false);
|
heartbeatActive.store(false);
|
||||||
if (heartbeatTimer) {
|
if (heartbeatTimer) {
|
||||||
@@ -94,7 +91,6 @@ Device::~Device()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up heartbeat resources
|
|
||||||
heartbeatTimer.reset();
|
heartbeatTimer.reset();
|
||||||
heartbeatSocket.reset();
|
heartbeatSocket.reset();
|
||||||
}
|
}
|
||||||
@@ -199,7 +195,12 @@ bool Device::executeHandshake(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// Create boost::asio UDP socket
|
/** EXPLANATION:
|
||||||
|
* This io_context queue here will allow us to async-bridge the
|
||||||
|
* handshake request and response without having to worry about
|
||||||
|
* re-enqueueing messages, as we would have to do if we used the
|
||||||
|
* io_context of a ComponentThread.
|
||||||
|
*/
|
||||||
boost::asio::io_context io_context;
|
boost::asio::io_context io_context;
|
||||||
boost::asio::ip::udp::socket socket(io_context);
|
boost::asio::ip::udp::socket socket(io_context);
|
||||||
socket.open(boost::asio::ip::udp::v4());
|
socket.open(boost::asio::ip::udp::v4());
|
||||||
@@ -328,7 +329,15 @@ std::string Device::generateClientDeviceIpFromSerialNumber(
|
|||||||
const std::string& broadcastCode
|
const std::string& broadcastCode
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Determine if input is serial number (14 chars) or broadcast code (15 chars)
|
/** EXPLANATION:
|
||||||
|
* The input string is either a serial number (14 chars) or a broadcast code
|
||||||
|
* (15 chars). We need to determine which one it is and extract the serial
|
||||||
|
* number from the broadcast code.
|
||||||
|
*
|
||||||
|
* To generate a default IP address, we use the device's subnet: X.X.X.1XX
|
||||||
|
* where XX = last two digits of serial. We use the smoIp and smoSubnetNbits
|
||||||
|
* to determine the network prefix.
|
||||||
|
*/
|
||||||
if (broadcastCode.empty())
|
if (broadcastCode.empty())
|
||||||
{
|
{
|
||||||
throw std::invalid_argument(
|
throw std::invalid_argument(
|
||||||
@@ -383,7 +392,6 @@ std::string Device::generateClientDeviceIpFromSerialNumber(
|
|||||||
// Generate subnet mask based on nbits
|
// Generate subnet mask based on nbits
|
||||||
uint32_t subnetMask = getSubnetMaskFor(smoSubnetNbits);
|
uint32_t subnetMask = getSubnetMaskFor(smoSubnetNbits);
|
||||||
|
|
||||||
// Convert smoIp to uint32_t for bitwise operations
|
|
||||||
uint32_t smoIpAddr = (std::stoi(smoIpOctets->octet1) << 24) |
|
uint32_t smoIpAddr = (std::stoi(smoIpOctets->octet1) << 24) |
|
||||||
(std::stoi(smoIpOctets->octet2) << 16) |
|
(std::stoi(smoIpOctets->octet2) << 16) |
|
||||||
(std::stoi(smoIpOctets->octet3) << 8) |
|
(std::stoi(smoIpOctets->octet3) << 8) |
|
||||||
@@ -408,7 +416,10 @@ void Device::startHeartbeat()
|
|||||||
return; // Can't start heartbeat without component thread or IP
|
return; // Can't start heartbeat without component thread or IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create heartbeat socket using the component thread's io_service
|
/** EXPLANATION:
|
||||||
|
* Create heartbeat socket using io_service of the componentThread that was
|
||||||
|
* given to us for use by this device.
|
||||||
|
*/
|
||||||
heartbeatSocket = std::make_unique<boost::asio::ip::udp::socket>(
|
heartbeatSocket = std::make_unique<boost::asio::ip::udp::socket>(
|
||||||
componentThread->getIoService());
|
componentThread->getIoService());
|
||||||
heartbeatSocket->open(boost::asio::ip::udp::v4());
|
heartbeatSocket->open(boost::asio::ip::udp::v4());
|
||||||
@@ -432,7 +443,6 @@ void Device::sendHeartbeat()
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create heartbeat message using the new HeartbeatMessage type
|
|
||||||
comms::HeartbeatMessage heartbeatMsg;
|
comms::HeartbeatMessage heartbeatMsg;
|
||||||
|
|
||||||
heartbeatMsg.swapContentsToProtocolEndianness();
|
heartbeatMsg.swapContentsToProtocolEndianness();
|
||||||
@@ -440,15 +450,18 @@ void Device::sendHeartbeat()
|
|||||||
heartbeatMsg.header.swapCrc16ToProtocolEndianness();
|
heartbeatMsg.header.swapCrc16ToProtocolEndianness();
|
||||||
heartbeatMsg.footer.crc_32 = heartbeatMsg.calculateCrc32();
|
heartbeatMsg.footer.crc_32 = heartbeatMsg.calculateCrc32();
|
||||||
heartbeatMsg.footer.swapCrc32ToProtocolEndianness();
|
heartbeatMsg.footer.swapCrc32ToProtocolEndianness();
|
||||||
// Send the heartbeat packet
|
|
||||||
boost::asio::ip::udp::endpoint deviceEndpoint(
|
boost::asio::ip::udp::endpoint deviceEndpoint(
|
||||||
boost::asio::ip::address::from_string(discoveredDevice.ipAddr), cmdPort);
|
boost::asio::ip::address::from_string(discoveredDevice.ipAddr),
|
||||||
|
cmdPort);
|
||||||
|
|
||||||
heartbeatSocket->send_to(
|
heartbeatSocket->send_to(
|
||||||
boost::asio::buffer(&heartbeatMsg, sizeof(heartbeatMsg)),
|
boost::asio::buffer(&heartbeatMsg, sizeof(heartbeatMsg)),
|
||||||
deviceEndpoint);
|
deviceEndpoint);
|
||||||
|
|
||||||
// Schedule next heartbeat in 1 second
|
/** EXPLANATION:
|
||||||
|
* Schedule next heartbeat in 1 second, per the spec.
|
||||||
|
*/
|
||||||
heartbeatTimer->expires_from_now(boost::posix_time::seconds(1));
|
heartbeatTimer->expires_from_now(boost::posix_time::seconds(1));
|
||||||
heartbeatTimer->async_wait(
|
heartbeatTimer->async_wait(
|
||||||
[this](const boost::system::error_code& error) {
|
[this](const boost::system::error_code& error) {
|
||||||
@@ -543,7 +556,10 @@ std::optional<std::string> Device::detectSmoIp(const std::string& deviceIP)
|
|||||||
|
|
||||||
std::string found_ip;
|
std::string found_ip;
|
||||||
|
|
||||||
// Iterate through all network interfaces
|
/** EXPLANATION:
|
||||||
|
* Iterate through all network interfaces and check if the IP address is
|
||||||
|
* in the same subnet as the device's IP address.
|
||||||
|
*/
|
||||||
for (struct ifaddrs *ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
|
for (struct ifaddrs *ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
|
||||||
{
|
{
|
||||||
if (ifa->ifa_addr == nullptr) continue;
|
if (ifa->ifa_addr == nullptr) continue;
|
||||||
@@ -580,7 +596,7 @@ std::optional<std::string> Device::detectSmoIp(const std::string& deviceIP)
|
|||||||
if ((ipAddr & subnetMask) == (deviceIpAddr & subnetMask))
|
if ((ipAddr & subnetMask) == (deviceIpAddr & subnetMask))
|
||||||
{
|
{
|
||||||
found_ip = ip;
|
found_ip = ip;
|
||||||
break; // Exit loop, let unique_ptr handle cleanup
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,7 +614,11 @@ std::optional<std::string> Device::detectSmoIp(const std::string& deviceIP)
|
|||||||
|
|
||||||
std::string Device::getSmoIp(const std::string& deviceIP)
|
std::string Device::getSmoIp(const std::string& deviceIP)
|
||||||
{
|
{
|
||||||
// If smo-ip was provided, return it
|
/** EXPLANATION:
|
||||||
|
* If smo-ip was provided, return it.
|
||||||
|
* Otherwise, try to detect it based on the client device's IP address.
|
||||||
|
* If detection failed, throw an exception.
|
||||||
|
*/
|
||||||
if (!smoIp.empty()) {
|
if (!smoIp.empty()) {
|
||||||
return smoIp;
|
return smoIp;
|
||||||
}
|
}
|
||||||
@@ -608,7 +628,6 @@ std::string Device::getSmoIp(const std::string& deviceIP)
|
|||||||
return detectedIp.value();
|
return detectedIp.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If detection failed, throw an exception
|
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::string(__func__) + ": Failed to detect SMO IP address for device "
|
std::string(__func__) + ": Failed to detect SMO IP address for device "
|
||||||
+ deviceIP + " with subnet mask /" + std::to_string(smoSubnetNbits));
|
+ deviceIP + " with subnet mask /" + std::to_string(smoSubnetNbits));
|
||||||
|
|||||||
@@ -13,7 +13,10 @@
|
|||||||
namespace livoxProto1 {
|
namespace livoxProto1 {
|
||||||
namespace comms {
|
namespace comms {
|
||||||
|
|
||||||
// Livox SDK CRC constants
|
/** EXPLANATION:
|
||||||
|
* Undocumented Livox SDK CRC seed constants. These were found in the Livox SDK
|
||||||
|
* source code.
|
||||||
|
*/
|
||||||
constexpr uint16_t LIVOX_CRC16_SEED = 0x4c49;
|
constexpr uint16_t LIVOX_CRC16_SEED = 0x4c49;
|
||||||
constexpr uint32_t LIVOX_CRC32_SEED = 0x564f580a;
|
constexpr uint32_t LIVOX_CRC32_SEED = 0x564f580a;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user