From 36740cf5988c5330b10134958d77fe8e4e764522 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 30 Apr 2025 17:00:21 +0200 Subject: [PATCH] Aligned Participants --- src/Participants/ParticipantUDP.cs | 166 +++++++++++++++-------------- src/Participants/SiteServer.cs | 6 +- 2 files changed, 93 insertions(+), 79 deletions(-) diff --git a/src/Participants/ParticipantUDP.cs b/src/Participants/ParticipantUDP.cs index 2dced60..5e668e8 100644 --- a/src/Participants/ParticipantUDP.cs +++ b/src/Participants/ParticipantUDP.cs @@ -7,40 +7,41 @@ using System.Net.NetworkInformation; namespace RoboidControl { /// - /// A participant is used for communcation between things + /// 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() public class ParticipantUDP : Participant { - public byte[] buffer = new byte[1024]; - public ulong publishInterval = 3000; // = 3 seconds - - public string name = "Participant"; - - public bool isIsolated = false; - public Participant remoteSite; - - public IPEndPoint endPoint = null; - public UdpClient udpClient = null; - public string broadcastIpAddress = "255.255.255.255"; - - public readonly ConcurrentQueue messageQueue = new ConcurrentQueue(); #region Init /// - /// Create a participant with the give UDP port + /// Create a participant without connecting to a site /// /// The port number on which to communicate + /// 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. public ParticipantUDP(int port = 0) : base("127.0.0.1", port) { if (this.port == 0) this.isIsolated = true; Participant.AddParticipant(this); } - /// - /// Create a new participant for a site at the given address and port + /// Create a participant which will try to connect to a site. /// /// The ip address of the site server /// The port number of the site server + /// The port used by the local participant public ParticipantUDP(string ipAddress, int port = 7681, int localPort = 7681) : base("127.0.0.1", localPort) { if (this.port == 0) this.isIsolated = true; @@ -81,16 +82,48 @@ namespace RoboidControl { } + private static ParticipantUDP isolatedParticipant = null; + /// - /// Create a participant using the given udp client + /// Isolated participant is used when the application is run without networking /// - /// UDP client to use for communication - /// The port number on which to communicate - public ParticipantUDP(UdpClient udpClient, int port) : this() { - this.udpClient = udpClient; - this.port = port; + /// A participant without networking support + public static ParticipantUDP Isolated() { + if (isolatedParticipant == null) + isolatedParticipant = new ParticipantUDP(0); + return isolatedParticipant; } + #endregion Init + + /// + /// The name of the participant + /// + public string name = "ParticipantUDP"; + + /// + /// True if the participant is running isolated. + /// + /// Isolated participants do not communicate with other participants + public bool isIsolated = false; + /// + /// The remote site when this participant is connected to a site + /// + public Participant remoteSite = null; + + /// + /// The interval in milliseconds for publishing (broadcasting) data on the local network + /// + public ulong publishInterval = 3000; // = 3 seconds + + public byte[] buffer = new byte[1024]; + + public IPEndPoint endPoint = null; + public UdpClient udpClient = null; + public string broadcastIpAddress = "255.255.255.255"; + + public readonly ConcurrentQueue messageQueue = new ConcurrentQueue(); + protected void GetBroadcastAddress(IPAddress ip, IPAddress subnetMask) { byte[] ipBytes = ip.GetAddressBytes(); byte[] maskBytes = subnetMask.GetAddressBytes(); @@ -110,14 +143,6 @@ namespace RoboidControl { Console.WriteLine($"Broadcast address: {this.broadcastIpAddress}"); } - private static ParticipantUDP isolatedParticipant = null; - public static ParticipantUDP Isolated() { - if (isolatedParticipant == null) - isolatedParticipant = new ParticipantUDP(0); - return isolatedParticipant; - } - #endregion Init - #region Update protected ulong nextPublishMe = 0; @@ -208,9 +233,19 @@ namespace RoboidControl { this.Send(owner, new ThingMsg(this.networkId, thing)); this.Send(owner, new NameMsg(this.networkId, thing)); this.Send(owner, new ModelUrlMsg(this.networkId, thing)); + this.Send(owner, new PoseMsg(this.networkId, thing)); this.Send(owner, new BinaryMsg(this.networkId, thing)); } + public void PublishThingInfo(Thing thing) { + // Console.WriteLine("Publish thing info"); + this.Publish(new ThingMsg(this.networkId, thing)); + this.Publish(new NameMsg(this.networkId, thing)); + this.Publish(new ModelUrlMsg(this.networkId, thing)); + this.Publish(new PoseMsg(this.networkId, thing)); + this.Publish(new BinaryMsg(this.networkId, thing)); + } + public bool Send(Participant owner, IMessage msg) { int bufferSize = msg.Serialize(ref this.buffer); if (bufferSize <= 0) @@ -222,14 +257,6 @@ namespace RoboidControl { return true; } - public void PublishThingInfo(Thing thing) { - // Console.WriteLine("Publish thing info"); - this.Publish(new ThingMsg(this.networkId, thing)); - this.Publish(new NameMsg(this.networkId, thing)); - this.Publish(new ModelUrlMsg(this.networkId, thing)); - this.Publish(new BinaryMsg(this.networkId, thing)); - } - public bool Publish(IMessage msg) { int bufferSize = msg.Serialize(ref this.buffer); if (bufferSize <= 0) @@ -240,24 +267,6 @@ namespace RoboidControl { return true; } - // public bool SendBuffer(int bufferSize) { - // //if (this.ipAddress == null) - // // return false; - - // // UnityEngine.Debug.Log($"Send msg {buffer[0]} to {ipAddress}"); - // //this.udpClient.Send(this.buffer, bufferSize, this.ipAddress, this.port); - // this.udpClient?.Send(this.buffer, bufferSize, this.endPoint); - // return true; - // } - - // public bool PublishBuffer(int bufferSize) { - // if (this.broadcastIpAddress == null) - // return false; - - // this.udpClient?.Send(this.buffer, bufferSize, this.broadcastIpAddress, this.port); - // return true; - // } - #endregion #region Receive @@ -350,19 +359,19 @@ namespace RoboidControl { protected virtual void Process(Participant sender, InvestigateMsg msg) { #if DEBUG - Console.WriteLine($"Participant: InvestigateMsg [{msg.networkId}/{msg.thingId}]"); + Console.WriteLine($"{this.name}: Process InvestigateMsg [{msg.networkId}/{msg.thingId}]"); #endif } protected virtual void Process(Participant sender, ThingMsg msg) { #if DEBUG - Console.WriteLine($"Participant: Process ThingMsg [{msg.networkId}/{msg.thingId}] {msg.thingType} {msg.parentId}"); + Console.WriteLine($"{this.name}: Process ThingMsg [{msg.networkId}/{msg.thingId}] {msg.thingType} {msg.parentId}"); #endif } protected virtual void Process(Participant sender, NameMsg msg) { #if DEBUG - Console.WriteLine($"Participant: Process NameMsg [{msg.networkId}/{msg.thingId}] {msg.nameLength} {msg.name}"); + Console.WriteLine($"{this.name}: Process NameMsg [{msg.networkId}/{msg.thingId}] {msg.nameLength} {msg.name}"); #endif Thing thing = sender.Get(msg.thingId); @@ -372,7 +381,7 @@ namespace RoboidControl { protected virtual void Process(Participant sender, ModelUrlMsg msg) { #if DEBUG - Console.WriteLine($"Participant: Process ModelUrlMsg [{msg.networkId}/{msg.thingId}] {msg.urlLength} {msg.url}"); + Console.WriteLine($"{this.name}: Process ModelUrlMsg [{msg.networkId}/{msg.thingId}] {msg.urlLength} {msg.url}"); #endif Thing thing = sender.Get(msg.thingId); @@ -382,28 +391,29 @@ namespace RoboidControl { protected virtual void Process(Participant sender, PoseMsg msg) { #if DEBUG - Console.WriteLine($"Participant: Process PoseMsg [{msg.networkId}/{msg.thingId}] {msg.poseType}"); + Console.WriteLine($"{this.name}: Process PoseMsg [{msg.networkId}/{msg.thingId}] {msg.poseType}"); #endif - Thing thing = sender.Get(msg.thingId); - if (thing != null) { - if ((msg.poseType & PoseMsg.Pose_Position) != 0) - thing.position = msg.position; - if ((msg.poseType & PoseMsg.Pose_Orientation) != 0) - thing.orientation = msg.orientation; - if ((msg.poseType & PoseMsg.Pose_LinearVelocity) != 0) { - thing.linearVelocity = msg.linearVelocity; - //Console.Write($"linear velocity = {thing.linearVelocity.ToVector3()}"); - } - if ((msg.poseType & PoseMsg.Pose_AngularVelocity) != 0) { - thing.angularVelocity = msg.angularVelocity; - //Console.Write($"angular velocity = {thing.angularVelocity.ToVector3()}"); - } - } + Participant owner = Participant.GetParticipant(msg.networkId); + if (owner == null) + return; + + Thing thing = owner.Get(msg.thingId); + if (thing == null) + return; + + if ((msg.poseType & PoseMsg.Pose_Position) != 0) + thing.position = msg.position; + if ((msg.poseType & PoseMsg.Pose_Orientation) != 0) + thing.orientation = msg.orientation; + if ((msg.poseType & PoseMsg.Pose_LinearVelocity) != 0) + thing.linearVelocity = msg.linearVelocity; + if ((msg.poseType & PoseMsg.Pose_AngularVelocity) != 0) + thing.angularVelocity = msg.angularVelocity; } protected virtual void Process(Participant sender, BinaryMsg msg) { #if DEBUG - Console.WriteLine($"Participant: Process BinaryMsg [{msg.networkId}/{msg.thingId}] {msg.dataLength}"); + Console.WriteLine($"{this.name}: Process BinaryMsg [{msg.networkId}/{msg.thingId}] {msg.dataLength}"); #endif Thing thing = sender.Get(msg.thingId); thing?.ProcessBinary(msg.data); diff --git a/src/Participants/SiteServer.cs b/src/Participants/SiteServer.cs index fc3d2d9..ab79190 100644 --- a/src/Participants/SiteServer.cs +++ b/src/Participants/SiteServer.cs @@ -10,10 +10,12 @@ namespace RoboidControl { /// public class SiteServer : ParticipantUDP { + #region Init + /// /// Create a new site server /// - /// + /// The port of which to receive the messages public SiteServer(int port = 7681) : base(port) { this.name = "Site Server"; Participant.AddParticipant(this); @@ -51,6 +53,8 @@ namespace RoboidControl { } + #endregion Init + /// /// Close the site ///