Esempio n. 1
0
        async Task UnlockByRfid(string rfid)
        {
            if (!isRunning)
            {
                return;
            }

            if (!_rfidSettingsManager.Settings.IsRfidEnabled)
            {
                return;
            }

            if (Interlocked.CompareExchange(ref _isConnecting, 1, 1) == 1)
            {
                return;
            }

            HwVaultShortInfoFromHesDto info = null;

            try
            {
                _screenActivator?.ActivateScreen();

                if (_hesConnection == null)
                {
                    throw new Exception(TranslationSource.Instance["ConnectionFlow.RfidConnection.Error.NotConnectedToHes"]);
                }


                // get MAC address from the HES
                info = await _hesConnection.GetHwVaultInfoByRfid(rfid);

                await _clientUiManager.SendNotification(TranslationSource.Instance["ConnectionFlow.RfidConnection.ContactingHesMessage"], info.VaultMac);

                if (Interlocked.CompareExchange(ref _isConnecting, 1, 0) == 0)
                {
                    try
                    {
                        await _connectionFlowProcessor.ConnectAndUnlock(info.VaultMac, OnUnlockAttempt);
                    }
                    catch (Exception)
                    {
                        // Silent handling. Log is already printed inside of _connectionFlowProcessor.ConnectAndUnlock()
                    }
                    finally
                    {
                        // this delay allows a user to move away the device from the rfid
                        // and prevents the repeated call of this method
                        await Task.Delay(SdkConfig.DelayAfterMainWorkflow);

                        Interlocked.Exchange(ref _isConnecting, 0);
                    }
                }
            }
            catch (Exception ex)
            {
                WriteLine(ex);
                await _clientUiManager.SendError(HideezExceptionLocalization.GetErrorAsString(ex), info?.VaultMac);
            }
        }
        async Task SetPinWorkflow(IDevice device, int timeout, CancellationToken ct)
        {
            Debug.WriteLine(">>>>>>>>>>>>>>> SetPinWorkflow +++++++++++++++++++++++++++++++++++++++");

            await _ui.SendNotification(TranslationSource.Instance.Format("ConnectionFlow.Pin.NewPinMessage", device.MinPinLength), device.Mac);

            while (device.AccessLevel.IsNewPinRequired)
            {
                string pin = await _ui.GetPin(device.Id, timeout, ct, withConfirm : true);

                ct.ThrowIfCancellationRequested();

                if (string.IsNullOrWhiteSpace(pin))
                {
                    // we received an empty PIN from the user. Trying again with the same timeout.
                    WriteLine("Received empty PIN");
                    continue;
                }

                var pinResult = await device.SetPin(pin); //this using default timeout for BLE commands

                ct.ThrowIfCancellationRequested();

                if (pinResult == HideezErrorCode.Ok)
                {
                    Debug.WriteLine($">>>>>>>>>>>>>>> PIN OK");
                    break;
                }
                else if (pinResult == HideezErrorCode.ERR_PIN_TOO_SHORT)
                {
                    await _ui.SendError(TranslationSource.Instance["ConnectionFlow.Pin.Error.PinToShort"], device.Mac);
                }
                else if (pinResult == HideezErrorCode.ERR_PIN_WRONG)
                {
                    await _ui.SendError(TranslationSource.Instance["ConnectionFlow.Pin.Error.WrongPin"], device.Mac);
                }
            }
            Debug.WriteLine(">>>>>>>>>>>>>>> SetPinWorkflow ---------------------------------------");
        }
        async Task WorkflowCleanup(string errorMessage, string mac, IDevice device, bool workflowFinishedSuccessfully, bool deleteVaultBond)
        {
            // Cleanup
            try
            {
                await _ui.HidePinUi();

                if (!string.IsNullOrEmpty(errorMessage))
                {
                    if (device != null && !string.IsNullOrWhiteSpace(device.SerialNo))
                    {
                        var sb = new StringBuilder();
                        sb.Append(errorMessage);
                        sb.Append(Environment.NewLine);
                        sb.Append(Environment.NewLine);
                        sb.Append(string.Format(TranslationSource.Instance["ConnectionFlow.VaultSerialNo"], device.SerialNo));

                        errorMessage = sb.ToString();
                    }

                    WriteLine(errorMessage);
                    await _ui.SendError(errorMessage, mac);
                }

                if (device != null)
                {
                    if (workflowFinishedSuccessfully)
                    {
                        WriteLine($"Successfully finished the main workflow: ({device.Id})");
                        DeviceFinishedMainFlow?.Invoke(this, device);
                    }
                    else if (deleteVaultBond)
                    {
                        WriteLine($"Mainworkflow critical error, Removing ({device.Id})");
                        await _deviceManager.Remove(device);
                    }
                    else
                    {
                        WriteLine($"Main workflow failed, Disconnecting ({device.Id})");
                        await _deviceManager.DisconnectDevice(device);
                    }
                }
            }
            catch (Exception ex)
            {
                WriteLine(ex, LogErrorSeverity.Error);
            }
        }
        public async Task <HwVaultInfoFromHesDto> ActivateVault(IDevice device, HwVaultInfoFromHesDto vaultInfo, CancellationToken ct)
        {
            HwVaultInfoFromHesDto newVaultInfo = null;

            if (device.IsLocked && device.IsCanUnlock)
            {
                try
                {
                    do
                    {
                        ct.ThrowIfCancellationRequested();

                        var code = await _ui.GetActivationCode(device.Id, 30_000, ct); // Todo: activation timeout should not be a magic number

                        ct.ThrowIfCancellationRequested();

                        if (code.Length < 6)
                        {
                            await _ui.SendError(TranslationSource.Instance["ConnectionFlow.ActivationCode.Error.CodeToShort"], device.Mac);

                            continue;
                        }

                        if (code.Length > 8)
                        {
                            await _ui.SendError(TranslationSource.Instance["ConnectionFlow.ActivationCode.Error.CodeToLong"], device.Mac);

                            continue;
                        }

                        try
                        {
                            await device.UnlockDeviceCode(code);
                        }
                        catch (HideezException ex) when(ex.ErrorCode == HideezErrorCode.ERR_PIN_WRONG)  // Entered invalid activation code
                        {
                        }
                        catch (HideezException ex) when(ex.ErrorCode == HideezErrorCode.ERR_DEVICE_LOCKED_BY_CODE)  // Unlock attempts == 0
                        {
                            throw new WorkflowException(TranslationSource.Instance["ConnectionFlow.ActivationCode.Error.LockedByInvalidAttempts"]);
                        }

                        ct.ThrowIfCancellationRequested();

                        await device.RefreshDeviceInfo();

                        ct.ThrowIfCancellationRequested();

                        if (!device.IsLocked)
                        {
                            WriteLine($"({device.SerialNo}) unlocked with activation code");
                        }
                        else if (device.UnlockAttemptsRemain > 0)
                        {
                            await _ui.SendNotification(TranslationSource.Instance.Format("ConnectionFlow.ActivationCode.Error.InvalidCode", device.UnlockAttemptsRemain), device.Mac);
                        }
                        else
                        {
                            // We won't reach this line, but will leave it just in case
                            throw new WorkflowException(TranslationSource.Instance["ConnectionFlow.ActivationCode.Error.LockedByInvalidAttempts"]);
                        }
                    }while (device.IsLocked);
                }
                catch
                {
                    if (_hesConnection.State == HesConnectionState.Connected)
                    {
                        await _hesConnection.UpdateHwVaultStatus(new HwVaultInfoFromClientDto(device), ct);
                    }

                    throw;
                }
                finally
                {
                    await _ui.HideActivationCodeUi();
                }

                if (_hesConnection.State == HesConnectionState.Connected)
                {
                    newVaultInfo = await _hesConnection.UpdateHwVaultStatus(new HwVaultInfoFromClientDto(device), ct);
                }
            }

            if (device.IsLocked)
            {
                if (_hesConnection.State == HesConnectionState.Connected)
                {
                    throw new WorkflowException(TranslationSource.Instance["ConnectionFlow.ActivationCode.Error.VaultIsLocked"]);
                }
                else
                {
                    throw new WorkflowException(TranslationSource.Instance["ConnectionFlow.ActivationCode.Error.VaultIsLockedNoNetwork"]);
                }
            }

            return(newVaultInfo ?? vaultInfo);
        }