使用 Arduino 和 InfluxDB 入门

导航至

本文由 Cameron Pavey 撰写。向下滚动查看作者的照片和简介。

时间序列数据 与“普通”数据在一个有趣的方面有所不同。其本质特征是,数据的首要参考点是一个时间戳,显示数据样本是在哪个时间点测量的。 时间序列数据库 如 InfluxDB 对于涉及此类数据的情况非常有用。例如,您可能想要记录车辆随时间变化的速度并识别最大速度,或者您可能想要每十秒记录给定位置的温度和湿度。后一个示例将构成本教程的基础。使用一块小型、廉价的开发板,您将了解如何创建一个 Arduino 应用程序,用于通过 WiFi 在 InfluxDB 实例中记录气候数据。

客户端库

在本教程中,您可以使用 Arduino 的 InfluxDB 客户端 。该库支持 InfluxDB 1 和 2,但本教程将重点介绍 InfluxDB 2。

入门

在您开始深入了解之前,您需要准备一些东西。作为一个 Arduino 项目,当然,硬件是必不可少的。客户端库与 ESP8266 和 ESP32 开发板(均与 Arduino IDE 兼容)配合良好。本教程将使用 ESP32 开发板,它使用 WiFi 连接到 InfluxDB 服务器。您也可以使用其他硬件配置来完成此操作,例如带有 WiFi 扩展板的 Arduino Uno,但如果您这样做,下面显示的示例可能需要进行一些调整。

除了 ESP32 之外,没有数据存储在其中的数据库有什么用呢?为了获得一些有趣的数据来使用,我们将 ESP32 与 DHT11 温度和湿度传感器配对。如果您没有这些传感器,但手头有不同的传感器,则可以记录一些其他数据。数据的重要性不如您将如何处理它。如果您没有本教程中使用的硬件,InfluxDB 包含一些 示例数据集 供您使用。

在软件方面,您需要一个 InfluxDB 实例来发送您的数据。本教程将使用 Influx Docker 镜像来实现这一点。如果您想继续学习但没有 Docker,您可以参考他们的 官方文档 ,找到适合您操作系统的文档。您也可以使用 InfluxDB Cloud 来获得 InfluxDB 的免费托管实例。

一旦 Docker 启动并运行,您可以通过运行以下命令来启动您的 InfluxDB 实例

docker run -d --name=influxdb \
 -p 8086:8086 \
 -v /tmp/testdata/influx:/root/.influxdb2 \
      Influxdb:2.0

这将在您的系统上创建一个运行 InfluxDB 2 镜像的容器,应用程序将在您主机的端口 8086 上公开。如果命令成功,它将返回一个容器 ID 作为输出。接下来,您可以使用浏览器登录 InfluxDB 并设置一些其他元素。

在您的浏览器中导航到 http://localhost:8086,您应该会看到设置用户的提示。继续执行此操作,并记下您稍后要设置的详细信息。

InfluxDB user setup

完成此操作后,InfluxDB 应该会向您展示一些快速入门选项。选择 加载数据,当它要求您选择客户端库时,您可以选择 Arduino。这提供了一些入门代码,非常方便。此页面上还有一些其他参考资料,例如您的令牌,您可以在稍后想要从 Arduino 设备发送数据时使用它。这就是您现在需要在此处执行的所有操作。接下来,是时候处理 Arduino 代码了。

Arduino

如果您尚未安装 Arduino IDE,请访问 此处 并选择适合您操作系统的版本进行安装。由于 ESP32 不是默认的 Arduino 开发板之一,因此您必须通过开发板管理器添加它。转到 工具 > 开发板 > 开发板管理器,IDE 将向您显示一个对话框。在搜索字段中,输入“ESP”,您应该会看到一个名为 esp32 的条目。安装这一个(或者如果您使用不同的开发板,则安装相应的条目)。

接下来,您需要添加几个库。如果您继续学习并使用 DHT 传感器,您将需要一个用于传感器的库和一个用于 InfluxDB 客户端的库。

在菜单栏中,转到 Sketch > Include Libraries > Manage Libraries

同样,IDE 将向您显示一个对话框。这次,搜索“InfluxDB”并安装相应的库

InfluxDB-client-library

对于 DHT 传感器,只需搜索“DHT”并安装“DHT sensor library”,如此处所示

DHT-client-library

一旦您拥有了开发板,以及这两个库(或者如果您使用不同的传感器,则您需要的其他任何库),您就可以开始编写代码了。

代码

该代码将基于您选择 Arduino 时 InfluxDB Web 界面提供的示例,但进行了修改,以与 DHT11 传感器配合使用,而不是像默认程序那样记录有关 WiFi 的测量值。

您可以在 此处 找到所有代码,或者您可以继续学习。您需要做的第一件事是定义一些常量并导入您的库

// This helps with compatibility with the ESP8266
#if defined(ESP32)
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
#define DEVICE "ESP32"
#elif defined(ESP8266)
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti;
#define DEVICE "ESP8266"
#endif

// Import the InfluxDB libraries
#include <InfluxDbClient.h>
#include <InfluxDbCloud.h>

// Import the DHT sensor library, and set some constants
#include "DHT.h"

#define DHTPIN 4 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 // DHT 11

// Set up your WiFi connection here

// WiFi AP SSID
#define WIFI_SSID "<your ssid>"
// WiFi password
#define WIFI_PASSWORD "<your password>"

// Set up your InfluxDB details here

// InfluxDB v2 server url (Use: InfluxDB UI -> Load Data -> Client Libraries)
#define INFLUXDB_URL "http://<your influx server ip>:8086"

// InfluxDB v2 server or cloud API authentication token (Use: InfluxDB UI -> Data -> Tokens -> <select token>)
#define INFLUXDB_TOKEN "<your influx token>

// InfluxDB v2 organization id (Use: InfluxDB UI -> User -> About -> Common Ids )
#define INFLUXDB_ORG "<your org name>"

// InfluxDB v2 bucket name (Use: InfluxDB UI -> Data -> Buckets)
#define INFLUXDB_BUCKET "<your bucket name>"

// Set timezone string according to <https://gnu.ac.cn/software/libc/manual/html_node/TZ-Variable.html>
#define TZ_INFO "CET-1CEST,M3.5.0,M10.5.0/3"

// InfluxDB client instance with preconfigured InfluxCloud certificate
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN, InfluxDbCloud2CACert);

// Create your Data Point here
Point sensor("climate");

// Set up the DHT connection
DHT dht(DHTPIN, DHTTYPE);

在此代码中,您设置了所有依赖项,特别是针对 WiFi、DHT 和 Influx 的依赖项。请注意,所有这些都在 public void setup() {} 函数之前,您将在下一步准备该函数

void setup() {
  // Start Serial for monitoring
  Serial.begin(115200);

  // Init the DHT sensor
  dht.begin();

  // Setup wifi
  WiFi.mode(WIFI_STA);
  wifiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);

  Serial.print("Connecting to wifi");
  while (wifiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();

  // Add tags. Here we will track which device our data is coming from
  sensor.addTag("device", DEVICE);

  // Accurate time is necessary for certificate validation and writing in batches
  // For the fastest time sync, find NTP servers in your area: https://www.pool.ntp.org/zone/
  // Syncing progress and the time will be printed to Serial.
  timeSync(TZ_INFO, "pool.ntp.org", "time.nis.gov");

  // Check server connection
  if (client.validateConnection()) {
    Serial.print("Connected to InfluxDB: ");
    Serial.println(client.getServerUrl());
  } else {
    Serial.print("InfluxDB connection failed: ");
    Serial.println(client.getLastErrorMessage());
  }
}

在设置代码中,发生了一些事情。所有库都已初始化,串行通信已启动,并且标签已添加到您的 Influx Point 对象中。在本示例中,唯一的标签是您设备的名称 (ESP32)。如果您在周围设置了多个实例,这将帮助您区分这些读数来自何处,因此包含它可能会有所帮助。还有一个时间同步,以确保您的设备不会因与服务器时间不同步而出现任何问题。最后,InfluxDB 客户端确认其与服务器的连接。如果一切顺利,您应该在串口监视器中看到“Connected to InfluxDB”。最后要看的是 loop 函数

void loop() {
  // Clear fields for reusing the point. Tags will remain untouched
  sensor.clearFields();

  // Read the temperature and humidity from the sensor, and add them to your data point, along with a calculated heat index
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  sensor.addField("humidity", h);
  sensor.addField("temperature", t);
  sensor.addField("heat_index", dht.computeHeatIndex(t, h, false));

  // Print what are we exactly writing
  Serial.print("Writing: ");
  Serial.println(sensor.toLineProtocol());

  // If no Wifi signal, try to reconnect it
  if ((WiFi.RSSI() == 0) && (wifiMulti.run() != WL_CONNECTED)) {
    Serial.println("Wifi connection lost");
  }

  // Write point
  if (!client.writePoint(sensor)) {
    Serial.print("InfluxDB write failed: ");
    Serial.println(client.getLastErrorMessage());
  }

  //Wait 10s
  Serial.println("Wait 10s");
  delay(10000);
}

在这里,Point 对象的字段被清除,以便在循环之间重用,然后读取 DHT11 传感器。来自传感器的读数随后作为字段添加到 Point 中。如果您使用不同的传感器或以其他方式记录不同的数据,则需要进行一些更改。在此之后,串口监视器将向您显示要写入的数据的 Line Protocol 形式。如果您需要调试任何问题,此信息可能会有所帮助。最后,客户端写入数据点,然后等待十秒钟以重复此过程。

您可以在此 GitHub Gist 上找到完整的代码。继续将其上传到您的开发板,然后从工具菜单连接串口监视器。您应该会看到类似这样的内容

Serial-monitor

如果您这样做,您现在应该在 InfluxDB 实例中填充一些数据。返回 Web 界面并转到 Data > Buckets > {您的存储桶},然后选择您创建的测量值(赋予您的 Point 对象的名称 — 在本示例中为“Climate”)。您需要让它运行一段时间才能获得一些有趣的数据,但这就是它断断续续运行一整天的样子

Data chart

您可以与图表进行交互,查看特定时间点的具体值。如果您已完成到这一步,您现在已成功地通过 WiFi 将传感器数据从 Arduino 开发板记录到 InfluxDB 中。

为什么选择 InfluxDB?

InfluxDB 是一种时间序列数据库,擅长存储与特定时间戳相关的数据。这种数据库有很多使用案例,本示例很好地展示了其强大功能。对于温度之类的东西,随着时间的推移记录它以便您可以查看它在一段时间内的变化非常有意义。使用标签,您可以进一步分类您的数据。在本示例中,有一个设备名称的标签,但这很容易被考虑用于“位置”之类的标签。如果您在不同的位置或气象站运行多个温度传感器,这将是标签的绝佳选择,因为它将允许您的所有气候数据一起存在,按位置分类,这便于比较和分析。

结论

如果您已完成本教程的学习,那么您现在拥有一个与 Arduino 兼容的开发板,可以将传感器数据发送到 InfluxDB 实例。虽然这是一个相当基础的教程,但希望您能看到这种配对背后的潜力。使用廉价的 Arduino 开发板,您可以记录您能想到的任何传感器数据,并将其无线发送到时间序列数据库。时间序列数据库为各种新的机会打开了大门,这些机会通常在使用传统数据库时不可行,例如轻松分析纵向数据,例如本示例中来自 DHT11 传感器的数据。如果您发现自己需要利用应用程序中的时间序列数据,请记住,InfluxDB 不仅适用于 Arduino。InfluxDB 拥有大量的集成,使您可以从许多来源收集和处理数据。

关于作者

Cmeraon Pavey shows how to get started with InfluxDB and PHP

Cameron 是一位在墨尔本生活和工作的全栈开发人员。他致力于永无止境的旅程,以理解高质量代码、开发者生产力和工作满意度的复杂性。