diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-02-06 19:46:56 +0200 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-02-06 19:46:56 +0200 |
| commit | a37d0e9c9203d680bf63698cf9d47447a57b5684 (patch) | |
| tree | 0547105ad8973076ddc558f6e5afdd192b86f7b3 /Software/Visual_Studio | |
| parent | 198a620cf30e86158c60cb632df740ca94b73b57 (diff) | |
| download | Tango-a37d0e9c9203d680bf63698cf9d47447a57b5684.tar.gz Tango-a37d0e9c9203d680bf63698cf9d47447a57b5684.zip | |
Diagnostics Data Playing Works!
Diffstat (limited to 'Software/Visual_Studio')
8 files changed, 417 insertions, 46 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs index edc6274c3..2ca3d215e 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs @@ -55,6 +55,16 @@ namespace Tango.MachineStudio.Developer.ViewModels set { _recorder = value; RaisePropertyChangedAuto(); } } + private DiagnosticsFilePlayer _player; + /// <summary> + /// Gets or sets the diagnostics file player. + /// </summary> + public DiagnosticsFilePlayer Player + { + get { return _player; } + set { _player = value; RaisePropertyChangedAuto(); } + } + /// <summary> /// Gets or sets the application manager. /// </summary> @@ -443,6 +453,16 @@ namespace Tango.MachineStudio.Developer.ViewModels /// </summary> public RelayCommand MediaLoadFileCommand { get; set; } + /// <summary> + /// Gets or sets the media play pause command. + /// </summary> + public RelayCommand MediaPlayPauseCommand { get; set; } + + /// <summary> + /// Gets or sets the media load command. + /// </summary> + public RelayCommand MediaLoadCommand { get; set; } + #endregion #region Constructors @@ -461,6 +481,7 @@ namespace Tango.MachineStudio.Developer.ViewModels Graphs = new ObservableCollection<IRealTimeGraph>(); _controllers = new Dictionary<String, GraphControllerBase>(); Recorder = new DiagnosticsFileRecorder(); + Player = new DiagnosticsFilePlayer(); } /// <summary> @@ -491,8 +512,10 @@ namespace Tango.MachineStudio.Developer.ViewModels StopJobCommand = new RelayCommand(StopJob, () => IsJobRunning); CloseJobCompletionStatusCommand = new RelayCommand(CloseJobCompletionStatusBar); ExitFullScreenCommand = new RelayCommand(ExitFullScreen); - MediaRecordingCommand = new RelayCommand(StartDiagnosticsRecording, () => !Recorder.IsRecording && MachineOperator != null); - MediaStopCommand = new RelayCommand(StopRecorderOrPlayer, () => Recorder.IsRecording); + MediaRecordingCommand = new RelayCommand(StartDiagnosticsRecording, () => !Recorder.IsRecording && MachineOperator != null && !Player.IsPlaying); + MediaStopCommand = new RelayCommand(StopRecorderOrPlayer, () => Recorder.IsRecording || Player.IsPlaying); + MediaLoadCommand = new RelayCommand(LoadDiagnosticsRecordingFile,() => !Recorder.IsRecording && !Player.IsPlaying); + MediaPlayPauseCommand = new RelayCommand(DiagnosticsTogglePlayPause,() => !Recorder.IsRecording && Player.IsLoaded); CaptureDevices = new ObservableCollection<CaptureDevice>(); var availableDevices = CaptureDevice.GetAvailableCaptureDevices(); @@ -518,6 +541,11 @@ namespace Tango.MachineStudio.Developer.ViewModels #region Event Handlers + private void Player_FrameReceived(object sender, DataFileFrame frame) + { + PopulateDiagnosticsData(frame.PushDiagnosticsResponse); + } + private void ApplicationManager_ConnectedMachineChanged(object sender, Integration.Services.IExternalBridgeClient machine) { MachineOperator = machine; @@ -536,27 +564,12 @@ namespace Tango.MachineStudio.Developer.ViewModels Recorder.PushData(response); } - foreach (var prop in response.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) + if (!Player.IsPlaying) { - GraphControllerBase controller = null; - - if (_controllers.TryGetValue(prop.Name, out controller)) - { - if (controller is GraphController) - { - double[] arr = Enumerable.ToArray(prop.GetValue(response) as IEnumerable<double>); - (controller as GraphController).PushData(arr); - } - else - { - DoubleArray[] arrayOfDoubles = Enumerable.ToArray(prop.GetValue(response) as IEnumerable<DoubleArray>); - (controller as GraphMultiController).PushData(arrayOfDoubles.Select(x => x.Data.ToList()).ToList()); - } - } + PopulateDiagnosticsData(response); } } - /// <summary> /// Handles the Saved event of the SelectedMachine. /// </summary> @@ -665,6 +678,74 @@ namespace Tango.MachineStudio.Developer.ViewModels #region Private Methods + private void ClearGraphs() + { + _controllers.ToList().ForEach(x => x.Value.Clear()); + } + + private void PopulateDiagnosticsData(PushDiagnosticsResponse data) + { + foreach (var prop in data.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) + { + GraphControllerBase controller = null; + + if (_controllers.TryGetValue(prop.Name, out controller)) + { + if (controller is GraphController) + { + double[] arr = Enumerable.ToArray(prop.GetValue(data) as IEnumerable<double>); + (controller as GraphController).PushData(arr); + } + else + { + DoubleArray[] arrayOfDoubles = Enumerable.ToArray(prop.GetValue(data) as IEnumerable<DoubleArray>); + (controller as GraphMultiController).PushData(arrayOfDoubles.Select(x => x.Data.ToList()).ToList()); + } + } + } + } + + private void DiagnosticsTogglePlayPause() + { + if (!Player.IsPlaying || Player.IsPaused) + { + if (!Player.IsPlaying) + { + ClearGraphs(); + } + Player.Play(); + } + else + { + Player.Pause(); + } + + InvalidateRelayCommands(); + } + + private async void LoadDiagnosticsRecordingFile() + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Title = "Select Tango Diagnostics Recording File"; + dlg.Filter = "Tango Diagnostics Recording|*.tdr"; + if (dlg.ShowDialog().Value) + { + using (_notification.PushTaskItem("Loading Recording...")) + { + if (Player != null) + { + Player.Dispose(); + } + + Player = new DiagnosticsFilePlayer(); + Player.FrameReceived += Player_FrameReceived; + await Player.Load(dlg.FileName); + } + } + + InvalidateRelayCommands(); + } + private void StartDiagnosticsRecording() { using (_notification.PushTaskItem("Starting Recording...")) @@ -677,24 +758,34 @@ namespace Tango.MachineStudio.Developer.ViewModels private async void StopRecorderOrPlayer() { - using (_notification.PushTaskItem("Stopping Recording...")) + if (Recorder.IsRecording) { - await Recorder.Stop(); - } + using (_notification.PushTaskItem("Stopping Recording...")) + { + await Recorder.Stop(); + } - SaveFileDialog dlg = new SaveFileDialog(); - dlg.Title = "Select diagnostics file location"; - dlg.Filter = "Tango Diagnostics Recording|*.tdr"; - if (dlg.ShowDialog().Value) - { - using (_notification.PushTaskItem("Saving Recording...")) + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Title = "Select diagnostics file location"; + dlg.Filter = "Tango Diagnostics Recording|*.tdr"; + if (dlg.ShowDialog().Value) { - await Recorder.Save(dlg.FileName); + using (_notification.PushTaskItem("Saving Recording...")) + { + await Recorder.Save(dlg.FileName); + } } + + Recorder.Dispose(); + Recorder = new DiagnosticsFileRecorder(); + } + else if (Player.IsPlaying) + { + await Player.Stop(); + ClearGraphs(); } - Recorder.Dispose(); - Recorder = new DiagnosticsFileRecorder(); + InvalidateRelayCommands(); } private void ExitFullScreen() @@ -986,6 +1077,13 @@ namespace Tango.MachineStudio.Developer.ViewModels if (SelectedBrushStop != null && SelectedSegment != null) { SelectedSegment.BrushStops.Remove(SelectedBrushStop); + + if (SelectedSegment.BrushStops.Count > 1) + { + SelectedSegment.BrushStops.Last().OffsetPercent = 100; + } + + SelectedSegment.BrushStops.ToList().ForEach(x => x.RaiseOffsetChanged()); } } @@ -997,10 +1095,13 @@ namespace Tango.MachineStudio.Developer.ViewModels if (SelectedSegment != null) { var stop = new BrushStop(); + stop.OffsetPercent = 100; + stop.Segment = SelectedSegment; stop.ColorSpace = Adapter.ColorSpaces.FirstOrDefault(); stop.Color = Colors.Black; stop.SetLiquidVolumes(SelectedMachine.Configuration, SelectedRML, SelectedProcessParametersTable); SelectedSegment.BrushStops.Add(stop); + SelectedSegment.BrushStops.ToList().ForEach(x => x.RaiseOffsetChanged()); } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MainView.xaml index 33652f119..820c5bb18 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MainView.xaml @@ -1608,22 +1608,36 @@ <DockPanel> <DockPanel DockPanel.Dock="Top"> <StackPanel Orientation="Horizontal" DockPanel.Dock="Left" Height="50" VerticalAlignment="Bottom" Margin="0 0 0 5"> - <Button Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="28" Height="28" Background="Transparent" ToolTip="Load Data File"> + <Button Command="{Binding MediaLoadCommand}" Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="28" Height="28" Background="Transparent" ToolTip="Load Data File"> <materialDesign:PackIcon Width="20" Height="20" Kind="Eject" Foreground="{StaticResource AccentColorBrush}" /> </Button> - <Button Margin="5 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="35" Height="35" Background="Transparent"> - <materialDesign:PackIcon Width="20" Height="20" Kind="Play" Foreground="{StaticResource AccentColorBrush}" /> + <Button Command="{Binding MediaPlayPauseCommand}" Margin="5 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="35" Height="35" Background="Transparent"> + <materialDesign:PackIcon Width="20" Height="20" Foreground="{StaticResource AccentColorBrush}"> + <materialDesign:PackIcon.Style> + <Style TargetType="materialDesign:PackIcon"> + <Setter Property="Kind" Value="Play"></Setter> + <Style.Triggers> + <MultiDataTrigger> + <MultiDataTrigger.Conditions> + <Condition Binding="{Binding Player.IsPlaying}" Value="True" /> + <Condition Binding="{Binding Player.IsPaused}" Value="False" /> + </MultiDataTrigger.Conditions> + <Setter Property="Kind" Value="Pause"></Setter> + </MultiDataTrigger> + </Style.Triggers> + </Style> + </materialDesign:PackIcon.Style> + </materialDesign:PackIcon> </Button> <Button Command="{Binding MediaStopCommand}" Margin="5 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="28" Height="28" Background="Transparent"> <materialDesign:PackIcon Width="20" Height="20" Kind="Stop" Foreground="{StaticResource AccentColorBrush}" /> </Button> <Button Command="{Binding MediaRecordingCommand}" Margin="5 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Foreground="#FF7A7A" BorderBrush="#FF8585" Padding="0" Width="20" Height="20" Background="Transparent" ToolTip="Start Recording"> - <materialDesign:PackIcon Width="10" Height="10" Kind="Record" /> </Button> </StackPanel> <Grid> - <TextBlock Text="00:00:00 / 00:00:00" Margin="0 -5 0 0" VerticalAlignment="Center" HorizontalAlignment="Right" Foreground="#FF8585" FontSize="20" FontFamily="{StaticResource digital-7}"> + <TextBlock Margin="0 -5 0 0" VerticalAlignment="Center" HorizontalAlignment="Right" Foreground="#FF8585" FontSize="20" FontFamily="{StaticResource digital-7}"> <TextBlock.Style> <Style TargetType="TextBlock"> <Setter Property="Opacity" Value="1"></Setter> @@ -1652,11 +1666,14 @@ </Style.Triggers> </Style> </TextBlock.Style> + <Run Text="{Binding Player.CurrentTime,Mode=OneWay,StringFormat=hh\\:mm\\:ss,FallbackValue='00:00:00'}"/> + <Run>/</Run> + <Run Text="{Binding Player.TotalTime,Mode=OneWay,StringFormat=hh\\:mm\\:ss,FallbackValue='00:00:00'}"/> </TextBlock> </Grid> </DockPanel> <Grid> - <Slider Visibility="{Binding Recorder.IsRecording,Converter={StaticResource BooleanToVisibilityInverseConverter}}"></Slider> + <Slider Visibility="{Binding Recorder.IsRecording,Converter={StaticResource BooleanToVisibilityInverseConverter}}" Maximum="{Binding Player.TotalFrames}" Value="{Binding Player.CurrentFrame}"></Slider> <DockPanel Visibility="{Binding Recorder.IsRecording,Converter={StaticResource BooleanToVisibilityConverter}}"> <TextBlock DockPanel.Dock="Left"> <Run FontWeight="SemiBold" FontStyle="Italic">Total Frames:</Run> diff --git a/Software/Visual_Studio/Tango.Integration/Diagnostics/DiagnosticsFilePlayer.cs b/Software/Visual_Studio/Tango.Integration/Diagnostics/DiagnosticsFilePlayer.cs new file mode 100644 index 000000000..463aecc06 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/Diagnostics/DiagnosticsFilePlayer.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Tango.Core; +using Tango.PMR.Diagnostics; +using Tango.Serialization; + +namespace Tango.Integration.Diagnostics +{ + public class DiagnosticsFilePlayer : ExtendedObject, IDisposable + { + private FileStream _dataFileStream; + private TimeCodeChannel _timeCodeChannel; + private long _diagnosticsDataOffset; + private Thread _playThread; + private TaskCompletionSource<object> _stopTaskSource; + + public event EventHandler<DataFileFrame> FrameReceived; + + private bool _isLoaded; + public bool IsLoaded + { + get { return _isLoaded; } + private set { _isLoaded = value; RaisePropertyChangedAuto(); } + } + + private bool _isPlaying; + public bool IsPlaying + { + get { return _isPlaying; } + private set { _isPlaying = value; RaisePropertyChangedAuto(); } + } + + private bool _isPaused; + public bool IsPaused + { + get { return _isPaused; } + set { _isPaused = value; RaisePropertyChangedAuto(); } + } + + private TimeSpan _currentTime; + public TimeSpan CurrentTime + { + get { return _currentTime; } + private set { _currentTime = value; RaisePropertyChanged(nameof(CurrentTime)); } + } + + private TimeSpan _totalTime; + public TimeSpan TotalTime + { + get { return _totalTime; } + set { _totalTime = value; RaisePropertyChangedAuto(); } + } + + private int _currentFrame; + public int CurrentFrame + { + get { return _currentFrame; } + set + { + _currentFrame = value; + + OnCurrentFrameChanged(); + + RaisePropertyChanged(nameof(CurrentFrame)); + } + } + + private long _totalFrames; + public long TotalFrames + { + get { return _totalFrames; } + private set { _totalFrames = value; RaisePropertyChangedAuto(); } + } + + public Task Load(String fileName) + { + return Task.Factory.StartNew(() => + { + if (_dataFileStream != null) + { + _dataFileStream.Dispose(); + } + + _dataFileStream = new FileStream(fileName, FileMode.Open); + + BinaryReader binaryReader = new BinaryReader(_dataFileStream); + + int timeCodeDataSize = binaryReader.ReadInt32(); + byte[] timeCodeData = binaryReader.ReadBytes(timeCodeDataSize); + + BinaryDataSerializer serializer = new BinaryDataSerializer(); + _timeCodeChannel = serializer.DeserializeFromBytes<TimeCodeChannel>(timeCodeData); + + _diagnosticsDataOffset = _dataFileStream.Position; + + CurrentFrame = 0; + TotalFrames = _timeCodeChannel.Frames.Count; + TotalTime = _timeCodeChannel.Frames.Last().TimeStamp; + + IsLoaded = true; + }); + } + + public void Seek(int frameIndex) + { + if (frameIndex < 0) + { + frameIndex = 0; + } + else if (frameIndex > TotalFrames - 1) + { + frameIndex = (int)(TotalFrames - 1); + } + + CurrentFrame = frameIndex; + } + + public void Play() + { + IsPaused = false; + + if (!IsPlaying) + { + IsPlaying = true; + _playThread = new Thread(PlayThreadMethod); + _playThread.IsBackground = true; + _playThread.Start(); + } + } + + private void OnCurrentFrameChanged() + { + if (IsPlaying) + { + if (_currentFrame > _timeCodeChannel.Frames.Count - 1) + { + _currentFrame = _timeCodeChannel.Frames.Count - 1; + } + + if (_dataFileStream != null && _dataFileStream.CanSeek) + { + _dataFileStream.Position = _diagnosticsDataOffset + _timeCodeChannel.Frames[_currentFrame].Position; + } + + byte[] data = new byte[_timeCodeChannel.Frames[_currentFrame].FrameLength]; + _dataFileStream.Read(data, 0, data.Length); + DataFileFrame frame = DataFileFrame.Parser.ParseFrom(data); + OnFrameReceived(frame); + data = null; + } + + if (_timeCodeChannel != null) + { + CurrentTime = _timeCodeChannel.Frames[_currentFrame].TimeStamp; + } + } + + private void PlayThreadMethod() + { + while (IsPlaying) + { + if (!IsPaused) + { + CurrentFrame++; + + if (CurrentFrame >= TotalFrames - 1) + { + CurrentFrame = 0; + } + } + + if (CurrentFrame > 0) + { + Thread.Sleep(_timeCodeChannel.Frames[CurrentFrame].TimeStamp - _timeCodeChannel.Frames[CurrentFrame - 1].TimeStamp); + } + else + { + Thread.Sleep(10); + } + } + + CurrentFrame = 0; + CurrentTime = TimeSpan.Zero; + + _stopTaskSource.SetResult(new object()); + } + + public Task Stop() + { + _stopTaskSource = new TaskCompletionSource<object>(); + IsPlaying = false; + IsPaused = false; + return _stopTaskSource.Task; + } + + public void Pause() + { + if (IsPlaying) + { + IsPaused = true; + } + } + + protected virtual void OnFrameReceived(DataFileFrame frame) + { + FrameReceived?.Invoke(this, frame); + } + + public void Dispose() + { + Stop(); + + if (_dataFileStream != null) + { + _dataFileStream.Dispose(); + } + } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/Diagnostics/DiagnosticsFileRecorder.cs b/Software/Visual_Studio/Tango.Integration/Diagnostics/DiagnosticsFileRecorder.cs index e52f39944..81f3217e7 100644 --- a/Software/Visual_Studio/Tango.Integration/Diagnostics/DiagnosticsFileRecorder.cs +++ b/Software/Visual_Studio/Tango.Integration/Diagnostics/DiagnosticsFileRecorder.cs @@ -95,6 +95,9 @@ namespace Tango.Integration.Diagnostics DataFileFrame frame = null; if (_frames.TryDequeue(out frame)) { + TimeCodeChannelFrame timeCodeFrame = new TimeCodeChannelFrame(); + timeCodeFrame.Position = TotalBytesRecorded; + byte[] data = frame.ToBytes(); _dataFileStream.Write(data, 0, data.Length); @@ -102,7 +105,10 @@ namespace Tango.Integration.Diagnostics TotalFramesRecorded++; TotalBytesRecorded += data.Length; - _timeCodeChannel.Frames.Add(new TimeCodeChannelFrame(data.Length, _stopWatch.Elapsed)); + timeCodeFrame.TimeStamp = _stopWatch.Elapsed; + timeCodeFrame.FrameLength = data.Length; + + _timeCodeChannel.Frames.Add(timeCodeFrame); } } diff --git a/Software/Visual_Studio/Tango.Integration/Diagnostics/TimeCodeChannelFrame.cs b/Software/Visual_Studio/Tango.Integration/Diagnostics/TimeCodeChannelFrame.cs index c1f0f0582..22c2e0477 100644 --- a/Software/Visual_Studio/Tango.Integration/Diagnostics/TimeCodeChannelFrame.cs +++ b/Software/Visual_Studio/Tango.Integration/Diagnostics/TimeCodeChannelFrame.cs @@ -9,13 +9,8 @@ namespace Tango.Integration.Diagnostics [Serializable] public class TimeCodeChannelFrame { + public long Position { get; set; } public long FrameLength { get; set; } public TimeSpan TimeStamp { get; set; } - - public TimeCodeChannelFrame(long frameLength, TimeSpan timeStamp) - { - FrameLength = frameLength; - TimeStamp = timeStamp; - } } } diff --git a/Software/Visual_Studio/Tango.Integration/Printing/BrushStop.cs b/Software/Visual_Studio/Tango.Integration/Printing/BrushStop.cs index 947ff9013..b11ef9f15 100644 --- a/Software/Visual_Studio/Tango.Integration/Printing/BrushStop.cs +++ b/Software/Visual_Studio/Tango.Integration/Printing/BrushStop.cs @@ -65,13 +65,25 @@ namespace Tango.Integration.Observables [NotMapped] public double OffsetMeters { - get { return Segment.Length * (OffsetPercent / 100d); } + get + { + if (Segment != null) + { + return Segment.Length * (OffsetPercent / 100d); + } + else + { + return 0; + } + } } public void RaiseOffsetChanged() { RaisePropertyChanged(nameof(OffsetPercent)); RaisePropertyChanged(nameof(OffsetMeters)); + RaisePropertyChanged(nameof(IsFirst)); + RaisePropertyChanged(nameof(IsLast)); } public void SetLiquidVolumes(Configuration configuration, Rml rml, ProcessParametersTable processParametersTable) diff --git a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj index 6924c3abe..5417e7c0f 100644 --- a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj +++ b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj @@ -73,6 +73,7 @@ <Compile Include="..\Versioning\GlobalVersionInfo.cs"> <Link>GlobalVersionInfo.cs</Link> </Compile> + <Compile Include="Diagnostics\DiagnosticsFilePlayer.cs" /> <Compile Include="Diagnostics\DiagnosticsFileRecorder.cs" /> <Compile Include="Diagnostics\TimeCodeChannel.cs" /> <Compile Include="Diagnostics\TimeCodeChannelFrame.cs" /> diff --git a/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs index 26dcdad83..71efe9318 100644 --- a/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs +++ b/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs @@ -42,6 +42,21 @@ namespace Tango.Serialization } /// <summary> + /// Deserialize object from bytes. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="filePath">The full path of the data file.</param> + /// <returns>The resulting object.</returns> + public T DeserializeFromBytes<T>(byte[] bytes) + { + using (MemoryStream ms = new MemoryStream(bytes)) + { + ms.Position = 0; + return DeserializeFromStream<T>(ms); + } + } + + /// <summary> /// Serialize object to stream. /// </summary> /// <typeparam name="T">Type of specified object.</typeparam> @@ -54,7 +69,7 @@ namespace Tango.Serialization } /// <summary> - /// Serialize object to stream. + /// Serialize object to byte array. /// </summary> /// <typeparam name="T">Type of specified object.</typeparam> /// <param name="obj">The specified object.</param> |
