原文地址:cfdevelop.medium.com/device-net-…
发布时间: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(免费版)翻译