227 lines
7.3 KiB
C++
227 lines
7.3 KiB
C++
#pragma once
|
|
|
|
#include "Messages/BinaryMsg.h"
|
|
#include "Messages/DestroyMsg.h"
|
|
#include "Messages/InvestigateMsg.h"
|
|
#include "Messages/ModelUrlMsg.h"
|
|
#include "Messages/NameMsg.h"
|
|
#include "Messages/NetworkIdMsg.h"
|
|
#include "Messages/ParticipantMsg.h"
|
|
#include "Messages/PoseMsg.h"
|
|
#include "Messages/TextMsg.h"
|
|
#include "Messages/ThingMsg.h"
|
|
#include "Participant.h"
|
|
|
|
#if !defined(NO_STD)
|
|
#include <functional>
|
|
#include <list>
|
|
// #include <unordered_map>
|
|
#endif
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
#include <winsock2.h>
|
|
#elif defined(__unix__) || defined(__APPLE__)
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
namespace RoboidControl {
|
|
|
|
constexpr int MAX_SENDER_COUNT = 256;
|
|
|
|
class RemoteParticipantUDP : public Participant {
|
|
public:
|
|
/// @brief Create a new participant with the given communcation info
|
|
/// @param ipAddress The IP address of the participant
|
|
/// @param port The UDP port of the participant
|
|
/// @remarks This does not belong here, it should move to ParticipantUDP or
|
|
/// something like that in the future
|
|
RemoteParticipantUDP(const char* ipAddress, int port);
|
|
|
|
/// @brief The Ip Address of a participant.
|
|
/// @remarks This does not belong here, it should move to ParticipantUDP or
|
|
/// something like that in the future
|
|
const char* ipAddress = "0.0.0.0";
|
|
/// @brief The port number for UDP communication with the participant.
|
|
/// @remarks This does not belong here, it should move to ParticipantUDP or
|
|
/// something like that in the future
|
|
unsigned int port = 0;
|
|
|
|
bool Send(IMessage* msg) override;
|
|
};
|
|
|
|
/// @brief class which manages all known participants
|
|
class ParticipantRegistry {
|
|
public:
|
|
/// @brief Retrieve a participant by its address
|
|
/// @param ipAddress The IP address of the participant
|
|
/// @param port The port number of the participant
|
|
/// @return The participant or a nullptr when it could not be found
|
|
RemoteParticipantUDP* Get(const char* ipAddress, unsigned int port);
|
|
/// @brief Retrieve a participant by its network ID
|
|
/// @param networkID The network ID of the participant
|
|
/// @return The participant or a nullptr when it could not be found
|
|
RemoteParticipantUDP* Get(unsigned char networkID);
|
|
|
|
/// @brief Add a participant with the given details
|
|
/// @param ipAddress The IP address of the participant
|
|
/// @param port The port number of the participant
|
|
/// @return The added participant
|
|
RemoteParticipantUDP* Add(const char* ipAddress, unsigned int port);
|
|
|
|
/// @brief Add a participant
|
|
/// @param participant The participant to add
|
|
void Add(RemoteParticipantUDP* participant);
|
|
|
|
/// @brief Remove a participant
|
|
/// @param participant The participant to remove
|
|
void Remove(RemoteParticipantUDP* participant);
|
|
|
|
private:
|
|
#if defined(NO_STD)
|
|
public:
|
|
RemoteParticipantUDP** GetAll() const;
|
|
int count = 0;
|
|
|
|
private:
|
|
RemoteParticipantUDP** participants;
|
|
#else
|
|
public:
|
|
/// @brief Get all participants
|
|
/// @return All participants
|
|
const std::list<RemoteParticipantUDP*>& GetAll() const;
|
|
|
|
private:
|
|
/// @brief The list of known participants
|
|
std::list<RemoteParticipantUDP*> participants;
|
|
#endif
|
|
};
|
|
|
|
/// @brief A participant using UDP communication
|
|
/// A local participant is the local device which can communicate with
|
|
/// other participants It manages all local things and communcation with other
|
|
/// participants. Each application has a local participant which is usually
|
|
/// explicit in the code. An participant can be isolated. In that case it is
|
|
/// standalong and does not communicate with other participants.
|
|
///
|
|
/// It is possible to work with an hidden participant by creating things without
|
|
/// specifying a participant in the constructor. In that case an hidden isolated
|
|
/// participant is created which can be obtained using
|
|
/// RoboidControl::IsolatedParticipant::Isolated().
|
|
/// @sa RoboidControl::Thing::Thing()
|
|
class ParticipantUDPGeneric : public RemoteParticipantUDP {
|
|
#pragma region Init
|
|
|
|
public:
|
|
/// @brief Create a participant without connecting to a site
|
|
/// @param port The port on which the participant communicates
|
|
/// These participant typically broadcast Participant messages to let site
|
|
/// servers on the local network know their presence. Alternatively they can
|
|
/// broadcast information which can be used directly by other participants.
|
|
ParticipantUDPGeneric(int port = 7681);
|
|
/// @brief Create a participant which will try to connect to a site.
|
|
/// @param ipAddress The IP address of the site
|
|
/// @param port The port used by the site
|
|
/// @param localPort The port used by the local participant
|
|
ParticipantUDPGeneric(const char* ipAddress,
|
|
int port = 7681,
|
|
int localPort = 7681);
|
|
|
|
#pragma endregion Init
|
|
|
|
#pragma region Properties
|
|
|
|
public:
|
|
/// @brief True if the participant is running isolated.
|
|
/// Isolated participants do not communicate with other participants
|
|
bool isIsolated = false;
|
|
|
|
/// @brief The remote site when this participant is connected to a site
|
|
RemoteParticipantUDP* remoteSite = nullptr;
|
|
|
|
/// The interval in milliseconds for publishing (broadcasting) data on the
|
|
/// local network
|
|
long publishInterval = 3000; // 3 seconds
|
|
|
|
protected:
|
|
#if !defined(ARDUINO)
|
|
#if defined(__unix__) || defined(__APPLE__)
|
|
int sock;
|
|
#elif defined(_WIN32) || defined(_WIN64)
|
|
sockaddr_in remote_addr;
|
|
sockaddr_in server_addr;
|
|
sockaddr_in broadcast_addr;
|
|
#endif
|
|
#endif
|
|
public:
|
|
void begin();
|
|
bool connected = false;
|
|
|
|
#pragma endregion Properties
|
|
|
|
#pragma region Update
|
|
|
|
public:
|
|
virtual void Update(bool recurse = true) override;
|
|
|
|
protected:
|
|
unsigned long nextPublishMe = 0;
|
|
|
|
/// @brief Prepare the local things for the next update
|
|
// virtual void PrepMyThings();
|
|
virtual void UpdateMyThings();
|
|
virtual void UpdateOtherThings();
|
|
|
|
#pragma endregion Update
|
|
|
|
#pragma region Send
|
|
|
|
void SendThingInfo(Participant* remoteParticipant, Thing* thing);
|
|
void PublishThingInfo(Thing* thing);
|
|
|
|
virtual bool Send(IMessage* msg) override;
|
|
virtual bool Publish(IMessage* msg) = 0;
|
|
|
|
#pragma endregion Send
|
|
|
|
#pragma region Receive
|
|
|
|
protected:
|
|
void ReceiveData(unsigned char bufferSize,
|
|
char* senderIpAddress,
|
|
unsigned int senderPort);
|
|
void ReceiveData(unsigned char bufferSize, RemoteParticipantUDP* remoteParticipant);
|
|
|
|
virtual void SetupUDP(int localPort, const char* remoteIpAddress, int remotePort) = 0;
|
|
|
|
virtual void ReceiveUDP() = 0;
|
|
|
|
virtual void Process(RemoteParticipantUDP* sender, ParticipantMsg* msg);
|
|
virtual void Process(RemoteParticipantUDP* sender, NetworkIdMsg* msg);
|
|
virtual void Process(RemoteParticipantUDP* sender, InvestigateMsg* msg);
|
|
|
|
virtual void Process(RemoteParticipantUDP* sender, ThingMsg* msg);
|
|
virtual Thing* ProcessNewThing(RemoteParticipantUDP* sender,
|
|
ThingMsg* msg,
|
|
bool isRemote);
|
|
|
|
virtual void Process(RemoteParticipantUDP* sender, NameMsg* msg);
|
|
virtual void Process(RemoteParticipantUDP* sender, ModelUrlMsg* msg);
|
|
virtual void Process(RemoteParticipantUDP* sender, PoseMsg* msg);
|
|
virtual void Process(RemoteParticipantUDP* sender, BinaryMsg* msg);
|
|
virtual void Process(RemoteParticipantUDP* sender, TextMsg* msg);
|
|
virtual void Process(RemoteParticipantUDP* sender, DestroyMsg* msg);
|
|
|
|
#pragma endregion Receive
|
|
|
|
public:
|
|
static ParticipantRegistry registry;
|
|
|
|
};
|
|
|
|
} // namespace RoboidControl
|
|
|
|
#include "EspIdf/EspIdfParticipant.h"
|