本网页已闲置超过3分钟,按键盘任意键或点击空白处,即可回到网页

自制Azure遥控灯

发布时间:2022-09-01
分享到:

自制Azure遥控灯

发布时间:2022-09-01
分享到:

看过《生活大爆炸》的人可能还记得,那些物理学家打造了一个互联网控制的灯。从他们的笔记本电脑发出的信号传遍了世界各地,然后回到他们家点亮灯。现在,借助 Windows 10 IoT Core 和 Microsoft Azure,我们也可以在 Raspberry Pi 3 上实现相同的目标。

首先,我建议你应该先阅读这2个 Azure 文档:

开始使用适用于 .NET 的 Azure IoT 中心

https://azure.microsoft.com/en-us/documentation/articles/iot-hub-csharp-csharp-c2d/

1. 创建 Azure IoT Hub 并注册设备

请参阅文档 开始使用适用于 .NET 的 Azure IoT 中心 来创建 IoT 中心。过程是一样的。

对于注册设备,我找到了一种简单的方法。微软在这里有一个工具 https://github.com/Azure/azure-iot-sdks/tree/master/tools/DeviceExplorer 

下载安装后。复制 IoT 中心连接字符串并将其粘贴到主选项卡中。然后点击“更新”按钮。

你可以在 Azure 门户中找到连接字符串。需要的关键参数是:

主机名,SharedAccessKeyName ,SharedAccessKey

连接字符串格式为:

HostName=YOURIOTHUBNAME.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=YOURKEY

然后转到“管理”选项卡,单击“创建”,输入您的 Raspberry Pi 3 设备名称并选择“自动生成密钥”

注册后,你将能看到网格视图中列出的结果。

2. Pi 上的物理连接
所需物品:1 个 LED,2 根跳线。

将 LED 的长脚接 DC3.3V,短脚接 GPIO 04。如果您的 LED 不是标准的 3.3V,请注意,您需要在其上放置一个电阻。

连接后是这样的:

3. 编码
我们需要2个项目。一种是在 Raspberry Pi 上运行,作为信号接收器,寻找来自 Azure 的消息并切换 LED。另一个用于在您的 PC 上运行,作为向 Azure 发送消息的控制器。

项目结构如下:

树莓派项目

使用 Visual Studio 2015 创建一个新的 UWP 项目,例如“ AzureRemoteLight”,添加对“Windows IoT Extensions for the UWP”的引用

从 NuGet 安装此包:

"Microsoft.Azure.Devices.Client": "1.0.5"

顺便说一句,建议将 Json.NET 更新到最新版本,现在是:

"Newtonsoft.Json": "8.0.3"

我还使用了 MVVMLight 和 Edi.UWP.Helpers,但这些不是必须的。

我的项目.json:

{
  "dependencies": {
    "Edi.UWP.Helpers": "1.0.11",
    "Microsoft.Azure.Devices.Client": "1.0.5",
    "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0",
    "MvvmLight": "5.2.0",
    "Newtonsoft.Json": "8.0.3"
  },
  "frameworks": {
    "uap10.0": {}
  },
  "runtimes": {
    "win10-arm": {},
    "win10-arm-aot": {},
    "win10-x86": {},
    "win10-x86-aot": {},
    "win10-x64": {},
    "win10-x64-aot": {}
  }
}
用户界面

至于切换灯光,UI 虽然不是必需的。然而,得到一个 UI 会让你的项目看起来更酷,所以我做了一个这样的简单 UI:

UI 中有 2 点:  

  • Azure IoT Hub Connection将显示与 Azure 的连接状态。
  • CloudToDeviceLog显示操作细节。

视图模型代码

首先,我们需要定义 GPIO 控制器和 LED 的 PIN

#region GPIO Settings
public GpioController GpioController { get; }
public GpioPin LedPin { get; }
#endregion

此外,Azure IoT 中心连接属性

#region Azure IoT Hub Settings
public DeviceClient DeviceClient { get; }
public string IotHubUri { get; } = "YOURIOTHUBNAME.azure-devices.net";
public string DeviceKey { get; } = "YOUR DEVICE KEY";
public string DeviceId => "YOUR DEVICE NAME";
#endregion

您可以在设备资源管理器的“管理”选项卡下找到这些属性。

最后,定义 2 个用于在 UI 上显示的属性。

#region Display Fields
private bool _isAzureConnected;
private string _cloudToDeviceLog;
public bool IsAzureConnected
{
    get { return _isAzureConnected; }
    set { _isAzureConnected = value; RaisePropertyChanged(); }
}
public string CloudToDeviceLog
{
    get { return _cloudToDeviceLog; }
    set { _cloudToDeviceLog = value; RaisePropertyChanged(); }
}
#endregion

在构造函数中,启动 GPIO 控制器和 LED PIN。

public MainViewModel()
{
    DeviceClient = DeviceClient.Create(IotHubUri, new DeviceAuthenticationWithRegistrySymmetricKey(DeviceId, DeviceKey));
    GpioController = GpioController.GetDefault();
    if (null != GpioController)
    {
        LedPin = GpioController.OpenPin(4);
        LedPin.SetDriveMode(GpioPinDriveMode.Output);
    }
}

然后创建一个方法向 Azure 发送消息以确保连接成功。

public async Task SendDeviceToCloudMessagesAsync()
{
    try
    {
        var telemetryDataPoint = new
        {
            deviceId = DeviceId,
            message = "Hello"
        };
        var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
        var message = new Message(Encoding.ASCII.GetBytes(messageString));
        await DeviceClient.SendEventAsync(message);
        Debug.WriteLine("{0} > Sending message: {1}", DateTime.Now, messageString);
        IsAzureConnected = true;
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }
}

不要忘记调用 MainPage.xaml.cs 中的方法

public sealed partial class MainPage : Page
{
    private MainViewModel _vm;
    public MainPage()
    {
        this.InitializeComponent();
        _vm = this.DataContext as MainViewModel;
        Loaded += async (sender, args) =>
        {
            // send device connected message
            await _vm.SendDeviceToCloudMessagesAsync();
        };
    }
}
运行

重要提示:请确保您的系统时间在树莓派上是最新的,否则 SAS 令牌将过期。

在运行应用程序之前,切换到设备资源管理器中的“数据”选项卡。单击“监视器”以接收从您的 Raspberry Pi 发送到 Azure 的消息。

通过 ARM/Remote Machine 将您的项目部署到您的 Pi。如果您成功运行,您将在设备资源管理器中收到消息:

然后我们可以继续编码。

在 ViewModel 中,创建另一个从 Azure 接收消息的方法,并根据消息内容打开或关闭 LED。

public async Task ReceiveCloudToDeviceMessageAsync()
{
    CloudToDeviceLog = "Receiving events...";
    Debug.WriteLine("\nReceiving cloud to device messages from service");
    while (true)
    {
        Message receivedMessage = await DeviceClient.ReceiveAsync();
        if (receivedMessage == null) continue;
        var msg = Encoding.ASCII.GetString(receivedMessage.GetBytes());
        CloudToDeviceLog += "\nReceived message: " + msg;
        if (msg == "on")
        {
            LedPin.Write(GpioPinValue.Low);
        }
        if (msg == "off")
        {
            LedPin.Write(GpioPinValue.High);
        }
        await DeviceClient.CompleteAsync(receivedMessage);
    }
}

我使用的消息是字符串类型,“on”表示打开 LED,“off”表示关闭 LED。

而且,您需要在 MainPage.xaml.cs中执行此方法

public sealed partial class MainPage : Page
{
    private MainViewModel _vm;
    public MainPage()
    {
        this.InitializeComponent();
        _vm = this.DataContext as MainViewModel;
        Loaded += async (sender, args) =>
        {
            // send device connected message
            await _vm.SendDeviceToCloudMessagesAsync();
            // receive remote light control events
            await _vm.ReceiveCloudToDeviceMessageAsync();
        };
    }
}

现在,再次运行您的应用程序。您应该能从 Raspberry Pi 屏幕上看到结果。

至此,树莓派的工作就完成了。

控制器项目

创建一个WPF项目,例如 LightController,它不能是UWP,并添加NuGet包“Microsoft.Azure.Devices”。这个包不支持 UWP,所以我们必须创建一个 WPF 应用程序。

在 MainWindow 中添加 2 个按钮用于打开和关闭 LED。

逻辑代码:

public partial class MainWindow : Window
{
    static ServiceClient serviceClient;
    static string connectionString = "YOU IOT HUB CONNECTION STRING";
    public MainWindow()
    {
        InitializeComponent();
        serviceClient = ServiceClient.CreateFromConnectionString(connectionString);
    }
    private async Task TurnLight(bool isOn)
    {
        await SendCloudToDeviceMessageAsync(isOn);
    }
    private static async Task SendCloudToDeviceMessageAsync(bool isOn)
    {
        var commandMessage = new Message(Encoding.ASCII.GetBytes(isOn ? "on" : "off"));
        await serviceClient.SendAsync("你的设备名称", commandMessage);
    }
    private async void BtnTurnOn_OnClick(object sender, RoutedEventArgs e)
    {
        await TurnLight(true);
    }
    private async void BtnTurnOff_OnClick(object sender, RoutedEventArgs e)
    {
        await TurnLight(false);
    }
}

这里发送的消息也是字符串类型,与树莓派上的程序一致。

此处使用的 IoT 中心连接字符串与您在设备资源管理器的主页中使用的完全相同。

4. 测试
因为我们得到了控制器和客户端项目,所以我们需要一起启动它们。在 Visual Studio 中,右键单击您的解决方案,选择“属性”并选择多个启动项目,如下所示:

项目启动后。您将能够使用 WPF 应用程序控制 PC 上的灯光。您的树莓派会在屏幕上显示详细的操作日志。

如果您对此项目有任何想法、意见或问题,请在下方留言。

以上内容翻译自网络,原作者:Edi Wang,如涉及侵权,可联系删除。

加入微信技术交流群

技术交流,职业进阶

关注与非网服务号

获取电子工程师福利

加入电路城 QQ 交流群

与技术大牛交朋友

讨论