Esempio n. 1
0
        public async Task<bool> ProcessDevice(SmlComServiceClient svc, Guid guid, CommunicationPort port, CancellationToken token)
        {
            // cancellation setup
            this.cts?.Cancel();
            var timeoutCts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
            this.cts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, token);
            token = cts.Token;

            var sw = Stopwatch.StartNew();
            try
            {
                if (!this.IsOccupiedByDevice)
                {
                    Log.Warning($"Station {this.Number} is not assigned by a device (MAC address missing)");
                    // only use active stations where a device is assigned (by scanning or user action)
                    return false;
                }

                var dr = new DeviceRepository();
                
                this.Device = dr.GetOne(this.Device.ServerId);

                this.SetStatusMessageAndProgress("Processing started...", 5);
                this.Status = StationStatus.Processing;
                
                var rnd = new Random();

                var policy = Policy
                        .Handle<Exception>()
                        .WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2) });

                var portlist = await svc.GetPortListAsync();
                if (!portlist.FirstOrDefault(p => p.ComPortName == this.ComAddress).IsInitialized)
                {
                    throw new InvalidOperationException("Service Comport is not initialized!");
                }

                foreach (var param in this.Device.ParameterList)
                {
                    await Task.Delay(100, token);
                    if (!param.IsActive)
                    {
                        continue;
                    }

                    // execute communication with retry policy...
                    await policy.ExecuteAsync(async () =>
                    {
                        this.SetStatusMessageAndProgress($"Writing at {port.ComPortName} parameter {param.TagId} with value {param.TargetValue}...", this.Progress);
                        switch (param.TagId)
                        {
                            case ParameterTagId.ServerId:
                                var serverId = param.TargetValue.FromHexString();
                                await svc.WriteServerIdAsync(guid, port, serverId);

                                var serverIdParam = await svc.ReadServerIdAsync(guid, port);
                                param.RealValue = serverIdParam.Data.AsHexString("-");
                                break;
                            case ParameterTagId.ManufacturerSerialNumber:
                                await svc.WriteManufacturerSerialNumberAsync(guid, port, param.TargetValue);

                                var serialNoParam = await svc.ReadManufacturerSerialNoAsync(guid, port);
                                var serialNoBytes = serialNoParam.Data;
                                param.RealValue = Encoding.UTF8.GetString(serialNoBytes);
                                break;
                            case ParameterTagId.GenerateKeys:
                                await svc.WriteCreateKeysAsync(guid, port);

                                param.RealValue = "True";
                                param.IsWritten = true;
                                break;
                            case ParameterTagId.PublicKey:
                                param.RealValue = (await svc.ReadPublicKeyAsync(guid, port)).Data.AsHexString("-");
                                break;
                            case ParameterTagId.PinCodeActive:
                                var isPinActive = bool.Parse(param.TargetValue);
                                await svc.WriteIsPinProtectionActiveAsync(guid, port, isPinActive);

                                param.RealValue = (await svc.ReadIsPinProtectionActiveAsync(guid, port)).Data.ToString();
                                break;
                            case ParameterTagId.InitialKeyM:
                                await svc.WriteInitialSymKeyAsync(guid, port, param.TargetValue.FromHexString());
                                param.RealValue = (await svc.ReadInitialSymKeyAsync(guid, port)).Data.AsHexString("-");
                                break;
                            case ParameterTagId.PinCode:
                                await svc.WritePinAsync(guid, port, param.TargetValue);

                                param.RealValue = param.TargetValue;
                                param.IsWritten = true;
                                break;
                            case ParameterTagId.MeasurementMode:
                                await svc.WriteMeasurementModeAsync(guid, port, param.TargetValue);

                                param.RealValue = $"MM{(await svc.ReadMeasurementModeAsync(guid, port)).Data}";
                                break;
                            case ParameterTagId.GridOption:
                                var isGridOption = bool.Parse(param.TargetValue);
                                await svc.WriteEnableGridOptionAsync(guid, port, isGridOption);

                                param.RealValue = (await svc.ReadEnableGridOptionAsync(guid, port)).Data.ToString();
                                break;
                            case ParameterTagId.TarifOptionActive:
                                var isTariffActive = bool.Parse(param.TargetValue);
                                await svc.WriteEnableTariffFunctionAsync(guid, port, isTariffActive);

                                param.RealValue = (await svc.ReadEnableTariffFunctionAsync(guid, port)).Data.ToString();
                                break;
                            case ParameterTagId.InverseTariffControl:
                                var isInverse = bool.Parse(param.TargetValue);
                                await svc.WriteIsTerminalControlReverseAsync(guid, port, isInverse);

                                param.RealValue = (await svc.ReadIsTerminalControlReverseAsync(guid, port)).Data.ToString();
                                break;
                            case ParameterTagId.BaudRateConfigurable:
                                var isBaudrateConfigurable = bool.Parse(param.TargetValue);
                                await svc.WriteEnableBaudRateSettingAsync(guid, port, isBaudrateConfigurable);

                                param.RealValue = (await svc.ReadEnableBaudRateSettingAsync(guid, port)).Data.ToString();
                                break;
                            case ParameterTagId.BaudRate:
                                break;
                            case ParameterTagId.Type:
                                param.RealValue = param.TargetValue;
                                param.IsWritten = true;
                                break;
                            case ParameterTagId.Eigentumsnummer:
                                param.RealValue = param.TargetValue;
                                param.IsWritten = true;
                                break;
                            default:
                                throw new InvalidEnumArgumentException();
                        }
                        this.SetStatusMessageAndProgress($"{port.ComPortName} parameter {param.TagId} with value {param.TargetValue} write OK...", this.Progress += 5);
                    });
                }

                this.Device.SetAllParametersWritten(true);

                sw.Stop();
                Log.Warning("Device completed in {@sw}!", sw.Elapsed);

                // update database
                this.Device.ProducedAt = DateTime.Now;
                // dr.Update(device);

                this.LastProducedDeviceServerId = this.Device.ServerId;
                this.SetStatusMessageAndProgress("Processed", 100);
                this.Status = StationStatus.ProcessingCompleted;
                await Task.Delay(TimeSpan.FromSeconds(1), token);

                return true;
            }
            catch (OperationCanceledException)
            {
                Log.Warning("Station {s} cancelled", this.Number);
                this.SetStatusMessageAndProgress($"Cancelled", 0);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Station {s} failed", this.Number);
                this.SetStatusMessageAndProgress($"Error: {ex.Message}", 0);
                this.Status = StationStatus.Error;
            }

            return false;
        }