Reset counter every second - android

I am trying to reset a counter that runs on a Bluetooth receive thread. I have 4 data bytes in each packet being sent by a BT transmitter. Packet time is 300 ms. The receive data gets out of sequence for an unknown reason after some time so I thought I could add a timer to reset the counter between packets to ensure valid data. According to the blogs I have read there is no built in timeouts so I assume someone has created one.
while (true) {
try {
byte[] packetBytes = new byte[20]; // Start new packetbyte
Log.d(TAG, " Counter " + counter);
mmInStream.read(packetBytes); // Read Bluetooth socket
b [counter]= packetBytes[0]; // Save each byte into B
counter++;
if(counter == 4){ // After 4 bytes DO this
Log.d(TAG, " Done ");
counter=0; // Reset counter
h.obtainMessage(RECIEVE_MESSAGE, counter, -1, b).sendToTarget(); // Send to message queue Handler
}
} catch (IOException e) {
break;
}
}
This is the code to count the data. I am trying to reset the counter.

Related

Android set timeout on a bluetooth socket

On a bluetooth socket created with device.createRfcommSocketToServiceRecord(MY_UUID) I wish that after an certain amount of time when nothing arrives, to run some code, but still be able to process the bytes as soon as they arrive.
The description of .setSoTimeout explains exactly what I am willing to do:
With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid.
So it looks like the perfect opportunity to put my code in the catch statement.
But unfortunately .setSoTimeout does not work with Bluetooth sockets according to my Android Studio. How can I implement such functionality without such method?
Thread.sleep is obviously also not a option, because I cannot lock the thread.
I solved it with Thread.sleep anyway, by using small intervals for the sleep and so trying to mimic the .setSoTimeout operation:
short sleep, check for incoming data, cycle until the timeout is reached then execute the timeout code.
I suppose there are better solutions, but this works for now.
The code given will execute the "timeout code" every second (set by the int timeOut), when no byte arrives on the input stream. If a byte arrives, then it resets the timer.
// this belongs to my "ConnectedThread" as in the Android Bluetooth-Chat example
public void run() {
byte[] buffer = new byte[1024];
int bytes = 0;
int timeOut = 1000;
int currTime = 0;
int interval = 50;
boolean letsSleep = false;
// Keep listening to the InputStream
while (true) {
try {
if (mmInStream.available() > 0) { // something just arrived?
buffer[bytes] = (byte) mmInStream.read();
currTime = 0; // resets the timeout
// .....
// do something with the data
// ...
} else if (currTime < timeOut) { // do we have to wait some more?
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
// ...
// exception handling code
}
currTime += interval;
} else { // timeout detected
// ....
// timeout code
// ...
currTime = 0; // resets the timeout
}
} catch (IOException e) {
// ...
// exception handling code
}
}
}

Android TCP connection receiving packets out of order

I have a Particle Photon microcontroller sending TCP packets over a hotspot WiFi network to an Android Phone. The microcontroller is acting as server, the phone as client.
The phone however is receiving some (but not all) of the packets out of order, despite the information being transmitted via tcp. It was my understanding that this would not happen - am i wrong, or is there something i can do to correct this?
Microcontroller Code:
// This #include statement was automatically added by the Particle IDE.
#include "databuffer5.h"
// This #include statement was automatically added by the Particle IDE.
#include "databuffer7.h"
const unsigned int localPort = 10000;
IPAddress remoteIP(a, b, c, d);
// An TCP instance to let us send and receive packets over wifi
TCPServer server = TCPServer(localPort);
TCPClient client;
// UDP Port used for two way communication
short msg_count = 0;
const int adcPin = A0;
int byteBuffer;
unsigned long loopTimer;
const int packetSize = 40; //number of bytes in packet - 10 ints with 4 bytes each
byte buffer[packetSize];
int j = 0;
int dataCount = 0; //dummy data that increments every loop point, to measure packet contiuity
//(creates a line with slope 1 as data)
void setup() {
// start the UDP
server.begin();
// Print your device IP Address via serial
Serial.begin(9600);
Serial.println(WiFi.localIP());
//Serial.println(System.ticksPerMicrosecond()); //returns 120, ie 120MHz
}
void loop()
{
if (client.connected())
{
loopTimer = millis(); //mark start time of loop
for (int i = 0; i < 10; i++)
{
//for testing connection
byteBuffer = i+j*10;
buffer[i*4] = ( (byteBuffer >> 24) & 0xFF); //take upper 8 bits
buffer[i*4+1] = ( (byteBuffer >> 16) & 0xFF); //take middle upper 8 bits
buffer[i*4+2] = ( (byteBuffer >> 8 ) & 0xFF); //take middle lower 8 bits
buffer[i*4+3] = ( byteBuffer & 0xFF); //take lower 8 bits
dataCount++;
if (i != 9)
{
while(millis() < (loopTimer+10*(i+1))); //ie do nothing for 10 ms (time is in ms, want to delay by exactly 10ms for each loop)
//goal here is to sample every 10ms, by delaying for the remaining time
//dont delay here for the last sample, as the udp packet will take time
//delay after instead
}
}
server.write(buffer, sizeof(buffer)); //using sizeof on a byte array so dont need to scale (ie scaling factor is 1)
j++;
if (j < 0){j = 0;}
while(millis() < (loopTimer+10*10)); //delay till 100ms after loops started
}
else
{
client = server.available();
}
}
Android (client) code:
async_udp = new AsyncTask<Void, int[], Void>() {
#Override
protected Void doInBackground(Void... params) {
byte b1[];
b1 = new byte[100];
while (serverActive) {
Socket socket = null; //previously this was DatagramSocket (UDP) - no Socket (TCP)
try {
//DatagramSocket s = new DatagramSocket(server_port, server_ip);
socket = new Socket(server_ip, server_port);
socket.setPerformancePreferences(1, 2, 2);
InputStream socketStream = socket.getInputStream();
DatagramPacket p1 = new DatagramPacket(b1, b1.length);
ByteBuffer wrapped;
int data[] = new int[10+1]; //first number for message data, second is for the message number
while (serverActive) //TODO include shutdown function
{
while (socketStream.available() < 39){}
socketStream.read(b1, 0, 40);
//packet structure is a char containing message number, and 10 shorts (2 bytes) containing data points (between 0 and 4096)
wrapped = ByteBuffer.wrap(Arrays.copyOfRange(b1, 0, 40)); // extract 40 bytes to convert to 10 ints
for (int i = 0; i < 10; i++) {
data[i] = wrapped.getInt();
}
String str = data.toString();
server_port = p1.getPort();
server_ip = p1.getAddress();
String str_msg = "RECEIVED FROM CLIENT IP =" + server_ip + " port=" + server_port + " message no = " + b1[0] +
" data=" + str; //first character is message number
statusText = str_msg;
publishProgress(data);
}
socketStream.close();
socket.close();
} catch (SocketException e) {
if (socket != null) {}
//status.append("Error creating socket");
statusText = (" Error creating socket"); //this doesn't work!
} catch (IOException e) {
//status.append("Error recieving packet");
statusText = (" Error receiving packet"); //this doesn't work!
}
try{
Thread.sleep(100, 0); //sleep for 10ms if no wifi lock is found, to stop battery being silly
} catch(Exception e){
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(int[]... data1)
{
super.onProgressUpdate(data1);
int data[] = data1[0];
//send data to graph
for (int i = 0; i < 9; i++)
{
series.appendData(new DataPoint(lastDataX++, data[i]), false, graphPointsMax);
//append 9 points to graph, but only redraw the grpah on the 10th
}
series.appendData(new DataPoint(lastDataX++, data[9]), true, graphPointsMax);
}
};
if (Build.VERSION.SDK_INT >= 11)
{
async_udp.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else
{
async_udp.execute();
}
What is guaranteed by TCP, is that when you send a message - it will come in the right order, even if split by the TCP stack along the way (see TCP Segment Number, which serves as an indication which split message part belongs together with which, and in what order). So, in your case, all you are sending using:
server.write(buffer, sizeof(buffer));
no meter how big is the buffer (within the limits of TCP protocol, of course) is guaranteed to arrive in the right order and complete.
Sending several buffers one-by-one over TCP will provide you guaranteed delivery, or error notification (if any), but not the order of the messages sent. Down to the protocol level, these packets will contain different Sequence Numbers, and therefore will be treated by the TCP stack of the receiver separately, in the order the stack prefers.
I see two relatively simple things that could be done here:
try to put all you can in one buffer (not really practical approach, though)
Introduce the counter and increment each time you are sending the buffer out. Put the counter along with the buffer and check the precedence on the receiving side (phone, in your case).

Android Bluetooth InputStream real time read

I am working on an Android application that receives a real time data by Bluetooth and plots it on the screen.
The data is a gyro sensor position information. I am sending it from a custom Freescale Kinetis K10 microcontroller board (designed and tested by myself). For the Bluetooth communication I am using HC-05 Bluetooth module.
The format of the data is as follows:
byte_1: position identification byte, always equals to -128
byte_2: position of axis 1
byte_3: position of axis 2
byte_4: position of axis 3
I am sending these 4 bytes continuously one after another, in that particular order. I am sending this packet of 4 bytes every 5 ms and sending the packet takes about 4.7 ms (9600 baud rate).
The data output from the microcontroller is perfect in terms of accuracy and timing (checked with a logic analyzer).
The problem is that when it is being received from the phone, some of the bytes seem to get lost. Here is the part of the code, where I am reading the InputStream:
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e("Printer Service", "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
#Override
public void run() {
Log.i("BluetoothService", "BEGIN mConnectedThread");
byte[] buffer = new byte[4];
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
int position = 0;
if(buffer[0] == -128) {
if(bytes >= 2) {
sendArray.errorTilt = buffer[1];
}
if(bytes >= 3) {
sendArray.errorRoll = buffer[2];
}
if(bytes == 4) {
sendArray.errorPan = buffer[3];
}
}
else if(buffer[1] == -128) {
position = 1;
if(bytes >= 3) {
sendArray.errorTilt = buffer[2];
}
if(bytes == 4) {
sendArray.errorRoll = buffer[3];
}
if(bytes >= 2) {
sendArray.errorPan = buffer[0];
}
}
else if(buffer[2] == -128 && bytes >= 3) {
position = 2;
sendArray.errorRoll = buffer[0];
sendArray.errorPan = buffer[1];
if(bytes == 4) {
sendArray.errorTilt = buffer[3];
}
}
else if(buffer[3] == -128 && bytes == 4) {
position = 3;
sendArray.errorTilt = buffer[0];
sendArray.errorRoll = buffer[1];
sendArray.errorPan = buffer[2];
}
if(position <= bytes && bytes > 1) {
sendArray.errorUpdate = true;
}
} catch (Exception e) {
e.printStackTrace();
connectionLost();
BluetoothService.this.stop();
break;
}
}
}
public void write(int oneByte) {
try {
mmOutStream.write(oneByte);
} catch (IOException e) {
Log.e("BluetoothService", "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e("BluetoothService", "close() of connect socket failed", e);
}
}
}
sendArray is a singleton that keeps many different variables.
errorTilt, errorRoll and errorPan are the current values of the axis, which are being updated from the receiving buffer.
"position" keeps the position of the position identification byte. It is used for a check if any variables have been updated.
Many times just one byte is received in the input buffer and since I don't know which axis is that supposed to be, since I don't have information about it's relative position to the position byte, this particular byte is useless and gets lost.
I've tested the accuracy of receiving by the following method. I made the MCU output a triangular wave on one of the axis, instead of the axis data. On the phone the lines of the triangular wave are not straight as they are supposed to be, but randomly curved and containing artifacts.
To plot the data I am using GraphView and I am updating the graph on equal intervals from a separate thread.
I've tried using longer receiving buffer (with a modified receiving algorithm), but this doesn't help as only a few bytes are being received at a time.
I've tried implementing InputStream.available() but it was always giving 127 bytes available, which didn't seem to be true.
I've read many threads about similar problems and I spent the last 5 days working on it, but I couldn't find a good solution.
To summarize, I need to achieve accurate, real time (or close to real time) receiving of all the bytes.
Thread with a similar problem:
How to do good real-time data streaming using Java Android SDK
Thank you.
UPDATE:
I've tried sending the information just for one of the axis, so it is simple and clear, without the need of position bytes. I was sending it again every 5 ms, but this time it was more time between the consecutive bytes, since it's just one byte in the packet.
I used InputStream.read() this time, which doesn't require a buffer. However, the incoming data was corrupted again, because random bytes couldn't be received.
I've seen different project using this method successfully, I don't know why it's not working with me. I thought it might be a problem with the HC-05 Bluetooth module I'm using, but I tried a different one - HC-06, and the situation is the same. I haven't tried a different phone, but my phone (Samsung Galaxy S3, Android 4.1.2) seems to be working OK.
UPDATE2: I've tried again testing the original code with InputStream.available() before reading from the stream.
When the condition is available()>0, there are no major changes, maybe it works slightly worse.
When the condition is available()>1, it never reads. I guess that is because of the unreliable available() method, as it says in the documentation.
you have incorrect processing of data, if you want to get data from microcontroller board. You have to use bytesAvaliable because android bluetooth Socket is pretty slow over microcontroller boards with bluetooth. But "bytesAvaliable way" has nuance - As socket is slow receiver, bytesAvaliable can catch more then 1 packet from board in one time so you gotta devide readed data by yourself, Check my code out below! My code is getting 38 bytes packets from inertial sensor so you gotta only change count of bytes! 0xAA is the first byte of every next packet so if you find 0xAA byte and have 38 bytes you get packet and nullify iterator. But anyway I'm sure that you still can sometimes lose data because it's not high frequency data transfering way
public void run() {
byte[] bytes = new byte[38];
int iterator = 0;
while (true) {
try {
int bytesAvailable = mmInStream.available();
if (bytesAvailable > 0) {
byte[] curBuf = new byte[bytesAvailable];
mmInStream.read(curBuf);
for (byte b : curBuf) {
if (b == (byte) 0xAA && iterator == 38) {
mHandler.obtainMessage(MainActivity.DATA_READ, bytes.length, -1, bytes).sendToTarget();
iterator = 0;
bytes[iterator] = b;
} else {
bytes[iterator] = b;
}
iterator++;
}
}
} catch (IOException ex) {
Log.e(TAG, "disconnected", ex);
connectionLost();
break;
}
}
}

android bluetoothsocket receive zero-value bytes?

Got a problem at receiving bytes from bluetooth socket. I'm trying to send message created by arduino - couple of single bytes values i.e. 0x41, 0x05, 0xFF(...) into my phone with android. It works fine until one of these value is zero (0x00). Transmission hangs until new message comes. Anyone meet with that situation?
My "reader" works in separate thread, processBuffer() do sth with data that should be received:
public void run() {
while(stop == false){
try {
bytes = InStream.read(readbuffer);
for (int i = 0; i < bytes; i++){
Log.d("FRAME", "Read bytes "+readbuffer[i]);
}
Log.d("FRAME", "Read number of bytes "+bytes);
processBuffer(bytes);
} catch (Exception e){
Log.d("BT_debug", "Cannot read bytes");
Log.d("BT_debug", "iterator: "+iterator);
e.printStackTrace();
break;
}
}
}

Implementing BlockingQueue Buffer used in Bluetooth Communication for Android

I'm really stumped with this and I've trying to debug for the passed three days. Hopefully someone will be able to tell me what I am doing wrong.
I am implementing a BlockingQueue (FIFO) buffer to receive information being streamed from my PC over bluetooth. I am sending prerecorded electrocardiogram signal over a Hyperterminal link using RealTerm.
I have tested the buffer as I start up the app by adding values and then removing them, and it seems to work as it should.
The problem comes in when I try to store in the buffer while I'm receiving data from the bluetooth connection. I don't know if I am adding faster than the BlockingQueue can cope, but when I stop the data transmission and check my buffer, the whole buffer contains the last value that was added. The size of the buffer is correct, but the content isn't.
Here is my buffer:
public class IncomingBuffer {
private static final String TAG = "IncomingBuffer";
private BlockingQueue<byte[]> inBuffer;
public IncomingBuffer() {
inBuffer = new LinkedBlockingQueue<byte[]>();
Log.i(TAG, "Initialized");
}
public int getSize() {
int size;
size = inBuffer.size();
return size;
}
// Inserts the specified element into this queue, if possible. Returns True
// if successful.
public boolean insert(byte[] element) {
Log.i(TAG, "Inserting " + element[0]);
boolean success = inBuffer.offer(element);
return success;
}
// Retrieves and removes the head of this queue, or null if this queue is
// empty.
public byte[] retrieve() {
Log.i(TAG, "Retrieving");
return inBuffer.remove();
}
// Retrieves, but does not remove, the head of this queue, returning null if
// this queue is empty.
public byte[] peek() {
Log.i(TAG, "Peeking");
return inBuffer.peek();
}
}
The portion of my BluetoothCommunication class which receives the information and sends it to the buffer is the following:
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
ringBuffer = new IncomingBuffer();
byte[] buffer = new byte[1024];
Log.i(TAG, "Declared buffer byte");
int bytes;
byte[] retrieve;
int size;
Log.i(TAG, "Declared int bytes");
//Setting up desired data format 8
write(helloworld);
Log.i(TAG, "Call write(initialize)");
// Keep listening to the InputStream while connected
while (true) {
try {
Log.i(TAG, "Trying to get message");
// Read from the InputStream
bytes = mmInStream.read(buffer);
//THIS IS WHERE THE BYTE ARRAY IS ADDED TO THE IncomingBuffer
RingBuffer.insert(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
Log.i(TAG, "Sent to target" +ringBuffer.getSize());
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothCommService.this.start();
break;
}
}
}
So an example of my problem would be:
Send values over bluetooth connection (8 bit values from 1 to 20). In the insert method of the IncomingBuffer class, the log message confirms the proper value is sent. When values are retrieved from buffer, it contains twenty byte arrays which all contain the last number inserted (20).
Any clue as to why the buffer would work in other circumstances but not during the bluetooth communication?
I figured out what my problem was.
When I was using the variable buffer to read from mmInStream and then pass that to the ringBuffer, I pass the same byte array variable every time i go through the while loop. From what I can understand that simply assigns a specific memory location where the byte array is calculated and that is why at the end all of the elements in my ringBuffer are the last value that was assigned to 'buffer' from the mmInStream.
What i did to change that is make a separate variable that i clone the 'buffer' byte array to. Before I pass 'buffer' to 'RingBuffer', i do the following:
byte[] newBuf;
newBuf = buffer.clone();
ringBuffer.store(newBuf);
This takes care of my problem.

Categories

Resources