#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 #include // #include #endif #if defined(_WIN32) || defined(_WIN64) #include #elif defined(__unix__) || defined(__APPLE__) #include #include #include #include #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& GetAll() const; private: /// @brief The list of known participants std::list 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" #include "Posix/PosixParticipant.h"