Публикация данных телеметрии на локальном сервере Thingsboard работает с mqtt.js, но не с примером ESP arduino - PullRequest
0 голосов
/ 13 февраля 2019

Я установил виртуальную машину, на которой работает брокер ThingsBoard, для проекта IoT, над которым я работаю, и столкнулся с некоторыми странными проблемами.Я использую ESP32 с несколькими подключенными датчиками (температура, влажность, давление и т. Д.) И хочу просто передать эти значения брокеру ThingsBoard с помощью MQTT.Я создал тестовую программу на основе примера кода, предоставленного 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 8 июня 2016 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, часы DIV: 1 нагрузка: 0x3fff0018, длина: 4 нагрузка:0x3fff001c, len: 928 ho 0 tail 12 room 4 load: 0x40078000, len: 9280 load: 0x40080400, len: 5848 entry 0x40080698

Подключение к WiFiNetwork .... IP-адрес, подключенный по WiFi: 192.168.0.15 Попытка MQTTсоединение ... не удалось, rc = -1, повторите попытку через 5 секунд. Попытка подключения MQTT ... не удалось, rc = -1, повторите попытку через 5 секунд

Из просмотра библиотеки PubSubClientдокументация , код состояния -1 означает «клиент отключен чисто», что на самом деле не имеет смысла ...

Итак, если предположить, что с моим сервером ThingsBoard что-то не так, яиспользовал примеры файлов клиента MQTT.js из графического интерфейса ThingsBoard Getting Startedde и изменил файлы .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 делаетПохоже, что порт 8080 указан не так, как мой код Arduino.Понятно, что проблема заключается в коде Arduino, а не в самом сервере, но я совершенно тупик ... Есть идеи?

РЕДАКТИРОВАТЬ: После исправления проблемы с неправильным MQQTномер порта сервер смог правильно подключиться.Затем после некоторого тестирования я заметил, что строка полезной нагрузки вообще не обновлялась на приборной панели, как только все переменные были включены.Оказалось, что строка была слишком длинной для правильной передачи, поэтому я обновил код, чтобы разделить строку на две передачи, что в конечном итоге все исправило.

1 Ответ

0 голосов
/ 13 февраля 2019

Вы сказали, что запускаете ThingsBoard на виртуальной машине.

Если вы явно не настроили это иначе, эта виртуальная машина будет доступна только программному обеспечению, работающему на том же компьютере, что и виртуальная машина.Вот почему файл .bat работает.

Виртуальные машины обычно устанавливают частную виртуальную сеть внутри компьютера, на котором они работают, только с самим собой и с этим компьютером в сети.

Вы будетенеобходимо проверить документацию к программному обеспечению для виртуальной машины, чтобы выяснить, как сделать виртуальную машину доступной с других компьютеров в сети, к которой подключен компьютер с Windows.

Возможно также, что вы используете неправильный номер порта.MQTT обычно использует 1883, а не 8080, как определил ваш код ESP32.Я бы сначала проверил это, прежде чем копаться в конфигурации виртуальной машины.

...