Qt reading serial input then splitting it into separate variables - c++

I'm working on Qt, however I have come across an issue which for the life of me I cant fix at all. I have tried many different combinations to my code, but it still hasn't given me the output I'm looking for. I am hoping someone can help me.
QStringList buffer_split = serialBuffer.split(","); // split the serialBuffer string, parsing with ',' as the separator
// Check to see if there less than 3 tokens in buffer_split.
// If there are at least 3 then this means there were 2 commas,
// means there is a parsed temperature value as the second token (between 2 commas)
if(buffer_split.length() < 3){
// no parsed value yet so continue accumulating bytes from serial in the buffer.
serialData = arduino->readAll();
serialBuffer = serialBuffer + QString::fromStdString(serialData.toStdString());
serialData.clear();
}else{
// the second element of buffer_split is parsed correctly, update the temperature value on temp_lcdNumber
serialBuffer = "";
qDebug() << buffer_split << "\n";
parsed_data = buffer_split[1];
}
The above solution has worked for me, in turn I am reading the values being sent over the serial port such as:
0,0,0,0,0,0
Above is how parsed_data is reading the information from the serial port, which is correct.
The issue I am having, is splitting that, then storing them in separate variables to start some if statements. so far I can't seem to get it to work.
If anyone can help me I would be grateful
Thank You

You don't need an extra parsed_data variable buffer_split stores them, all you just need int num1 = buffer_split[0].toInt(); int num2 = buffer_split[1].toInt(); ...

Related

C++ Recognize UTF-8 or Hebrew languague

I'm working on some code that his target it recognize if the strings equal
Have two type of string - string 1 came from text file , string 2 came from server side from chat packet
i try very different options , this my last trying but nothing success the sentence not recognize has equal at all for example this string on text file "בדיקה" and the string that came from packet side is "בדיקה" too and still nothing equal
`
if(gSentenceEvent.IsRunning())
{
std::string s = lpMsg->message;
int Len = strlen(gSentenceEvent.RandomSentence);
std::string str;
str.assign(gSentenceEvent.RandomSentence, gSentenceEvent.RandomSentence + Len);
if (str.compare(s) == 0)
{
gSentenceEvent.SetRunning(false);
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,gMessage.GetMessage(1130));
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,gMessage.GetMessage(1127),lpObj->Name);
}
else
{
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,"%s Try %s\n",lpObj->Name,s);
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,"Answer Is %s\n",str);
}
}
`
if someone have any idea for solving the issue i will be happy to hear some ways that recognize it well
Thanks in advance !
trying convert the text for wstring as well but still nothing
when i check the hex value of both sentence even they equal
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,"%.2X",lpMsg->message);
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,"%.2X",gSentenceEvent.RandomSentence);
that really came different from example "בדיקהה 3" On both sides
ServerSide = 22B6970
TextFile = D9C0B0

Why does getline behave weirdly after 3 newlines?

I'll preface this by saying I'm relatively new to posting questions, as well as C++ in general, my title is a little lame as it doesn't really specifically address the problem I am dealing with, however I couldn't really think of another way to word it, so any suggestions on improving the title is appreciated.
I am working on a relatively simple function which is supposed to get a string using getline, and read the spaces and/or newlines in the string so that it can output how many words have been entered. After reaching the character 'q' it's basically supposed to stop reading in characters.
void ReadStdIn2() {
std::string userInput;
const char *inputArray = userInput.c_str();
int count = 0;
getline(std::cin, userInput, 'q');
for (int i = 0; i < strlen(inputArray); i++){
if ((inputArray[i] == ' ') || (inputArray[i] == '\n')){
count += 1;
}
}
std::cout << count << std::endl;
}
I want to be able to enter multiple words, followed by newlines, and have the function accurately display my number of words. I can't figure out why but for some reason after entering 3 newlines my count goes right back to 0.
For example, if I enter:
hello
jim
tim
q
the function works just fine, and returns 3 just like I expect it to. But if I enter
hello
jim
tim
bill
q
the count goes right to 0. I'm assuming this has something to do with my if statement but I'm really lost as to what is wrong, especially since it works fine up until the 3rd newline. Any help is appreciated
The behaviour of the program is undefined. Reading input into std::string potentially causes its capacity to increase. This causes pointers into the string to become invalid. Pointers such as inputArray. You then later attempt to read through the invalid pointer.
P.S. calculating the length of the string with std::strlen in every iteration of the loop is not a good idea. It is possible to get the size without calculation by using userInput.size().
To fix both issues, simply don't use inputArray. You don't need it:
for (int i = 0; i < userInput.size(); i++){
if ((userInput[i] == ' ') || (userInput[i] == '\n')){
...

how to parse stream data(string) to different data files

#everyone, I have some problem in reading data form IMU recently.
Below is the data I got from My device, it is ASCII, all are chars,and my data size is [122], which is really big, I need convert them to short, and then float, but I dont know why and how.....
unsigned char data[33];
short x,y,z;
float x_fl,y_fl,z_fl,t_fl;
float bias[3]={0,0,0};//array initialization
unsigned char sum_data=0;
int batch=0;
if ( !PurgeComm(file,PURGE_RXCLEAR ))
cout << "Clearing RX Buffer Error" << endl;//this if two sentence aim to clean the buffer
//---------------- read data from IMU ----------------------
do { ReadFile(file,&data_check,1,&read,NULL);
//if ((data_check==0x026))
{ ReadFile(file,&data,33,&read,NULL); }
/// Wx Values
{
x=(data[8]<<8)+data[9];
x_fl=(float)6.8664e-3*x;
bias[0]+=(float)x_fl;
}
/// Wy Values
{
y=(data[10]<<8)+data[11];
y_fl=(float)6.8664e-3*y;
bias[1]+=(float)y_fl;
}
/// Wz Values
{
z=(data[12]<<8)+data[13];
z_fl=(float)6.8664e-3*z;
bias[2]+=(float)z_fl;
}
batch++;
}while(batch<NUM_BATCH_BIAS);
$VNYMR,+049.320,-017.922,-024.946,+00.2829,-00.2734,+00.2735,-02.961,+03.858,-08.325,-00.001267,+00.000213,-00.001214*64
$VNYMR,+049.322,-017.922,-024.948,+00.2829,-00.2714,+00.2735,-02.958,+03.870,-08.323,+00.004923,-00.000783,+00.000290*65
$VNYMR,+049.321,-017.922,-024.949,+00.2821,-00.2655,+00.2724,-02.984,+03.883,-08.321,+00.000648,-00.000391,-00.000485*61
$VNYMR,+049.320,-017.922,-024.947,+00.2830,-00.2665,+00.2756,-02.983,+03.874,-08.347,-00.003416,+00.000437,+00.000252*6C
$VNYMR,+049.323,-017.921,-024.947,+00.2837,-00.2773,+00.2714,-02.955,+03.880,-08.326,+00.002570,-00.001066,+00.000690*67
$VNYMR,+049.325,-017.922,-024.948,+00.2847,-00.2715,+00.2692,-02.944,+03.875,-08.344,-00.002550,+00.000638,+00.000022*6A
$VNYMR,+049.326,-017.921,-024.945,+00.2848,-00.2666,+00.2713,-02.959,+03.876,-08.309,+00.002084,+00.000449,+00.000667*6A
all I want to do is:
extract last 6 numbers separated by commas, btw, I don't need the last 3 chars(like *66).
Save the extracted data to 6 .dat files.
What is the best way to do this?
Since I got this raw data from IMU, and I need the last 6 data, which are accelerations(x,y,z) and gyros(x,y,z).
If someone could tell me how to set a counter to the end of each data stream, that will be perfect, because I need the time stamp of IMU also.
Last word is I am doing data acquisition under windows, c++.
Hope someone could help me, I am freaking out because of so much things to do and that's really annoying!!
There's a whole family of scanf functions (fscanf, sscanf and some "secure" ones).
Assuming you have read a line into a string:-
sscanf( s, "VNYMR,%*f,%*f,%*f,%*f,%*f,%*f,%f,%f,%f,%f,%f,%f", &accX, &accY, &accZ, &gyroX, &gyroY, &gyroZ )
And assuming I have counted correctly! This will verify that the literal $VNYMR is there, followed by about five floats that you don't assign and finally the six that you care about. &accaX, etc are the addresses of your floats. Test the result - the number of assignments made..

String parsing to extract int in C++ for Arduino

I'm trying to write a sketch that allows a user to access data in EEPROM using the serial monitor. In the serial monitor the user should be able to type one of two commands: “read” and “write. "Read" should take one argument, an EEPROM address. "Write" should take two arguments, an EEPROM address and a value. For example, if the user types “read 7” then the contents of EEPROM address 7 should be printed to the serial monitor. If the user types “write 7 12” then the value 12 should be written into address 7 of the EEPROM. Any help is much appreciated. I'm not an expert in Arudino, still learning ;). In the code below I defined inByte to be the serail.read(). Now how do I extract numbers from the string "inByte" to assign to "val" and "addr"
void loop() {
String inByte;
if (Serial.available() > 0) {
// get incoming byte:
inByte = Serial.read();
}
if (inByte.startsWith("Write")) {
EEPROM.write(addr, val);
}
if (inByte.startsWith("Read")) {
val= EEPROM.read(addr);
}
delay(500);
}
Serial.read() only reads a single character. You should loop until no more input while filling your buffer or use a blocking function like Serial.readStringUntil() or Serial.readBytes() to fill a buffer for you.
https://www.arduino.cc/en/Serial/ReadStringUntil
https://www.arduino.cc/en/Serial/ReadBytes
Or you can use Serial.parseInt() twice to grab the two values directly into a pair of integers. This function will skip the non numerical text and grab the values. This method is also blocking.
https://www.arduino.cc/en/Reference/StreamParseInt
A patch I wrote to improve this function is available in the latest hourly build, but the old versions still work fine for simple numbers with the previous IDE's
The blocking methods can be tweaked using Serial.setTimeout() to change how long they wait for input (1000ms default)
https://www.arduino.cc/en/Serial/SetTimeout
[missed the other answer, there's half my answer gone]
I was going to say use Serial.readStringUntil('\n') in order to read a line at a time.
To address the part:
how do I extract numbers from the string "inByte" to assign to "val" and "addr"
This is less trivial than it might seem and a lot of things can go wrong. For simplicity, let's assume the input string is always in the format /^(Read|Write) (\d+)( \d+)?$/.
A simple way to parse it would be to find the spaces, isolate the number strings and call .toInt().
...
int val, addr;
int addrStart = 0;
while(inByte[addrStart] != ' ' && addrStart < inByte.length())
addrStart++;
addrStart++; //skip the space
int addrEnd = addrStart + 1;
while(inByte[addrEnd] != ' ' && addrEnd < inByte.length())
addrEnd++;
String addrStr = inByte.substring(addrStart, addrEnd); //excludes addrEnd
addr = addrStr.toInt();
if (inByte.startsWith("Write")) {
int valEnd = addrEnd+1;
while(inByte[varEnd] != ' ' && varEnd < inByte.length())
valEnd++;
String valStr = inByte.substring(addrEnd+1, valEnd);
val = valStr.toInt();
EEPROM.write(addr, val);
}
else if (inByte.startsWith("Read")) {
val = EEPROM.read(addr);
}
This can fail in all sorts of horrible ways if the input string has a double space or the numbers are malformed, or has any other subtle error.
If you're concerned with correctness, I suggest you look into a regex library, or even an standard format such as JSON - see ArduinoJson.

C++ socket writing too many characters

This code is embedded in a "chat room" program using sockets. It is reading from the client (myFD) and successfully appending a username to the front.
However, I have a problem writing extra characters in the write buffer. What was sent last time is still stored and also sending.
For example, the first time I'd send (and write correctly)
UN: Hello.
But on the second try, when I'd write, say, "NOT", the message sent would be:
UN: NOTlo
The cout statement correctly "cout's" without the "lo" at the end, but the clients receive the "lo" at the end. Am I overlooking something simple?
Code Below:
while ( (amount_read = read(myFD, buffer, 1024)) > 0)
{
total = 0;
strcpy(second, "");
strcpy(second, username);
total += unLength;
strcat(second, ": ");
total += 2;
strcat(second, buffer);//, amount_read);
total += amount_read;
cout << second << endl;
write(myFD, second, total);
}
Thanks!
Your string is not null terminated that's why you print old string. You can fix it adding \0 at the end of string buffer[amount_read]=0 or just clear whole string before next iteration.
To clear buffer you can use memset (buffer,'\0', 1024). Maybe it's not fastest way but prevent storing rubbish or data that shouldn't be hosted longer than it's necessary.
You are not adding in '\0' correctly.
I guess your transmit looks like this write(myFD, buffer, strlen(buffer)), then you will send everything but the 0 terminator. It works the first time because you probably did a memset.
buffer[amount_read]=0; will probably fix it.