SPP Android BT Connection quits after seconds (EEG readings) - android

I have created an app that receives data from a bt transmitter (Bluegiga). The readings are from EEG signals. The data rate is 1Khz (I have to admit it's high). Anyway, I acquire some data for some seconds and then the Bluetooth acts like there is no incoming data (which is not true). If I try to disconnect the Bluetooth using the app is clear that there is no more communication with the bt module at the EEG board since it doesn't respond to the desconnection (It has a led that indicates when is connected, and it doesn't turn of/on or anything).
If I decrease the data rate to (let's say 500hz) the app works ok, with some occasional 'quits', but tolerable. If I decrease it more the app works with no problems.
Of curse, by design, my app must work at 1Khz data rate so here is where the problem comes.
I have check some other post, trying to hit some kind of sns but nothing match my problem exactly (anyway I have tried to use the information on them but with no success obviously).
Sometimes I get this message, "dm_pm_timer expires", sometimes no (after the bt stops working).
Sadly there is no indication, Exception or message that can tell me what's going on.
Here is my Code for the BT reception Thread
class BluetoothReadThread extends Thread {
private final InputStream iStream;
private final OutputStream mmOutputStream;
private boolean continueReading = true;
public BluetoothReadThread() {
InputStream tmp = null;
OutputStream tmp2 = null;
try {
tmp = btSocket.getInputStream();
tmp2 = btSocket.getOutputStream();
} catch (IOException e) {
}
iStream = tmp;
mmOutputStream = tmp2;
}
#Override
public void run() {
int c;
int waitCount = 0;
while (continueReading) {
try {
if (iStream.available() > 0) {
waitCount = 0;
c = iStream.read();
readBuffer[readBufferPosition++] = c;
if (readBufferPosition == bitsExpected) {
if (bitsExpected == 22) {
ch1 = MultiplicationCombine(readBuffer[4], readBuffer[3]);
ch2 = MultiplicationCombine(readBuffer[6], readBuffer[5]);
ch3 = MultiplicationCombine(readBuffer[8], readBuffer[7]);
ch4 = MultiplicationCombine(readBuffer[10], readBuffer[9]);
ch5 = MultiplicationCombine(readBuffer[12], readBuffer[11]);
ch6 = MultiplicationCombine(readBuffer[14], readBuffer[13]);
ch7 = MultiplicationCombine(readBuffer[16], readBuffer[15]);
ch8 = MultiplicationCombine(readBuffer[18], readBuffer[17]);
} else {
ch1 = (int) filter_3((double)MultiplicationCombine(readBuffer[5], readBuffer[4], readBuffer[3]));
ch2 = (int) filter_4((double)MultiplicationCombine(readBuffer[8], readBuffer[7], readBuffer[6]));
ch3 = (int) filter_2((double)MultiplicationCombine(readBuffer[11], readBuffer[10], readBuffer[9]));
ch4 = (int) filter_2((double)MultiplicationCombine(readBuffer[14], readBuffer[13], readBuffer[12]));
ch5 = (int) filter_2((double)MultiplicationCombine(readBuffer[17], readBuffer[16], readBuffer[15]));
ch6 = (int) filter_2((double)MultiplicationCombine(readBuffer[20], readBuffer[19], readBuffer[18]));
ch7 = (int) filter_2((double)MultiplicationCombine(readBuffer[23], readBuffer[22], readBuffer[21]));
ch8 = (int) filter_2((double)MultiplicationCombine(readBuffer[26], readBuffer[25], readBuffer[24]));
}
Header_int = readBuffer[0];
PK_ID_int = readBuffer[1];
PK_Counter_int = readBuffer[2];
if (downsample++ == downsample_value) {
addEntry(ch1 / scaCh1, ch2 / scaCh2, ch3 / scaCh3, ch4 / scaCh4, ch5 / scaCh5, ch6 / scaCh6, ch7 / scaCh7, ch8 / scaCh8);
downsample = 0;
}
//ProgrNum,PacketType,Ch1,Ch2,Ch3,Ch4,Ch5,Ch6,Ch7,Ch8,MRK
if (write_open) {
osw.write(PK_Counter_int + "," + PK_ID_int + "," + ch1 + "," + ch2 + "," + ch3 + "," + ch4 + "," + ch5 + "," + ch6 + "," + ch7 + "," + ch8 + "," + bolOpenClose + "\n");
//osw.write(PK_Counter_int + "," + PK_ID_int + "," + ch1 + "," + ch2 + "," + ch3 + "," + ch4 + "," + ch5 + "," + ch6 + "," + ch7 + "," + ch8 + "," + "\n");
}
System.out.println(PK_Counter_int + "," + PK_ID_int + "," + ch1 + "," + ch2 + "," + ch3 + "," + ch4 + "," + ch5 + "," + ch6 + "," + ch7 + "," + ch8 + ", AV=" + iStream.available() );
mmOutputStream.write(valueSTR.getBytes());
// if(downsample++==14) { safe_copy(readBuffer); plot=true; downsample=0;}
readBufferPosition = 0;
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
System.out.println(e + "\nError sending data + :" + e);
// Bluetooth error! Stop reading.
//this.stopAndSendIntent();
}
}
}
/*
public void stopAndSendIntent() {
this.cancel();
Intent intent = new Intent();
intent.setAction(BLUETOOTH_ACTION_DONE_READING);
sendBroadcast(intent);
}
*/
public void cancel() {
System.out.println("-----Cancelling readThread!!");
try {
iStream.close();
} catch (IOException e) {
} catch (NullPointerException e) {
}
;
continueReading = false;
}
}
It works like this:
I read a received character (c=iStream.read()).
Then I copy this character to an int array until I reach the length of the packet (it can be 22 or 28 (bitsExpected)).
The following part is just filtering and plotting of the signal.
I have tried many other implementations but I get the same result.
Even if I eliminate the part of the filtering and plotting (just reading data) the problem persists.
If instead of working with array, I work with string, i.e, using append() (which should be the same?) I manage to get an working connection (no quits) but, as soon as I manipulate the program using the array everything is the same.
I'm stuck with this for 1 month already, so I will really appreciate any comments, past experience or suggestions.
Thanks in advance.

I just added this piece of code
if (PK_Counter_int % 100 == 0) mmOutputStream.write(startTring.getBytes());
and it works just fine so far.

Related

Random gaps while recording data on Android smartwatch

I'm using a Fossil Gen 5 smartwatch running WearOS to record sensor data from Accelerometer, Gyroscope (32 Hz) and PPG sensor (64 Hz). I'm using a unique bufferedWriter object for each sensor to write data to a .txt file as each sensor event is created (shown below):
void registerSensor(){
Log.i(TAG,"Sensor Registered");
try {
accWriter = new BufferedWriter(new FileWriter(accFile, true));
gyrWriter = new BufferedWriter(new FileWriter(gyrFile, true));
ppgWriter = new BufferedWriter(new FileWriter(ppgFile, true));
} catch (IOException e) {
e.printStackTrace();
}
//just in case
if (sensorManager == null)
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
listener = new SensorEventListener() {
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case 65572:
String msg1 = "Recording PPG";
mData1.setText(msg1);
ppgTime = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000L;
try {
ppgWriter.write(ppgTime + ", " + event.values[0] + ", " + ambient + "\n");
} catch (IOException e) {
e.printStackTrace();
}
break;
case Sensor.TYPE_ACCELEROMETER:
String msg2 = "Recording ACC";
mData2.setText(msg2);
accTime = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000L;
try {
accWriter.write(accTime + ", " + df.format(event.values[0]) + ", " + df.format(event.values[1]) + ", " + df.format(event.values[2]) + ", " + ambient + "\n");
} catch (IOException e) {
e.printStackTrace();
}
break;
case Sensor.TYPE_GYROSCOPE:
String msg3 = "Recording GYR";
mData3.setText(msg3);
gyrTime = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000L;
try {
gyrWriter.write(gyrTime + ", " + df.format(event.values[0]) + ", " + df.format(event.values[1]) + ", " + df.format(event.values[2]) + ", " + ambient + "\n");
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
};
sensorManager.registerListener(listener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),31250); // SensorManager.SENSOR_DELAY_FASTEST);
sensorManager.registerListener(listener, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), 31250);
sensorManager.registerListener(listener, sensorManager.getDefaultSensor(65572), 15625);
}
I expect the sampling frequency to hover around the intended value. But I'm getting random missing data chunks of ~ 60 s in all 3 sensor streams.
Please see this image that visually describes the issue (I'm not able to embed images yet)
I've tested this a number of times, with the same result. I thought some events might be dropped, so I tried writing all the data to a String and then writing the String to a file after a certain size is exceeded. This didn't solve the issue.
Any help or suggestions are greatly appreciated! Excuse my etiquette as I'm new to StackOverflow.
If the samples are being dropped when the screen is off you need to use wakeup sensors.
You can do that by passing true to sensorManager.registerListener.
And according to the doc, the sampling frequency is only a hint to the os.

How to get the results from multiple servers in a function in Android

I'm installing Hybrid Ranking algorithm for Linked Data Extraction & Context on Android. Documents you can search Google for the keywords above.
And now I'm installing semantic similarity between two uri1 and uri2.
Input: two DBpedia URIs
Output: a value representing their similarity
private float similarity(String uri1, String uri2) {
float wikipedia = wikiS(uri1, uri2);
float abtract = abtractS(uri1, uri2);
float google = engineS(uri1, uri2, google);
float yahoo = engineS(uri1, uri2, yahoo);
float bing = engineS(uri1, uri2, bing);
float dilicious = engineS(uri1, uri2, dilicicous);
return wikipedia + abtract + google + yahoo + bing + dilicious;
}
And with each child function, I have to query data using SPARQL dbpedia, google, yahoo, bing, dilicious using provided API. The results obtained will be calculated to the parser and returns the corresponding float value.
Example for abtractS(uri1, uri2) below:
private float abstractS(String uri1, String uri2, final float wikiS){
String url = createUrlAbstractS(uri1, uri2);
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
float abtractS = 0.0f;
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray data = jsonObject.getJSONObject("results").getJSONArray("bindings");
if(data.length() == 0){
showLogAndToast("No result");
}else{
JSONObject element = data.getJSONObject(0);
String label1 = element.getJSONObject("label1").getString("value");
String abtract1 = element.getJSONObject("abtract1").getString("value");
String label2 = element.getJSONObject("label2").getString("value");
String abtract2 = element.getJSONObject("abtract2").getString("value");
abtractS = calWordContained(label1, abtract2) + calWordContained(label2, abtract1) + wikiS;
//TODO: RESULT ABTRACTS HERE. How next?
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(request);
return 0.0f;//HERE: no results
}
private float calWordContained(String label, String abtract){
if(label.length() == 0 || abtract.length() == 0){
return 0.0f;
}
List<String> words = Arrays.asList(label.split(" "));
int count = 0;
float length = words.size();
for(int i = 0; i < length; i++){
if(abtract.toLowerCase().contains(words.get(i).toLowerCase())){
count++;
}
}
return (count/length);
}
public String createUrlAbstractS(String uri1, String uri2){
private String BASE_URL_DBPEDIA = "http://dbpedia.org/sparql?default-graph-uri=&query=";
String query = createQueryAbstractS(uri1, uri2);
String url = "";
try {
url = Config.BASE_URL_DBPEDIA + URLEncoder.encode(query, "UTF-8") + Config.RESULT_JSON_TYPE;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return url;
}
private String createQueryAbstractS(String uri1, String uri2){
String query = Config.PREFIX_DBPEDIA + " \n" +
"prefix dbpedia-owl: <http://dbpedia.org/ontology/>\n" +
"\n" +
"\n" +
"select ?label1, ?label2, ?abtract1, ?abtract2 where\n" +
"{\n" +
" {\n" +
" select *\n" +
" where{\n" +
" <" + uri1 + "> rdfs:label ?label1 ;\n" +
" dbpedia-owl:abstract ?abtract1 .\n" +
" FILTER langMatches(lang(?abtract1),'en') . \n" +
" FILTER langMatches(lang(?label1),'en') .\n" +
" }\n" +
" }\n" +
"\n" +
"\n" +
" {\n" +
" select *\n" +
" where{\n" +
" <" + uri2 + "> rdfs:label ?label2 ;\n" +
" dbpedia-owl:abstract ?abtract2 .\n" +
" FILTER langMatches(lang(?label2),'en') . \n" +
" FILTER langMatches(lang(?abtract2),'en') .\n" +
" }\n" +
" }\n" +
"}";
return query;
}
but how to do this on, I could not get the results I wanted in the similarity function (uri1, uri2). Therefore it will affect the results in different functions.
So I'm asking is: how can I get all the results of the function Wikis, abtractS, engine (google), engine (bing), engine (yahoo), engine (dilicious) in a simple way Best. I currently do on Android and data load times is very important.
Thank you very much!

onSimulatorDataUpdated() not getting called

private void initFlightController() {
DJIAircraft aircraft = DJISimulatorApplication.getAircraftInstance();
if (aircraft == null || !aircraft.isConnected()) {
log("initFlightController: aircraft not connected");
showToast("Disconnected");
mFlightController = null;
return;
} else {
log("initFlightController: aircraft CONNECTED");
mFlightController = aircraft.getFlightController();
DJISimulator djiSimulator = mFlightController.getSimulator();
log("initFlightController: djiSimulator has started : "+djiSimulator.hasSimulatorStarted());
djiSimulator.setUpdatedSimulatorStateDataCallback(new DJISimulator.UpdatedSimulatorStateDataCallback() {
#Override
public void onSimulatorDataUpdated(final DJISimulatorStateData djiSimulatorStateData) {
log("onSimulatorDataUpdated: ");
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
String yaw = String.format("%.2f", djiSimulatorStateData.getYaw());
String pitch = String.format("%.2f", djiSimulatorStateData.getPitch());
String roll = String.format("%.2f", djiSimulatorStateData.getRoll());
String positionX = String.format("%.2f", djiSimulatorStateData.getPositionX());
String positionY = String.format("%.2f", djiSimulatorStateData.getPositionY());
String positionZ = String.format("%.2f", djiSimulatorStateData.getPositionZ());
mTextView.setText("Yaw : " + yaw + ", Pitch : " + pitch + ", Roll : " + roll + "\n" + ", PosX : " + positionX +
", PosY : " + positionY +
", PosZ : " + positionZ);
}
});
}
});
}
}
I am testing the sample code given for android in Dji-Developer. Every thing goes fine but the onSimulatorDataUpdated() doesnt get called.
it even prints the log
"initFlightController: djiSimulator has started : true"
I found the solution for the problem. The code doesn't have any problem, the RC has a button at the left front area which has to be set to P mode.

networking oneway connection android

my todays problem is the following:
I have a network connection, at which both sides have to send commands (bytes), but my reader blocks my writer, thats how it seems to be. If I "disable" my reader (by deleting the reader from source) the writer works as he should, But when my reader is there, too, my writer just do the half of the work.
Lets say my writer has to send a command with an interval of 15 seconds and stay aware of incoming commands whach has to be answered by a little byte block. The answer block is send, but the command from the interval seems blocked.
Here my source:
protected String doInBackground(URL... params) {
try {
btw1 = (byte) sendbeg;
btw2 = (byte) w2;
btw3 = (byte) w3;
btw4 = (byte) w4;
btw5 = (byte) w5;
if (w5 == 79) {
btw6 = (byte) mins;
btw7 = (byte) seks;
btw8 = (byte) w6;
btw9 = (byte) sendend;
} else {
btw6 = (byte) w6;
btw7 = (byte) sendend;
}
SocketAddress sockaddr = new InetSocketAddress("192.168.0.7", 2001);
sock = new Socket();
int timeout = 1000; // 1000 millis = 1 second
sock.connect(sockaddr, timeout);
sock.setReuseAddress(true);
System.out.println(sock);
DataOutputStream dos = new DataOutputStream(
(OutputStream) sock.getOutputStream());
BufferedWriter wrtr = new BufferedWriter(
new OutputStreamWriter(dos), 300);
DataInputStream dis = new DataInputStream(sock.getInputStream());
BufferedReader rdr = new BufferedReader(new InputStreamReader(dis),
300);
getbyte((byte) btw1, (byte) btw2, (byte) btw3, (byte) btw4,
(byte) btw5, (byte) btw6, (byte) btw7, (byte) btw8,
(byte) btw9, (byte) btw10); //getbyte works fine, too. It's just there for putting the single bytes into an array.
System.out.println(btw.length);
dos.write(btw);
diny1 = (dis).read();
diny2 = (dis).read();
diny3 = (dis).read();
diny4 = (dis).read();
diny5 = (dis).read();
dinymin = (dis).read();
dinysek = (dis).read();
diny6 = (dis).read();
diny7 = (dis).read();
if (diny5 != 79) {
System.out.println("diny" + diny1 + " " + diny2 + " " + diny3
+ " " + diny4 + " " + diny5 + " " + dinymin + " "
+ dinysek);
} else {
if (diny7 != 5) {
diny6 = 0;
diny7 = 0;
}
System.out.println("diny" + diny1 + " " + diny2 + " " + diny3
+ " " + diny4 + " " + diny5 + " " + dinymin + " "
+ dinysek + " " + diny6 + " " + diny7);
}
dos.close();
wrtr.close();
dis.close();
rdr.close();
if (diny5 != 32) {
sendbeg = 3;
w2 = diny3;
w3 = diny2;
w4 = 48;
w5 = 32;
w6 = 11;
sendend = 5;
System.out.println(diny5 + " ^^ ");
doInBackground();
}
System.out.println("case 144-49-000.1" + context);
reccom(context);
sock.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println("IO error " + e);
}
return "Done";
}
My intervalsource works fine, because it works, if the reader is inactive, so i think the problem is in this code above. please help.
You can delete the setReuseAddress() call; it's only for server sockets.
AsyncTask is not exactly the right class for your readers and writers if you stay in a loop there all the time; it would be more suitable to use Thread.
It sounds as if you need a seperate reader and writer Thread if one is not allowed to block the other.
You'll probably have to use synchronized along the way if reader and writer act independently

Get repeated Entries for Some Items in DataBase!

I am working on an android application. In which i have slideShows. I am parsing these through an xml and after parsing them, saving in the SQLite DB. Majority of the slideshows are saved properly but, sometimes this happens that the slides are saved two times that is, every slide in the slideShow is saved two times obviously with different PK but same content. which should be avoided.
Partial code is here, where i am getting the slides and trying to store them in DB.
ArrayList<SlideShowItem> slideItems = null;
slideItems=Utils.database.getSlideItemOfUrl(Constants.StoriesTable,tempSlideShow.getFullStoryUrl().substring(0, index - 1), type);
if (slideItems == null) {
Log.d("store in DB: ", " when SlideItems == null ");
Log.d("SlideShow Title: ", tempSlideShow.getTitle());
Log.d("SlideShow pub Date: ", tempSlideShow.getPubDate());
slideItems = tempSlideShow.getSlideShow();
Utils.database.storeSlideItem(Constants.StoriesTable, myUrl,slideItems, type);
Utils.topStorySlidesArrayList = slideItems;
slideItems = null ;
} else {
Log.d("SlideShow Title: ", tempSlideShow.getTitle());
Utils.topStorySlidesArrayList = slideItems;
slideItems = null ;
}
and code of function storeSlideItem in DataBase is:
public synchronized void storeSlideItem(String tableName, String, url,ArrayList<SlideShowItem> list, String type) {
System.out.println("size of the Array list: " + list.size());
String newType = null;
if (type == null) {
newType = "List";
}else{
newType = type;
}
ArrayList<SlideShowItem> newList = new ArrayList<SlideShowItem>();
//newList = null;
Iterator<SlideShowItem> iterator = list.iterator();
while (iterator.hasNext())
{
SlideShowItem sSItem = iterator.next();
if(!newList.contains(sSItem))
{
newList.add(sSItem);
}
}
try {
for (int i = 0; i < newList.size(); i++) {
SlideShowItem item = newList.get(i);
String itemUrl = url + i;// Unique URL for the DB;
String imgString = null;
Log.e("Loop Counter", " time " + i);
Drawable drawable = item.getImage();
if (item.getBody() != null) {
item.setBody(item.getBody().replace('\'', '`'));
// replace as it create syntax error for storing data
}
if (item.getSubTitle() != null) {
item.setSubTitle(item.getSubTitle().replace('\'', '`'));
}
if (drawable != null) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
imgString = Base64.encodeBytes(b);
}
if (isOpen()) {
myDB.execSQL("INSERT INTO " + tableName + "(" + column[1] + "," + column[2] + "," + column[3] + "," + column[4] + "," + column[6]
+ "," + column[7] + ",type) VALUES('" + itemUrl + "','" + item.getSubTitle() + "','" + item.getBody() + "','"
+ item.getImagePath() + "','" + item.getIndex() + "','" + imgString + "','" + newType + "Slide')");
if (item.getBody() != null) {
item.setBody(item.getBody().replace('`', '\''));// " ' "
// replace as it create syntax error for storing data
}
if (item.getSubTitle() != null) {
item.setSubTitle(item.getSubTitle().replace('`', '\''));
}
if (tableName.equals(Constants.StoriesTable)) {
item.setItemId(getItemID(tableName, itemUrl));
Utils.hashListStoriesIds.put(itemUrl, item.getItemId());
if (imgString != null) {
Utils.hashListImages.put(item.getItemId(), new Boolean(true));
} else {
Utils.hashListImages.put(item.getItemId(), new Boolean(false));
}
}
}
}
} catch (Exception e) {
Log.e("Error", "Exception: storeSlideItem type " + e.toString());
} finally {
closeConnection();
}
}
Please tell me anything that can get me out of this irritating problem. Any help is appreciated.
in DB for duplication of slides the view is somewhat like:
1 abc USA 111
2 abc USA 111
and so on this was for one slide of a slideShow. if i have 3 slides in a slideshow, i'll get 6 entries in DB each slide being saved for two times.
Use HashSet instead of ArrayList

Categories

Resources