如何从 Arduino Uno 向 InfluxDB 发送传感器数据

导航至

简介

由于 InfluxDB 是一个 时间序列数据库,因此它是存储从传感器和构成 物联网 的各种其他设备收集的数据的完美选择。在本文中,我们将研究一个基本用例,该用例涉及从连接到 Arduino Uno 的温度传感器收集数据,然后通过本机 UDP 插件发送到 InfluxDB。

为什么选择 UDP?

由于大多数支持互联网的设备中的处理器都设计为节能型(因此相对低功耗),并且也可能通过低带宽链路连接,因此我们最好使用需要尽可能少的处理和网络开销的通信方法。

因此,UDP(用户数据报协议)是此练习的绝佳选择。与其姊妹协议 TCP(传输控制协议)不同,它是无连接的 - 这意味着它不需要任何握手或等待数据传输成功的确认。这也意味着使用 UDP 的一个潜在缺点是,失败的传输将无法检测到。因此,它通常被称为“发射后不管”协议。

其他协议,例如 MQTT,提供的数据传输属性在效率上与 UDP 相似,但需要更复杂的客户端实现才能获得关于数据接收的更好保证。

InfluxDB 行协议

幸运的是,向 InfluxDB 发送数据很容易 - 它有一个紧凑的、基于文本的 行协议,用于通过 HTTP API 和 UDP 接口写入数据。点按行提供,规范如下

[key] [fields] [timestamp]

时间戳字段(以自 epoch 以来的纳秒为单位指定)是可选的,因此样本点可能如下所示

temperature,device=arduino01 value=83.2

在此示例中,device 指定了一个标签,该标签允许在 InfluxDB 中方便地进行索引。您可以提供其他标签来帮助识别有关测量位置或方式的具体详细信息。

在 InfluxDB 上启用 UDP

默认情况下,InfluxDB 上的 UDP 接口处于禁用状态。您需要修改配置文件,使其看起来类似于这样

...

[[udp]]
  enabled = true
  bind-address = ":8888"
  database = "arduino"

...

您需要先创建指定的数据库,然后才能通过 UDP 接口接收数据包。为此,您可以使用 InfluxDB CLI 发出以下命令

CREATE DATABASE arduino

硬件

arduino

我们将使用以下硬件

注意: 某些版本的 Arduino WiFi Shield 出厂时固件存在缺陷。如果您在检查完所有其他内容后,在发送 UDP 数据包时遇到问题,您可以在此处了解如何升级固件。

示例代码

此代码假定 TMP36 连接到模拟引脚 0,并将每秒轮询一次,并通过 UDP 将值发送到指定的 InfluxDB 主机。

#include <SPI.h>
#include <WiFi.h>
#include <WiFiUDP.h>

char ssid[] = "your network name";     //  your network SSID (name) 
char pass[] = "network password";    // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status

// the IP address of your InfluxDB host
byte host[] = {10, 0, 1, 11};

// the port that the InfluxDB UDP plugin is listening on
int port = 8888;

WiFiUDP udp;

void setup() {
  // initialize serial port
  Serial.begin(9600);

  // attempt to connect using WPA2 encryption
  Serial.println("Attempting to connect to WPA network...");
  status = WiFi.begin(ssid, pass);

  // if unable to connect, halt
  if ( status != WL_CONNECTED) { 
    Serial.println("Couldn't get a WiFi connection");
    while(true);
  } 
  // if the conneciton succeeded, print network info
  else {
    Serial.println("Connected to network");
    // print your WiFi shield's IP address:
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);

    // print the received signal strength:
    long rssi = WiFi.RSSI();
    Serial.print("signal strength (RSSI):");
    Serial.print(rssi);
    Serial.println(" dBm");
  }
}

float getTemperature() {
  // get the reading from the temperature sensor
  int reading = analogRead(0);
 
  // convert that reading to voltage
  float voltage = reading * 5.0;
  voltage /= 1024.0; 
 
  // convert the voltage to temperature in Celsius (10mV per degree + 500mV offset)
  float temperatureC = (voltage - 0.5) * 100 ;  
  
  // now convert to Fahrenheit
  float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;

  return temperatureF;
}

void loop() {
  String line, temperature;

  // wait 1 second
  delay(1000);
  
  // get the current temperature from the sensor, to 2 decimal places
  temperature = String(getTemperature(), 2);

  // concatenate the temperature into the line protocol
  line = String("temperature value=" + temperature);
  Serial.println(line);
  
  // send the packet
  Serial.println("Sending UDP packet...");
  udp.beginPacket(host, port);
  udp.print(line);
  udp.endPacket();
}

从 InfluxDB 查询数据

数据写入 InfluxDB 后,现在您可以发出查询来检索它。最快的方法是从命令行使用 curl。使用上面代码示例中提供的主机和端口,以下命令应为您提供来自 temperature 测量的最新点

curl -G 'http://localhost:8086/query' --data-urlencode "db=arduino" --data-urlencode "q=SELECT value FROM temperature LIMIT 1"

如果 InfluxDB 已成功接收到数据,您应该看到这样一行

{"results":[{"series":[{"name":"temperature","columns":["time","value"],"values":[["2015-08-27T04:09:53.883221046Z",83.2]]}]}]}

恭喜 - 您的数据正在被收集!

故障排除

如果您没有看到任何数据点,以下是一些您可以检查的事项

  • 确保 WiFi Shield 正在运行最新固件
  • 确保 InfluxDB 内部已启用 UDP 接口,并且服务已重启
  • 确保主机和端口与您的实际 InfluxDB 实例匹配
  • 确保 WiFi 或以太网 Shield 已成功连接到网络
  • 确保您尝试写入的数据库已创建

下一步

希望以上其中一项能帮助您回到正轨。祝你好运!