using Logger; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net.Sockets; using System.Threading; using UnityEngine; namespace Networkreader { public class NWreader :AbstractNWReader, INWReader { #region Parameter private readonly int ROWLENGTHINBYTES = 3 * sizeof(Int32) + 1 * sizeof(Double) + 9 * sizeof(Single) + 2 * sizeof(UInt32); /// /// The time(in ms) data is buffered befor it is sorted and written to file. /// private double BufferTime { get; set; } /// /// A buffer for data containing the timestamp of the date and the the object as byte[] rep. /// private List> Buffer { get; set; } /// /// Holds the latest read timestamp. /// private double NewestTimeStamp; /// /// Holds the first read timestamp. /// private double OldestTimeStamp; #endregion #region Constructor public NWreader(string ipAdress, int port, double buffertime) : base(ipAdress, port) { this.BufferTime = buffertime; this.Buffer = new List>(); this.NewestTimeStamp = 0; this.OldestTimeStamp = double.NaN; } #endregion #region Exposed /// /// Returns the newest timestamp that was written to the file. /// /// public double GetNewestTimestamp() { return NewestTimeStamp; } /// /// Returns the first timestamp that was written to the file. /// /// public double GetOldestTimestamp() { return OldestTimeStamp; } #endregion #region Internal private bool IsOutdated(Tuple elem) { return elem.Item1 < NewestTimeStamp; } /// /// A Thread that reads data from , stores it in and calls after . /// /// Filepath of the .bin file. protected override void WriteToFileThread(object filepath) { Streaming = true; NWStream = Client.GetStream(); Stopwatch watch = new Stopwatch(); double lastWritten = 0; byte[] buffer; watch.Start(); while (Streaming) { try { if (NWStream.DataAvailable) { buffer = new byte[ROWLENGTHINBYTES]; ReadBuffer(buffer); //the timestamp is always at the second position of the bytearray adter the ID of the object double timestamp = BitConverter.ToDouble(buffer, sizeof(int)); Buffer.Add(Tuple.Create(timestamp, buffer)); } else Thread.Sleep(10); } catch (Exception e) { CityLogger.LogWarning("Unable to read data from NW stream with error: " + e.Message); return; } if (lastWritten + watch.ElapsedMilliseconds > BufferTime) { lastWritten = 0; DumpBuffer(filepath.ToString()); watch.Restart(); } } Client.Close(); } /// /// Dumps to filepath. /// /// Filepath of the .bin file. private void DumpBuffer(string filepath) { //Sort the buffered elements so that they will be saved in the right time order Buffer.Sort((a, b) => a.Item1.CompareTo(b.Item1)); //and delete the one that are outdated int deleted = 0; if (Buffer.Count > 0) deleted = Buffer.RemoveAll(IsOutdated); if (deleted > 0) CityLogger.Log("Some timestamps came after their time: " + deleted, LogLevel.INFO); using (BinaryWriter sw = new BinaryWriter(new FileStream(filepath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))) foreach (Tuple line in Buffer) sw.Write(line.Item2, 0, line.Item2.Length); if (Buffer.Count >= 1) NewestTimeStamp = Buffer.Last().Item1; if (double.IsNaN(OldestTimeStamp) && Buffer.Count >= 1) OldestTimeStamp = Buffer.First().Item1; Buffer.Clear(); } protected override string GetFilename() { return "Stream_" + DateTime.Now.ToString(new CultureInfo("de-DE")).Replace(" ", "_").Replace(":", ".") + ".bin"; } #endregion } }