服务点入门Getting started with Point of Service

服务点、销售点或服务点设备是用于帮助零售交易的计算机外设。Point of service, point of sale, or Point of Service devices are computer peripherals used to facilitate retail transactions. 服务点设备的示例包括电子收银机、条形码扫描仪、磁条阅读器和收据打印机。Examples of Point of Service devices include electronic cash registers, barcode scanners, magnetic stripe readers, and receipt printers.

在这里,你将了解使用服务 Api 的 Windows 运行时点与服务点交互相关的基础知识。Here you’ll learn the basics of interfacing with Point of Service devices by using the Windows Runtime Point of Service APIs. 我们将介绍设备枚举、检查设备功能、声明设备和设备共享。We’ll cover device enumeration, checking device capabilities, claiming devices, and device sharing. 我们以条形码扫描仪设备为例,但这里的几乎所有指南都适用于任何兼容 UWP 的服务点设备。We use a barcode scanner device as an example, but almost all the guidance here applies to any UWP-compatible Point of Service device. (有关受支持的设备的列表,请参阅服务点设备支持)。(For a list of supported devices, see Point of Service device support).

查找和连接到服务点外设Finding and connecting to Point of Service peripherals

应用可以使用服务点设备之前,必须与运行应用的电脑配对。Before a Point of Service device can be used by an app, it must be paired with the PC where the app is running. 可通过多种方法连接到服务点设备,比如通过编程方式或通过“设置”应用。There are several ways to connect to Point of Service devices, either programmatically or through the Settings app.

通过使用“设置”应用连接到设备Connecting to devices by using the Settings app

将服务点设备(如条形码扫描仪)插入电脑后,它将像任何其他设备一样显示。When you plug a Point of Service device like a barcode scanner into a PC, it shows up just like any other device. 你可以在“设置”应用的设备 > 蓝牙和其他设备部分找到。You can find it in the Devices > Bluetooth & other devices section of the Settings app. 在此位置,你可以通过选择添加蓝牙或其他设备与服务点设备配对。There you can pair with a Point of Service device by selecting Add Bluetooth or other device.

有些服务点设备可能不会在“设置”应用中显示,直到使用服务点 API 以编程方式对其进行枚举。Some Point of Service devices may not appear in the Settings app until they are programmatically enumerated by using the Point of Service APIs.

GetDefaultAsync 获取单个服务点设备Getting a single Point of Service device with GetDefaultAsync

在一个简单的用例中,你可能仅将一个服务点外设连接到运行应用的电脑上,并且希望尽快对其进行设置。In a simple use case, you may have just one Point of Service peripheral connected to the PC where the app is running and want to set it up as quickly as possible. 若要执行该操作,请使用此处所示的 GetDefaultAsync 方法检索“默认”设备。To do that, retrieve the “default” device with the GetDefaultAsync method as shown here.

using Windows.Devices.PointOfService;

BarcodeScanner barcodeScanner = await BarcodeScanner.GetDefaultAsync();

如果找到默认设备,就可以准备声明检索到的设备对象。If the default device is found, the device object retrieved is ready to be claimed. “声明”设备向应用程序提供它的独占访问权,防止来自多个进程的命令冲突。“Claiming” a device gives an application exclusive access to it, preventing conflicting commands from multiple processes.

备注

如果多个服务点设备连接到电脑,GetDefaultAsync 将返回它发现的第一个设备。If more than one Point of Service device is connected to the PC, GetDefaultAsync returns the first device it finds. 出于此原因,请使用 FindAllAsync,除非你确定只有一个服务点设备对应用程序可见。For this reason, use FindAllAsync unless you’re sure that only one Point of Service device is visible to the application.

使用 FindAllAsync 枚举设备的集合Enumerating a collection of devices with FindAllAsync

当连接到多台设备时,你必须枚举 PointOfService 设备对象的集合才能找到你想要声明的设备对象。When connected to more than one device, you must enumerate the collection of PointOfService device objects to find the one you want to claim. 例如,以下代码创建当前连接的所有条形码扫描仪的集合,然后搜索集合中具有特定名称的扫描仪。For example, the following code creates a collection of all the barcode scanners currently connected, and then searches the collection for a scanner with a specific name.

using Windows.Devices.Enumeration;
using Windows.Devices.PointOfService;

string selector = BarcodeScanner.GetDeviceSelector();       
DeviceInformationCollection deviceCollection = await DeviceInformation.FindAllAsync(selector);

foreach (DeviceInformation devInfo in deviceCollection)
{
    Debug.WriteLine("{0} {1}", devInfo.Name, devInfo.Id);
    if (devInfo.Name.Contains("1200G"))
    {
        Debug.WriteLine(" Found one");
    }
}

限定设备选择的范围Scoping the device selection

连接到设备时,你可能希望将搜索限定在你的应用有权访问的一组服务点外设。When connecting to a device, you may want to limit your search to a subset of Point of Service peripherals that your app has access to. 使用 GetDeviceSelector 方法可以限定选择的范围,以通过特定的方法(蓝牙、USB 等)仅检索连接的设备。Using the GetDeviceSelector method, you can scope the selection to retrieve devices connected only by a certain method (Bluetooth, USB, etc.). 你可以创建通过蓝牙IP本地所有连接类型搜索设备的选择器。You can create a selector that searches for devices over Bluetooth, IP, Local, or All connection types. 这可能很有用,因为无线设备发现需要的时间比本地(有线)发现要长。This can be useful, as wireless device discovery takes a long time compared to local (wired) discovery. 你可以通过将 FindAllAsync 限制为本地连接类型来确保本地设备连接的确定性等待时间。You can ensure a deterministic wait time for local device connection by limiting FindAllAsync to Local connection types. 例如,此代码检索所有可通过本地连接访问的条形码扫描仪。For example, this code retrieves all barcode scanners accessible via a local connection.

string selector = BarcodeScanner.GetDeviceSelector(PosConnectionTypes.Local);
DeviceInformationCollection deviceCollection = await DeviceInformation.FindAllAsync(selector);

对设备连接的反应根据 DeviceWatcher 进行改变Reacting to device connection changes with DeviceWatcher

当你的应用运行时,有时设备会断开连接或更新,或需要添加新设备。As your app runs, sometimes devices will be disconnected or updated, or new devices will need to be added. 你可以使用 DeviceWatcher 类访问设备相关的事件,使你的应用可以作出相应的响应。You can use the DeviceWatcher class to access device-related events, so your app can respond accordingly. 下面是如何使用 DeviceWatcher 的示例,如果添加、删除或更新设备,将调用方法存根。Here’s example of how to use DeviceWatcher, with method stubs to be called if a device is added, removed, or updated.

DeviceWatcher deviceWatcher = DeviceInformation.CreateWatcher(selector);
deviceWatcher.Added += DeviceWatcher_Added;
deviceWatcher.Removed += DeviceWatcher_Removed;
deviceWatcher.Updated += DeviceWatcher_Updated;

void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
    // TODO: Add the DeviceInformation object to your collection
}

void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
    // TODO: Remove the item in your collection associated with DeviceInformationUpdate
}

void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate args)
{
    // TODO: Update your collection with information from DeviceInformationUpdate
}

检查服务点设备的功能Checking the capabilities of a Point of Service device

即使在设备类范围内,如条形码扫描仪,每台设备的属性可能会根据型号的不同而有很大的差异。Even within a device class, such as barcode scanners, the attributes of each device may vary considerably between models. 如果你的应用需要特定的设备属性,你可能需要检查每个连接的设备对象,以确定是否支持属性。If your app requires a specific device attribute, you may need to inspect each connected device object to determine whether the attribute is supported. 例如,你的企业可能要求使用特定的条形码打印模式创建标签。For example, perhaps your business requires that labels be created using a specific barcode printing pattern. 下面介绍如何检查以查看已连接的条形码扫描仪是否支持某个符号。Here’s how you could check to see whether a connected barcode scanner supports a symbology.

备注

符号是条形码用于编码消息的语言映射。A symbology is the language mapping that a barcode uses to encode messages.

try
{
    BarcodeScanner barcodeScanner = await BarcodeScanner.FromIdAsync(deviceId);
    if (await barcodeScanner.IsSymbologySupportedAsync(BarcodeSymbologies.Code32))
    {
        Debug.WriteLine("Has symbology");
    }
}
catch (Exception ex)
{
    Debug.WriteLine("FromIdAsync() - " + ex.Message);
}

使用 Device.Capabilities 类Using the Device.Capabilities class

Device.Capabilities 类是所有服务点设备类的属性,用于获取有关每个设备的一般信息。The Device.Capabilities class is an attribute of all Point of Service device classes and can be used to get general information about each device. 例如,此示例中确定设备是否支持统计报告,且如果支持,则检索受支持的任何类型的统计信息。For example, this example determines whether a device supports statistics reporting and, if it does, retrieves statistics for any types supported.

try
{
    if (barcodeScanner.Capabilities.IsStatisticsReportingSupported)
    {
        Debug.WriteLine("Statistics reporting is supported");

        string[] statTypes = new string[] {""};
        IBuffer ibuffer = await barcodeScanner.RetrieveStatisticsAsync(statTypes);
    }
}
catch (Exception ex)
{
    Debug.WriteLine("EX: RetrieveStatisticsAsync() - " + ex.Message);
}

声明服务点设备Claiming a Point of Service device

在你可以使用服务点设备进行活动输入或输出前,你必须声明它,授予应用程序对其许多功能的独占访问权。Before you can use a Point of Service device for active input or output, you must claim it, granting the application exclusive access to many of its functions. 此代码演示在你使用前文所述的其中一种方法找到设备后,如何声明条形码扫描仪设备。This code shows how to claim a barcode scanner device, after you’ve found the device by using one of the methods described earlier.

try
{
    claimedBarcodeScanner = await barcodeScanner.ClaimScannerAsync();
}
catch (Exception ex)
{
    Debug.WriteLine("EX: ClaimScannerAsync() - " + ex.Message);
}

保留设备Retaining the device

当通过网络或蓝牙连接使用服务点设备时,你可能希望与网络上的其他应用共享该设备。When using a Point of Service device over a network or Bluetooth connection, you may wish to share the device with other apps on the network. (有关详细信息,请参阅共享设备。)在其他情况下,你可能要保留此设备以便长期使用。(For more info about this, see Sharing Devices.) In other cases, you may want to hold on to the device for prolonged use. 此示例演示在另一个应用请求发布设备后,如何保留已声明的条形码扫描仪。This example shows how to retain a claimed barcode scanner after another app has requested that the device be released.

claimedBarcodeScanner.ReleaseDeviceRequested += claimedBarcodeScanner_ReleaseDeviceRequested;

void claimedBarcodeScanner_ReleaseDeviceRequested(object sender, ClaimedBarcodeScanner e)
{
    e.RetainDevice();  // Retain exclusive access to the device
}

输入和输出Input and output

声明设备后,你几乎可以准备使用它了。After you’ve claimed a device, you’re almost ready to use it. 若要接受来自该设备的输入,必须设置和启用一个用来接收数据的代理。To receive input from the device, you must set up and enable a delegate to receive data. 在下面的示例中,我们声明了一个条形码扫描仪设备,并设置其解码属性,然后调用 EnableAsync 启用对来自设备的输入解码。In the example below, we claim a barcode scanner device, set its decode property, and then call EnableAsync to enable decoded input from the device. 此过程因设备类而异,因此若要获取有关如何设置用于非条形码设备的代理的指南,请参阅相关的 UWP 应用示例This process varies between device classes, so for guidance about how to set up a delegate for non-barcode devices, refer to the relevant UWP app sample.

try
{
    claimedBarcodeScanner = await barcodeScanner.ClaimScannerAsync();
    if (claimedBarcodeScanner != null)
    {
        claimedBarcodeScanner.DataReceived += claimedBarcodeScanner_DataReceived;
        claimedBarcodeScanner.IsDecodeDataEnabled = true;
        await claimedBarcodeScanner.EnableAsync();
    }
}
catch (Exception ex)
{
    Debug.WriteLine("EX: ClaimScannerAsync() - " + ex.Message);
}


void claimedBarcodeScanner_DataReceived(ClaimedBarcodeScanner sender, BarcodeScannerDataReceivedEventArgs args)
{
    string symbologyName = BarcodeSymbologies.GetName(args.Report.ScanDataType);
    var scanDataLabelReader = DataReader.FromBuffer(args.Report.ScanDataLabel);
    string barcode = scanDataLabelReader.ReadString(args.Report.ScanDataLabel.Length);
}

在不同应用间共享设备Sharing a device between apps

服务点设备通常用于在短时间内有多个应用需要访问它们的情况。Point of Service devices are often used in cases where more than one app will need to access them in a brief period. 通过蓝牙或 IP 网络本地(USB 或其他有线连接)连接到多个应用的设备可以共享。A device can be shared when connected to multiple apps locally (USB or other wired connection), or through a Bluetooth or IP network. 根据每个应用的需要,一个进程可能需要释放它在设备上的声明。Depending on the needs of each app, one process may need to dispose of its claim on the device. 此代码释放我们已声明的条形码扫描仪设备,允许其他应用声明并使用它。This code disposes of our claimed barcode scanner device, allowing other apps to claim and use it.

if (claimedBarcodeScanner != null)
{
    claimedBarcodeScanner.Dispose();
    claimedBarcodeScanner = null;
}

备注

已声明和未声明的服务点设备类会实现 IClosable 接口Both the claimed and unclaimed Point of Service device classes implement the IClosable interface. 如果设备已通过网络或蓝牙连接到应用,在连接另一个应用前必须丢弃已声明和未声明的对象。If a device is connected to an app via network or Bluetooth, both the claimed and unclaimed objects must be disposed of before another app can connect.

另请参阅See also