MQTT Toppic mit MacAdresse

Hallo zusammen
Da das hier mein erster Post ist möchte ich mich kurz vorstellen:

Ich bin derzeit ein 37 Jahre alter Familienvater der berufsbegleitend eine Schule besuch!

Ich lebe wohne und arbeite in der Schweiz.

Meine Kenntnisse sind auf Anfängerniveau, ich habe zwar schon ein Paar Arduino Projekte umgesetzt aber kratze sicher erst an der Oberfläche!

Für ein Schulprojekt sollen wir jetzt mittels Adafruit Feather HUZZAH ESP8266 Daten sammeln, diese dann via MQTT an einen RaspPi schicken und in eine MYSQL Datenbank speichern.

Grundsätzlich funktioniert das auch schon ausser das mit der MYSQL aber das ist jetzt nicht das Thema :slight_smile:

Mein bisheriger Code: (ich weis er ist noch nicht Kommentiert und aufgeräumt aber er tut was er soll)

#include "Seeed_BME280.h"
#include <Wire.h>
#include <Digital_Light_TSL2561.h>
#include "rgb_lcd.h"
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

//Display Init
rgb_lcd lcd;

const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
const char* ssid     = "AUT-18H-21H-SG-G2";
const char* password = "ZbW-WebTech";
const char* host = "wifitest.adafruit.com";
#define AIO_SERVER      "192.168.0.101"
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME    "84:F3:EB:77:00:70"
#define AIO_KEY         ""

WiFiClient client;


//Temperatursensor
BME280 bme280;

//Definition Sound Sensor
#define PHOTOCELL_PIN A0

//RGB
int rgb_R = 13;
int rgb_G = 15;
int rgb_B = 12;

int Perioden = 10;
int Sensoren = 6;
float Data [10][6];
int period = 1000;
unsigned long time_now = 0;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish Time = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"AIO_USERNAME"/Time");
Adafruit_MQTT_Publish Temp = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"AIO_USERNAME"/Temp");
Adafruit_MQTT_Publish Pressure = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"AIO_USERNAME"/Pressure");
Adafruit_MQTT_Publish Altitude = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"AIO_USERNAME"/Altitude");
Adafruit_MQTT_Publish Humidity = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"AIO_USERNAME"/Humidity");
Adafruit_MQTT_Publish LightValue = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"AIO_USERNAME"/LightValue");
Adafruit_MQTT_Publish SoundValue = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"AIO_USERNAME"/SoundValue");

void setup()
{
  Serial.begin(115200);

  //Initial Temperatursensor
  if (!bme280.init()) {
    Serial.println("Device error!");
  }

  //Initial Lichtsensor
  TSL2561.init();

  delay(500);
  //Inital RGB
  pinMode(rgb_R, OUTPUT);
  pinMode(rgb_G, OUTPUT);
  pinMode(rgb_B, OUTPUT);

  digitalWrite(rgb_R, LOW);
  digitalWrite(rgb_G, LOW);
  digitalWrite(rgb_B, LOW);



  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  //  WifiMac = WiFi.macAddress();
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  for (int i = 0; i < 20; i++) {
    digitalWrite(rgb_G, HIGH);
    delay(30);
    digitalWrite(rgb_G, LOW);
    delay(30);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("MAC: ");
  Serial.println(WiFi.macAddress());
  for (int i = 0; i < 20; i++) {
    digitalWrite(rgb_G, HIGH);
    delay(30);
    digitalWrite(rgb_G, LOW);
    delay(30);
  }

}


void loop() {
  if (Timer() == HIGH) {
    digitalWrite(rgb_B, HIGH);
    MQTT_connect();
    float pressure;
    Data [0][0] = millis();
    Data [0][0] = Data [0][0] / 1000;
    Data [0][1] = bme280.getTemperature();
    Data [0][2] = bme280.getPressure();
    Data [0][3] = bme280.calcAltitude(pressure);
    Data [0][4] = bme280.getHumidity();
    Data [0][5] = TSL2561.readVisibleLux();
    Data [0][6] = analogRead(PHOTOCELL_PIN);
    Serial.println("Sende als MQTT: ");
    Serial.println(WifiMac);
    for (int n = 0; n < Sensoren; n++) {
      switch (n) {
        case 0:
          Serial.print("     Time: ");
          Serial.print(Data[0][n]);
          if (! Time.publish(Data[0][n])) {
            Serial.println(F(" Failed"));
          } else {
            Serial.println(F(" OK!"));
          }
          break;
        case 1:
          Serial.print("     Temp: ");
          Serial.print(Data[0][n]);
          if (! Temp.publish(Data[0][n])) {
            Serial.println(F(" Failed"));
          } else {
            Serial.println(F(" OK!"));
          }
          break;
        case 2:
          Serial.print("     Pressure: ");
          Serial.print(Data[0][n]);
          if (! Pressure.publish(Data[0][n])) {
            Serial.println(F(" Failed"));
          } else {
            Serial.println(F(" OK!"));
          }
          break;
        case 3:
          Serial.print("     Altitude: ");
          Serial.print(Data[0][n]);
          if (! Altitude.publish(Data[0][n])) {
            Serial.println(F(" Failed"));
          } else {
            Serial.println(F(" OK!"));
          }
          break;
        case 4:
          Serial.print("     Humidity: ");
          Serial.print((int)Data[0][n]);
          if (! Humidity.publish((int)Data[0][n])) {
            Serial.println(F(" Failed"));
          } else {
            Serial.println(F(" OK!"));
          }
          break;
        case 5:
          Serial.print("     The Light value is: ");
          Serial.print((int)Data[0][n]);
          if (! LightValue.publish((int)Data[0][n])) {
            Serial.println(F(" Failed"));
          } else {
            Serial.println(F(" OK!"));
          }
          break;
        case 6:
          Serial.print("     The Sound value is: ");
          Serial.print((int)Data[0][n]);
          if (! SoundValue.publish((int)Data[0][n])) {
            Serial.println(F(" Failed"));
          } else {
            Serial.println(F(" OK!"));
          }
          break;
      }
    }
    digitalWrite(rgb_B, LOW);
    Serial.println();
    Serial.println();
  }
}

was ich aber nicht hinbekommen ist AIO_USERNAME Variabel zu machen so das ich mir die MAC Adresse auslesen kann und diese ins Toppic des MQTT schreiben kann!

das an der Stelle eh nicht geht ist mir klar!
ich habe schon versucht die Objekterzeugung im void setup oder nach dem void setup vor void loop zu setzen!
ich habe dann vorher einen String generiert mit dem Toppic das ich gerne hätte das dann an stelle von AIO_USERNAME eingetragen.
er akzeptiert aber keine andere Eingabe als eine mit “TEXT”

gibt es dafür eine Lösung?

Der Grund dafür ist, das ich den Code nachehr auf verschieden Notes schreiben möchte aber nicht vorher manuell die Adresse neu einstellen möchte!

Ich hoffe ich konnte mein Anliegen verständlich ausdrücken :slight_smile:

Ich habe schon viel gegoogelt konnte aber nix finden!
Sollte ich was übersehen haben wär eich für einen link sehr dankbar!

Ich danke euch schon mal für eure mithilfe!
Gruss
TaM

const char  AIO_USERNAME[] = "84:F3:EB:77:00:70";
wobei es sein kann, dass ich Dich falsch verstanden habe.

Gruß Tommy

Tommy56:
const char  AIO_USERNAME[] = "84:F3:EB:77:00:70";
wobei es sein kann, dass ich Dich falsch verstanden habe.

Gruß Tommy

Ja das scheint so

Du willst die MAC auslesen weil du den Code auf mehreren Controllern laufen lassen willst?
Ich weiß nicht wie das ginge, die MAC musst du doch am Anfang zuweisen, genau wie deine IP Adresse!?

Gruß
Scherheinz

Wenn man in die Lib schaut, gibt es 2 entsprechende Funktionen: eine verlangt nach einer fest definierten Zeichenkette, die andere Funktion nur nach einer Zeichenkette zusammen mit deren Länge. Eventuell hilft Dir das weiter....

 bool publish(const char *topic, const char *payload, uint8_t qos = 0);
  bool publish(const char *topic, uint8_t *payload, uint16_t bLen,
               uint8_t qos = 0);

Ich denke es liegt nicht an MQTT selbst, das ist nicht so schwer. Wenn ich das richtig verstanden habe will er mit dem Sketch die MAC Adresse der Netzwerk Schnittstelle auslesen und versenden damit er weiß von welchem Controller die Daten kommen. Das macht aber keinen Sinn da er sie ja zuweisen muss genau wie die IP Adresse.

Ist es so?

Hallo,

Scherheinz:
Ich denke es liegt nicht an MQTT selbst, das ist nicht so schwer. Wenn ich das richtig verstanden habe will er mit dem Sketch die MAC Adresse der Netzwerk Schnittstelle auslesen und versenden damit er weiß von welchem Controller die Daten kommen. Das macht aber keinen Sinn da er sie ja zuweisen muss genau wie die IP Adresse.

Ist es so?

Die Esp8266/ESP32 haben eine eindeutige MAC von Espressif.
Kann man mit

if (WiFi.status() == WL_CONNECTED)
{
  Serial.printf("Connected, mac address: %s\n", WiFi.macAddress().c_str());
}

Siehe auch
https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/station-class.html#macAddress

Gruß aus Berlin
Michael

Erstmal danke für euren Einsatz auch wenn es wohl nicht ganz klar ist was ich möchte.
Also Ja ich möchte die MacAdresse der Netzwerk Schnittstelle auslesen das geht auch mit WiFi.macAddress().

Ich kann die gelesene Adresse aber nicht Automatisch an die Stelle schreiben wo ich es hin haben möchte

Beispiel:
Adafruit_MQTT_Publish Time = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"WiFi.macAddress()"/Time");
geht nicht!

Das ich eine IP Adresse der Mac Adresse mittels DHCP-SERVER zu weise ist mir klar ich möchte aber unabhängig von einem DHCP-Server sein!

Die MAC-Adresse möchte ich mittels Toppic schicken um es später besser in der MYSQL DB ablegen zu können!

Danke amithlon, wieder was gelernt.

@tam-planlos:

Adafruit_MQTT_Publish Time = Adafruit_MQTT_Publish(&mqtt, "Proj/webtech/"WiFi.macAddress()"/Time");

Du kannst innerhalb von " " nicht noch " " einfügen. Hab das mal mit Leerstellen versucht deutlich zu machen:

"Proj/webtech/" WiFi.macAddress() "/Time"

WiFi.macAddress() gibt ein 6 byte Array zurück was du aber brauchst ist char

Ich kenne “Adafruit_MQTT” nicht sondern nutze selbst PubSubClient. Dort wird z.B. mit snprintf die Nachricht quasi zusammengebaut mit fixem Text und einer Variabel. Vielleicht hilft dir das weiter:

/*
 Basic ESP8266 MQTT example
 This sketch demonstrates the capabilities of the pubsub library in combination
 with the ESP8266 board/library.
 It connects to an MQTT server then:
  - publishes "hello world" to the topic "outTopic" every two seconds
  - subscribes to the topic "inTopic", printing out any messages
    it receives. NB - it assumes the received payloads are strings not binary
  - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
    else switch it off
 It will reconnect to the server if the connection is lost using a blocking
 reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
 achieve the same result without blocking the main loop.
 To install the ESP8266 board, (using Arduino 1.6.4+):
  - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
       http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
  - Select your ESP8266 in "Tools -> Board"
*/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.

const char* ssid = "........";
const char* password = "........";
const char* mqtt_server = "broker.mqtt-dashboard.com";

WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE	(50)
char msg[MSG_BUFFER_SIZE];
int value = 0;

void setup_wifi() {

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

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

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

  randomSeed(micros());

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

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is active low on the ESP-01)
  } else {
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  unsigned long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;
    ++value;
    snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("outTopic", msg);
  }
}

Gruß Scherheinz

Scherheinz:
WiFi.macAddress() gibt ein 6 byte Array zurück was du aber brauchst ist char

Es gibt auch eine Methode mit String als Returntype. Das hat amithlon in #6 bereits gezeigt, wie man da zum char-Array kommt.

Gruß Tommy

Danke für eure Hilfe!

ich habe die Bibliothek auf PubSubClient gewechselt und hier ist es recht einfach zu lösen!

Ich poste den Code hier nochmal wenn ich ihn aufgeräumt habe!

Vielen dank nochmal an alle Tippgeber!

Gruss
TaM

Der Vollständigkeits halber hier mein Code:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "Seeed_BME280.h"
#include <Wire.h>
#include <Digital_Light_TSL2561.h>
#include "rgb_lcd.h"

// Update these with values suitable for your network.

const char* ssid = "AUT-18H-21H-SG-G2";
const char* password = "ZbW-WebTech";
const char* mqtt_server = "192.168.0.101";

WiFiClient espClient;
PubSubClient client(espClient);

//Temperatursensor
BME280 bme280;

//Definition
#define PHOTOCELL_PIN A0
#define MSG_BUFFER_SIZE  (60)
#define Topic_BUFFER_SIZE  (50)

//RGB
int rgb_R = 13;
int rgb_G = 15;
int rgb_B = 12;

const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
float Data [6];
int period = 1000;
unsigned long lastMsg = 0;
char msg[MSG_BUFFER_SIZE];
char Topic[MSG_BUFFER_SIZE];
String Mac = "00:00:00:00:00:00";
unsigned long time_now = 0;


void setup() {
  Serial.begin(115200);
  //Initial Temperatursensor
  if (!bme280.init()) {
    Serial.println("Device error!");
  }

  delay(500);
  
  //Inital RGB
  pinMode(rgb_R, OUTPUT);
  pinMode(rgb_G, OUTPUT);
  pinMode(rgb_B, OUTPUT);
  digitalWrite(rgb_R, LOW);
  digitalWrite(rgb_G, LOW);
  digitalWrite(rgb_B, LOW);

  TSL2561.init();
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  Mac = WiFi.macAddress();
}

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

  if (Timer() == HIGH) {
    digitalWrite(rgb_B, HIGH);
    float pressure;
    Data [0] = bme280.getTemperature();
    Data [1] = bme280.getPressure();
    Data [2] = bme280.calcAltitude(pressure);
    Data [3] = bme280.getHumidity();
    Data [4] = TSL2561.readVisibleLux();
    Data [5] = analogRead(PHOTOCELL_PIN);
    char buf[50];
    Mac.toCharArray(buf, 50);
    snprintf (Topic, Topic_BUFFER_SIZE, "Proj/webtech/%s/String", buf);
    snprintf (msg, MSG_BUFFER_SIZE, "%s|%i|%i|%i|%i|%i|%i", buf, (int)(Data [0] * 100),  (int)(Data[1] * 100),  (int)(Data[2] * 100), (int)Data[3], (int)Data[4], (int)Data[5] );
    client.publish(Topic, msg);
    digitalWrite(rgb_B, LOW);
  }
}

er ist nicht perfekt aber er macht derzeit was er soll!

Gruss
TaM

Schön, dass es funktioniert. Du hast mit der Adafruit-MQTT-Lib also auch nur einen lokalen Server, und nicht den Internet-Server von Adafruit genutzt?

Ansonsten: es wäre ratsam, SSID, Passwort und IP-Adressen im Code zu verschleiern

Die Angaben sehen für mich wie Fantasiewerte aus ;D

Schön das es jetzt funktioniert wie gewünscht. Danke auch fürs Posten des funktionierenden Code, das wird oft vergessen.

Gruß
Scherheinz