65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Arm64 上运行 ASP.NET Core Web 服务器

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2023 年 9 月 8 日

CPOL

8分钟阅读

viewsIcon

4693

downloadIcon

47

本文演示了如何将 ASP.NET Core 与 Windows 11 结合使用,为无头物联网应用程序构建 Web 服务器。您将深入了解如何利用 Arm64 驱动的设备,这些设备可为您的物联网应用提供高性能,同时消耗极低的功率。

ASP.NET Core 是一个跨平台 Web 应用程序开发框架,可让您为各种场景开发 Web 服务作为后端。它还支持容器化,可用于构建云原生应用。这些特性及其跨平台设计使 ASP.NET Core 成为构建物联网 (IoT) Web 服务器的理想工具。

Arm64(有时也写成 AArch64 或 ARM64)芯片架构可让您创建高性能、省电的应用。Windows 11 可直接在 Arm64 驱动的设备上运行,因此您可以像使用 Windows 10 IoT Core 一样,使用它来开发物联网应用。例如,您可以使用 ASP.NET Core 构建一个 Web API,您的无头物联网设备可以通过该 API 与用户或其他设备进行通信。

通过将 ASP.NET 应用构建为原生支持 Arm64,您可以获得优于模拟方法的性能,同时享受低功耗。正如我们在本系列的第一部分中所演示的,与模拟相比,原生支持 Arm64 的应用可以将计算时间缩短近三分之二。

此外,微软还推出了 Windows Dev Kit 2023,这是一款由 Arm64 Snapdragon 芯片驱动的便捷、紧凑、对开发者友好的设备。该设备包含一个神经网络处理单元和一个 GPU,使您能够创建高性能的智能应用程序。

本文演示了如何将 ASP.NET Core 与 Windows 11 结合使用,为无头物联网应用程序构建 Web 服务器。您将深入了解如何利用 Arm64 驱动的设备,这些设备可为您的物联网应用提供高性能,同时消耗极低的功率。

本文使用 Windows Dev Kit 2023 作为开发 PC。该套件不包含任何实际传感器,因此您将实现一个温度传感器模拟器。

您可以在 此处找到配套代码。

项目设置

首先安装 .NET 8.0 SDK。您必须安装一个适用于运行在 Arm64 架构上的 Windows 的 SDK。安装过程很简单,不需要详细说明。如前一篇文章所述,.NET 8.0 SDK 为您提供了 .NET 命令行接口(dotnet 命令),您可以使用它来创建和运行项目。请注意,当您在支持的 Arm64 设备上安装 Arm64 SDK 时,dotnet 命令会自动默认为您的项目使用 Arm64 架构。

接下来,安装 适用于 Windows 的 Visual Studio Code,选择 **User Installer for Arm64**。然后,启动安装程序并使用默认设置。安装完成后,选择您的主题。或者,您也可以安装 Visual Studio 2022,并选择 ASP.NET 和 Web 开发工作负载

现在,您将创建一个新的 ASP.NET Core Web API 项目。

打开命令提示符窗口并键入以下命令

dotnet new webapi -o Arm64.HeadlessIoT

此命令将生成如下所示的输出

该命令会创建一个项目,其中包含一个在 `Controllers/WeatherForecastController.cs` 文件中实现的 Web API 控制器。该控制器返回一系列 模拟天气预报。由于您不需要此控制器,因此通过删除整个 `WeatherForecastController.cs` 文件来将其移除。项目现已准备就绪,您可以继续进行实现了。

实现

本节演示如何实现温度传感器模拟器、传感器服务注册以及 Web API 控制器。接下来,它将概述如何测试 Web API 服务器。

温度传感器模拟器

您将首先实现温度传感器模拟器,它模拟连接到运行 Web 服务的物联网设备的温度传感器的读数。

为了表示传感器读数,您将使用 `SensorReading` 类,该类在下面的代码片段中定义。要实现此类,请在 `Arm64.HeadlessIoT` 解决方案文件夹中创建一个 `Sensors` 文件夹,然后创建一个名为 `SensorReading.cs` 的新文件,并将以下代码放置在其中

namespace Arm64.HeadlessIoT.Sensors;
 
public class SensorReading 
{
    public double Value { get; private set; }
 
    public DateTime TimeStamp { get; }
 
    public SensorReading(double value)
    {
        Value = value;
        TimeStamp = DateTime.UtcNow;
    }
}

上面的类包含两个属性:`Value` 和 `TimeStamp`。Value 属性存储传感器读数,而 `TimeStamp` 表示获取读数的时间。`SensorReading` 类还实现了构造函数。您使用此类通过构造函数参数填充 `Value` 属性。`TimeStamp` 自动提供当前的 UTC 格式日期和时间。

然后,在 `Sensors` 文件夹中,再创建一个文件 `ISensor.cs`,该文件定义了以下接口

namespace Arm64.HeadlessIoT.Sensors;
 
public interface ISensor 
{
    public bool IsActive { get; set; }
 
    public SensorReading GetCurrentReading(); 
}

该接口 提供了实现传感器模拟器的类的通用契约。在这种情况下,所有实现该接口的类都必须实现以下两个成员

  • `IsActive` — 一个布尔属性,指定传感器是否处于活动状态且正在记录数据
  • `GetCurrentReading` — 一个方法,返回一个 `SensorReading` 类实例,其中包含传感器读数和时间戳

现在,您可以实现表示温度传感器的实际类了。在 `Sensors` 文件夹中,添加另一个文件 `TemperatureSensor.cs`,该文件定义了以下类

namespace Arm64.HeadlessIoT.Sensors;
 
public class TemperatureSensor : ISensor
{
    private const int minValue = -10;
 
    private const int maxValue = 40;
 
    private SensorReading lastKnownReading 
        = new SensorReading(random.Next(minValue, maxValue));
 
    private static Random random = new();
 
    public bool IsActive {get; set;} = true;
    
    public SensorReading GetCurrentReading() 
    {
        if(IsActive)
        {
            var currentSensorReading = new SensorReading(random.Next(minValue, maxValue));
 
            lastKnownReading = currentSensorReading;
 
            return currentSensorReading;
        }
        else
        {
            return lastKnownReading;
        }
    }    
}

`TemperatureSensor` 类实现了 `ISensor` 接口、`IsActive` 属性和 `GetCurrentReading` 方法。`IsActive` 属性是一个布尔值,初始值为 `true`,表示温度传感器模拟器处于活动状态。

第二个方法 `GetCurrentReading` 检查 `IsActive` 属性是否为 true。如果是,`GetCurrentReading` 方法将使用伪随机数生成器(`System.Random` 类实例)来模拟温度读数。具体来说,它使用该生成器的 `Next` 方法从 `TemperatureSensor` 类中存储的 `min` 和 `max` 字段的值范围中选择一个整数值。`lastKnownReading` 字段存储传感器读数。最后,`GetCurrentReading` 方法将把温度读数返回给调用者。

或者,如果 `IsActive` 属性为 false,`GetCurrentReading` 方法将返回最后一个已知的传感器读数。

传感器服务注册

在实现温度模拟器后,您将使用 依赖注入设计模式 将 `TemperatureSensor` 的实例注册为单例。为此,您必须修改 `Program.cs` 文件,添加 `using Arm64.HeadlessIoT.Sensors` 和 `builder.Services.AddSingleton<ISensor, TemperatureSensor>()`,如下所示

using Arm64.HeadlessIoT.Sensors;
 
var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
 
builder.Services.AddSingleton<ISensor, TemperatureSensor>();
 
var app = builder.Build();
 
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
 
app.UseHttpsRedirection();
 
app.UseAuthorization();
 
app.MapControllers();
 
app.Run();

这种方法确保整个应用程序都可以使用 `TemperatureSensor` 类的一个实例。任何需要访问该传感器的 Web API 控制器都可以简单地使用 构造函数注入

您还将使用 Swagger 工具集。如上所示,默认的 ASP.NET Core Web API 项目模板还会注册两个服务:`EndpointsApiExplorer` 和 `SwaggerGen`。

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

您将使用这些服务添加 Swagger 中间件,它会分析项目中的所有控制器。然后,它将生成一个包含 Web API 文档的 JSON 格式文件,并通过以下语句在 HTTP 端点上公开生成的文档

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

无头物联网设备的 Web API 控制器

现在,您已准备好实现 Web API 控制器。在 Controllers 文件夹中创建一个新文件 `IoTController.cs`。然后,在 `IoTController.cs` 文件中,添加两个 using 语句并定义命名空间

using Microsoft.AspNetCore.Mvc;
using Arm64.HeadlessIoT.Sensors;
 
namespace Arm64.HeadlessIoT.Controllers;

接下来,定义 `IoTController` 类,该类派生自 ControllerBase 并包含所需的控制器属性

[ApiController]
[Route("[controller]")]
public class IoTController : ControllerBase
{
    
}

然后在 `IoTController` 类中,定义只读字段 `temperatureSensor`,它存储在 `Program.cs` 文件中的依赖项容器中注册的 `TemperatureSensor` 类实例的引用

private readonly ISensor temperatureSensor;

您现在可以定义 `IoTController` 类的构造函数了

public IoTController(ISensor sensor)
{
    temperatureSensor = sensor;
}

此代码使用构造函数依赖注入来获取 `TemperatureSensor` 类实例的引用。`temperatureSensor` 字段存储 `Program.cs` 文件中定义的 `TemperatureSensor` 类的引用。

现在,您可以实现处理 `GET` 请求的 `IoTController` 方法了

[HttpGet]
[ProducesResponseType(typeof(SensorReading), StatusCodes.Status200OK)]
public SensorReading Get()
{
    return temperatureSensor.GetCurrentReading();
}

此方法返回温度传感器模拟器的当前读数。

最后,您将实现 `POST` 处理程序,该处理程序使用户能够更改传感器模拟器的 `IsActive` 属性

[HttpPost]
public IActionResult SetSensorStatus(bool isActive)
{
    temperatureSensor.IsActive = isActive;
 
    return Ok();
}

现在,您可以通过 Web API 更改模拟器的内部状态。

测试 Web API 服务器

要测试 Web API 服务器,您必须生成并运行应用程序。

打开命令提示符窗口,转到项目文件夹并键入

dotnet run

此命令将产生以下输出

请注意,该命令默认使用 Arm64 架构(因为您安装了适用于 Arm64 的 .NET SDK)。如果您有多个 SDK 可用,则必须使用 `-a` 参数显式指定架构。例如

dotnet run -a arm64

您可以通过打开任务管理器并单击“详细信息”窗格来确保应用程序使用此架构

现在,打开 Web 浏览器并导航到 `https://:/iot`,其中 `` 应与上面命令提示符屏幕截图中“Now listening on”之后显示的端口值匹配。执行此操作会调用 `IoTController` 的 `GET` 方法,您将看到传感器读数以 JSON 格式字符串显示

要测试 `POST` 方法,请使用 curlPostmanSwagger。最后一种选项最简单,因为 Swagger 已包含在项目模板中。

要访问 Swagger,请在 Web 浏览器的地址栏中键入 `https://:/swagger`。此 URL 将带您到以下屏幕

现在,展开 **POST** 部分,然后单击 **Try it out** 按钮,这将启用 `isActive` 下拉列表。将 `isActive` 设置为 `false`,然后单击 **Execute**。

此操作会将 `POST` 请求发送到 `IoTController` 并禁用模拟器。因此,所有后续对 `IoTController` 的 `GET` 调用都将返回最后一个已知的传感器读数(这是在禁用模拟器之前生成的最终读数),如下所示

当您将 `isActive` 设置回 **true** 并向 Web 服务器发送 `GET` 请求时,您将看到温度设置已更新。

摘要

本文演示了如何使用 ASP.NET Core 为运行在 Windows 11 on Arm 上的无头物联网应用实现 Web API 服务器。它可视化了 Web 服务器如何从温度传感器模拟器检索模拟传感器读数。它还展示了如何通过 Web 服务器控制模拟器。最后,它演示了如何在 ASP.NET Core 中使用依赖注入和 Swagger 来测试 Web API。ASP.NET Core 是跨平台的,允许您使用类似的方法在非 Windows 平台上运行 Web 服务器。

通过将 ASP.NET Core 与 Arm64 相结合,您可以为所有应用程序实现高性能、低功耗的 Web 服务器。虽然您可以将项目编译为任何 CPU,但在目标为 Arm64 时,通过原生运行可以提高 Web 服务器的性能。

尝试 Arm64 来了解更多信息。

© . All rights reserved.