Arduino Ethernet Parameterübergabe aber wie?

Hallo Hallo,
als erstes möchte ich euch um etwas bitten, an dem nachfolgendem Problem sitze ich nun schon seit einigen Tagen, sollte ich eine offensichtliche lösung übersehen haben bitte ich um entschuldigung!

Also was Habe ich:

Arduino Mega
Arduino Ehternet Shild

Ziel ist es dem das das Arduino einen Webserver zur verfügung stellt, der

  • Den Aktuellen Status anzeigt
  • Das ändern von Parametern, Ausgang schalten usw.

Soweit alles kein Problem, das Beispiel aus der IDE ist an sich ja schon sehr gut ...
Aber fangen wie vielleicht mit eine Paar grundlegenden Fragen an die mir aktuell noch nicht ganz klar ist

  1. Was ist besser GET oder POST für die übertragungen von Formulardaten?
  2. wenn ich ein POST verwende, komme ich nicht an die übertragenden parameter, bei GET bekomme ich über client.read(); früher oder später das GET Commando mit den angehängten Parameter, aber wie Funktioniert das bei POST, dort kommen die daten nämlich nicht über client.read();

Hintergrund:
Also ich will nicht einfach Schaltzustände übertragen, das wäre recht leicht, den das Internet ist voll von beispielen die 2 oder 3 Digital pins über Buttons ein oder ausschalten, ich will aber RGB werte übertragen, aber nicht nur ...

in meinem Aktuellen Projekt, habe ich bereits eine Funktion eingebaut die das Senden und empfangen von Befehlen über die Serielle schnittstelle ermöglicht im Format:

Command|Value1,Value2,Value3

Im Idealfall, kann ich das Ethernet Shild so nutzen das es zur bestehenden Funktion
Kompatible wird ....

Das Problem ist nun aber, wenn ich ein HTML Formular benutze bekomme ich zumindest bei der verwendung von GET (POST konnte ich mir ja nicht ansehen) die Daten so

GET /?rot=255&gruen=20&blau=200

Das erste Problem ist an dieser Stelle natürlich das ich das hier sehr umständlich Parsen muss, zudem selbst wenn ich es geparst habe, weis ich immer noch nicht genau, was eigentlich gewollt wird, den das Übertragen von RGB werten muss nicht zwangsläufig bedeutet das das Licht auch in diese Farbe gewechselt werden soll. Es könnte ja auch sein das ein anderes Bord nur die Informationen übermittelt welche Lichtfarbe dieses Bord aktuell eingestellt hat.
Auserdem will ich auch nicht das beim Setzen der Farbe auch das licht tatsächlich geschaltet wird, den ich habe das Getrennt, Farbe ist die eine sache, aber zusätzlich habe ich ein flag, welches das licht entweder auf den Farbwert setzt oder ausschaltet, so ist es möglich neuen Farben zu übertragen ohne das das lich auch tatsächlich leuchtet.

Also habe ich eine möglichkeit, in meine übertragung ein Komando / Befehl mit einzubauen?
Ich hatte schon die Idee das über die URL zu machen

/Befehl/?Parameter

aber auch hier müsste ich sehr auswendig die Parameter Parsen ..

Habt ihr bessere Ideen ?
wie würdet ihr das Realisieren ?

Kennt ihr coole Links wo das thema Datenübertragnung / Parametrübergabe behandelt wird?

Ich würde mich sehr über Hilfe freuen.
ich hoffe ich konnte klarmachen wo mein Problem liegt, wenn nicht einfach Fragen :slight_smile:

Danke im Vorraus

MultiStorm

  1. Was ist besser GET oder POST für die übertragungen von Formulardaten?

In Deiner Konfiguration ist ein GET einfacher zu verarbeiten und somit vorzuziehen. Generell lässt sich die Frage so nicht beantworten.

  1. wenn ich ein POST verwende, komme ich nicht an die übertragenden parameter, bei GET bekomme ich über client.read(); früher oder später das GET Commando mit den angehängten Parameter, aber wie Funktioniert das bei POST, dort kommen die daten nämlich nicht über client.read();

Du kommst auch beim POST an die Daten, aber dort musst Du viel mehr auswerten und das Parsing des Headers kann nicht mehr auf die simple Art erfolgen, die man in den meisten Beispielen findet. Dort musst Du nach dem Kopf-Feld "Content-Length" suchen, den Wert als Integer auslesen, dann das Kopf-Ende finden (Leerzeile) und von dort die Anzahl Bytes die im Header-Feld vorgegeben wurden, einlesen. Da dies nur der einfachste Fall ist (aber auch der häufigste), sollte beim Arduino GET der Vorzug gegeben werden.

Das erste Problem ist an dieser Stelle natürlich das ich das hier sehr umständlich Parsen muss, zudem selbst wenn ich es geparst habe, weis ich immer noch nicht genau, was eigentlich gewollt wird, den das Übertragen von RGB werten muss nicht zwangsläufig bedeutet das das Licht auch in diese Farbe gewechselt werden soll. Es könnte ja auch sein das ein anderes Bord nur die Informationen übermittelt welche Lichtfarbe dieses Bord aktuell eingestellt hat.
Auserdem will ich auch nicht das beim Setzen der Farbe auch das licht tatsächlich geschaltet wird, den ich habe das Getrennt, Farbe ist die eine sache, aber zusätzlich habe ich ein flag, welches das licht entweder auf den Farbwert setzt oder ausschaltet, so ist es möglich neuen Farben zu übertragen ohne das das lich auch tatsächlich leuchtet.

Entschuldige, das verstehe ich nur halb. Kannst Du Deinen Code posten, damit klar wird, was Du versuchst zu machen? Es scheint, dass Du Annahmen triffst, die nicht korrekt sind, wir aber nicht erkennen können, welche das sind, weil Du sie uns nicht mitteilst.

aber auch hier müsste ich sehr auswendig die Parameter Parsen ..

Das ist einfaches Parsen, das kann noch deutlich komplizierter werden.

okay ich versuchs mal,
ist nicht ganz einfach da aktuell eslles in 2 Projekten Liegt :slight_smile:
fangen wir mit dem Webserver mal an:

#include <SPI.h>
#include <Ethernet.h>

byte mac = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,178,177);
byte gateway = { 192, 168, 0, 1 };
byte subnet = { 255, 255, 255, 0 };
EthernetServer server(80);
String incommingData;

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}

void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println(“new client”);
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.print(c);
//getCommand(c);
incommingData = incommingData + c;
// if you’ve gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == ‘\n’ && currentLineIsBlank) {
//GET Separieren
if(incommingData.indexOf(“GET”) > -1)
{
Serial.println(“GET Gefunden!!!”);
Serial.println(incommingData);
incommingData = “”;
}
// send a standard http response header
client.println(“HTTP/1.1 200 OK”);
client.println(“Content-Type: text/html”);
client.println(“Connection: close”); // the connection will be closed after completion of the response
client.println(“Refresh: 30”); // refresh the page automatically every 5 sec
client.println();
client.println("");
client.println("");
client.println("");
client.println("
“);
client.println(”
“);
client.println(”<table border=“0” cellpadding=“0” cellspacing=“4”>");
client.println("");
client.println("<td align=“right”>Aktuelle Lichtfarbe:");
client.println("<td align=“right”>");
client.println("");
client.println("");
client.println("<td align=“right”>Lichtstatus:");
client.println("<td align=“right”>");
client.println("");
client.println("");
client.println("<td align=“right”>Temperatur:");
client.println("<td align=“right”>");
client.println("");
client.println("");
client.println("<td align=“right”>Luefterstatus:");
client.println("<td align=“right”>");
client.println("");
client.println("");
client.println("<td align=“right”>Luefterdrehzahl in Prozent:");
client.println("<td align=“right”>");
client.println("");
client.println("");
client.println("");
client.println("<form action=“http://192.168.178.177” method=“get”>");
client.println("
“);
client.println(”
“);
client.println(”<table border=“0” cellpadding=“0” cellspacing=“4”>");
client.println("");
client.println("<td align=“right”>Rot:");
client.println("<input name=“red” type=“text” size=“30” maxlength=“30”>");
client.println("");
client.println("");
client.println("<td align=“right”>Gruen:");
client.println("<input name=“green” type=“text” size=“30” maxlength=“30”>");
client.println("");
client.println("");
client.println("<td align=“right”>Blau:");
client.println("<input name=“blue” type=“text” size=“30” maxlength=“30”>");
client.println("");
client.println("");
client.println("<input type=“submit” value=" Lichtfarbe Setzen “>”);
client.println("<input type=“reset” value=" Abbrechen">");
client.println("");
client.println("");
client.println("");
client.println("");
client.println("");
client.println("");
break;
}
if (c == ‘\n’) {
// you’re starting a new line
currentLineIsBlank = true;
if(incommingData.indexOf(“GET”) > -1)
{
//Hier Begint mein Problem !!!
Serial.println(“GET Gefunden!!!”);
Serial.println(incommingData);
String httpParameter = incommingData.substring(incommingData.indexOf(" ") + 2);
if (httpParameter.substring(0, 1) == “?”)

{
Serial.println("Ja es kommen Daten Ueber due URL: " + httpParameter);
httpParameter = httpParameter.substring(1);
}

Serial.println(“Paratmeter vorne gesaubert: " + httpParameter);
httpParameter = httpParameter.substring(0, httpParameter.indexOf(” "));
Serial.println("Das ist der Reine Parameter String: " + httpParameter);
incommingData = “”;
}
else
{
//Serial.println(“Das Zeilenende wurde erreicht, aber es wurde kein GET gefunden!”);
incommingData = “”;
}
}
else if (c != ‘\r’) {
// you’ve gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println(“client disconnected”);
}
}

Und der Rest (War länger als 9000 Zeichen)

So das ist der COde des Webserver Sketches

hier jetzt noch ein auszug aus dem Sketch in den der webserver integriert werden soll.

Hier wird der Befehlt Analysiert und ensprechend gehandelt (Aktuell kommen die Daten über die Serielle Schnittstelle)

/*

  • Interpretiert das Commando, wir wird zwischen den einzelnen
  • Kommandos unterschieden, und ggf. weitere Funktionen gestartet.
    */
    void interpretCommand(String sCommand, String sValues)
    {
    int commaPosition;
    int iValuesCount;
    int counter = 0;
    char delimeterChar= ',';

iValuesCount = countSplitCharacters(sValues, delimeterChar);
String sCargoValues[iValuesCount+ 1];

do
{
sendDebugMessage("Begine durchlauf: " + String(counter));
commaPosition = sValues.indexOf(delimeterChar);
sendDebugMessage("Position des Delimeters: " + String(commaPosition));
if(commaPosition != -1)
{
sCargoValues[counter] = sValues.substring(0,commaPosition);
sValues = sValues.substring(commaPosition+1, sValues.length());
}
else
{ // here after the last comma is found
if(sValues.length() > 0)
sCargoValues[counter] = sValues;
}

counter = counter + 1;

}
while(commaPosition >=0);

if ( sCommand == "WhoAreYou" )
{
//Wird diese Kommando empfangen weis das Ardoino Bord, das auf den
//Seriellen Kanälen nach ihm gesucht wird, es wird sich nach erhalt
//dieser Anfrage Idenifizieren .....
sendDebugMessage("Empfange WhoAreYou Kommando.");
Iam();
}
else if( sCommand == "SetLightColor" ) //Beispielzeile zum erweitern neuer Kommandos
{
sendDebugMessage("SetLightColor wird ausgefuert.");
bRedLightValue = sCargoValues[0].toInt();
sendDebugMessage("RED: " + String(bRedLightValue));
bGreenLightValue = sCargoValues[1].toInt();
sendDebugMessage("GREEN: " + String(bGreenLightValue));
bBlueLightValue = sCargoValues[2].toInt();
sendDebugMessage("BLUE: " + String(bBlueLightValue));

SetLightColor();
}
else if( sCommand == "DisableLight" ) //Beispielzeile zum erweitern neuer Kommandos
{
DisableLight();
}
else if( sCommand == "EnableLight" ) //Beispielzeile zum erweitern neuer Kommandos
{
EnableLight();
}
else if( sCommand == "GetLightState" ) //Beispielzeile zum erweitern neuer Kommandos
{
SendValueOverSerial("LightState", String(isLightEnabled));
}
else if( sCommand == "GetRedLightValue" ) //Beispielzeile zum erweitern neuer Kommandos
{
SendValueOverSerial("RedLightValue", String(bRedLightValue));
}
else
{
sendErrorMessage("Sorry, but i downt now this command.");
}

}

Und das was ggfd. zum verständnis noch nötig ist:

/*

  • ##########################################################
  • Übersicht über Serielle Kommandos

  • Kommando: Parameter:

  • WhoAreYou N/A

  • ##########################################################
    */

/*

  • Identifikations Rotine ...
    */
    void Iam()
    {
    SendValueOverSerial("BORD",sBord);
    delay(5);
    SendValueOverSerial("SOFTWARE",sSoftwareName);
    delay(5);
    SendValueOverSerial("VERSION",sSoftwareVersion);
    delay(5);
    }

/*

  • Splittet den String, der über die Seriele Leitung kommt in
  • Kommando und Anhang (nutzdaten) auf. ggf. können die Nutzdaten
  • weitere Delimeter enthalten und müssen ein weiteres mal gesplittet
  • werden.
    */
    boolean splitString(String s, String parser, int index)
    {
    String rs="";
    String sCommand = "";
    String sValue = "";
    int parserIndex = index;
    int parserCnt=0;
    int rFromIndex=0;
    int rToIndex=-1;

sendDebugMessage ("Begine mit dem Splitten der Befehle ... .. .");
sendDebugMessage ("InputString: " + s);
sendDebugMessage ("Delimeter: " + parser);
sendDebugMessage ("Index: " + index);

while (index >= parserCnt)
{
rFromIndex = rToIndex+1;
rToIndex = s.indexOf(parser,rFromIndex);

if (index == parserCnt)
{
if (rToIndex == 0 || rToIndex == -1) {
return false;
}

sCommand = s.substring(rFromIndex,rToIndex);
sValue = s.substring(rToIndex + 1,s.length());

sendDebugMessage ("Command: " + sCommand);
sendDebugMessage ("Value: " + sValue);

interpretCommand(sCommand, sValue);

}
else
{
parserCnt++;
}
}

//String test = s.split("|");
//Serial.println("CONSOLE|Array Größe: " + sizeof(test));
return true;
}

/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
*/
void serialEvent()
{
sendDebugMessage("serialEveent wird ausgefuehrt");
String dataString = Serial.readStringUntil('\n');
sendDebugMessage("Empfangene Daten: " + dataString);
splitString(dataString, "|", 0);
}

/*

  • Sendet einen Befehl und entsprechende Nutzedaten
  • Ueber die Seriele Schnittstelle.
    */
    void SendValueOverSerial(String sCommand, String sCargo)
    {
    Serial.println(sCommand + "|" + sCargo);
    delay(5);
    }

int countSplitCharacters(String text, char splitChar)
{
sendDebugMessage("Zaehle Delimeter");
int returnValue = 0;
int index = 0;

while (index > -1)
{

index = text.indexOf(splitChar, index + 1);
sendDebugMessage("Index: " + String(index));
if(index > -1) returnValue+=1;
}

sendDebugMessage("Fertig mit zaehlen ich konnte: " + String(returnValue) + " Delimeter zaehlen");
return returnValue;
}

void sendDebugMessage(String sMessage)
{
SendValueOverSerial("CONSOLE", sMessage);
}

void sendErrorMessage(String sMessage)
{
SendValueOverSerial("ERROR", sMessage);
}

Reicht dir das ?
wird hier klar was ich vorhaben oder machen will?

Also noch mal eine kleine zusammenfassung:

Ich habe die Funkktion interpretCommand()
diese erhält 2 Werte, 1 x das Command (Befehl) und die Values (diese sind aktuell , separiert)
mein ziel wäre es das diese Funktion Funktioniert egal ob die Daten per Serieller schnittstelle kommen oder per Netzwerk.

Ich will später quasi die möglichkeit haben, das ich das Bord über alles stuern kann

Handy (Netzwerk)
Anderes Arduino Bord (Seriel)
Computer (Netzwerk)
Computer (windows 8 APP) (Seriell)
Tablett (netzwerk (HTTP))
usw.

also egal woher die Daten kommen, sie müssen (Sollten) einheitlich behandelt werden.

Hoffe solangsam wird klar was ich meine ...

Der Serielle Part Funktioniert übrigens tadellos (Kann man natürlich noch Optimieren)

MultiStorm:
also egal woher die Daten kommen, sie müssen (Sollten) einheitlich behandelt werden.

Wenn Du Daten, die "über die seriellle Schnittstelle" oder "über Heimnetzwerk" oder "über Internet" kommen "einheitlich behandeln" möchtest und die Kommandos dabei als "Text-Kommandos" eingetippt werden sollen, dann wäre für die die Netzwerk/Internet-Seite NICHT das Protokoll "HTTP" und ein Programm vom Typ "Web-Browser" die erste Wahl.

Eine "einheitliche" Behandlung hast Du eher, wenn Du das Protkoll "TELNET" und ein Programm vom Typ "Telnet-Client" verwendest.

Schaue Dir mal das Beispiel "ChatServer" zur Ethernet-Library an und greife mit einem Telnet-Clientprogramm darauf zu. Telnet-Clients gehören bei vielen Betriebssystemen mit zur Grundausstattung oder können leicht nachinstalliert werden (z.B. für Smartphones als App).

japp,
den Gedanken hatte ich auch schon ....
der vorteil, den der Webbrowser mit sich Bringt, ein Browser kann heutzutage von fast jedem endgerät
verarbeitet werden, also was ich meine ist, habe ich eine webseite, kann ich das vom Laptop, TABLET, Handy, so sogar von einem Fernseher Steuern ....

Grundsätzlich hast du natürlich recht, und ich werde deinen rat auch sicher befolgen und mir die entsprechenden beispiele noch einmal zu gemüte führen. Allerdings finde ich die Steuerung per Webseite schon recht Sexy ...

ICH habe die Sketches nicht im Kopf aber vielleicht kann man die telnet Sache ja ZUSÄTZLICH IMPLEMENTIEREN da diese ja auf einem Anderen Port läuft ....

ich denke um zum eigentlichen Problem zurückzufinden, ich werde mir eine Wrapper Methode bauen, die das GET Command, in mein Command|Value pair umwandelt, wird vermutlich ganz schön auf die Performance gehen, aber eine andere idee habe ich aktuell nicht ...

Telnet zu integrieren ist eine wirklich gute idee, aber wenn ich nicht für jedes Device eine APP schreiben will werde ich wohl an dem Browser nicht vorbei kommen, den wie sollte ich auch meiner Freundin erklären das sie in zukunft putty braucht um im Wohnzimmer das licht einzuschalten :slight_smile:

ich glaube einfach das auch noch nicht so ganz klar ist wohin ich will :slight_smile:
ist auch nicht so leicht zu erklären ... hatte gehöfft wenn ich ein wenig kontext weglasse wird das eigwentliche Problem klarer. ich will so ein bischen in richtig Home Automation gehen .. wobei es mir im ersten schritt eher um die Steuerung von beleuchtung geht, im 2ten schritt vielleicht auch Heizung o.ä. aber erstmal licht :slight_smile:
nur halt keine Glühbirnen sondern RGB LED Leisten ....

MultiStorm:
wie sollte ich auch meiner Freundin erklären das sie in zukunft putty braucht um im Wohnzimmer das licht einzuschalten :slight_smile:

Tja, das sind die modernen Zeiten. Früher hat sie auf den Lichtschalter gedrückt, damit das Licht angeht. Und wenn der Heimwerkerkönig dran gebastelt hat, muss man eben einen Telnet-Client starten und mit der Haussteuerung verbinden und dort den Text

Lichtschalter Wohnzimmer EIN

eintippen, bis das Licht angeht.

Du kannst natürlich das ganze auch per HTTP realisieren. Dann startet sie eben einen Web-Browser, verbindet sich mit der Haussteuerung, und kann den Lichtschalter ggf. über ein HTML-Benutzerinterface auswählen.

Ob Du HTTP per GET oder POST machst, spielt eigentlich keine große Rolle. Bei POST-Parametern mußt Du diese nur nach dem HTTP-Header auslesen, während GET-Parameter im HTTP-Header stehen.

wie schon gesagt, du hast nicht ganz unrecht, ich werde mir das alles auch noch einmal durch den kopf gehen lassen, aber wie ich auch schon sagte, ein webinterface ist eine recht einfache möglichkeiten, die daten das Bords mit einer GUI zu versehen, der es auch leuten ermöglich das system zu nutzen, der technische vielleicht nicht ganz so versiert ist :slight_smile:

So habe mir mal das Chatserver beispiel angesehen und versucht einzubauen ...
Fail, natürlich den was ich leider zugeben muss die Sache mit Char und String raff ich noch nicht so ganz.

Also die Server.Write() Methode verlangt ein einzelenen Zeichen Char, klar soweit ...
Aber wie bekomme ich nun einen String gesendet, und sagt bitte niht in einer Schleife !?!?!?
Da muss es doch eine Saubere Lösung für geben .....

Laut Refferenz gibt es auch die möglichkeit einen buffer zu übergeben

Syntax

server.write(val)
server.write(buf, len)
Parameters

val: a value to send as a single byte (byte or char)
buf: an array to send as a series of bytes (byte or char)
len: the length of the buffer

also theoritsch recht einfach ...
String der Gesende werden soll in ein Char umwandeln und reinschmeißen ....
Tja nix is ...

void loop() {
  // wait for a new client:
  EthernetClient client = server.available();

  // when the client sends the first byte, say hello:
  if (client) {
    if (!alreadyConnected) {
      // clead out the input buffer:
      client.flush();    
      //Begrüßung Senden!
      Serial.println("We have a new client");
      client.println("Arduino Mega 2560"); 
      client.println("Ehternet Shild 5100"); 
      alreadyConnected = true;
    } 
    while (client.connected()) 
    {
      if (client.available() > 0) 
      {
      // read the bytes incoming from the client:
      char thisChar = client.read();
      incommingData = incommingData + thisChar;
        if (thisChar == '\n') 
        {
        // echo the bytes back to the client:
        char sendBuffer[incommingData.length()];
        sendBuffer = incommingData.toCharArray(sendBuffer, incommingData.length());
        server.write(sendBuffer, sendBuffer.length());
        // echo the bytes to the server as well:
        Serial.write(incommingData);
        incommingData= "";
        }
      }
    }
  }
}

gibt folgenden Fehler zurück:

ChatServer_beispiel.ino: In function 'void loop()':
ChatServer_beispiel:80: error: incompatible types in assignment of 'void' to 'char [(((unsigned int)(((int)incommingData.String::length()) + -0x000000001)) + 1)]'
ChatServer_beispiel:81: error: no matching function for call to 'EthernetServer::write(String&, unsigned int)'
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetServer.h:17: note: candidates are: virtual size_t EthernetServer::write(uint8_t)
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetServer.h:18: note: virtual size_t EthernetServer::write(const uint8_t*, size_t)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:54: note: size_t Print::write(const char*, size_t)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:49: note: size_t Print::write(const char*)
ChatServer_beispiel:83: error: no matching function for call to 'HardwareSerial::write(String&)'
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/HardwareSerial.h:62: note: candidates are: virtual size_t HardwareSerial::write(uint8_t)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/HardwareSerial.h:63: note: size_t HardwareSerial::write(long unsigned int)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/HardwareSerial.h:64: note: size_t HardwareSerial::write(long int)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/HardwareSerial.h:65: note: size_t HardwareSerial::write(unsigned int)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/HardwareSerial.h:66: note: size_t HardwareSerial::write(int)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:54: note: size_t Print::write(const char*, size_t)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:53: note: virtual size_t Print::write(const uint8_t*, size_t)
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:49: note: size_t Print::write(const char*)

er hat Problem mit der Typemumwandlung ....
Scheinbar jedenfalls, kann mir jemand sagen wo mein Fehler ist ?

Die String Klasse ist Schrott, aber sie unterstützt inzwischen c_str():
http://www.cplusplus.com/reference/string/string/c_str/

Das ist in der Arduino Doku leider nicht aufgeführt, aber unendlich besser als toCharArray() wenn man nur lesenden Zugriff möchte, da man kein extra Array braucht. Statt dessen erhält man einen const Zeiger auf das interne Array.

Anmerkung zum Beispiel auf der Seite:
Das Array wird da mit strcpy() in neues Array kopiert weil strtok() den Inhalt verändert. Von daher ist das etwas unglücklich gewählt. In deinem Fall brauchst du das nicht.

Korrektur zur vorherigen Version:
Arrays Variabler Länge gehen auf dem Arduino wohl doch, solange sie nicht statisch sind. Da hatte ich was falsches gesagt. In Standard C/C++ geht es definitiv nicht, aber das ist so wie es aussieht eine Erweiterung des gcc Compilers. Also lokale Arrays auf dem Stack - wie hier - können auch zur Laufzeit erzeugt werden. Sogar sizeof() funktioniert. Aber es geht nicht wenn das Array global oder lokal statisch ist.

Cool danke für die infos aber ich befürchte ich kann das nicht von C++ in Aruino übersetzen ...
mit C++ stehe ich irgendwie auf Kriegsfuß, obwohl Arduino ja fast c++ ist ....
würde es sehr gerne besser beherrschen aber aktuell bekomme ich das mit deinem link nicht hin ...
Trotzdem Danke !

Es steht doch dort:

Returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.

Genaugenommen bekommst du einen Zeiger auf das interne char Array des String Objekts. Und mit dem kannst du wie mit deinem Array arbeiten. Allerdings mit dem riesigen Vorteil, dass nicht extra unnötig Speicher angelegt wird.

Sollte also so gehen:

server.write(sendBuffer.c_str(), sendBuffer.length());

Der Fehler bei toCharArray() wird übrigens klar wenn du dir mal das anschaust:

toCharArray() gibt nichts zurück. Du kannst also nicht sendBuffer = toCharArray() machen. Deshalb gab es Gemecker wegen "incompatible types in assignment of 'void' to 'char". Die Fehlermeldung hat also genau gezeigt was falsch war. Ist auch unnötig, da du das Ziel Array ja schon als Parameter übergibst. Das ist aber etwas unschön implementiert. Das hätte man ruhig so machen können dass ein Zeiger auf das Ziel Array zurückgegeben wird.

jo das läuft ...
Sauber vielen Dank !