Hey, bin interessiert die Wolke nachzubauen😊
Wollte fragen ob die Projektdokumentation noch fortgesetzt wird.
VG
Dieser Topic stammt aus einem Discord-Server. Manche Nutzer in diesem Topic können nicht wie gewohnt markiert werden, da sie keinen Account auf makesmart besitzen. Beiträge von Nutzern aus Discord-Servern ohne Account auf makesmart werden im eigenen Nutzernamen unter dem Benutzer Discord veröffentlicht.
Interesse daran auch auf deinem Server die Topics-Funktion bereitzustellen? Klicke hier um mehr zu erfahren.
Befehle über mqtt empfangen
-
Ich möchte auf dem esp Befehle über mqtt empfangen. Bisher nutze ich folgenden Weg: Mit “Nachricht = (char)payload[0];” in der callback-Funktion weise ich der Variablen Nachricht das erste Zeichen von payload zu.
Damit steure ich dann über if-Abfragen. if(Nachricht == ‘a’) {mache dies und das}. Damit kann man natürlich keine sprechenden Befehle gestalten. Ich würde gern Zeichenketten für die Befehle nutzen.
Ich dachte ich bekomme das über char* Nachricht hin - in einer for-Schleife mit Nachricht[i] = payload[i], klappt aber nicht
Hat jemand eine Idee, wie ich mein Ziel erreichen kann. Gern auch auf einem ganz anderen Weg -
void callback(char* topic, byte* payload, unsigned int length) { char *cstring = (char *) payload; cstring[length] = '\0'; Serial.println(cstring); }
payload ist doch ein Zeiger. Kannst man den nicht mit z.B. strcmp auch gegen eine Zeichenkette vergleichen?
-
So geht es auch
void callback(char* topic, byte* payload, unsigned int length) { // Die Variable leeren msg = ""; for (byte i = 0; i < length; i++) { char tmp = char(payload[i]); // Wird in die Globale-Variable `msg` geschrieben. msg += tmp; } Serial.println(msg); updateDisplay(); }
Hier noch zwei Links die dir evtl. weiterhelfen könnten:
Hier wird besprochen wie man auf mehrere Topics “reacten” kann, mit ein paar Einblicken in den Code:
https://my.makesmart.net/topic/144/esp8266-und-mqtt-subscribe-auf-ein-oled-anzeigen/Und hier kommt der Code her den ich dir gerade gepostet hab, der durch eine Schleife die komplette Message speichert:
https://makesmart.net/esp8266-d1-mini-mqtt/ -
Oder falls du lieber beim payload mit Strings arbeiten möchtest:
payload[length] = '\0'; String s = String((char*)payload);
Das kannst du dann ja auch in float, int oä wandeln
float f = s.toFloat();
oderint i= s.toInt();
-
msg
in in meiner geposteten Lösung btw. auch einString
also könntest du auch die beiden Vorschläge kombinieren und schauen wie du am besten zurechtkommst @ooheinzz -
Super vielen Dank. Bin gerade beim Arbeiten und komme deswegen erst heute Abende dazu, dass auszuprobieren.
-
payload[length] = '\0'; String s = String((char*)payload); Serial.print("s: "); Serial.println(s);
klappt soweit. Der payload landet in s und wird auf dem seriellen Monitor ausgegeben.
Ganz oben im Code - vor void setup() - habe s deklariert (String s;) In der Hoffnung überall auf s zugreifen zu können. Außerhalb von callback hatSerial.println(s);
aber keine Wirkung. Es wird aber auch kein Fehler angezeigt - s wird als Variable offenbar erkannt.
Ich möchte die Variable in if-Abfragen in anderen Funktionen verwenden.
(Wie ich Strings miteinander vergleiche, muss ich noch rausbekommen -
Teil doch mal deinen kompletten Code, dann fällt es einfacher zu helfen.
Strings lassen sich mit
==
vergleichen.String a = "hallo"; String b = "hallo"; if(a == "hallo"){ // gleich } if(a == b){ // gleich }
Den Gültigkeitsbereich von Variablen nennt man Scope. Wenn du überall auf
s
zugreifen willst, musst du es außerhalb von Blöcken initialisieren.String s; void setup(){ } void loop(){ }
Das macht
s
zu einer globalen Variable und du kannst von überall darauf zugreifen. Zufälligerweise habe ich dazu schon ein Video produziert, was ich demnächst veröffentlichen möchte. -
@ooheinzz schrieb:
payload[length] = ‘\0’;
String s = String((char*)payload);
Serial.print("s: ");
Serial.println(s);klappt soweit. Der payload landet in s und wird auf dem seriellen Monitor ausgegeben.
Ganz oben im Code - vor void setup() - habe s deklariert (String s;) In der Hoffnung überall auf s zugreifen zu können. Außerhalb von callback hatSerial.println(s);
aber keine Wirkung. Es wird aber auch kein Fehler angezeigt - s wird als Variable offenbar erkannt.
Ich möchte die Variable in if-Abfragen in anderen Funktionen verwenden.
(Wie ich Strings miteinander vergleiche, muss ich noch rausbekommenHast du vllt jn der callback s noch mal deklariert anstatt einfach nur s =… Zu nutzen?
-
@Daniel-Scheidler Das war das Problem. Ich habe s in der callback nochmal deklariert.
Der ganze Code sieht jetzt so aus und macht was er soll.
nclude <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h> //für MQTT
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <ArduinoOTA.h>
#include <Adafruit_NeoPixel.h>// ++++++++++++++++++++++++++++++++++++++++++ Raum auswählen ++++++++++++++++++++++++
//#define RAUM “Schlafzimmer”
//#define HOSTNAME “SensorSchlafzimmer”
// --------------------------------------------
#define RAUM “Arbeitszimmer”
#define HOSTNAME “SensorArbeitszimmer”
// --------------------------------------------
//#define RAUM “Wohnzimmer”
//#define HOSTNAME “SensorWohnzimmer”
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#define UPDATE_TIME 10 // UpdateRythmus für pushen der Sensor-Werte in Sekunden
#define LED_red D4
#define LED_blue D0 // D0 kann kein PWM
#define LED_green D3
#define PUSH_TEMP “temp/”
#define PUSH_PRESURE “presure/”
#define PUSH_HUMIDITY “humidity/”
#define PUSH_HELLIGKEIT “helligkeit/”
#define MQTT_SERVER “192.168.178.29”
#define ssid “"
#define password "”
#define MQTT_USER “mqtt”
#define MQTT_PW “Picasso”
#define OTA_PASSWord “Picasso”#define DELAYVAL 500 // NeoPixel
#define PIN D6 // NeoPixel
#define NUMPIXELS 32 // NeoPixel
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);unsigned long timer1 = 0; // für Updaterythmus in der Loop
unsigned long timer2 = 0;
char Nachricht; //ein Zeichen
String s;// Funktionen deklarieren
void setup_wifi();
void callback(char* topic, byte* payload, unsigned int length);
void reconnect();
void intPublish(int x, int var); // wandelt int in char und schickt per mqtt
void floatPublish(int x, float var); // wandelt flaot in char und schickt per mqtt
void subscribe(int delayOn, int delayOff);
void printValues(); //BME 280
void licht(int r, int g, int b, int time);
void LichtAus(int zeitBisAus);WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;Adafruit_BME280 bme; // I2C
void setup() {
Serial.begin(9600);
Serial.println(F(“BME280 test”));
setup_wifi();
client.setServer(MQTT_SERVER, 1883);
client.setCallback(callback);pinMode(LED_red, OUTPUT);
pinMode(LED_green, OUTPUT);
pinMode(LED_blue, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);if (! bme.begin(0x76, &Wire)) {
Serial.println(“Could not find a valid BME280 sensor, check wiring!”);
while (1);
}Serial.println("-- Default Test --");
Serial.println(“normal mode, 16x oversampling for all, filter off,”);
Serial.println(“0.5ms standby period”);
Serial.println();ArduinoOTA.setHostname(HOSTNAME);
//ArduinoOTA.setPassword(OTA_PASSWord);
ArduinoOTA.begin();// +++++++++++++++++++++++++++++++++++++++ Neo Pixel
#if defined(AVR_ATtiny85) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
pixels.begin();} //void setup ended
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ L O O P ++++++++++++++++++++++
void loop() {
if (!client.connected()) {reconnect();}
client.loop();if(millis()-timer1 > UPDATE_TIME*1000){
floatPublish(1, (bme.readTemperature()));
floatPublish(2, (bme.readHumidity()));
intPublish(3, (bme.readPressure() / 100.0F));
intPublish(4, analogRead(A0));
timer1 = millis();
printValues();}
LichtAus(10000);
ArduinoOTA.handle();
subscribe(50,1000);
} // function loop ended// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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);
WiFi.hostname(HOSTNAME RAUM);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());
} //function setup_wifi endedvoid callback(char* topic, byte* payload, unsigned int length) {
Serial.print(“Nachricht eingegangen [”);
Serial.print(topic);
Serial.print("] ");
for (unsigned int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
String topicStr = topic;Nachricht = (char)payload[0];
payload[length] = ‘\0’;
s = String((char*)payload);
Serial.print("s: ");
Serial.println(s);} // function callback ended
void reconnect() {
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);
String clientId = “ESP8266Client-”;
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str(), MQTT_USER, MQTT_PW))
{
Serial.println(“connected”);
client.publish(“outTopic”, “SenBox1 läuft!”);
client.subscribe(“call/Arbeitszimmer”);
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.println(" try again in 5 seconds");delay(5000); }
}
} // function reconnect endedvoid printValues() {
Serial.print(“Temperature = “);
Serial.print(bme.readTemperature());
Serial.println(” *C”);Serial.print("Pressure = "); Serial.print(bme.readPressure() / 100.0F); Serial.println(" hPa"); Serial.print("Humidity = "); Serial.print(bme.readHumidity()); Serial.println(" %"); int helligkeit = analogRead(A0); Serial.print("Helligkeit: "); Serial.println(helligkeit); Serial.println(); Serial.println(s);
} // function printValues ended
void intPublish(int x, int var){
char buffer[10];
sprintf(buffer, “%d”, var);if(x==1){
client.publish(PUSH_TEMP RAUM, buffer);
} else if(x==2){
client.publish(PUSH_HUMIDITY RAUM, buffer);
} else if(x==3){
client.publish(PUSH_PRESURE RAUM, buffer);
} else if(x==4) {
client.publish(PUSH_HELLIGKEIT RAUM, buffer);
}
} // function in Publish endedvoid floatPublish(int x, float var){
//runden auf zwei Nachkommastellen
int y = var * 100;
float z = y/100.00;
char buffer[6];
sprintf(buffer, “%f”, z);if(x==1){ client.publish(PUSH_TEMP RAUM, buffer); } else if(x==2) { client.publish(PUSH_HUMIDITY RAUM, buffer); } else if(x==3) { client.publish(PUSH_PRESURE RAUM, buffer); }
} // function floatPublish ended
void subscribe(int delayOn, int delayOff) {
if(Nachricht == ‘r’){
digitalWrite(LED_red,HIGH);
} else if(Nachricht == ‘b’){
digitalWrite(LED_blue,HIGH);
} else if(Nachricht == ‘g’){
digitalWrite(LED_green,HIGH);
}
}void LichtAus(int zeitBisAus){
/* Befehl kommt über mqtt.
Nach festgelegtem intervall wird das Licht über mqtt ausgeschaltet.
Dauer bis zum Abschalten wird über NeoPixel signalisiert */
int intervall = zeitBisAus/NUMPIXELS/3;
if(s == “Wort”){
Serial.print(“Nachricht: “);
Serial.print(Nachricht);
Serial.println(” eingegangen!!”);
for(int i =0; i<NUMPIXELS; i++){
pixels.setPixelColor(i, pixels.Color(0, 50, 0));
pixels.show();
delay(intervall);
}
for(int i =0; i<NUMPIXELS; i++){
pixels.setPixelColor(i, pixels.Color(50, 40, 0));
pixels.show();
delay(intervall);
}
for(int i =0; i<NUMPIXELS; i++){
pixels.setPixelColor(i, pixels.Color(50, 0, 0));
pixels.show();
delay(intervall);
}pixels.clear(); pixels.show(); client.publish("FlurLicht/cmnd/POWER","OFF"); s = "";
}
}
-
Ansich ist es (fast) egal wo du es schreibst. Nur dass Discord halt nur Nachrichten bis 2000 Zeichen akzeptiert
Heißt, alle längeren Nachrichten werden nicht synchronisiert.
Aber Hauptsache das Problem ist gelöst
Formatierten Code kannst du hier ansonsten in Markdowns verpacken
```c++
… hier dein Code …