Probleme bei UDP mit If/Else bzw. Datentypen

Hallo,

bin Neuling. Aber durch probieren soll man ja was lernen. Leider hab ich jetzt schon einige erfolglose Abende hinter mir :slightly_frowning_face: und möchte mal nach Rat fragen.
Geplant ist eine Art Loxone Nano-Air mit einem

  • Wemos D1 mini
  • Relay Shield
  • per UDP (fürs erste) die beiden Relais anschalten
    Entweder meine IF-Anweisung ist falsch oder irgendetwas stimmt vielleicht mit meinen Datentypen nicht, aber ich komm nicht drauf. Es schaltet immer nur 1 Relais ein.
    Sollte ich das vielleicht besser mit einem Case-Befehl lösen?

Vielen Dank für eure Mithilfe im Vorraus.

PS: Ist das üblich, wenn man mit den // auskommentiert oder gibts da was anders?

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "xxxx";
const char* password = "xxxx";

const int RELAIS1 = D1; 
const int RELAIS2 = D5;

WiFiUDP Udp;
unsigned int localUdpPort = 5555;  // local port to listen on
char incomingPacket[255];  // buffer for incoming packets
char  replyPacket[] = "Hi there! Got the message :-)";  // a reply string to send back


void setup()
{
  pinMode(RELAIS1, OUTPUT);    
  digitalWrite(RELAIS1, HIGH); 
  pinMode(RELAIS2, OUTPUT);    
  digitalWrite(RELAIS2, HIGH); 

  Serial.begin(115200);
  Serial.println();

  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");

  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}
void loop()
{
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket, 255);

    Serial.printf("UDP packet contents: %s\n", incomingPacket);
      if (len == 1)
      {
      digitalWrite(RELAIS1, LOW);
      digitalWrite(RELAIS2, HIGH);
      }
      else if (len == 2)
      {
      digitalWrite(RELAIS2, LOW);
      digitalWrite(RELAIS2, HIGH);
      }
      else // sollte irgend ein anderes Byte per UDP reinkommen, alles Relais ausschalten!
      {
      digitalWrite(RELAIS1, HIGH);
      digitalWrite(RELAIS2, HIGH);
      }

    // send back a reply, to the IP address and port we got the packet from
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(replyPacket);
    Udp.endPacket();
  }
}

Hallo,

warum willst Du die Relais mit dem Wert der Paketlänge ansteuern? Die eigendlichen Nutzdaten sind in dem Cstring incomingPacket enthalten.

was willst Du den eigendlich senden um die Relais anzusteuern, anbieten würde sich für diesen einfachen Fall eine binäre Information mit einem Zeichen:

1 = relais 1 ein
2= relais 2 ein
3= beide relais ein

alles andere Relais aus.

Gruß Heinz

Ja, das würde mir vollkommen reichen:

1= relais 1 ein
2= relais 2 ein
alles andere Relais aus

Das mit dem Wert der Paketllänge verstehe ich nicht ganz.

Hallo,

war nicht ganz richtig, len als Rückgabe der Udp.read funktion , ist nicht die Paketlänge sondern Anzahl der Zeichen die gelesen wurden , siehe Auszug aus der UDP.h

// Read up to len characters from the current packet and place them into buffer
// Returns the number of characters read, or 0 if none are available
virtual int read(char* buffer, size_t len) =0;

also incomingPacket auf 1 oder 2 sonst aus . Achtung du fragst auf ein Zeichen ab nicht auf eine Zahl.

Gruß Heinz

Nachtrag

such mal nach dem Windows Programm PaketSender , ist zum Testen super

Jetzt hab ich das so geschrieben, funktioniert aber auch nicht (Wahrscheinlich falsch verstanden, oder):

char Rel = Udp.read(incomingPacket, 3);

PS: PaketSender habe ich bereits im Einsatz

Gruß Sascha

Hallo,

ja hast du falsch verstanden.

int len = Udp.read(incomingPacket, 255);

ist schon ok , lass dir doch mal mit

Serial.println (incommingPacket) anzeigen was siehst Du da ?

Heinz

Da bin ich wieder.

Ich sehe dann (richtigerweise):
Now listening at IP 192.168.178.50, UDP port 5555
Received 1 bytes from 192.168.178.49, port 50641
3
Received 1 bytes from 192.168.178.49, port 50641
2
Received 1 bytes from 192.168.178.49, port 50641
1

Jetzt hab ich es rausgefunden. Ich lese mit dem Befehl Udp.parsePacket() die länge des Paketes aus. dementsprechend funktionieren auch gerade meine Relais. Bei einem Zeichen schaltet das Relais 1 bei 2 Zeichen Relais 2 und bei drei oder mehr Zeichen gehen die Relais aus.

Damit könnte ich leben, aber warum setzt er meinen Befehl Udp.read nicht um?

Hallo,

womit sendest Du denn das UDP Paket überhaupt
was für Daten sendest Du in dem Paket
was steht in der Variablen incommingPaket, da sind deine Nutzdaten drin.

Heinz

Nachtrag

Du hast was nachträglich geändert ok alles klar die 1 ,2 3 ist der C string incommingPaket, dann hast du doch genau das was du willst.

jetzt noch die if abfragen ändern auf incommingPaket dann passt es doch.

if (incommingPaket[0] =='1' );

Damit könnte ich leben, aber warum setzt er meinen Befehl Udp.read nicht um?

Tut er doch. Der Returnwert von read ist nun mal die Anzahl der gelesenen Bytes. So what ?

Ulli

Danke für die Infos. Werde das heute Abend gleich probieren. Ich bin davon ausgegangen, dass ich mit read nicht die Anzahl sondern den Inhalt des Strings auslese.

Sascha

Ich bin davon ausgegangen, dass ich mit read nicht die Anzahl sondern den Inhalt des Strings auslese.

Es gibt verschiedene read.
Die beruhen alle auf int read(void); Das liefert 1 Zeichen oder -1, wenn nichts zum lesen da ist.
Deine Variante braucht einen Puffer, wo das Paket abgelegt werden kann.

Das hat super funktioniert. Vielen Dank euch allen. Und ich hab bisschen was gelernt :slight_smile:
Ich werde den sketch für Interessierte nacher nochmal komplett posten, will aber noch ein wenig kommentieren.

Wofür genau steht die 0 in den eckigen Klammern?

Rentner:
if (incommingPaket[0] =='1' );

Anbei noch der Sketch. Interessant z.B. für Besitzer einer Loxone-Hausautomation die z.B. ihre Rolläden damit steuern wollen, da ein Nano Air doch gleich mal schnell 100€ kostet.
An den Udp-Schaltereingängen arbeite ich noch :grin:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "xxxx";
const char* password = "xxxx";

const int RELAIS1 = D1;
const int RELAIS2 = D5;

WiFiUDP Udp;
unsigned int localUdpPort = 5555;  // local port to listen on
char incomingPacket[255];  // buffer for incoming packets
char replyPacket[] = "Hi there! Got the message :-)";  // a reply string to send back

void setup()
{
  pinMode(RELAIS1, OUTPUT);
  digitalWrite(RELAIS1, HIGH);
  pinMode(RELAIS2, OUTPUT);
  digitalWrite(RELAIS2, HIGH);

// Verbindungsroutine für das wifi
  Serial.begin(115200);
  Serial.println();
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");
  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}
//  Udp-Austausch
void loop()
{
  int packetSize = Udp.parsePacket(); // wird bei Udp immer beim Start benötigt
  Udp.read(incomingPacket, 255); //liest das ankommende Paket aus
  if (packetSize)
  {
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    Serial.println (incomingPacket);

    if (incomingPacket[0] =='1') //wenn das ankommende Paket mit einer 1 beginnt dann ...
    {
      digitalWrite(RELAIS1, LOW);
      digitalWrite(RELAIS2, HIGH);
    }
    else if (incomingPacket[0] =='2')  //wenn das ankommende Paket mit einer 2 beginnt dann ...
    {
      digitalWrite(RELAIS2, LOW);
      digitalWrite(RELAIS1, HIGH);
    }
    else // sollte irgend ein anderes Byte (mit Ausnahme einer 1 oder 2 am Beginn) per UDP reinkommen, dann ... alle Relais ausschalten!
    {
      digitalWrite(RELAIS1, HIGH);
      digitalWrite(RELAIS2, HIGH);
    }

    // send back a reply, to the IP address and port we got the packet from
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(replyPacket);

    Udp.endPacket();
  }
}