public FlashDumpLoadVM(RUSDeviceId rusDevice, BusyObject isBusy) { IsBusy = isBusy; DataStorageVM = new FlashDataStorageVM(this); Load = new ActionCommand(loadAsync, IsBusy); Cancel = new ActionCommand(cancelAsync, () => _currentOperation != null, IsBusy); async Task loadAsync() { using (IsBusy.BusyMode) { var path = IOUtils.RequestFileOpenPath("BIN (*.bin)|*.bin"); if (path == null) { return; } try { _currentOperation = new AsyncOperationInfo().UseInternalCancellationSource(); _currentOperationTask = LoadAsync(path, _currentOperation); Cancel.Update(); await _currentOperationTask; Logger.LogOKEverywhere("Дамп Flash успешно загружен"); } catch (OperationCanceledException) { Logger.LogInfoEverywhere("Чтение дампа Flash отменено"); PointsSource = null; } catch (Exception ex) { Logger.LogError("Ошибка загрузки дампа", $"-MSG", ex); PointsSource = null; } finally { _currentOperationTask = null; _currentOperation = null; } } } async Task cancelAsync() { _currentOperation?.Cancel(); } }
public RUSTelemetryStreamSenderVM(IRUSDevice device, BusyObject isBusy) { _isBusy = isBusy ?? throw new ArgumentNullException(nameof(isBusy)); _device = device ?? throw new ArgumentNullException(nameof(device)); ChooseFile = new ActionCommand(chooseFileAsync, _isBusy); Start = new ActionCommand(async() => { _sendingOperation = startSendingAsync(); Stop.Update(); await _sendingOperation; }, () => _currentData != null && _isBusy.IsNotBusy, _isBusy); Stop = new ActionCommand(stopSending, () => _sendingOperation != null, _isBusy); async Task stopSending() { _operationInfo.Cancel(); await _sendingOperation; } async Task startSendingAsync() { using (_isBusy.BusyMode) { try { Logger.LogOKEverywhere("Передача начата"); _operationInfo = new AsyncOperationInfo(Progress).UseInternalCancellationSource(); _operationInfo.Progress.Optimize = false; _operationInfo.Progress.MaxProgress = _currentData.Count; var sw = Stopwatch.StartNew(); var sendedCurveTotalDuration = TimeSpan.Zero; for (int i = 0, frameI = 0; i < _currentData.Count; frameI++) { TimeSpan duration = TimeSpan.Zero; var frame = new List <RegData>(); await Task.Run(async() => { var first = await _currentData[i]; frame.Add(first); for (; i < _currentData.Count - 1; i++) { var item = await _currentData[i + 1]; if (item.Time <= frame.LastElement().Time) { continue; } else { frame.Add(item); duration = item.Time - first.Time; if (duration.TotalMilliseconds >= FRAME_DURATION) { i++; break; } } } i++; }); if (i == _currentData.Count) { unchecked { frameI = (int)uint.MaxValue; }; Logger.LogOKEverywhere("Отправка файла завершена"); } var durationMs = duration.TotalMilliseconds.Round(); var frameData = frame.Select(d => d.Row[0]).ToArray(); var request = Requests.BuildRegDataFramePacket(frameI, durationMs, frameData); var result = await _device.BurnAsync(Command.REG_DATA_FRAME, request, DeviceOperationScope.DEFAULT, CancellationToken.None); //if (result.Status == BurnRequestStatus.OK) if (true) { var response = result.Response == null ? new ulong[0] : result.Response.Skip(6).SkipFromEnd(2).GroupBy(8).Select(bs => Deserialize(bs)).ToArray(); foreach (var pointI in frameData.Length.Range()) { var entities = new List <ViewDataEntity>(); entities.Add(new ViewDataEntity("Pressure", frameData[pointI], true)); if (response.Length > pointI) { entities.Add(new ViewDataEntity($"Response", response[pointI], true)); } else { entities.Add(new ViewDataEntity($"Response", "")); } var decoration = (Progress.Progress.Round() + pointI) % _avgSampleRate == 0 ? RowDecoration.LINE : RowDecoration.NONE; DecoratedDataRowAquired?.Invoke(entities, decoration); } ulong Deserialize(IEnumerable <byte> data) { return(BitConverter.ToUInt64(data.Take(8).Reverse().ToArray(), 0)); } sendedCurveTotalDuration += duration; _operationInfo.Progress.Report(i + 1); await Task.Delay( (sendedCurveTotalDuration.TotalMilliseconds - sw.Elapsed.TotalMilliseconds - PREEMPTIVE_READ_DURATION).Round().NegativeToZero(), _operationInfo.CancellationToken); } else { Logger.LogErrorEverywhere("Ошибка передачи кадра"); frameI--; i -= frame.Count; } _operationInfo.CancellationToken.ThrowIfCancellationRequested(); } } catch (OperationCanceledException) { Logger.LogInfoEverywhere("Пересылка отменена"); } catch (Exception ex) { Logger.LogErrorEverywhere("Цикл отправки завершился с ошибкой", ex); } finally { _sendingOperation = null; _operationInfo = null; Progress.Reset(); Stop.Update(); } } } async Task chooseFileAsync() { using (_isBusy.BusyMode) { try { var path = IOUtils.RequestFileOpenPath("RAW (*raw)|*.raw"); if (path == null) { Logger.LogInfoEverywhere("Файл не выбран"); return; } var file = new FileStream(path, FileMode.Open); _currentData?.Dispose(); _currentData = new RegDataReader(file); ChooseFile.Update(); using (Parameters.EventSuppressingMode) { Parameters.Clear(); var first = await _currentData[0]; var last = await _currentData[_currentData.Count - 1]; var duration = last.Time - first.Time; _avgSampleRate = (_currentData.Count / duration.TotalSeconds).Round(); Parameters.Add(new KeyValuePair <string, string>("Длительность (часов)", duration.TotalHours.Round().ToString())); Parameters.Add(new KeyValuePair <string, string>("Частота семплирования", (_currentData.Count / duration.TotalSeconds).ToStringInvariant("F2"))); } } catch (Exception ex) { Logger.LogErrorEverywhere("Ошибка при загрузке", ex); _currentData?.Dispose(); } } } }
/// <summary> /// /// </summary> /// <param name="device"></param> /// <param name="commandAddress"></param> /// <param name="handlerWidget">optional</param> /// <param name="isBusy"></param> public DeviceCommandVM(IRUSDevice device, Command commandAddress, ICommandHandlerWidget handlerWidget, BusyObject isBusy) { _device = device; _request = commandAddress; IsBusy = isBusy; Widget = handlerWidget; var requestinfo = Requests.GetRequestDescription(_device.Id, _request); Entities.AddRange(requestinfo.UserCommandDescriptors .Select(d => new CommandEntityVM(d)) .ToArray()); Name = _request.GetInfo().CommandName; Send = new ActionCommand(burnAsync, IsBusy); Read = new ActionCommand(readAsync, IsBusy); Cancel = new ActionCommand(cancelAsync, () => _currentRequest != null, IsBusy); Read.CanBeExecuted = IsReadSupported = commandAddress.GetInfo().IsReadSupported; Send.CanBeExecuted = IsSendSupported = commandAddress.GetInfo().IsWriteSupported; Cancel.CanBeExecuted = Widget?.Settings?.AllowCancelling ?? false; Progress = (Widget?.Settings?.ShowProgress ?? false) ? new RichProgress() : null; async Task burnAsync() { using (IsBusy.BusyMode) { Logger.LogInfoEverywhere($"Отправка комманды записи \"{Name}\""); if (Widget != null) { throw new NotImplementedException(); } assertViewValues(); var entitiesToWrite = Entities.Select(e => e.Entity).ToArray(); var allEntitiesToWrite = requestinfo.BuildWriteRequestBody(entitiesToWrite); var result = await _device.BurnAsync(_request, allEntitiesToWrite, DeviceOperationScope.DEFAULT, CancellationToken.None); if (result.Status == BurnStatus.OK) { if (IsReadSupported) { await verifyBurnAsync(allEntitiesToWrite); } else { Logger.LogOKEverywhere("Запись завершена"); } } else { Logger.LogErrorEverywhere("Ошибка отправки команды"); } } async Task verifyBurnAsync(IEnumerable <IDataEntity> allEntitiesToWrite) { var readEntities = await readAsync(); if (readEntities != null) { var isVerified = readEntities .Select(e => e.Value) .SequenceEqual(allEntitiesToWrite.Select(e => e.Value)); if (isVerified) { Logger.LogOKEverywhere("Запись завершена"); } else { Logger.LogWarningEverywhere("Записанные данные не совпадают с прочитанными"); } } } } async Task <IEnumerable <IDataEntity> > readAsync() { using (IsBusy.BusyMode) { Logger.LogInfoEverywhere($"Отправка комманды чтения \"{Name}\""); if (Widget != null) { await widgetsHandlerAsync(); return(null); } else { var result = await _device.ReadAsync(_request, DeviceOperationScope.DEFAULT, CancellationToken.None); if (result.Status == ReadStatus.OK) { foreach (var entity in Entities) { var match = result.Entities.First(e => e.Descriptor.Equals(entity.Descriptor)); entity.EntityValue.ModelValue = match.Value; } assertViewValues(); Logger.LogOKEverywhere("Чтение завершено"); return(result.Entities); } else { Logger.LogErrorEverywhere("Ошибка отправки команды"); return(null); } } } async Task widgetsHandlerAsync() { try { Progress.Reset(); _currentRequest = new AsyncOperationInfo(Progress).UseInternalCancellationSource(); Cancel.Update(); await Widget.Model.OnReadAsync(_currentRequest); } catch (OperationCanceledException) { Logger.LogInfoEverywhere("Команда была отменена"); } catch (Exception ex) { Logger.LogErrorEverywhere("Ошибка отправки команды", ex); } finally { _currentRequest = null; Cancel.Update(); } } } async Task cancelAsync() { _currentRequest.Cancel(); } void assertViewValues() { foreach (var e in Entities) { e.EntityValue.AssertValue(); } } }