Fix issue multiple local participants

This commit is contained in:
Pascal Serrarens 2025-05-01 14:28:14 +02:00
parent 19310377ff
commit 2d77aa2461
5 changed files with 110 additions and 92 deletions

View File

@ -4,7 +4,9 @@
namespace RoboidControl { namespace RoboidControl {
std::list<Participant*> Participant::participants; #pragma region Participant
ParticipantRegistry Participant::registry;
Participant::Participant(const char* ipAddress, int port) { Participant::Participant(const char* ipAddress, int port) {
// make a copy of the ip address string // make a copy of the ip address string
@ -24,6 +26,7 @@ Participant::Participant(const char* ipAddress, int port) {
} }
Participant::~Participant() { Participant::~Participant() {
registry.Remove(this);
delete[] this->ipAddress; delete[] this->ipAddress;
} }
@ -34,56 +37,6 @@ void Participant::Update(unsigned long currentTimeMs) {
} }
} }
Participant* Participant::GetParticipant(const char* ipAddress,
unsigned int port) {
for (Participant* participant : Participant::participants) {
if (participant == nullptr)
continue;
if (strcmp(participant->ipAddress, ipAddress) == 0 &&
participant->port == port)
return participant;
}
// std::cout << "Could not find participant " << ipAddress << ":" << (int)port
// << std::endl;
return nullptr;
}
Participant* Participant::GetParticipant(unsigned char participantId) {
for (Participant* participant : Participant::participants) {
if (participant == nullptr)
continue;
if (participant->networkId == participantId)
return participant;
}
// std::cout << "Could not find participant " << (int)participantId << std::endl;
return nullptr;
}
Participant* Participant::AddParticipant(const char* ipAddress, unsigned int port) {
Participant* participant = new Participant(ipAddress, port);
Participant::AddParticipant(participant);
return participant;
}
void Participant::AddParticipant(Participant* participant) {
Participant* foundParticipant =
Participant::GetParticipant(participant->ipAddress, participant->port);
if (foundParticipant == nullptr) {
#if defined(NO_STD)
this->things[this->thingCount++] = thing;
#else
Participant::participants.push_back(participant);
#endif
std::cout << "Add participant " << participant->ipAddress << ":"
<< participant->port << "[" << (int)participant->networkId
<< "]\n";
} else {
std::cout << "Did not add, existing participant " << participant->ipAddress << ":"
<< participant->port << "[" << (int)participant->networkId
<< "]\n";
}
}
Thing* Participant::Get(unsigned char thingId) { Thing* Participant::Get(unsigned char thingId) {
for (Thing* thing : this->things) { for (Thing* thing : this->things) {
if (thing->id == thingId) if (thing->id == thingId)
@ -154,4 +107,75 @@ void Participant::Remove(Thing* thing) {
#endif #endif
} }
#pragma endregion
#pragma region ParticipantRegistry
Participant* ParticipantRegistry::GetParticipant(const char* ipAddress,
unsigned int port) {
for (Participant* participant : ParticipantRegistry::participants) {
if (participant == nullptr)
continue;
if (strcmp(participant->ipAddress, ipAddress) == 0 &&
participant->port == port) {
std::cout << "found participant " << participant->ipAddress << ":"
<< (int)participant->port << std::endl;
return participant;
}
}
std::cout << "Could not find participant " << ipAddress << ":" << (int)port
<< std::endl;
return nullptr;
}
Participant* ParticipantRegistry::GetParticipant(unsigned char participantId) {
for (Participant* participant : ParticipantRegistry::participants) {
if (participant == nullptr)
continue;
if (participant->networkId == participantId)
return participant;
}
std::cout << "Could not find participant " << (int)participantId << std::endl;
return nullptr;
}
Participant* ParticipantRegistry::AddParticipant(const char* ipAddress,
unsigned int port) {
Participant* participant = new Participant(ipAddress, port);
AddParticipant(participant);
return participant;
}
void ParticipantRegistry::AddParticipant(Participant* participant) {
Participant* foundParticipant =
GetParticipant(participant->ipAddress, participant->port);
if (foundParticipant == nullptr) {
#if defined(NO_STD)
this->things[this->thingCount++] = thing;
#else
ParticipantRegistry::participants.push_back(participant);
#endif
std::cout << "Add participant " << participant->ipAddress << ":"
<< participant->port << "[" << (int)participant->networkId
<< "]\n";
std::cout << "participants " << ParticipantRegistry::participants.size()
<< "\n";
} else {
std::cout << "Did not add, existing participant " << participant->ipAddress
<< ":" << participant->port << "[" << (int)participant->networkId
<< "]\n";
}
}
void ParticipantRegistry::Remove(Participant* participant) {
// participants.remove(participant);
}
const std::list<Participant*>& ParticipantRegistry::GetAll() const {
return ParticipantRegistry::participants;
}
#pragma endregion ParticipantRegistry
} // namespace RoboidControl } // namespace RoboidControl

View File

@ -5,6 +5,24 @@ namespace RoboidControl {
constexpr int MAX_THING_COUNT = 256; constexpr int MAX_THING_COUNT = 256;
class ParticipantRegistry {
public:
Participant* GetParticipant(const char* ipAddress, unsigned int port);
Participant* GetParticipant(unsigned char participantId);
Participant* AddParticipant(const char* ipAddress, unsigned int port);
void AddParticipant(Participant* participant);
void Remove(Participant* participant);
const std::list<Participant*>& GetAll() const;
private:
#if defined(NO_STD)
#else
/// @brief The list of known participants
std::list<Participant*> participants;
#endif
};
/// @brief A participant is a device which manages things. /// @brief A participant is a device which manages things.
/// It can communicate with other participant to synchronise the state of /// It can communicate with other participant to synchronise the state of
/// things. This class is used to register the things the participant is /// things. This class is used to register the things the participant is
@ -52,17 +70,8 @@ class Participant {
/// @param currentTimeMs The current time in milliseconds (optional) /// @param currentTimeMs The current time in milliseconds (optional)
virtual void Update(unsigned long currentTimeMs = 0); virtual void Update(unsigned long currentTimeMs = 0);
public: public:
#if defined(NO_STD) static ParticipantRegistry registry;
#else
/// @brief The list of known participants
static std::list<Participant*> participants;
#endif
static Participant* GetParticipant(const char* ipAddress, unsigned int port);
static Participant* GetParticipant(unsigned char participantId);
static Participant* AddParticipant(const char* ipAddress, unsigned int port);
static void AddParticipant(Participant* participant);
}; };
} // namespace RoboidControl } // namespace RoboidControl

View File

@ -4,32 +4,18 @@
#include "Arduino/ArduinoParticipant.h" #include "Arduino/ArduinoParticipant.h"
#include "EspIdf/EspIdfParticipant.h" #include "EspIdf/EspIdfParticipant.h"
#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#include <ws2tcpip.h>
#include "Windows/WindowsParticipant.h" #include "Windows/WindowsParticipant.h"
#pragma comment(lib, "ws2_32.lib")
#elif defined(__unix__) || defined(__APPLE__)
#include <arpa/inet.h>
#include <fcntl.h> // For fcntl
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <chrono>
#include "Posix/PosixParticipant.h" #include "Posix/PosixParticipant.h"
#endif
#include <string.h> #include <string.h>
namespace RoboidControl { namespace RoboidControl {
ParticipantUDP::ParticipantUDP(int port) : Participant("0.0.0.0", port) { ParticipantUDP::ParticipantUDP(int port) : Participant("127.0.0.1", port) {
this->remoteSite = nullptr; this->remoteSite = nullptr;
if (this->port == 0) if (this->port == 0)
this->isIsolated = true; this->isIsolated = true;
Participant::AddParticipant(this); Participant::registry.AddParticipant(this);
} }
ParticipantUDP::ParticipantUDP(const char* ipAddress, int port, int localPort) ParticipantUDP::ParticipantUDP(const char* ipAddress, int port, int localPort)
@ -38,7 +24,7 @@ ParticipantUDP::ParticipantUDP(const char* ipAddress, int port, int localPort)
this->isIsolated = true; this->isIsolated = true;
else else
this->remoteSite = new Participant(ipAddress, port); this->remoteSite = new Participant(ipAddress, port);
Participant::AddParticipant(this); Participant::registry.AddParticipant(this);
} }
static ParticipantUDP* isolatedParticipant = nullptr; static ParticipantUDP* isolatedParticipant = nullptr;
@ -50,7 +36,7 @@ ParticipantUDP* ParticipantUDP::Isolated() {
} }
void ParticipantUDP::begin() { void ParticipantUDP::begin() {
if (this->isIsolated) if (this->isIsolated || this->remoteSite == nullptr)
return; return;
SetupUDP(this->port, this->remoteSite->ipAddress, this->remoteSite->port); SetupUDP(this->port, this->remoteSite->ipAddress, this->remoteSite->port);
@ -157,11 +143,14 @@ void ParticipantUDP::UpdateMyThings(unsigned long currentTimeMs = 0) {
} }
void ParticipantUDP::UpdateOtherThings(unsigned long currentTimeMs = 0) { void ParticipantUDP::UpdateOtherThings(unsigned long currentTimeMs = 0) {
for (Participant* participant : Participant::participants) { for (Participant* participant : Participant::registry.GetAll()) {
if (participant == nullptr || participant == this) if (participant == nullptr || participant == this)
continue; continue;
participant->Update(currentTimeMs); // Call only the Participant version of the Update.
// This is to deal with the function where one of the (remote)
// participants is actually a local participant
participant->Participant::Update(currentTimeMs);
if (this->isIsolated) if (this->isIsolated)
continue; continue;
@ -301,9 +290,9 @@ void ParticipantUDP::ReceiveData(unsigned char packetSize,
unsigned int senderPort) { unsigned int senderPort) {
// std::cout << "Receive data from " << senderIpAddress << ":" << senderPort // std::cout << "Receive data from " << senderIpAddress << ":" << senderPort
// << std::endl; // << std::endl;
Participant* sender = this->GetParticipant(senderIpAddress, senderPort); Participant* sender = this->registry.GetParticipant(senderIpAddress, senderPort);
if (sender == nullptr) { if (sender == nullptr) {
sender = this->AddParticipant(senderIpAddress, senderPort); sender = this->registry.AddParticipant(senderIpAddress, senderPort);
#if !defined(NO_STD) #if !defined(NO_STD)
std::cout << "New remote participant " << sender->ipAddress << ":" std::cout << "New remote participant " << sender->ipAddress << ":"
<< sender->port << std::endl; << sender->port << std::endl;
@ -456,7 +445,7 @@ void ParticipantUDP::Process(Participant* sender, PoseMsg* msg) {
std::cout << this->name << ": process PoseMsg [" << (int)this->networkId std::cout << this->name << ": process PoseMsg [" << (int)this->networkId
<< "/" << (int)msg->networkId << "] " << (int)msg->poseType << "\n"; << "/" << (int)msg->networkId << "] " << (int)msg->poseType << "\n";
#endif #endif
Participant* owner = Participant::GetParticipant(msg->networkId); Participant* owner = Participant::registry.GetParticipant(msg->networkId);
if (owner == nullptr) if (owner == nullptr)
return; return;
@ -480,7 +469,7 @@ void ParticipantUDP::Process(Participant* sender, BinaryMsg* msg) {
<< "/" << (int)msg->thingId << "]\n"; << "/" << (int)msg->thingId << "]\n";
#endif #endif
Participant* owner = Participant::GetParticipant(msg->networkId); Participant* owner = Participant::registry.GetParticipant(msg->networkId);
if (owner != nullptr) { if (owner != nullptr) {
Thing* thing = owner->Get(msg->thingId); Thing* thing = owner->Get(msg->thingId);
if (thing != nullptr) if (thing != nullptr)

View File

@ -11,13 +11,10 @@ namespace RoboidControl {
#pragma region Init #pragma region Init
SiteServer::SiteServer(int port) { SiteServer::SiteServer(int port) : ParticipantUDP(port) {
this->name = "Site Server"; this->name = "Site Server";
this->publishInterval = 0; this->publishInterval = 0;
this->ipAddress = "0.0.0.0";
this->port = port;
SetupUDP(port, ipAddress, 0); SetupUDP(port, ipAddress, 0);
} }
@ -34,7 +31,7 @@ void SiteServer::UpdateMyThings(unsigned long currentTimeMs) {
if (this->isIsolated == false) { if (this->isIsolated == false) {
// Send to all other participants // Send to all other participants
for (Participant* participant : Participant::participants) { for (Participant* participant : Participant::registry.GetAll()) {
if (participant == nullptr || participant == this) if (participant == nullptr || participant == this)
continue; continue;

View File

@ -66,7 +66,6 @@ class Thing {
public: public:
/// @brief Terminated things are no longer updated /// @brief Terminated things are no longer updated
void Terminate();
bool terminate = false; bool terminate = false;
#pragma region Properties #pragma region Properties