Convert SML Hex String to signed Integer
-
Hi,
hopefully this is a real easy one for the Pros - I'm not a c/ c++ programmer & struggeling hard.
I use the following code on one of my ESP's to read the current (in Watt) & that worked fine:
double getSubstrFromSMLasDouble(byte smlMessage[], int indexStart, int indexStop){ return std::strtoul(getSubstrFromSML(smlMessage, indexStart, indexStop).c_str(), 0, 16);
worked fine.. Until I started to generate electricity & now get negative values.
Something like
fffffb60
should convert into-1184
.
ffffd4b1
should convert into-110087
This guy (https://www.scadacore.com/tools/programming-calculators/online-hex-converter/) says it makes sense to him under the "INT32 - Big Endian (ABCD)" column.
I did quite a bit of research (not knowing what exactly I was looking for), saw fancy bit shifting in C and tried a couple of code snipets, including those two:
return std::strtol(getSubstrFromSML(smlMessage, indexStart, indexStop).c_str(), 0, 16); return (double) std::strtol(getSubstrFromSML(smlMessage, indexStart, indexStop).c_str(), 0, 16);
So far that was not very successful - any guidance what I'm up to is appreciated!
ItsMee
-
Wie sehen denn die Daten in
smlMessage
aus wenn du diese als Text ausgibst?
Steht da wirklichfffffb60
als Text drinnen? Oder stehen da binär die 4 Bytes0xff
,0xff
,0xfb
,0x60
drinnen?
-
Hi @hustbaer,
danke Dir für's quer lesen & nachdenken!
Ich habe mir eine angepasste Methode geschrieben um deine Frage zu beantworten:
String getSubstrFromSMLAsDoubleDirect(byte smlMessage[], int indexStart, int indexStop){ int arrSize = (2 * (indexStop-indexStart)) + 1; char returnValue[arrSize]; char *myPtr = &returnValue[0]; for (int i = indexStart; i <= indexStop; i++) { snprintf(myPtr, 3, "%02x", smlMessage[i]); //convert a byte to character string, and save 2 characters (+null) to charArr; mqttSendJson(OBJECT, getESPid(), opto_powermeter_topic+"/debug/doubleBytes" , "POWERSML", "CURRENTPOWER", String(smlMessage[i]), "Debug"); myPtr += 2; //increment the pointer by two characters in charArr so that next time the null from the previous go is overwritten. } return "-1"; }
Dort bekomme ich dann einzelne Bytes welche von meiner ursprünglichen zu einem String
ffffbbc0
concatiniert werden - aber schon die 'sauber' in einen String zu convertieren mache ich ggf. falsch. Da ich an das Gerät nur remote komme habe ich keine Möglichkeit print() zu verwenden sondern "muss" text über MQTT versenden.VALUE":"255 VALUE":"255 VALUE":"187 VALUE":"192
Wahrscheinlich hast Du einen Punkt und ich muss an der Stelle schon anfangen, ggf. noch endiness berücksichtigen?
ItsMee
-
@itsmee sagte in Convert SML Hex String to signed Integer:
Wahrscheinlich hast Du einen Punkt und ich muss an der Stelle schon anfangen, ggf. noch endiness berücksichtigen?
for (int i = indexStart; i <= indexStop; i++) { snprintf(myPtr, 3, "%02x", smlMessage[i]); ...
Ich denke ja, so wie du die einzelnen Bytes konvertierst - bei der niedrigsten Speicheradresse angefangen - muss der Wert in
smlMessage
im Big-Endian-Format abgelegt sein, damit du mit einem anschließendenstd::strtol
den korrekten Wert bekommst. Unabhängig von der Endianess des Systems, auf dem das Programm laufen soll.Wenn das bei diesem Protokoll nicht der Fall sein sollte, müsstest du die Bytes in umgekehrter Reihenfolge in den String schreiben oder das Ergebnis von
std::strtol
anpassen.