RoboidControl-cpp/Participant.cpp
2025-01-11 12:04:34 +01:00

233 lines
6.6 KiB
C++

#include "Participant.h"
// #include <ws2tcpip.h>
#define BUF_SIZE 1024
#include "UdpArduino.h"
#include "UdpPosix.h"
#include "UdpWindows.h"
#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#include <ws2tcpip.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>
#endif
Participant::Participant() {}
Participant::Participant(int port) {
this->ipAddress = "0.0.0.0";
this->port = port;
this->participants.push_back(this);
int randomPort = (rand() % (65535 - 49152 + 1)) + 49152;
SetupUDP(randomPort, ipAddress, port);
}
Participant::Participant(const char *ipAddress, int port) {
this->ipAddress = ipAddress;
this->port = port;
this->participants.push_back(this);
int randomPort = (rand() % (65535 - 49152 + 1)) + 49152;
SetupUDP(randomPort, ipAddress, port);
}
void Passer::Control::Participant::SetupUDP(int localPort,
const char *remoteIpAddress,
int remotePort) {
#if defined(_WIN32) || defined(_WIN64)
UdpWindows *thisWindows = static_cast<UdpWindows *>(this);
thisWindows->Setup(localPort, remoteIpAddress, remotePort);
#elif defined(__unix__) || defined(__APPLE__)
UdpPosix *thisPosix = static_cast<UdpPosix *>(this);
thisPosix->Setup(localPort, remoteIpAddress, remotePort);
#elif defined(ARDUINO)
UdpArduino *thisArduino = static_cast<UdpArduino *>(this);
thisArduino->Setup(localPort, remoteIpAddress, remotePort);
#endif
}
void Participant::Update(unsigned long currentTimeMs) {
if (this->publishInterval > 0 && currentTimeMs > this->nextPublishMe) {
ClientMsg *msg = new ClientMsg(this->networkId);
this->Publish(msg);
delete msg;
std::cout << this->name << " published ClientMsg\n";
this->nextPublishMe = currentTimeMs + this->publishInterval;
}
this->ReceiveUDP();
Thing::UpdateAll(currentTimeMs);
}
void Participant::ReceiveUDP() {
#if defined(_WIN32) || defined(_WIN64)
UdpWindows *thisWindows = static_cast<UdpWindows *>(this);
thisWindows->Receive();
#elif defined(__unix__) || defined(__APPLE__)
UdpPosix *thisPosix = static_cast<UdpPosix *>(this);
thisPosix->Receive();
#elif defined(ARDUINO)
UdpArduino *thisArduino = static_cast<UdpArduino *>(this);
thisArduino->Receive();
#endif
}
Participant *Participant::GetParticipant(const char *ipAddress, int port) {
for (Participant *participant : this->participants) {
if (participant->ipAddress == ipAddress && participant->port == port)
return participant;
}
return nullptr;
}
Participant *Participant::AddParticipant(const char *ipAddress, int port) {
Participant *participant = new Participant(ipAddress, port);
participant->networkId = (unsigned char)this->participants.size();
this->participants.push_back(participant);
return participant;
}
#pragma region Send
void Participant::SendThingInfo(Thing *thing) {
std::cout << "Send thing info\n";
IMessage *msg = new ThingMsg(this->networkId, thing);
this->Send(msg);
delete msg;
msg = new NameMsg(this->networkId, thing);
this->Send(msg);
delete msg;
msg = new ModelUrlMsg(this->networkId, thing);
this->Send(msg);
delete msg;
}
void Passer::Control::Participant::PublishThingInfo(Thing *thing) {
// std::cout << "Publish thing info" << thing->networkId << "\n";
// Strange, when publishing, the network id is irrelevant, because it is
// connected to a specific site...
ThingMsg *thingMsg = new ThingMsg(this->networkId, thing);
this->Publish(thingMsg);
delete thingMsg;
NameMsg *nameMsg = new NameMsg(this->networkId, thing);
this->Publish(nameMsg);
delete nameMsg;
ModelUrlMsg *modelMsg = new ModelUrlMsg(this->networkId, thing);
this->Publish(modelMsg);
delete modelMsg;
}
bool Participant::Send(IMessage *msg) {
#if defined(_WIN32) || defined(_WIN64)
UdpWindows *thisWindows = static_cast<UdpWindows *>(this);
return thisWindows->Send(msg);
#elif defined(__unix__) || defined(__APPLE__)
UdpPosix *thisPosix = static_cast<UdpPosix *>(this);
return thisPosix->Send(msg);
#elif defined(ARDUINO)
UdpArduino *thisArduino = static_cast<UdpArduino *>(this);
return thisArduino->Send(msg);
#endif
}
bool Participant::Publish(IMessage *msg) {
#if defined(_WIN32) || defined(_WIN64)
UdpWindows *thisWindows = static_cast<UdpWindows *>(this);
return thisWindows->Publish(msg);
#elif defined(__unix__) || defined(__APPLE__)
UdpPosix *thisPosix = static_cast<UdpPosix *>(this);
return thisPosix->Publish(msg);
#elif defined(ARDUINO)
UdpArduino *thisArduino = static_cast<UdpArduino *>(this);
return thisArduino->Publish(msg);
#endif
}
// Send
#pragma endregion
#pragma region Receive
void Participant::ReceiveData(unsigned char bufferSize,
Participant *remoteParticipant) {
unsigned char msgId = this->buffer[0];
switch (msgId) {
case ClientMsg::id: {
ClientMsg *msg = new ClientMsg(this->buffer);
Process(remoteParticipant, msg);
delete msg;
}
case NetworkIdMsg::id: {
NetworkIdMsg *msg = new NetworkIdMsg(this->buffer);
Process(remoteParticipant, msg);
delete msg;
} break;
case InvestigateMsg::id: {
InvestigateMsg *msg = new InvestigateMsg(this->buffer);
Process(msg);
delete msg;
} break;
case ThingMsg::id: {
ThingMsg *msg = new ThingMsg(this->buffer);
Process(msg);
delete msg;
} break;
case PoseMsg::id: {
PoseMsg *msg = new PoseMsg(this->buffer);
Process(msg);
delete msg;
} break;
case CustomMsg::id: {
CustomMsg *msg = new CustomMsg(this->buffer);
Process(msg);
delete msg;
} break;
};
}
void Participant::Process(Participant *sender, ClientMsg *msg) {}
void Participant::Process(Participant *sender, NetworkIdMsg *msg) {
std::cout << this->name << " receive network id " << (int)this->networkId
<< " " << (int)msg->networkId << "\n";
if (this->networkId != msg->networkId) {
this->networkId = msg->networkId;
// Thing **allThings = Thing::GetAllThings();
// for (uint16_t ix = 0; ix < THING_STORE_SIZE; ix++) {
// Thing *thing = allThings[ix];
// if (thing == nullptr)
// continue;
// sender->SendThingInfo(thing);
// }
for (Thing *thing : allThings) {
sender->SendThingInfo(thing);
}
}
}
void Participant::Process(InvestigateMsg *msg) {}
void Participant::Process(ThingMsg *msg) {}
void Participant::Process(PoseMsg *msg) {}
void Participant::Process(CustomMsg *msg) {
Thing *thing = Thing::Get(msg->networkId, msg->thingId);
if (thing != nullptr)
thing->ProcessBytes(msg->bytes);
}
// Receive
#pragma endregion