AutoClaim POS Bluetooth сканер штрих-кода, когда в пределах досягаемости - PullRequest
0 голосов
/ 20 января 2019

У меня есть требование к приложению UWP требовать любое сопряженное устройство сканера Bluetooth при запуске приложения, а также после циклов включения питания сканера Bluetooth или возвращения в зону действия после выхода за пределы допустимого диапазона.Пользователям даже не нужно думать о подключении / утверждении.Включение устройства сканера и запуск приложения UWP должны сделать это.

Я не нашел надежного метода или события для автоматического определения, когда сканер Bluetooth находится в диапазоне в диапазоне и готовбыть востребованным ».(Например, после выхода из / в зону досягаемости или после включения или выключения и включения / выключения питания устройства сканера Bluetooth.)

В основном это привело к следующему коду, в котором мой код постоянно пытается запросить любой сканер Bluetooth, обнаруженныйDeviceWatcher.Так будет, пока не получится.Для любых невостребованных сканеров в DeviceWatcher попытки запроса делаются по таймеру.Также я должен использовать довольно уродливую конструкцию try / catch, чтобы предотвратить неудачные вызовы ClaimScannerAsync () , вызывающие сбой приложения, так как этот метод, похоже, не генерирует собственный унаследованный класс Exception.

Кажется, это работает, но мне интересно, есть ли лучший способ для этого.

Есть ли лучший способ проверить, когда готовые к заявке сканеры Bluetooth находятся в радиусе действия?

Пожалуйста, примите во внимание процесс подачи заявок на сканеры штрих-кодов Bluetooth.

  1. Сначала подключите Bluetooth в настройках Windows, устройство будет доступно и отобразится как сопряженное.Даже если он выключен.
  2. Только после фактического запроса сканера в приложении устройство будет отображаться как подключенное.

(Я вставляю код, который я описал дляссылка и для других людей, которые могут иметь такое же требование)

private readonly List<BarcodeScanner> btScannerList = new List<BarcodeScanner>();
private readonly List<ClaimedBarcodeScanner> ClaimedScannerList = new List<ClaimedBarcodeScanner>();

/// <summary>
/// Function to claim scanner with retry timer in case of claim failure (used to reclaim scanner when scanner can go out/in of range or turned on/off)
/// In this case a device removed event is not fired by DeviceWatcher
/// This function is called for each bluetooth scanner detected by DeviceWatcher
/// </summary>
/// <param name="deviceId"></param>
private async void TryClaimBtScannerByDeviceId(string deviceId)
{
    try
    {
        if (!await this.ClaimBtScannerByDeviceId(deviceId))
        {
            Log.Debug($"BarcodeService.TryClaimBtScannerByDeviceId Failed to reconnect, setting timer to reconnect.");
            this.SetReclaimTimerForBtScanner(deviceId);
        }
    }
    catch
    {
        Log.Debug($"BarcodeService.TryClaimBtScannerByDeviceId Exception while trying to reconnect (probably a timeout), setting timer to reconnect.");
        this.SetReclaimTimerForBtScanner(deviceId);
    }
}

private void SetReclaimTimerForBtScanner(string deviceId)
{
    var timer = new System.Timers.Timer
    {
        Interval = 3000,
        AutoReset = false
    };
    timer.Elapsed += delegate { this.TryClaimBtScannerByDeviceId(deviceId); };
    timer.Start();
}

private async Task<bool> ClaimBtScannerByDeviceId(string deviceId)
{
    var scanner = await BarcodeScanner.FromIdAsync(deviceId);
    scanner.StatusUpdated += this.Scanner_StatusUpdated;
    this.btScannerList.Add(scanner);
    return await this.ClaimScannerAsync(scanner);
}

private void Scanner_StatusUpdated(BarcodeScanner sender, BarcodeScannerStatusUpdatedEventArgs args)
{
    if (args.Status == BarcodeScannerStatus.OffOrOffline || args.Status == BarcodeScannerStatus.Offline || args.Status == BarcodeScannerStatus.Off)
    {
        Log.Information($"BarcodeService.DeviceWatcher StatusUpdated to off or offline, setting reclaim timer for deviceId: {sender.DeviceId} -> {args.Status}");
        var deviceId = sender.DeviceId;
        this.UnsetScannerByDeviceId(deviceId);
        this.SetReclaimTimerForBtScanner(deviceId);
    }
}

private async Task<bool> ClaimScannerAsync(BarcodeScanner scanner)
{
    Log.Information($"BarcodeService.ClaimBarcodeScannerAsync() Trying to (re)claim scanner with DeviceId: {scanner.DeviceId} for exclusive use...");

    // after successful creation, claim the scanner for exclusive use and enable it so that data reveived events are received.
    var claimedScanner = await scanner.ClaimScannerAsync();

    if (claimedScanner == null)
    {
        Log.Warning($"BarcodeService.ClaimBarcodeScannerAsync() Couldn't claim barcode scanner for exclusive use (deviceid {scanner.DeviceId})");
        return false;
    }
    else
    {
        Log.Information($"BarcodeService.ClaimBarcodeScannerAsync() Claimed scanner for exclusive use. Setting up event handlers...");

        // It is always a good idea to have a release device requested event handler. If this event is not handled, there are chances of another app can
        // claim ownsership of the barcode scanner.
        claimedScanner.ReleaseDeviceRequested += this.ClaimedScanner_ReleaseDeviceRequested;

        // after successfully claiming, attach the datareceived event handler.
        claimedScanner.DataReceived += this.ClaimedScanner_DataReceived;

        // Ask the API to decode the data by default. By setting this, API will decode the raw data from the barcode scanner and
        // send the ScanDataLabel and ScanDataType in the DataReceived event
        claimedScanner.IsDecodeDataEnabled = true;

        // enable the scanner.
        // Note: If the scanner is not enabled (i.e. EnableAsync not called), attaching the event handler will not be any useful because the API will not fire the event
        // if the claimedScanner has not beed Enabled
        await claimedScanner.EnableAsync();

        this.ClaimedScannerList.Add(claimedScanner);
        Log.Information("BarcodeService.ClaimBarcodeScannerAsync() Ready to scan. Device ID: " + claimedScanner.DeviceId);
        return true;
    }
}

public void UnsetScannerByDeviceId(string deviceId)
{
    try
    {
        foreach (var claimedScanner in this.ClaimedScannerList.Where(x => x.DeviceId.Equals(deviceId)).ToList())
        {
            this.DisposeClaimedScanner(claimedScanner);
        }

        foreach (var scanner in this.btScannerList.Where(x => x.DeviceId.Equals(deviceId)).ToList())
        {
            this.DisposeScanner(scanner);
        }
    }
    catch
    {
        Log.Warning($"BarcodeService.UnsetScannerByDeviceId() Error while disposing scanner with scannerId: {deviceId}");
    }

}

private void DisposeScanner(BarcodeScanner scanner)
{
    scanner.StatusUpdated -= this.Scanner_StatusUpdated;
    scanner.Dispose();
    this.btScannerList.Remove(scanner);
    scanner = null;
}

private void DisposeClaimedScanner(ClaimedBarcodeScanner claimedScanner)
{
    // Detach the event handlers
    claimedScanner.DataReceived -= this.ClaimedScanner_DataReceived;
    claimedScanner.ReleaseDeviceRequested -= this.ClaimedScanner_ReleaseDeviceRequested;

    // Release the Barcode Scanner and set to null
    claimedScanner.Dispose();
    this.ClaimedScannerList.Remove(claimedScanner);
    claimedScanner = null;
}
...