练习:使用 .NET IoT 库
在本单元中,你将使用 .NET IoT 库来编写与洞穴监视器设备交互的代码。 尽管支持 .NET SDK 在 Raspberry Pi 和其他 IoT 板上运行,但建议使用计算机。 通过计算机,你可以使用功能齐全的 IDE 和编辑器,例如 Visual Studio 和 Visual Studio Code。
创建应用
从开发计算机上的命令 shell 完成以下步骤。
创建一个名为 cheeseave.net 的新控制台应用。
dotnet new console -o cheesecave.net cd ./cheesecave.net
前面的命令:
- 在名为 cheeseave.net 的文件夹中创建一个新的 .NET 控制台应用。
- 将当前位置设置为 cheeseave.net 文件夹。
将 .NET IoT 库添加到项目中。
dotnet add package System.Device.Gpio --version 2.1.0 dotnet add package IoT.Device.Bindings --version 2.1.0
前面的命令:
- 将
System.Device.Gpio
和Iot.Device.Bindings
包添加到项目中。 - 指定为两个包添加版本
2.1.0
。
- 将
添加代码
使用首选的 IDE 或编辑器,将 Program.cs 的内容替换为以下代码:
using System; using System.Device.Gpio; using System.Device.Gpio.Drivers; using System.Device.I2c; using Iot.Device.Bmxx80; using Iot.Device.Bmxx80.ReadResult; bool _fanOn = false; bool _exit = false; int _pin = 21; // Initialize the GPIO controller using GpioController gpio = new GpioController(); // Open the GPIO pin for output gpio.OpenPin(_pin, PinMode.Output); gpio.Write(_pin, PinValue.Low); // Get a reference to a device on the I2C bus var i2cSettings = new I2cConnectionSettings(1, Bme280.DefaultI2cAddress); using I2cDevice i2cDevice = I2cDevice.Create(i2cSettings); // Create a reference to the BME280 using var bme280 = new Bme280(i2cDevice); // Write the fan, temperature, and humidity statuses to the console WriteStatus(); // Main control loop while (!_exit) { string commandText = Console.ReadLine() ?? string.Empty; DoCommand(commandText); } // Close the pin before exit gpio.ClosePin(_pin); // Exit return; void DoCommand(string commandText) { switch (commandText) { case "exit": Console.WriteLine("Exiting!"); _exit = true; break; case "fan": if (!_fanOn) { // Turn on the fan gpio.Write(_pin, PinValue.High); Console.WriteLine("Turned fan on!"); } else { // Turn off the fan gpio.Write(_pin, PinValue.Low); Console.WriteLine("Turned fan off!"); } _fanOn = !_fanOn; WriteStatus(); break; case "status": WriteStatus(); break; default: Console.WriteLine("Command not recognized! Try again."); return; } } void WriteStatus() { // Read the BME280 Bme280ReadResult output = bme280.Read(); double temperatureF = output.Temperature?.DegreesFahrenheit ?? double.NaN; double humidityPercent = output.Humidity?.Percent ?? double.NaN; // Print statuses Console.WriteLine(); Console.WriteLine("DEVICE STATUS"); Console.WriteLine("-------------"); Console.WriteLine($"Fan: {(_fanOn ? "ON" : "OFF")}"); Console.WriteLine($"Temperature: {temperatureF:0.#}°F"); Console.WriteLine($"Relative humidity: {humidityPercent:#.##}%"); Console.WriteLine(); Console.WriteLine("Enter command (status/fan/exit):"); }
检查代码以了解它如何与 GPIO 引脚进行交互。 在上述代码中:
创建了一个
GpioController
实例以用于 GPIO 操作。通过
gpio.OpenPin()
打开引脚 21。 该引脚通过PinMode.Output
打开输出。引脚 21 的值设置为
PinValue.Low
。 该值表示引脚可以发出的最低电压量。 为了点亮 LED,PinValue.Low
代表“关”,PinValue.High
代表“开”。 结果,代表风扇的 LED 关闭。该代码通过写入
PinValue.Low
和PinValue.High
来打开和关闭风扇/LED。提示
许多真实的中继使用
PinValue.High
表示“关”,使用PinValue.Low
表示“开”。 这与你在本练习中为代表风扇中继的 LED 实施的操作相反。在代码退出之前,通过
gpio.ClosePin()
关闭引脚 21。
检查代码以了解它如何与 BME280 交互。 在上述代码中:
创建了
I2cConnectionSettings
的实例。 第一个构造函数参数busId
设置为1
,即 Raspberry Pi 上的 I2C 总线 ID。 第二个构造函数参数deviceAddress
设置为Bme280.DefaultI2cAddress
。警告
某些 BME280 分线使用
Bme280.SecondaryI2cAddress
作为设备地址。 如果应用引发System.IO.IOException: Error 121 performing I2C data transfer.
,请尝试改用此值。I2cDevice
的实例是使用I2cConnectionSettings
对象创建的。Bme280
的实例是使用I2cDevice
对象创建的。 该对象代表物理 BME280。在
WriteStatus()
方法中,Bme280ReadResult
对象是通过调用Bme280.Read()
创建的。Bme280ReadResult
对象包含Temperature
和Humidity
属性。Temperature
和Humidity
属性均可为空,这意味着它们可能包含null
。 因此,null 条件运算符?.
用于访问其成员。- 这些属性本身公开进行自动单位转换的属性,例如
DegreesFahrenheit
和Percent
。 - 在这两种情况下,null 合并运算符
??
会检查返回值,如果返回值为null
,则将其替换为double.NaN
。
提示
如果需要了解 null 安全方面的帮助,请参阅 C# 中的 null 安全。
生成应用
运行以下命令以生成应用。
dotnet build
生成完成,没有错误或警告。
在下一单元中,你将应用部署到 Raspberry Pi 并进行测试。