(第一部分是这里第二部分是这里)

使用 Oplà Kit 让 2 个不同的 IoT 设备相互通信的教程。这是关于 IoT、Heroku 和 Arduino 的文章的第三部分。

最近,我收到了新的Arduino Oplà Kit进行测试。为了进行尝试,我决定创建一个 IoT 项目,其中包含多个环境传感器,这些传感器可以远程收集数据,然后通过云报告该数据并返回到我的家庭 IoT 设备。这听起来很复杂,但设置很简单,并且将来可以进行许多高级自定义。

在本文中,我将介绍创建类似设置(架构、设备和代码)是多么简单。你把它从那里拿走取决于你!

项目

首先,我创建了一个简单的项目来捕获外部温度,将其显示在我家的设备上,并将其与内部温度进行比较。我还想确保我创建了一些可定制且功能强大的东西,我可以在其中添加自己的逻辑以允许将来进行更复杂的项目。

注意:有关 IoT 术语(事物、变量、草图等)的快速背景知识,查看此概述。

我们的架构

架构简单但功能强大。我们将利用 Arduino IoT Cloud REST 和 Realtime API 来允许两个不同的设备相互通信。在中间,我们将在Heroku上托管一个自定义 Node.js 应用程序。我们还将使用我的朋友 Francesco Stasi 编写的代码来帮助我们移动数据。该代码是完全开源的,具有 MIT 许可证,可在我的GitHub repo中获得。如果有兴趣,Francesco 和我将继续研究代码。

架构如下所示:

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--usd6iXtE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/jfs796cl9hmf5f3zq2d9.png)

我们的第一个事物(事物 1)是通过 Wi-Fi 连接的。它从环境中读取数据(例如温度)并将数据发送到 Arduino IoT Cloud。通过在 Heroku 上创建我们自己的 Node.js 应用程序,我们能够使用 MQTT/WebSockets API 近乎实时地从 Arduino IoT 获取数据。

一旦我们将数据流式传输到我们的应用程序,我们就可以根据需要处理传入的信息。为简单起见,我们将简单地在事物 2 上重新发布事物 1 的相同值。(注意:仅当事物 1 和事物 2 具有相同的属性名称时,您才能执行此操作。)

这一切都比听起来简单。让我们看看如何构建它!

我们需要的:

  • 1x Oplà 套件(该套件包含 1x MKR1010 和 Arduino IoT 的一年免费服务。)

  • Arduino IoT Cloud 帐户(包含在 Oplà 套件中)

  • Heroku 帐号(免费的爱好帐号应该没问题)

  • 1xArduino MKR1010(带 Wi-Fi 的基本 Arduino 板,包含在 Oplà 套件中)

  • 1xMKR ENV Shield(环境传感器)

创建事物 1:外部传感器

首先,打开 Arduino IoT 云仪表板并创建一个只有一个名为“温度”的变量的户外传感器事物。

如下图所示,变量的类型是“温度传感器 (°c)”。在草图中,它表示为 CloudTemperatureSensor。该属性不需要设置;它只是一个传感器,而不是执行器,因此我们不需要任何类型的用户交互。为了避免向云端发送太多数据,我设置了 0.2 C 的阈值。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--yoQEg9Kk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/m7e1ynpzt0m3sda6d50w.png)

然后,我用我的 MKR Wifi 1010 创建了一个新设备并将它附加到这个东西上。

整个设置如下所示:

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--3GFPV4MM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/ioxpwbjf2zxx5ktjscit.png)

请记住在上传草图之前添加网络参数。如果不这样做,您将收到一条错误消息。

接下来,我在 MKR Wi-Fi 1010 顶部添加了 MKR ENV Shield,并创建了一个简单的草图来在线发送温度。这是整个Sensors Sketch的代码。

除了打印到串口之外,实际上只有两条重要的行:ArduinoCloud.update() 将数据发送到 Arduino IoT Cloud,以及 ENV.readTemperature() 方法,它允许我们测量温度并将其放入变量中。然后,该变量将被发送到云端。

void loop() {
  ArduinoCloud.update();
  // Your code here 
  temperature = ENV.readTemperature();
  delay(200);
}

进入全屏模式 退出全屏模式

将草图上传到板上后,您应该在串行监视器中看到以下内容:

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--e12HI6Rr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/7nxk44z6f4qxncdaeppj.png)

我们每 200 毫秒记录一次温度,但只有在温度变化至少 0.2 摄氏度时才将其发送到云端。其他所有内容都在本地记录和可见,但不会发送到我们的云应用程序。随意改进草图并添加您自己的远程属性。

内部数据可视化设备

我想到了整个项目,因为我刚刚收到了新的Arduino Oplà Kit进行测试。该套件包括许多传感器(或多或少与 MKR ENV Shield 相同)、五个 LED 和五个电容式按钮(触摸传感器)。更重要的是,它有一个有用的电池供电屏幕来显示数据。 To power the Oplà Kit, I bought some Samsung 18650 batteries from RS Components.

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--GMgUkw7---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to -uploads.s3.amazonaws.com/uploads/articles/zzgbj05pxhr4hqnnxnsu.jpg)

因为我们有如此强大的工具包,所以我决定在屏幕上创建三种不同的可视化。

  • 按钮 1 显示 Oplà Kit 的室内温度(internalTemperature 属性)。

  • 按钮 2 显示带有 ENV Shield 的 MKR Wi-Fi 1010 的室外温度(我称之为户外板设备和户外传感器设备)。

  • 按钮 3 显示内部和外部温度之间的差异。

  • LED 1:如果差值为负(外部比内部冷),LED 变为蓝色,否则变为红色。

在 Arduino IoT Cloud 中设置套件

要设置套件,首先请务必拔下您的电路板;否则,它将无法正常工作。然后,配置您的 MKR1010。我将其命名为 CarrierBoard,如下图所示:

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--K88Bvgi6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/8ck2doz6g6pucmzy7sl9.png)

设置板后,我创建了一个名为 OplaKit 的新事物,然后我添加了两个不同的属性:internalTemperature 和 temperature。另一块板获取温度属性,而 internalTemperature 来自 Oplà Kit 本身。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--4dK_66wA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/wb7hrd2uk29cg756utuu.png)

内部温度为:

  • 类型:温度

  • 用户交互:已禁用(只读)

  • 发送值:更改时(阈值:0.1 C)

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--3HEHsNR0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/su288l3hlegxuejqlzy3.png)

请注意,温度属性与 Outdoor Sensors Thing 中的属性完全相同。

创建草图并添加交互

在 Oplà Kit 中运行的草图看起来很神奇,但一切都非常简单。我们需要检测何时按下按钮,并在屏幕上相应地更改值。

首先,我们需要在草图中添加适当的库来控制 LED 和触摸按钮。

// Arduino_MKRIoTCarrier - Version: Latest 
#include <Arduino_MKRIoTCarrier.h>
#include <Arduino_MKRIoTCarrier_Qtouch.h>

进入全屏模式 退出全屏模式

然后,我们需要包含云库(自动完成)并告诉系统我们是否正在使用该案例。 (它将校准触摸按钮的灵敏度。)然后,我设置了一个变量 changeDisplayCounter 来在多个屏幕之间切换。

#include "thingProperties.h"
MKRIoTCarrier carrier;
bool CARRIER_CASE = true;
int changeDisplayCounter = 0;

进入全屏模式 退出全屏模式

循环很简单。在屏幕上显示数据之前,我们检查每个按钮是否被按下。

void loop() {
 ArduinoCloud.update();
 // Your code here
 carrier.Buttons.update();
 if (carrier.Button1.onTouchDown()) {
   Serial.println("Touching Button 1");
   changeDisplayCounter = 0;
   printMeasure(internalTemperature, "Int. Temp");
 }
 // Checks if new data are available
 if (carrier.Button2.onTouchDown()) {
   Serial.println("Touching Button 2");
   changeDisplayCounter = 1;
   printMeasure(temperature, "Ext. Temp");
 }
 if (carrier.Button3.onTouchDown()) {
   Serial.println("Touching Button 3");
   changeDisplayCounter = 2;
   printMeasure(temperature - internalTemperature, "Temp. diff");
 }
 internalTemperature = carrier.Env.readTemperature();
 calcDiff(temperature, internalTemperature);
 delay(200);
}

进入全屏模式 退出全屏模式

最后,我们总是从套件中读取内部温度,并计算与外部温度的差异。

草图的其余部分包含有关功能的详细信息:

void onTemperatureChange() {
 // Do something
 calcDiff(temperature, internalTemperature);
}
void calcDiff(float temp1, float temp2){
 if(temp1 >= temp2) {
   //( led index , red , green , blue )
   carrier.leds.setPixelColor(0, 10, 180, 10);
   // return true;
 }
 else {
   carrier.leds.setPixelColor(0, 10, 10, 180);
   // return false;
 }
 carrier.leds.show();
}
void printMeasure(float temp, String name){
 int colors[] = {ST77XX_RED, ST77XX_BLUE, ST77XX_YELLOW};
 int index = 0;
 Serial.println(name);
 Serial.print(temp);
 Serial.println(" C");
 // Reset screen
 carrier.display.fillScreen(ST77XX_BLACK);
 index = changeDisplayCounter % 3;
 carrier.display.setTextColor(colors[index]);
 carrier.display.setCursor(30, 100);
 carrier.display.setTextSize(2);
 carrier.display.println(name);
 carrier.display.setTextSize(4);
 carrier.display.setCursor(50, 120);
 carrier.display.print(temp);
 carrier.display.setTextSize(2);
 carrier.display.print(" C");
}

进入全屏模式 退出全屏模式

在这里您可以找到我的Oplà Kit Sketch的完整副本。

截至目前,第二个草图将不会收到任何类型的可变温度值,因为该数据存在于 MKR Wi-Fi 1010 中。虽然它已发送到 Arduino IoT Cloud,但尚未发送回我们的 Oplà Kit。我们可以通过创建自己的 Node.js 应用程序来中继数据来解决这个问题。

在 Heroku 上创建自定义 Node.js 应用程序

要创建我们的自定义应用程序,我们可以使用两种不同的 Arduino IoT API:一种是REST API,另一种是实时 MQTT/WebSocket API。后者尚未记录,但幸运的是有一个 JavaScript 客户端可用。你可以在这里找到两个 JavaScript 模块:一个是Arduino IoT Js Client,另一个是Arduino IoT Js lib。

要与 API 交互,我们需要一个 API 令牌。您可以通过单击屏幕顶部的集成按钮找到您的:

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--BVmHubw9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/t5ocy1u086neuj5d29s4.png)

请务必将您的 API 密钥放在手边。我们稍后会使用它。

我的朋友Francesco Stasi是一位了不起的开发人员。 (您可以在 GitHub 上找到他。)他帮助创建了将第一个事物的属性代理到第二个事物中具有相同名称的另一个属性的应用程序。

整个软件真的很小,可以在我自己的Js-IoT-ProxyGitHub仓库中找到。该软件旨在本地开发并部署到 Heroku。它的主要部分在 repo](https://github.com/mastrolinux/js-iot-proxy/blob/13d8002eb1af0d4b34ca85e738fbca5ca3aa0751/src/thing.mjs#L43-L72)上可用的这个[代码片段中可见。

// Register a callback for every property in the object to keep the values
updatedObject.keys(thingProperties).forEach((propertyName) => {
   console.log(`${thingId} - register callback for ${propertyName}`);
   ArduinoIoTCloud.onPropertyValue(thingId, propertyName, (newValue) => {
     console.log(`${thingId} - property ${propertyName} changed`);
     thingProperties[propertyName].value = newValue;
     // Invoke the proxy callback
     proxyThingProperty(thingId, propertyName, newValue);
   });
 });
 return {
   // Get the array of known properties names
   getPropertiesList() {
     return Object.keys(thingProperties);
   },
   // Get the value of a property
   getPropertyValue(propertyName) {
     return typeof thingProperties[propertyName] !== "undefined"
       ? thingProperties[propertyName].value
       : null;
   },
   // Set the value for a property
   setPropertyValue(propertyName, newValue) {
     console.log(`${thingId} - writing ${propertyName}, value: ${newValue}`);
     return ArduinoIoTCloud.sendProperty(thingId, propertyName, newValue);
   },
 };

进入全屏模式 退出全屏模式

如您所见,如果两个属性具有相同的名称,则设备会相互通信。该逻辑在proxy.mjs 文件中可见。

部署应用程序

我做 Linux 工程师已经很长时间了。但是,当我需要开箱即用且无需任何维护的强大功能时,我更喜欢使用 Heroku。

为了部署应用程序,我使用了我最近发现的一个非常方便的功能:GitHub 自动部署功能。每次我合并到 main 时,该应用程序都会立即显示在我的 Heroku 面板中。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--qOeYYCXO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/d8bnt5ghq3oslmapratr.png)

我们只是缺少一些东西来完成所有这些工作。我们需要创建和存储包含以下内容的不同环境变量:

  • Arduino API 应用程序 ID (IOT_CLIENT_ID)

  • Arduino API 密钥 (IOT_CLIENT_SECRET)

  • 户外传感器的事物 ID (THING_ID_FROM)

  • OplaKit 的事物 ID (THING_ID_TO)

我们可以通过使用仪表板中的 Heroku 设置面板来完成所有这些操作。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s---5Gr_Lgy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to -uploads.s3.amazonaws.com/uploads/articles/9cz6gtere62f0tcik9sl.png)

最后,我们可以部署应用程序并检查日志。现在,每次 ENV Shield 中的温度变化时,您都可以看到它被实时发送到 Oplà Kit。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--Z6Ogm42m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/s9jvcnw8q2d3568rrakk.png)

这是设备本身的一切外观。您可以通过单击按钮 1 查看内部温度。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--f9TZmnKa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/5buxwk1zcalb27pcp2li.jpg)

使用按钮 2,我们可以获得外部温度。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--iC2PAl0N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/ewbik3kjg0knyon61hl1.jpg)

最后,使用按钮 3,我们可以看到温差。如果外部温度低于内部温度,LED 将变为蓝色。否则,它将是红色的。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--AM8PXy0R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/c176q0kc3if9pnc6y6x1.jpg)

为了记录温度,我在 Arduino IoT Cloud 中创建了一个仪表板,直接将 Things 添加到我们的仪表板中。

[Alt](https://res.cloudinary.com/practicaldev/image/fetch/s--hBSS9rpE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/5k2pricaemlwzij0lrsk.png)

如果您希望您的系统更加先进和互动,您还可以安装 Arduino IoT Remote 应用程序。

资源

为了简化您的系统创建过程,我收集了您需要的所有信息。

  • ENV Shield 户外传感器草图

  • Oplà 套件草图

  • iot-js-proxy Node.js 应用程序

未来的想法

而已!现在,您拥有了一个功能齐全的 IoT 传感器,可以记录外部环境变量,通过云传输它们,并将它们报告给您家中的第二台设备。将来,我计划通过创建自己的具有自定义界面的移动或 Web 应用程序来进一步增强这一点。 (使用我们已经使用的 JavaScript 客户端应该很简单。)然后,最重要的是,我想将所有数据点存储在我自己的 Heroku Postgres 实例中,并通过 Heroku 的Dataclips共享它们。

Logo

ModelScope旨在打造下一代开源的模型即服务共享平台,为泛AI开发者提供灵活、易用、低成本的一站式模型服务产品,让模型应用更简单!

更多推荐