/// <summary> /// Override to provide new behavior for receipt of a complete PosiStageNet info frame /// </summary> /// <param name="header"></param> /// <param name="systemName"></param> /// <param name="infoPackets"></param> protected virtual void OnCompleteInfoFrameReceived(PsnInfoHeaderChunk header, string systemName, IReadOnlyCollection <PsnInfoPacketChunk> infoPackets) { var infoTrackerChunks = infoPackets.SelectMany(p => ((PsnInfoTrackerListChunk)p.SubChunks.Single(c => c.ChunkId == PsnInfoPacketChunkId.PsnInfoTrackerList)) .SubChunks) .ToList(); if (infoTrackerChunks.Select(c => c.TrackerId).Distinct().Count() != infoTrackerChunks.Count) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, false, "Duplicate tracker IDs in frame")); return; } if (RemoteSystemName != systemName) { RemoteSystemName = systemName; RemoteSystemNameUpdated?.Invoke(this, RemoteSystemName); } foreach (var chunk in infoTrackerChunks) { PsnInfoTrackerNameChunk trackerNameChunk = null; foreach (var subchunk in chunk.SubChunks) { switch (subchunk.ChunkId) { case PsnInfoTrackerChunkId.PsnInfoTrackerName: if (trackerNameChunk != null) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, !IsStrict, $"Tracker ID {chunk.TrackerId} has multiple tracker name chunks")); if (IsStrict) { return; } } trackerNameChunk = (PsnInfoTrackerNameChunk)subchunk; break; default: throw new ArgumentOutOfRangeException(); } } if (trackerNameChunk == null) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, !IsStrict, $"Tracker ID {chunk.TrackerId} has no tracker name chunk")); if (IsStrict) { return; } continue; } if (!_trackers.TryGetValue(chunk.TrackerId, out var tracker)) { tracker = new PsnTracker(chunk.TrackerId, trackerNameChunk.TrackerName, null, header.TimeStamp); _trackers.TryAdd(chunk.TrackerId, tracker); } else { tracker = tracker.SetTrackerName(trackerNameChunk.TrackerName); tracker = tracker.SetInfoTimeStamp(header.TimeStamp); } _trackers[chunk.TrackerId] = tracker; } TrackersUpdated?.Invoke(this, Trackers); }
/// <summary> /// Override to provide new behavior for a receipt of a complete PosiStageNet data frame /// </summary> /// <param name="header"></param> /// <param name="dataPackets"></param> protected virtual void OnCompleteDataFrameReceived(PsnDataHeaderChunk header, IReadOnlyCollection <PsnDataPacketChunk> dataPackets) { var dataTrackerChunks = dataPackets.SelectMany(p => ((PsnDataTrackerListChunk)p.SubChunks.Single(c => c.ChunkId == PsnDataPacketChunkId.PsnDataTrackerList)) .SubChunks) .ToList(); if (dataTrackerChunks.Select(c => c.TrackerId).Distinct().Count() != dataTrackerChunks.Count) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(dataPackets, false, "Duplicate tracker IDs in frame")); return; } foreach (var chunk in dataTrackerChunks) { if (!_trackers.TryGetValue(chunk.TrackerId, out var tracker)) { tracker = new PsnTracker(chunk.TrackerId); } Tuple <float, float, float> position = null; Tuple <float, float, float> speed = null; Tuple <float, float, float> orientation = null; Tuple <float, float, float> acceleration = null; Tuple <float, float, float> targetPosition = null; float?validity = null; foreach (var subchunk in chunk.SubChunks) { switch (subchunk.ChunkId) { case PsnDataTrackerChunkId.PsnDataTrackerPos: position = ((PsnDataTrackerPosChunk)subchunk).Vector; break; case PsnDataTrackerChunkId.PsnDataTrackerSpeed: speed = ((PsnDataTrackerSpeedChunk)subchunk).Vector; break; case PsnDataTrackerChunkId.PsnDataTrackerOri: orientation = ((PsnDataTrackerOriChunk)subchunk).Vector; break; case PsnDataTrackerChunkId.PsnDataTrackerStatus: validity = ((PsnDataTrackerStatusChunk)subchunk).Validity; break; case PsnDataTrackerChunkId.PsnDataTrackerAccel: acceleration = ((PsnDataTrackerAccelChunk)subchunk).Vector; break; case PsnDataTrackerChunkId.PsnDataTrackerTrgtPos: targetPosition = ((PsnDataTrackerTrgtPosChunk)subchunk).Vector; break; default: throw new ArgumentOutOfRangeException(nameof(subchunk.ChunkId)); } } tracker = PsnTracker.CloneInternal(tracker, dataTimeStamp: header.TimeStamp, position: position, clearPosition: position == null, speed: speed, clearSpeed: speed == null, orientation: orientation, clearOrientation: orientation == null, acceleration: acceleration, clearAcceleration: acceleration == null, targetposition: targetPosition, clearTargetPosition: targetPosition == null, validity: validity, clearValidity: validity == null); _trackers[chunk.TrackerId] = tracker; } TrackersUpdated?.Invoke(this, Trackers); }
/// <summary> /// Override to provide new behavior for receipt of a complete PosiStageNet info frame /// </summary> /// <param name="header"></param> /// <param name="systemName"></param> /// <param name="infoPackets"></param> protected virtual void OnCompleteInfoFrameReceived(IPEndPoint ipEndPoint, PsnInfoHeaderChunk header, string systemName, IReadOnlyCollection <PsnInfoPacketChunk> infoPackets) { var infoTrackerChunks = infoPackets.SelectMany(p => ((PsnInfoTrackerListChunk)p.SubChunks.Single(c => c.ChunkId == PsnInfoPacketChunkId.PsnInfoTrackerList)) .SubChunks) .ToList(); if (infoTrackerChunks.Select(c => c.TrackerId).Distinct().Count() != infoTrackerChunks.Count) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, false, "Duplicate tracker IDs in frame")); return; } var endPointData = getEndpointData(ipEndPoint); if (endPointData.RemoteSystemName != systemName) { string lastSystemName = systemName; endPointData.UpdateRemoteSystemName(systemName); RemoteSystemNameUpdated?.Invoke(this, new Tuple <string, EndPointData>(lastSystemName, endPointData)); } foreach (var chunk in infoTrackerChunks) { PsnInfoTrackerNameChunk trackerNameChunk = null; foreach (var subChunk in chunk.SubChunks) { switch (subChunk.ChunkId) { case PsnInfoTrackerChunkId.PsnInfoTrackerName: if (trackerNameChunk != null) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, !IsStrict, $"Tracker ID {chunk.TrackerId} has multiple tracker name chunks")); if (IsStrict) { return; } } trackerNameChunk = (PsnInfoTrackerNameChunk)subChunk; break; default: throw new ArgumentOutOfRangeException(); } } if (trackerNameChunk == null) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, !IsStrict, $"Tracker ID {chunk.TrackerId} has no tracker name chunk")); if (IsStrict) { return; } continue; } if (!_endpoints.TryGetValue(ipEndPoint, out var trackerList)) { trackerList.updateTracker(chunk, trackerNameChunk, header); _endpoints.TryAdd(ipEndPoint, trackerList); } else { trackerList.updateTracker(chunk, trackerNameChunk, header); } TrackersUpdated?.Invoke(this, new TrackerUpdateEventArgs() { TrackerId = chunk.TrackerId, Data = endPointData }); } }