簡體   English   中英

將電報數據發布到本地Thingsboard服務器可與mqtt.js一起使用,但不能與ESP arduino示例一起使用

[英]Publishing telemtry data to local Thingsboard server works with mqtt.js but not ESP arduino sample

我為正在處理的IoT項目設置了運行ThingsBoard代理的VM,並遇到了一些奇怪的問題。 我正在使用連接了幾個傳感器(溫度,濕度,壓力等)的ESP32,並想使用MQTT將這些值簡單地推送到ThingsBoard代理。 我基於ThingsBoard提供的代碼示例創建了一個測試程序,但是在連接服務器時遇到了問題。 這是我的代碼如下:

#include <WiFi.h>
#include <Wire.h>
#include <OneWire.h>
#include <PubSubClient.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <DallasTemperature.h>

// Constants
#define ONE_WIRE_PIN  14  // One-Wire pin for water temperature sensor
#define TURBIDITY_PIN 36  // Analog pin for turbidity sensor
#define SEALEVELPRESSURE_HPA (1013.25)

// WiFi Login Info
#define ssid              "WiFiNetwork"
#define password          "password"

// MQTT Broker IP address:
#define mqtt_server       "192.168.0.10"
#define mqtt_server_port  1883

// MQTT Client Info
#define MQTT_CLIENT_NAME "ESP32"
#define ACCESS_TOKEN "ESP32_DEMO_TOKEN"

// Sensor Variables
float airTemperature = 0;
float waterTemperature = 0;
float humidity = 0;
float pressure = 0;
float altitude = 0;
float turbidity = 0;

// Control Variables
long lastMsg = 0;   // keeps track of timestamp since the last message was sent

// Objects
Adafruit_BME280 BME280; // I2C
OneWire oneWire_in(ONE_WIRE_PIN);
DallasTemperature temperature_sensor(&oneWire_in);

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  int status = 0;

  Serial.begin(115200);

  // Initialize BME280
  status = BME280.begin();  
  if (!status) {
      while(true) {
        Serial.println("Could not find a valid BME280 sensor, check wiring!");
        delay(5000);
      }
  }

  // Initialize the One-Wire Temperature Sensor
  temperature_sensor.begin();

  // Initialize the WiFi and MQTT connections
  setup_wifi();
  client.setServer(mqtt_server, mqtt_server_port);
  client.setCallback(mqtt_callback);
}

void loop() {
  // Update/refresh the Wifi/MQTT connection
  updateWirelessConnection();

  // Read and transmit the sensor values every 5 seconds
  long now = millis();
  if (now - lastMsg > 5000) {
    lastMsg = now;

    // Read all the sensor values
    collectMeasurements();

    // Publish updated sensor values
    publishMeasurements();

    // Print all sensor values
    printMeasurements();
  }
}

void updateWirelessConnection()
{
  if (!client.connected()) {
    reconnect();
  }

  client.loop();
}

void printMeasurements()
{
  Serial.print("Air Temperature: ");
  Serial.print(airTemperature);
  Serial.println( " *C");

  Serial.print("Air Pressure: ");
  Serial.print(pressure);
  Serial.println( " hPa");

  Serial.print("Humidity: ");
  Serial.print(humidity);
  Serial.println( " %RH");

  Serial.print("Altitude: ");
  Serial.print(altitude);
  Serial.println( " m");

  Serial.print("Water Temperature: ");
  Serial.print(waterTemperature);
  Serial.println( " *C");

  Serial.print("Water Turbidity: ");
  Serial.print(turbidity);
  Serial.println( " NTUs");

  Serial.println();
}

void collectMeasurements()
{
  // Read the measurements from the BME280 sensor
  airTemperature = BME280.readTemperature();
  pressure = BME280.readPressure() / 100.0F;
  altitude = BME280.readAltitude(SEALEVELPRESSURE_HPA);
  humidity = BME280.readHumidity();

  // Read the water temperature sensor
  temperature_sensor.requestTemperatures();
  waterTemperature = temperature_sensor.getTempCByIndex(0);

  // Read the turbidity sensor
  turbidity = calculateTurbidityValue(analogRead(TURBIDITY_PIN), waterTemperature);
}

// Calculates the temperature-compensated Turbidity value based on the raw ADC voltage and water temperature in celsius
float calculateTurbidityValue(int adcValue, float waterTemp)
{
  // Convert ADC value to original voltage reading
  float voltage = adcValue * (5.0 / 4096.0);

  // Correct the voltage value for temperature
  // TODO: TBD later

  // Convert the voltage to NTUs
  float NTUs = -1120.4 * pow(voltage, 2.0) + 5742.3 * voltage - 4352.9;

  if (NTUs < 0) {
    return 0;
  } else {
    return NTUs;
  }
}

// Publishes all measurements to the MQTT broker
void publishMeasurements()
{
  // Create Payload string
  // Paylod String format: {"key1":"value1", "key2":"value2"}
  String payload1 = "{";
  payload1 += "\"airTemperature\":";   payload1 += airTemperature;    payload1 += ",";
  payload1 += "\"pressure\":";         payload1 += pressure;          payload1 += ",";
  payload1 += "\"humidity\":";         payload1 += humidity;
  payload1 += "}";

  String payload2 = "{";
  payload2 += "\"altitude\":";         payload2 += altitude;          payload2 += ",";
  payload2 += "\"waterTemperature\":"; payload2 += waterTemperature;  payload2 += ",";
  payload2 += "\"turbidity\":";        payload2 += turbidity;
  payload2 += "}";

  transmitPayload(payload1);
  transmitPayload(payload2);
}

void transmitPayload(String payload)
{
  // Convert Payload string to c-string and transmit
  char attributes[500];
  payload.toCharArray(attributes, 500);
  client.publish("v1/devices/me/telemetry", attributes);
}

void setup_wifi() {
  delay(10);

  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void mqtt_callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;

  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();

  // Feel free to add more if statements to control more GPIOs with MQTT

  // If a message is received on the topic esp32/output, you check if the message is either "on" or "off". 
  // Changes the output state according to the message
  /*if (String(topic) == "esp32/output") {
    Serial.print("Changing output to ");
    if(messageTemp == "on"){
      Serial.println("on");
      digitalWrite(ledPin, HIGH);
    }
    else if(messageTemp == "off"){
      Serial.println("off");
      digitalWrite(ledPin, LOW);
    }
  }*/
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected())
  {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(MQTT_CLIENT_NAME, ACCESS_TOKEN, NULL)) {
      Serial.println("connected");
      // Subscribe
      //client.subscribe("esp32/output");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

對於那些感興趣的人來說,實際讀取傳感器值並將其打印出來的代碼可以正常工作,問題在於連接到ThingsBoard服務器的代碼。 當我運行此代碼時,這是我在串行終端中看到的內容:

ets 2016年6月8日00:22:57

rst:0x1(POWERON_RESET),啟動:0x13(SPI_FAST_FLASH_BOOT)configsip:0,SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00模式:DIO 1個負載:0x3fff0018,len:4個負載:0x3fff001c,len:928 ho 0尾部12個房間4​​個負載:0x40078000,len:9280負載:0x40080400,len:5848入口0x40080698

正在連接到WiFiNetwork .... WiFi已連接IP地址:192.168.0.15正在嘗試進行MQTT連接...失敗,rc = -1請在5秒鍾內重試。正在嘗試進行MQTT連接...失敗,rc = -1嘗試在5秒鍾內重試。

通過查看PubSubClient庫文檔 ,狀態代碼-1表示“客戶端已完全斷開連接”,這實際上沒有任何意義。

因此,假設我的ThingsBoard服務器可能有問題,我使用了《 ThingsBoard入門指南》中的MQTT.js客戶端示例文件,並修改了.bat和.json文件以匹配我的輸入,如下所示:

MQTT-js.bat

@echo off

REM Set ThingsBoard host to "demo.thingsboard.io" or "localhost"
set THINGSBOARD_HOST=192.168.0.10

REM Replace YOUR_ACCESS_TOKEN with one from Device details panel.
set ACCESS_TOKEN=ESP32_DEMO_TOKEN

REM Read serial number and firmware version attributes
set /p ATTRIBUTES=<attributes-data.json

REM Read timeseries data as an object without timestamp (server-side timestamp will be used)
set /p TELEMETRY=<telemetry-data.json

REM publish attributes and telemetry data via mqtt client
node publish.js

遙測data.json

{"airTemperature":21, "humidity":55.0, "pressure": 101.6}

當我執行.bat文件時,數據將毫無問題地發布到我的服務器上!

奇怪的是,這個MQTT.js文件似乎不需要像我的Arduino代碼一樣指定端口8080。 很明顯,問題出在Arduino代碼上,而不是服務器本身上,但是我絕對感到困惑……有什么想法嗎?

編輯:用不正確的MQQT端口號糾正問題后,服務器即可正確連接。 然后經過一些測試,我注意到一旦包含所有變量,有效負載字符串就根本不會在儀表板上更新。 原來,字符串太長而無法正確傳輸,因此我更新了代碼,將字符串分成兩次傳輸,最終修復了所有問題。

您說您正在VM中運行ThingsBoard。

除非您另外進行了明確配置,否則只有與該虛擬機在同一台計算機上運行的軟件才能訪問該虛擬機。 這就是.bat文件起作用的原因。

虛擬機通常會在運行它們的計算機內部建立一個專用虛擬網絡,該虛擬網絡只能自己運行,也可以運行在網絡上。

您需要查看VM軟件的文檔,以弄清楚如何使Windows計算機所連接的網絡上的其他計算機可以訪問該VM。

您也可能使用了錯誤的端口號。 MQTT通常使用1883,而不是您的ESP32代碼所定義的8080。 在深入研究VM的配置之前,我將首先進行驗證。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM