[.Net翻译]Device.Net (Usb.Net, Hid.Net) 4.0

967 阅读4分钟

原文地址:cfdevelop.medium.com/device-net-…

原文作者:cfdevelop.medium.com/

发布时间:2021年1月31日-3分钟阅读

Device.Net是一个跨平台的.NET框架,用于与USB、Serial Port和Hid设备等连接设备进行对话。它的目的是使设备通信在所有平台和设备类型上统一。它可以运行在.NET 5、.NET Framework、UWP、Android等平台上。新的4.0版本带来了一系列的修复和功能,使设备通信更加易于管理和稳定。请在GitHub上启动repo,并加入Device.Net Discord服务器上的对话。

支持这个博客。赞助我的Github开源,雇佣我为你的联网设备构建一个应用,或者注册我的课程《Uno平台介绍》

查看4.0项目,了解完整的bug和功能列表。

#131 - 使用微软标准ILogger进行日志记录

对于设备通信来说,记录和跟踪是一个广阔的话题。您需要将遥测数据发送到一个可读和可查询的位置。Device.Net通过可调节的日志级别为整个系统带来了改进的日志记录。将您的遥测数据发送到像Application Insights这样的系统,以存储日志和一个中央可查询的位置。

//Configure logging
var loggerFactory = LoggerFactory.Create((builder) =>
{
    _ = builder.AddDebug().SetMinimumLevel(LogLevel.Trace);
});

//Register the factory for creating Hid devices. 
var hidFactory =
    new FilterDeviceDefinition(vendorId: 0x534C, productId: 0x0001, label: "Trezor One Firmware 1.6.x", usagePage: 65280)
    .CreateWindowsHidDeviceFactory(loggerFactory);

#126 - USB控制传输

USB设备在上传固件和执行设置操作时需要特殊的传输。4.0版本实现了所有平台的控制传输。这个例子可以清除设备的状态。

public static Task ClearStatusAsync(this IUsbDevice usbDevice)
    => usbDevice.PerformControlTransferAsync(new SetupPacket
    (
        requestType: new UsbDeviceRequestType(
            RequestDirection.In,
            RequestType.Class,
            RequestRecipient.Interface),
        request: DFU_CLEARSTATUS,
        length: 0
    ));

#105 - 改进的公共接口

公共接口就简单多了。使用扩展方法来创建工厂,并快速枚举设备。

#2 - 取消令牌(超时)

现在您可以使用取消令牌实现超时。长期运行的任务接受CancellationToken作为参数。

var cancellationTokenSource = new CancellationTokenSource();
//Fire a timeout after 1000 milliseconds
cancellationTokenSource.CancelAfter(1000);
var result = await device.WriteAndReadAsync(writeData, cancellationTokenSource.Token);

#182 - SourceLink支持(进入代码)

SourceLink是一个调试功能,它允许你进入Device.Net库中的代码。它从Github下载代码,这样你就可以进入代码,看看到底发生了什么问题。

使用Polly实现.NET弹性和瞬态故障处理。

使用Polly来处理瞬时故障的重试。设备经常不能按预期工作,用户有时会碰到电缆。这个示例使用Polly来重试失败的控制传输。

public static Task<T> PerformControlTransferWithRetry<T>(
    this IUsbDevice usbDevice,
    Func<IUsbDevice, Task<T>> func,
    int retryCount = 3,
    int sleepDurationMilliseconds = 250)
{
    var retryPolicy = Policy
        .Handle<ApiException>()
        .Or<ControlTransferException>()
        .WaitAndRetryAsync(
            retryCount,
            i => TimeSpan.FromMilliseconds(sleepDurationMilliseconds),
            onRetryAsync: (e, t) => usbDevice.ClearStatusAsync()
            );

    return retryPolicy.ExecuteAsync(() => func

反应式编程

使用Reactive Extensions来使用可组合的现代语法的消息传递。该示例从温度计中读取数据,并仅在温度变化时报告结果。

private static async Task DisplayTemperature()
{
    //Connect to the device by product id and vendor id
    var temperDevice = await new FilterDeviceDefinition(vendorId: 0x413d, productId: 0x2107, usagePage: 65280)
        .CreateWindowsHidDeviceFactory(_loggerFactory)
        .ConnectFirstAsync()
        .ConfigureAwait(false);

    //Create the observable
    var observable = Observable
        .Timer(TimeSpan.Zero, TimeSpan.FromSeconds(.1))
        .SelectMany(_ => Observable.FromAsync(() => temperDevice.WriteAndReadAsync(new byte[] { 0x00, 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 })))
        .Select(data => (data.Data[4] & 0xFF) + (data.Data[3] << 8))
        //Only display the temperature when it changes
        .Distinct()
        .Select(temperatureTimesOneHundred => Math.Round(temperatureTimesOneHundred / 100.0m, 2, MidpointRounding.ToEven));

    //Subscribe to the observable
    _ = observable.Subscribe(t => Console.WriteLine($"Temperature is {t}"));

    //Note: in a real scenario, we would dispose of the subscription afterwards. This method runs forever.
}

改进的文档

文档已经好了很多,而且还在不断改进。XML文档现在在Nuget包里,所有的文档都发布在Github页面上。

稳定性

还有更多的修复和功能,但稳定性在这个版本中是一个显著的进步。单元测试和集成测试多了很多,抽象化使得系统的很多部分都可以测试。每一次修订都是一次进步,我们的代码覆盖率约为70%,我们将向90%+的代码覆盖率努力。

社区搬到了Device.Net Discord服务器上。在这里,你会发现其他在.NET领域使用连接设备的人。加入并打招呼吧。在报告bug之前,请随时在这里提问。

Device.Net已经获得了良好的势头,我个人正在努力将这个框架提升到你所期望的.NET基金会的标准。我计划通过Blazor将Device.Net带入浏览器,并继续为更多设备类型添加支持。如果可以的话,请贡献或赞助。


原文发表于2021年1月31日christianfindlay.com。


通过www.DeepL.com/Translator(免费版)翻译