sprintf "%d" vs. itoa und weitere Fragen zum Arduino "String Objekt Verzicht"

Ich bin dabei meinen Arduino-MEGA Webclient von GET auf PUT umzubauen und auf das String Objekt zu verzichten.

Was bisher geschah:
Im ersten Schritt habe ich einfach im Webclient die client.print ausgetauscht gegen ein
String Objekt “message” und die message mit einfachen Verkettungen zusammengestückelt was auch erwartungsgemäß funktioniert hat.

message ="board=";
message +"TXT_BOARDID";

usw.

Der zweite Schritt ist nun das String Objekt gegen ein char Array ausztauschen.

für den HTML-BODY habe ich nun ein “großen” message Buffer und einen kleinen temporären definiert

const uint16_t MESSAGE_SIZE_MAX = 600;        // maximum bytes for Message Buffer
char message[MESSAGE_SIZE_MAX];               // the temporary sending message - html body
char val[32];                                 // to convert floats and integers before appending
#define TXT_BOARDID "65"                        // brauchen wir noch weiter unten im Beispiel

Die Message baue ich nun mit strcat zusammen also

strcpy(message, "board=");           // Anfang
strcat(message, TXT_BOARDID);        // Jedes weitere ...

war Tipparbeitet, aber klappt soweit.

Nun die Fragen:
Frage 1:
bei Integers bin ich mir nicht sicher, ob ich eher ein sprintf oder ein itoa verwenden soll also
Variante A

    strcat(message,   "&relay=");
    sprintf(val, "%d", portRelay);
    strcat(message, val);

oder Variante B

strcat(message, "&ldr=");
sprintf(val, "%d", analogRead(LDRSENSOR_PIN));
itoa(analogRead(LDRSENSOR_PIN), val, 10);
strcat(message, val);

Frage 2:
Gibt es für Floats eine Alternative zu dtostrf - oder ist das eh in Ordnung

strcat(message, "&voltage=");                          //                   aktuell gemessene Spannung
dtostrf(voltageActual, 1, 2, val);
strcat(message, val);

Frage 3:
Ich bekomme aus meinem Solarregler einige Werte in zwei separaten Registern (zwei int, eins um 16bit shiften) und die baue ich dann
zu einem Float:

float IntToFloat (int low, int high)
//converts two integers with each of two bytes to one float value
//in:     low byte high byte
//out:    the float value of low and high byte
{ float num;
  long temp = (long)high << 16 | low; 
  num = (float)temp / 100;
  return num;
}

wenn ich den Float nun in meine “message” einbauen möchte, gibt es da etwas einfacheres,
als zunächst die zwei Integer in ein Float zu wandeln und diese Float dann mit dtostrf “printbar” zu machen?

    // zum Verständnis
    int regs[50];                                           // mein Registry Master Array das über Modbus befüllt wird
    const byte solarChargingEquipmentInputPower =       2;  // Startregister für den Wert
    //...

    strcat(message, "&sceip=");
    dtostrf(IntToFloat(regs[solarChargingEquipmentInputPower], regs[solarChargingEquipmentInputPower + 1]), 1, 1, val);    //Float
    strcat(message, val);

also im Prinzip funktioniert alles, aber wenn ich etwas “einfacher” machen könnte (muss der ganze Aufriss mit strcat wirklich sein?), nehme ich gern eure Tipps.

Warum willst Du die ganze Website erst in eine einzige Zeichenkette packen und diese dann printen?
client.print(...) kann man auch mehrfach nacheinander aufrufen und die Zahlen direkt ausgeben (wie bei Serial.print).
z.B.

client.print(F("board=")); // F-Macro, damit konstante Texte im Flash landen
client.print(TXT_BOARDID);
float f = 1.23;
client.print(F("&wert=")); // F-Macro, damit konstante Texte im Flash landen
client.print(f,2); // 2 Nachkommastellen

Gruß Tommy

noiasca:
Frage 1:
bei Integers bin ich mir nicht sicher, ob ich eher ein sprintf oder ein itoa verwenden soll also
...

Ich würde ausschließlich Dinge verwenden, die im „Standard“ (ISO-C++) festgeschrieben sind. Damit fällt itoa schon mal weg.

Soviel zunächst zu Frage 1.

Gruß

Gregor

Tommy56:
Warum willst Du die ganze Website erst in eine einzige Zeichenkette packen und diese dann printen?

... damit ich die Länge der Message ermitteln kann und im HTML Header die Content-Length setzen kann.

Für GET und Parameter im URI alles kein Problem, für POST und Parameter im HTML Body aber notwendig.

Hast Recht, das hatte ich übersehen.

Gruß Tommy

Such mal nach der PString und Streaming Lib

Damit kannst du komfortabel in eine Variable streamen wie normalerweise auf die serielle Schnittstelle oder in den client

@ElEspanol ... PString scheint genau das zu sein, dass ich Vorgestern abend hätte wissen sollen ^^
Danke!

KARMA

noiasca:
... damit ich die Länge der Message ermitteln kann und im HTML Header die Content-Length setzen kann.

Die .print/.write Methoden haben als Rückgabewert die Anzahl von Zeichen die sie ausgegeben haben.

Was narürlich nicht viel hilft, wenn man die Anzahl vorher wissen muss.

Das kann man aber bei RAM Knappheit trotzdem nutzen. Einfach die Ausgabe in eine Funktion schreiben, das Ziel (z.B. seriell oder Dummy client) mit übergeben und die Zeichen ermitteln. Danach nochmals mit Ziel (client), wobei du die vorher ermittelte Bytezahl bereits zur Verfügung hast.

Zweimaliger Aufruf überlege ich mir noch, überzeugt mich aber noch nicht.
Ich habe ablauftechnisch die Situation, dass sich die Werte zwischen den zwei Aufrufen ändern könnten (analogRead...) und sich die zwei Ausgaben dann unterscheiden könnten.

RAM Knappheit habe ich imho noch nicht, je nach aktivierter Hardware und Debug Level bin ich momentan auf:

Der Sketch verwendet 75146 Bytes (29%) des Programmspeicherplatzes. Das Maximum sind 253952 Bytes.
Globale Variablen verwenden 2751 Bytes (33%) des dynamischen Speichers, 5441 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.

Wie geschrieben, ich bin am MEGA.

Du könntest wechselweise mit 2 Structs und den Pointern/Referenzen darauf arbeiten.
Nach der Messung wird geswitcht und das Mess-Struct wird das Übertragungs-Struct und umgekehrt.
Damit würde sich bei mehrmaligen Durchlauf nichts ändern.

Gruß Tommy

noiasca:
Zweimaliger Aufruf überlege ich mir noch, überzeugt mich aber noch nicht.
Ich habe ablauftechnisch die Situation, dass sich die Werte zwischen den zwei Aufrufen ändern könnten (analogRead...) und sich die zwei Ausgaben dann unterscheiden könnten.

Die Aufrufe macht man natürlich unmittelbar hintereinander. Dann ändern sich keine Werte zwischendurch, es sei denn, du ermittelst Werte per Interrupt. Dann musst du mit Kopien der Werte arbeiten, die du nach erfolgreichem Upload updatest.