Android usb host input bulktransfer fails to read randomly when data available - android-usb

The following code is inside a thread and reads input data coming over usb. Approximately every 80 readings it misses one of the packets coming from an stm32 board. The board is programmed to send data packets to the android tablet every one second.
// Non Working Code
while(running){
int resp = bulktransfer(mInEp,mBuf,mBuf.lenght,1000);
if(resp>0){
dispatchMessage(mBuf);
}else if(resp<0)
showsBufferEmptyMessage();
}
I was looking the Missile Launcher example in android an other libraries on the internet and they put a delay of 50ms between each poll. Doing this it solves the missing package problem.
//Working code
while(running){
int resp = bulktransfer(mInEp,mBuf,mBuf.lenght,1000);
if(resp>0){
dispatchMessage(mBuf);
}else if(resp<0)
showsBufferEmptyMessage();
try{
Thread.sleep(50);
}catch(Exception e){}
}
Does anyone knows the reason why the delay works. Most of the libraries on github has this delay an as I mention before the google example too.

I am putting down my results regarding this problem. After all seems that the UsbConnection.bulkTransfer(...) method has some bug when called continuously. The solution was to use the asynchronous API, UsbRequest class. Using this method I could read from the input endpoint without delay and no data was lost during the whole stress test. So the direction to take is asynchronous UsbRequest instead of synchronously bulktransfer.

Related

Why is my Arduino MKR NB 1500 stuck after sending or receiving a couple of MQTT messages?

Good morning everyone, newcomer writing his first question here (and new to C++/OOP).
So, i'm currently working on a project in which i have to send 2 types of JSON payloads to a MQTT broker after regular intervals (which can be set by sending a message to the Arduino MKR NB 1500).
I'm currently using these libraries: ArduinoJson, StreamUtils to generate and serialize/deserialize the JSONs, PubSubClient to publish/receive, and MKRNB in my VS code workplace.
What I noticed is that my program runs fine for a couple of publishes/receives and then stays stuck in the serialization function: I tried to trace with the serial monitor to see exactly where, but eventually arrived at a point in which my knowledge in C++ is too weak to recognize where to even put the traces in the code...
Let me show a small piece of the code:
DynamicJsonDocument coffeeDoc(12288); //i need a big JSON document (it's generated right before
//the transmission and destroyed right after)
coffeeDoc["device"]["id"] = boardID
JsonObject transaction = coffeeDoc.createNestedObject("transaction");
transaction["id"] = j; //j was defined as int, it's the number of the message sent
JsonArray transaction_data = transaction.createNestedArray("data");
for(int i = 0; i < total; i++){ //this loop generates the objects in the JSON
transaction_data[i] = coffeeDoc.createNestedObject();
transaction_data[i]["id"] = i;
transaction_data[i]["ts"] = coffeeInfo[i].ts;
transaction_data[i]["pwr"] = String(coffeeInfo[i].pwr,1);
transaction_data[i]["t1"] = String(coffeeInfo[i].t1,1);
transaction_data[i]["t2"] = String(coffeeInfo[i].t2,1);
transaction_data[i]["extruder"] = coffeeInfo[i].extruder;
transaction_data[i]["time"] = coffeeInfo[i].time;
}
client.beginPublish("device/coffee", measureJson(coffeeDoc), false);
BufferingPrint bufferedClient{client, 32};
serializeJson(coffeeDoc, bufferedClient); //THE PROGRAM STOPS IN THIS AND NEVER COMES OUT
bufferedClient.flush();
client.endPublish();
j++;
coffeeDoc.clear(); //destroy the JSON document so it can be reused
The same code works as it should if i use an Arduino MKR WiFi 1010, I think i know too little about how the GSM works.
What am I doing wrong? (Again, it works about twice before getting stuck).
Thanks to everybody who will find the time to help, have a nice one!!
Well, here's a little update: turns out i ran out of memory, so 12288 bytes were too many for the poor microcontroller.
By doing some "stupid" tries, i figured 10235 bytes are good and close to the maximum available (the program won't use more than 85% of the RAM); yeah, that's pretty close to the maximum, but the requirements of the project give no other option.
Thanks even for having read this question, have a nice one!

ESP32 attempt reconnect to when network drops without halting loop (Arduino)

I have an ESP 32 collect data from a moisture sensor, which it then serves on our network. Our WiFi turns off between 1am and 6 am (because no one is using it). The ESP does not automatically try to reconnect, so it gathered data all night which I straight up can not access now.
For obvious reasons I do not want it to halt data collection when it looses connection to our network, so I can not have a loop try to reconnect. I tried this code:
void loop() {
sensor_value = analogRead(sensor_pin);
Serial.println(sensor_value);
push_value(float(sensor_value)/2047.0);
//============
//RELEVANT BIT
//============
if( WiFi.status() != WL_CONNECTED ){
//Try to recconect if connection is lost....
WiFi.disconnect();
WiFi.begin(ssid, pwd);
}
delay(second_delay*1000);
}
I've seen everyone run Wifi.disconnect() before attempting reconnecting. Is that necessary. Also does WiFi.begin() pause execution? I can't test my code right now unfortunately.
I am using the Arduino IDE and Wifi.h
And before you ask: Yes, 2047 is correct. I am running the sensor on the wrong voltage which results in about this max value.
Given that you've tagged esp8266 wifi, I'm assuming you're using that library. If so, then wifi.begin will not block execution. The library sets autoreconnect by default, so it'll automatically reconnect to the last access point when available. Any client functions will simply return an error code while disconnected. I do not know of any reason that wifi.disconnect should be called before begin.

How to benchmark packet processing functions using Google benchmark? Basically functions that are repeated with state constraints?

Basically I want to measure the time while traversing over a packet dump file. Looking at the google benchmark documentation, I have come with:
BENCHMARK_DEFINE_F(MyFixture, FooTest)(benchmark::State& state) {
for (auto _ : state) {
// read
if (readPacket() == NO_MORE_PACKET) {
break;
}
if (!isPacketOfConsideration()) {
continue;
}
// some extra bookkeeping code if required
time t1{};
processPacket();
time t2{};
state.SetIterationTime(t2 - t1);
}
}
BENCHMARK_REGISTER_F(MyFixture, Footest)->UseManualTime();
The above is a pseudocode which uses manual time to measure and set iteration time. The questions are basically:
Can I break from the google benchmark's for loop on the state?
Can I continue the google benchmark's for loop on the state without setting iteration time?
I would suggest trying black box testing. Micro benchmarks here will likely not help.
I would divide this in several steps.
Generate or record lots of packet data.
Feed this packet data in your parser and measure time needed to fully process it. Potentially this can be function inside your code, or a whole application.
Make change, rerun benchmark, compare results
I worked on open source project, which used this scheme for benchmarking of game server. First, sendto and recv function were hooked and all packets were recorded. Then sleep was hooked, so server didn't sleep between game loop iterations. sendto just returns and recv reads packet data from file.
Detailed description.

QSerialPort continuous reading accumulative delay

I am trying to do communication from QT Application to Arduino. The flow is like this: QT Application sends a '1' and Arduino is expected to respond with some data(the data String length is huge, around 300). QT Application is sending '1' at the rate of around 5Hz(every 200ms).
The problem I am facing is, there is an accumulative delay between the Arduino to QT communication. That is, the data I receive from Arduino is not recent data but the frequency of data coming of Arduino is 5Hz only(which is as expected), just the data coming is not recent. This delay keeps on increasing with time. I believe there is some problem with buffer or something.
What I tried:
QSerialPort serialPort; is my device port
serialPort.clear()
serialPort.flush()
Increasing and decreasing Baud Rate from both ends.
Reduce character length from Arduino, here delay reduces significantly but the accumulated delay is observed after a long time.
to clear serial communication buffer, but the issue still persists.
Here is my code snippet:
connect(timer_getdat, SIGNAL(timeout()), this, SLOT(Rec()));
timer_getdat->start(200);
where Rec() is the function where I do communication part.
In Rec():
serialPort.write("1", 2);
// serialPort.waitForBytesWritten(100);
long long bytes_available = serialPort.bytesAvailable();
if (bytes_available >= 1)
{
serialPort.readLine(temp, 500);
serialPort.flush(); // no change
serialPort.clear(); // no change by .clear() also
}
I have been stuck on this issue for a quite long time. The above code snippet is what I think is necessary but if anyone needs more clarification, I may reveal more of the code.
I also encountered with the same issue, and yes QSerialPort.clear() and QSerialPort.flush() doesn't help. Try doing readAll()
So change the part in your Rec() function to something like this:
serialPort.write("1", 2);
long long bytes_available = serialPort.bytesAvailable();
if (bytes_available >= 1)
{
serialPort.readLine(temp, 500);
serialPort.readAll(); // This reads all the data in buffer at once and clears the queue.
}
Even on QT forums, I didn't find the answer to this, was playing with all functions available with QSerialPort class and readAll() seems to work.
About readAll(), Qt documentation says:
Reads all remaining data from the device, and returns it as a byte
array.
My explanation for the resolution is that readAll captures all of the data from the communication buffer and empties it.
This should be the job of clear() function but apparently readAll() seems to work.

QTcpSocket sends more data than wanted - Qt/C++

first of all a little background on my situation:
- Qt/C++ UI desktop application
- embedded device (Stm32l4xx family) +ATWINC1500 wifi module
I'm developing the gui application in order to send commands and files to the emdedded device via sockets.
For simple commands I've done all successfully, but for sending files (text files in GCODE format) I am stuck with some issues.
The embedded device has already a socket management(not written by me, so I have not the possibility to modify the way sockets are managed, coming from third party company), and the reception of that type of files is managed in a way that the API waits for every single line of the file being sent, and then wrotes it into a reserved portion of the flash.
My problem is that when I send file from qt Application(by reading each line and and calling write() on the line, in reality my socket sends an entire chunk of the file, like 50 lines, resulting in my device not managing the file reception.
My sending code is this:
void sendGCODE(const QString fileName)
{
QFile *file = new QFile(fileName,this);
bool result = true;
if (file->open(QIODevice::ReadOnly))
{
while (!file->atEnd())
{
QByteArray bytes(file->readLine());
result = communicationSocket->write(bytes);
communicationSocket->flush();
if(result)
{
console->append("-> GCODE line sent:"+ QString(bytes));
}
else
{
console->append("-> Error sending GCODE line!");
}
}
file->close();
}
}
Have anyone of you guys any hints on what I am doing wrong?
I've already searched and someone suggests on other topic that for this purpose it should be better to use UDP instead of TCP sockets, but unfortunately I cannot touch the embedded-device-side code.
thank you all!
EDIT
After suggestions from comments, I've sniffed tcp packets and the packets are sent correctly(i.e. each packet contains a single line). BUT... at the receiver(device), I understood that there is something regarding memory which is not well managed. an example:
sender sends the line "G1 X470.492 Y599.623 F1000" ; receiver receives correctly the string "G1 X470.492 Y599.623 F1000"
next, if the line length is less than the previous sent, i.e. sending "G1 Z5", the receiver receives: "G1 Z5\n\n.492 Y599.623 F1000", so it is clear that the buffer used to store the data packet is not re-initialized from previous packet content, and the new part overwrites the previous values where the remaining part is from the previous packet
I'm trying to figure out how I could reset that part of memory.
This is all wrong. TCP is not a message-oriented protocol. There is no way to ensure that the TCP packets contain any particular amount of data. The receiver code on the device mustn't expect that either - you perhaps misunderstood the receiver's code, or are otherwise doing something wrong (or the vendor is). What the receiver must do is wait for a packet, add the packet's data to a buffer, then extract and process as many complete lines as it can, then move the remaining data to the beginning of the buffer. And repeat that on every packet.
Thus you're looking for the wrong problem at the wrong place, unless your device never ever had a chance of working. If that device works OK with other software, then your "packetized" TCP assumption doesn't hold any water.
Here's how to proceed:
If the device is commercially available and has been tested to work, then you're looking in the wrong place.
If the device is a new product and still in development, then someone somewhere did something particularly stupid and you either need to fix that stupidity, or have the vendor fix it, or hire a consultant to fix it. But just to be completely clear: that's not how TCP works, and you cannot just accept that "it's how it is".