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

导航至

简介

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

为什么使用 UDP?

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

因此,UDP(用户数据报协议)是这项练习的一个优秀选择。与它的姐妹协议TCP不同,UDP是无连接的——这意味着它不需要任何握手或等待成功数据传输的确认。这也意味着使用UDP的一个潜在缺点是,失败的传输将不会被检测到。正因为如此,它通常被称为“发射并忘记”协议。

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

InfluxDB 行协议

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

[key] [fields] [timestamp]

时间戳字段(以纪元以来的纳秒指定)是可选的,因此一个样本点可能如下所示

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 'https://127.0.0.1:8086/query' --data-urlencode "db=arduino" --data-urlencode "q=SELECT value FROM temperature LIMIT 1"

如果数据已成功接收,您应该看到以下行

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

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

故障排除

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

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

下一步

希望上述之一能帮助您回到正轨。祝你好运!