Android Open Source - airprobe Bluetooth History Manager






From Project

Back to project page airprobe.

License

The source code is released under:

GNU General Public License

If you think the Android project airprobe listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * AirProbe/*  w  w w  .  j a v a2 s  .  c om*/
 * Air quality application for Android, developed as part of 
 * EveryAware project (<http://www.everyaware.eu>).
 *
 * Copyright (C) 2014 CSP Innovazione nelle ICT. All rights reserved.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * For any inquiry please write to <devel@csp.it>
 * 
 * CONTRIBUTORS
 * 
 * This program was made with the contribution of:
 *   Fabio Saracino <fabio.saracino@csp.it>
 *   Patrick Facco <patrick.facco@csp.it>
 * 
 * 
 * SOURCE CODE
 * 
 *  The source code of this program is available at
 *  <https://github.com/CSPICT/airprobe>
 */

package org.csp.everyaware.bluetooth;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
import java.util.UUID;

import org.csp.everyaware.Constants;
import org.csp.everyaware.Utils;
import org.csp.everyaware.db.DbManager;
import org.csp.everyaware.db.Record;
import org.csp.everyaware.db.SemanticSessionDetails;
import org.csp.everyaware.gps.GpsTrackingService;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class BluetoothHistoryManager 
{    
    private int mState; //current connection status
    
  private final BluetoothAdapter mBluetoothAdapter;
  private Context mContext;
  private Handler mStartHistoryHandler;
  private Handler mDownloadHandler;
  
  //it opens RFCOMM socket and estabilishes a remote device connection on socket
  private ConnectThread mConnectThread;

  //it reads received data on socket from remote device
  private ConnectedThread mConnectedThread;
  
  //to close while cycle in run() method of ConnectedThread
  private boolean mTransferON;
  
  //Patrick
  private static volatile BluetoothHistoryManager mBluetoothManager;
  
  private DbManager mDbManager;
  
  private String mHistoryBuffer; //containes raw history records
  
  private List<Record>mHistoryRecordsSerie = null; //containes a list of history records to be saved on db
  
  private boolean mHistoryDownloadFinished;
  
  private static long mPrecBoxTs;
  private static String mCurrentHistSessionId;
  
  public static BluetoothHistoryManager getInstance(Context ctx, Handler handler)
  {
    if(mBluetoothManager == null)
      mBluetoothManager = new BluetoothHistoryManager(ctx, handler);
    
    return mBluetoothManager;
  }
  
  private BluetoothHistoryManager(Context ctx, Handler handler)
  {
    Log.d("BluetoothHistoryManager", "BluetoothHistoryManager()");
    
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    mContext = ctx;    
    mStartHistoryHandler = handler;
    
    mPrecBoxTs = 0;
    mCurrentHistSessionId = Utils.getSessionId(mContext);
    
    mDbManager = DbManager.getInstance(mContext);
    mDbManager.openDb();

    setState(Constants.STATE_NONE);
  }
  
  public void setDownloadHandler(Handler handler)
  {
    Log.d("BluetoothHistoryManager", "setDownloadHandler()");
    
    mDownloadHandler = handler;
  }

  //starts ConnectThread
  public synchronized void connect(BluetoothDevice device)
  {
    Log.d("BluetoothHistoryManager", "connect()--> Connecting to: " +device);
    
    if(mState == Constants.STATE_CONNECTING)
    {
      if(mConnectThread != null)
      {
        mConnectThread.cancel();
        mConnectThread = null;
      }
    }
    
    if(mConnectedThread != null)
    {
      mConnectedThread.cancel();
      mConnectedThread = null;
    }
    
    //starting of Connect Thread (opening socket and estabilishing remote device connection on it)
    
    mConnectThread = new ConnectThread(device);
    mConnectThread.start();
    
    setState(Constants.STATE_CONNECTING);
  }
  
  public synchronized void connected(BluetoothSocket socket, BluetoothDevice device)
  {
    Log.d("BluetoothHistoryManager", "connected()");
    
    if(mConnectThread != null)
    {
      mConnectThread.cancel();
      mConnectThread = null;
    }
    
    if(mConnectedThread != null)
    {
      mConnectedThread.cancel();
      mConnectedThread = null;
    }
    
    mConnectedThread = new ConnectedThread(socket);
    mConnectedThread.start();
    
    setState(Constants.STATE_CONNECTED);
      
  }

  //to track failure of attempt to connect to remote device
  //UI main thread is advised
    private void connectionFailed() 
    {
      Log.d("BluetoothHistoryManager", "connectionFailed()");
      
        setState(Constants.STATE_NONE);

        if(Utils.getStep(mContext) == Constants.START)
        {
          if(mStartHistoryHandler == null)
            return;
          
          Message msg = mStartHistoryHandler.obtainMessage(Constants.CONNECTION_FAILED);
          mStartHistoryHandler.sendMessage(msg);
          return;
        }
    }
    
    //to track losed bluetooth connection
    public void connectionLost()
    {
      Log.d("BluetoothHistoryManager", "connectionLost()");
      
      setState(Constants.STATE_NONE);
      
        if(Utils.getStep(mContext) == Constants.START)
        {
          if(mStartHistoryHandler == null)
            return;
          
          Log.d("BluetoothHistoryManager", "connectionLost()--> sending CONNECTION_LOST message to start history handler");
          
          Message msg = mStartHistoryHandler.obtainMessage(Constants.CONNECTION_LOST);
          mStartHistoryHandler.sendMessage(msg);
          return;
        }
    }
    
    private synchronized void setState(int state)
    {
      Log.d("BluetoothHistoryManager", "setState()");
      mState = state;
      
        if(Utils.getStep(mContext) == Constants.START)
        {
          Log.d("BluetoothHistoryManager", "setState()--> going to send message to start history handler");
          
          if(mStartHistoryHandler == null)
            return;
          
          Message msg = mStartHistoryHandler.obtainMessage(mState);
          mStartHistoryHandler.sendMessage(msg);    
          return;
        } 
    }
    
    //stop all threads
    public synchronized void stop() 
    {
        if (mConnectThread != null) 
        {
          mConnectThread.cancel(); 
          mConnectThread = null;
        }

        if (mConnectedThread != null) 
        {
          mConnectedThread.cancel(); 
          mConnectedThread = null;
        }

        setState(Constants.STATE_NONE);
    }
    
    
    private void sensorBoxMacNotRead() 
    { 
      Log.d("BluetoothHistoryManager", "sensorBoxMacNotRead()");
      
        if(Utils.getStep(mContext) == Constants.START)
        {
          if(mDownloadHandler == null)
            return;
          
          Message msg = mDownloadHandler.obtainMessage(Constants.SENSOR_BOX_MAC_NOT_READ);          
          mDownloadHandler.sendMessage(msg);
          return;
        }
    }
    
    /************ THREAD APERTURA SOCKET E CONNESSIONE AL DISPOSIIVO SCELTO *********************/
    
  private class ConnectThread extends Thread
  {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
    
    public ConnectThread(BluetoothDevice device)
    {
      Log.d("ConnectThread", "ConnectThread()");
      
      mmDevice = device; 
      BluetoothSocket tmp = null;
      
      try
      {
        //5 - opening RFCOMM socket
        tmp = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
        //to resolve pairing problem on Samsung Galaxy Tab2 - this solution requires Android 2.3.4 and later (minSdkVersion = 10)
        //tmp = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
      }
      catch(IOException e)
      {
        e.printStackTrace();
      }
      mmSocket = tmp;
    }
    
    public void run()
    {
      try
      {
        //6 - opening remote device connection on RFCOMM socket
        //    this call is blocking and it returns success or exception
        if(mmSocket != null)
          mmSocket.connect();
        
        Log.d("ConnectThread", "run()--> socket connected ");
      }
      //failure on opening connection
      catch(IOException e) 
      {
        e.printStackTrace();
        
        Log.d("ConnectThread", "run()--> IOException ");
        
        connectionFailed();
        
        try
        {
          if(mmSocket != null)
            mmSocket.close();
        }
        catch(IOException e2)
        {
          e.printStackTrace();
          Log.d("ConnectThread", "run()--> IOException2 ");
        }
        
        return; //exit from run()
      }
      
      //ConnectThread reset
      synchronized(BluetoothHistoryManager.this)
      {
        mConnectThread = null;
      }
      
      if(mmSocket != null)
        connected(mmSocket, mmDevice);
      else
        connectionFailed();
    }
    
    public void cancel()
    {
      try
      {
        if(mmSocket != null)
          mmSocket.close();
      }
      catch(IOException e)
      {
        e.printStackTrace();
      }
    }
  }
  
  /***************** THREAD RICEZIONE DATI DA DEVICE REMOTO SUL SOCKET APERTO *****************/
  
  private class ConnectedThread extends Thread
  {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;
    
    boolean transmittingInfos = false;
    private int mNumOfHistoryRecords;
    
    boolean transmittingHNR = false; //transimitting HistoryNumberRecords
    //Patrick
    private byte[] buffer;
    //----
    public ConnectedThread(BluetoothSocket socket)
    {
      //Patrick
      buffer = new byte[Constants.BLUETOOTH_BUFFER_SIZE];
      //--------
      Log.d("ConnectedThread", "ConnectedThread()");
      
      mmSocket = socket;
      InputStream tmpIn = null;
      OutputStream tmpOut = null;
      
      mTransferON = true;

      mNumOfHistoryRecords = 0;
      
      //important initializations
      Utils.counterHR = 0; //received history records      
      Utils.lostHR = 0; //lost history records
      //mHistoryBuffer = ""; //raw buffer history records    
      mHistoryRecordsSerie = new ArrayList<Record>();
      mHistoryDownloadFinished = false;      
      
      //getting I/O streams on RFCOMM socket
            try 
            {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } 
            catch (IOException e) 
            {
                e.printStackTrace();
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;  
    }
    
    public void run()
    {
      Looper.prepare();
      
        //receiving buffer
        //byte[] buffer = new byte[Constants.BLUETOOTH_BUFFER_SIZE]; //for a set of 50 records, buffer size must be about 6500 bytes
        int bytesRead = 0;
        
        boolean connectionFailed = false;
        //hardware informations from sensor box
        String infoMsg = "";
        //contantins number of history records on sd card of sensor box
        String numberHR = "";;

        /* 1 - ASK for infos to sensor box */

        transmittingInfos = true;
        
        try
        {
          //sending of "%I" string to tell the sensor box that smartphone is ready to receive data
          mmOutStream.write(Constants.askForInfo);
          
          //Log.d("ConnectedThreadHI", "run()--> SENT " +new String(Constants.askForInfo));
        }
        catch(IOException e)
        {
          e.printStackTrace();
        }
        while(transmittingInfos)
        {
          try
          {
            bytesRead = mmInStream.read(buffer);
            infoMsg += new String(buffer, 0, bytesRead);
            //Log.d("ConnectedThreadHI", "run()--> infoMsg: " +infoMsg);
            
            if((infoMsg.length() >= 4)&&(infoMsg.substring(infoMsg.length()-4, infoMsg.length()-2).equalsIgnoreCase("%K")))
            {
              transmittingInfos = false;
              infoMsg = infoMsg.substring(0, infoMsg.length()-4); //toggle %K
              Log.d("ConnectedThreadHI", "run()--> read box infos: " +infoMsg);
              
              String[] infos = infoMsg.split("\\*\\*");
              if(infos != null)
              {
                for(int i = 0; i < infos.length; i++)
                Log.d("ConnectedThreadHI", "run()--> infos: "+infos[i]);
                
                //Save firmware version and mac address on static variable for continuous usage on saving record
                Constants.mFirmwareVersion = infos[0];
                Constants.mMacAddress = Utils.getDeviceAddress(mContext);

                Log.d("ConnectedThreadHI", "run()--> mac address: "+Constants.mMacAddress);
                
                if((Constants.mMacAddress != null)&&(!Constants.mMacAddress.equals("")))
                {
                  if(infos.length > 1)
                  {
                    if((infos[1] != null)&&(infos[1].length() == 12))
                    {
                      Constants.mMacAddress = infos[1].substring(0, 2)+":"+infos[1].substring(2, 4)+":"+
                          infos[1].substring(4, 6)+":"+infos[1].substring(6, 8)+":"+infos[1].substring(8, 10)+
                          ":"+infos[1].substring(10);
                      
                      Utils.setDeviceAddress(Constants.mMacAddress, mContext);
                      
                      Log.d("ConnectedThreadHI", "run()--> mac address recovered from info!--> mac: "+Constants.mMacAddress);
                    }
                  }
                }
                
                //check mac address with mac address read from max/min.txt files
                if(Utils.addresses != null)
                {
                  boolean found = false;
                  int j = 0;
                
                  while((j < Utils.addresses.length)&&(!found))
                  {
                    Log.d("ConnectedThreadHI", "run()--> address["+j+"] = " +Utils.addresses[j]);
                    
                    if(Utils.addresses[j].equals(Constants.mMacAddress))
                    {
                      found = true;
                      Utils.actual_sb_index = j;
                      
                      Log.d("ConnectedThreadHI", "run()--> found sensor box with address: " +Constants.mMacAddress+ " and index: " +Utils.actual_sb_index);
                    }
                    else
                      j++;
                  }
                  
                  //if actual sensor box is recognized, use it mac address to select the right column in min_matrix and max_matrix
                  if(found)
                  {
                    int rows = Utils.max_matrix.length;
                    
                    Utils.max = new double[rows];
                    Utils.min = new double[rows];
                    
                    //copy j-mo column into max vector
                    for(int i = 0; i < rows; i++)
                    {
                      Utils.max[i] = Utils.max_matrix[i][j];
                      Utils.min[i] = Utils.min_matrix[i][j];
                      
                      //Log.d("ConnectedThreadHI", "run()--> max["+i+"] = " +Utils.max[i]+" - min["+i+"] = " +Utils.min[i]);
                    }
                  }
            
                  Utils.mac_recognized = found;
                }

                //save received informations on shared prefs
                if(infos.length < 3)
                {
                  Utils.setBoxInfoMsg("Firmware version: not read\nSensor models: not read", mContext);
                }
                else
                  Utils.setBoxInfoMsg("Firmware version: V" +infos[0]+"\nSensor models: " +infos[2], mContext);
              }
              //if infos from sensor box has not read, comunicate it
              else
              {
                
              }
            }
          }
          //this exception happens when bluetooth connection fails
          catch(IOException ex)
          {
            ex.printStackTrace();
                
            connectionLost();
            connectionFailed = true;
            
            try
            {
              if(mmSocket != null)
                mmSocket.close();
            }
            catch(IOException e2)
            {
              e2.printStackTrace();
            }
            
            break; //if connection fails, exit from while
          }
        }
        
        if(connectionFailed)
          return;
      
        /* 2 - ASK for number of history records saved on sensor box sd card */
          
        transmittingHNR = true;
          
        try
        {
          //sending of "%N" string to tell the sensor box that smartphone wants to know the number of history records
          //saved on its sd card
          mmOutStream.write(Constants.askForNumberHist);                    
            
          //Log.d("ConnectedThreadHI", "run()--> INVIATO " +new String(Constants.askForNumberHist)); 
        }
        catch(IOException e)
        {
          e.printStackTrace();
        }        
          
        while(transmittingHNR)
        {
          try
          {
            bytesRead = mmInStream.read(buffer);
  
            numberHR += new String(buffer, 0, bytesRead);
              
            Log.d("ConnectedThreadHI", "numberHR parziale: " +numberHR);
             if((numberHR.length() >= 4)&&(numberHR.substring(numberHR.length()-4, numberHR.length()-2).equalsIgnoreCase("%K")))
            {
               transmittingHNR = false;
               numberHR = numberHR.substring(0, numberHR.length()-4); //toggle %K and slash r slash n
               
               Utils.numberHR = Integer.valueOf(numberHR);

               if(mDownloadHandler != null)
               {
                 Log.d("ConnectedThreadHI", "run()--> sending TOTAL_HISTORY_NUM to download handler ");
                 Message msg = mDownloadHandler.obtainMessage(Constants.TOTAL_HISTORY_NUM);
                 mDownloadHandler.sendMessage(msg);
               }
               
              Log.d("ConnectedThreadHI", "run()--> number of history records on sensor box sdcard: " +Utils.numberHR);
            }
          }
          //this exception happens when bluetooth connection fails
          catch(IOException ex)
          {
            ex.printStackTrace();
                  
            connectionLost();
            connectionFailed = true;
            
          try
          {
            if(mmSocket != null)
              mmSocket.close();
          }
          catch(IOException e2)
          {
            e2.printStackTrace();
          }
          
            break; //if connection fails, exit from while
          }
         catch(NumberFormatException e)
         {
           e.printStackTrace();
         }
        }
        
        //if infos lack of some information, comunicate it
      if(Constants.mMacAddress.equals(""))
      {
        sensorBoxMacNotRead();
        return;
      }
      
        if(connectionFailed)
          return;
        
        /* 3 - ASK for history data to sensor box */
        if(Utils.numberHR > 0)
        {
          try
          {    
            //sending of string to tell the sensor box to stop to collect and save real time data
            mmOutStream.write(Constants.askForTurnOffRealTime);
            //Log.d("ConnectedThreadHI", "run()--> SENT " +new String(Constants.askForTurnOffRealTime));
            
            Log.d("ConnectedThreadHI", "run()--> WAIT 200 millisec ");
          Thread.currentThread().sleep(200);

            //sending of  string to tell the sensor box that smartphone is ready to receive history data          
            mmOutStream.write(Constants.askForHistory);        
            Log.d("ConnectedThreadHI", "run()--> SENT " +new String(Constants.askForHistory));
            
            bytesRead = 0;
          }
          catch(IOException e)
          {
            e.printStackTrace();
            
            Log.d("ConnectedThreadHI", "run()--> IOException1");
          }
          catch (InterruptedException e1) 
          {
          e1.printStackTrace();
          
          Log.d("ConnectedThreadHI", "run()--> InterruptedException");
        }
  
          //listening on socket (for all the time the connection is up)
          while(mTransferON)
          {           
            try
            {                
              Log.d("ConnectedThreadHI", "run()--> bytesRead = "+bytesRead+ " buffer length = " +buffer.length+ " buffer length - bytesRead = " +(buffer.length-bytesRead));
              bytesRead += mmInStream.read(buffer, bytesRead, buffer.length-bytesRead);  //3rd parameter: the maximum number of bytes to store in buffer            

                //save on string buffer contents
                if(bytesRead != 0)
                {              
                  if((bytesRead >= 2) && (buffer[bytesRead-2] == 13) && (buffer[bytesRead-1] == 10)) // \r\n
                  {       
                    if((bytesRead >= 4) && (buffer[bytesRead-4] == Constants.endHistorySet[0]) && ((buffer[bytesRead-3]) == Constants.endHistorySet[1])) // %K
                    {
                      //create string array from buffer, last four bytes ('%' 'K' '\r' '\n') excluded
                      String[] historyRecordsStr = new String(buffer, 0, bytesRead-4).split("\r\n");
                        
                      //reset byte count on buffer
                      bytesRead = 0;
                        
                      mNumOfHistoryRecords = historyRecordsStr.length;
                      if(mNumOfHistoryRecords == 50)
                      {
                        new SaveHistoryTask().execute(historyRecordsStr);
                        
                        if(mDownloadHandler != null)
                        {
                          Log.d("ConnectedThreadHI", "run()--> update progress bar - sending UPDATE_PROGRESS to download handler");
                          //update progress bar 
                        Message msg = mDownloadHandler.obtainMessage(Constants.UPDATE_PROGRESS);
                        mDownloadHandler.sendMessage(msg);
                        }
                      }

                      String command = "";
                        
                    if(mNumOfHistoryRecords < 10)
                      command = new String(Constants.receivedRecordsNum)+"0"+String.valueOf(mNumOfHistoryRecords);
                    else
                      command = new String(Constants.receivedRecordsNum)+String.valueOf(mNumOfHistoryRecords);
                      
                    //inform sensor box of the number of records received (so sensor box can keep track of these record as sent)
                    mmOutStream.write( command.getBytes() );
                      
                    //Log.d("ConnectedThreadHI", "run()--> SENT " +new String(command.getBytes())); 
                    }
                    else if((bytesRead >= 5) && (buffer[bytesRead-5] == Constants.endHistory[0]) && (buffer[bytesRead-4] == Constants.endHistory[1]) && (buffer[bytesRead-3] == Constants.endHistory[2])) // %KK
                      {
                      //create string array from buffer, last five bytes ('%' 'K' 'K' '\r' '\n') excluded
                      String[] historyRecordsStr = new String(buffer, 0, bytesRead-5).split("\r\n");
                        
                      mNumOfHistoryRecords = historyRecordsStr.length;
                        
                      if(mNumOfHistoryRecords > 0)
                      {
                      new SaveHistoryTask().execute(historyRecordsStr);
                        
                      //update progress bar 
                      Message msg = mDownloadHandler.obtainMessage(Constants.FINISHED_HIST_DOWN);
                        mDownloadHandler.sendMessage(msg);
                            
                        String command = "";
                          
                      if(mNumOfHistoryRecords < 10)
                        command = new String(Constants.receivedRecordsNum)+"0"+String.valueOf(mNumOfHistoryRecords);
                      else
                        command = new String(Constants.receivedRecordsNum)+String.valueOf(mNumOfHistoryRecords);
                        
                      //inform sensor box of the number of records received (so sensor box can keep track of these record as sent)
                      mmOutStream.write( command.getBytes() );
                        
                      //Log.d("ConnectedThreadHI", "run()--> SENT " +new String(command.getBytes())); 
                      }
                    }
                    else
                    {
                      Log.d("ConnectedThreadHI", "run()--> update progress bar - Non so parsificare---------*****");
                    }
                  }             
                }    
            }
            //this exception happens when bluetooth connection falls
            catch(IOException ex)
            {
              ex.printStackTrace();
                
              Log.d("ConnectedThreadHI", "run()--> IOException2");
              
              connectionLost();
              connectionFailed = true;
              
              try
              {
                if(mmSocket != null)
                  mmSocket.close();
              }
              catch(IOException e2)
              {
                e2.printStackTrace();
              }
              
              break; //if connection fails, exit from while
            }
            catch(NumberFormatException e)
            {
              e.printStackTrace();
            }
          }
          Looper.loop();
        }
        else
        {
          Log.d("ConnectedThreadHI", "run()--> NO HISTORY records to download!");
          
          this.cancel(); //stop the thread
          
          //update progress bar 
        Message msg = mDownloadHandler.obtainMessage(Constants.NO_HIST_RECS);
          mDownloadHandler.sendMessage(msg);
        }
    }
    
    public void cancel()
    {
      mTransferON = false;
      
      try
      {
        //delayed socket closing; in this way while cycle can't read socket when this is closed
        new Handler().postDelayed(new CloseSocketDelayedRunnable(mmSocket), 1500);
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
    }  
  }
  
  private class CloseSocketDelayedRunnable implements Runnable
  {
    private final BluetoothSocket mSocket;
    
    public CloseSocketDelayedRunnable(BluetoothSocket socket)
    {
      mSocket = socket;
    }
    
    @Override
    public void run()
    {
      try
      {
        mSocket.close();
        
        Log.d("CloseSocketDelayedRunnable", "close socket");
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
    }
  };
    
  /******************** RIEMPIMENTO ARRAY VALORI ********************************************/
  
  public double[] fillValues(String[] values) throws NumberFormatException
  {
    double[] valuesArray = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
    
    //lat
    if(!values[4].equals(""))
      valuesArray[0] = Double.valueOf(values[4]);
    
    //lon
    if(!values[6].equals(""))
      valuesArray[1] = Double.valueOf(values[6]);

    //co
    if(!values[8].equals(""))
      valuesArray[2] = Double.valueOf(values[8]);            
    if(!values[9].equals(""))
      valuesArray[3] = Double.valueOf(values[9]);  
    if(!values[10].equals(""))
      valuesArray[4] = Double.valueOf(values[10]);
    if(!values[11].equals(""))
      valuesArray[5] = Double.valueOf(values[11]);

    //no2
    if(!values[12].equals(""))
      valuesArray[6] = Double.valueOf(values[12]);  
    if(!values[13].equals(""))
      valuesArray[7] = Double.valueOf(values[13]);
    
    //voc
    if(!values[14].equals(""))
      valuesArray[8] = Double.valueOf(values[14]);  
    
    //o3
    if(!values[15].equals(""))
      valuesArray[9] = Double.valueOf(values[15]);  
    
    //temp
    if(!values[16].equals(""))
      valuesArray[10] = Double.valueOf(values[16]);
    //hum
    if(!values[17].equals(""))
    {
      //Log.d("BluetootManager", "fillValues()--> " +values[16]);
      
      //to correct a possible bug of substring! do not remove
      int index = values[17].indexOf("<");
      if(index != -1)
        values[17] = values[17].substring(0, index);
      valuesArray[11] = Double.parseDouble(values[17]);
    }
    return valuesArray;
  }
  
  public class SaveHistoryTask extends AsyncTask<String[], Integer, Integer>
  {
    private DbManager mDbManager;
    private String mSourceSessionSeed = "";
    private int mSourceSessionNumber = 0;
    private int mSourcePointNumber = 0;  
    private SemanticSessionDetails mSemantic;
    private String mSemanticSessionSeed = "";
    private int mSemanticSessionNumber = 0;  
    private int mSemanticPointNumberStart = 0;
    private String mBoxMacAddr;
    
    double boxAcc = 0.0, boxBear = 0.0, boxSpeed = 0.0, boxAltitude = 0.0;
    int boxNumSat = 0;
    
    @Override
    protected Integer doInBackground(String[]... params) 
    {      
      //split history buffer in <hi> strings
      String[] historyRecordsStr = params[0];
      
      Log.d("SaveHistoryTask", "doInBackground()--> # received records: " +historyRecordsStr.length);

      mDbManager = DbManager.getInstance(null);

      for(int i = 0; i < historyRecordsStr.length; i++)
      {
        String msg = historyRecordsStr[i];
        
        //remove <hi> and </hi> tags
        int i1 = msg.indexOf(">");
        int i2 = msg.lastIndexOf("<");
        if((i1 != -1)&&(i2 != -1))
          msg = msg.substring(i1+1, i2); //in some cases, substring doens't remove final tag </hi>
              
        //Log.d("SaveHistoryTask", "msg post: " +msg);
        
        //Log.d("BluetoothManager", "saveHistoryRecordsOnDb()--> " +historyRecordsStr[i]);
        String[] values = msg.split(",");
        
        //from sensorbox firmware >= 1.18
        if(values.length == 26)
        {  
          //Log.d("SaveHistoryTask", "doInBackground()--> history data - fields number: " +values.length);
          
          long boxTs = 0;
          String gpsProvider = "";
          
          //if history records contains valid gps coordinates, then it contains also valid sensorbox timestamp
          if(values[3].equalsIgnoreCase("A"))
          {
            boxTs = Utils.getTsFromBoxTimestampFields(values[0], values[1]);
            gpsProvider = Constants.GPS_PROVIDERS[0]; //sensorbox gps provider
          }
          else
            gpsProvider = Constants.GPS_PROVIDERS[3]; //no gps data
          
          //if timestamp of actual history records is almost five minutes after timestamp of precedent history 
          //record, this is a new track. So I change current session Id and save it in new records from now
          if(Math.abs(boxTs - mPrecBoxTs) >= Constants.mHistoryTracksDistance)
          {
            String sessionId = String.valueOf(boxTs);
      
            mCurrentHistSessionId = sessionId;
            
            //Log.d("SaveHistoryTask", "doInBackground()--> new session id: " +mCurrentSessionId);
          }
          //else if this is first history records (mPrecBoxTs is zero) then save its timestamp as current session id
          else if(mPrecBoxTs == 0)
          {
            String sessionId = String.valueOf(boxTs);
        
            mCurrentHistSessionId = sessionId;
          }
          
          //save ts of actual timestamp 
          mPrecBoxTs = boxTs;
          
          Record newHistRec = null;
          
          mSourcePointNumber = Integer.valueOf(values[2]); //sinceOn field (also called sb_time_on)

          mSourceSessionSeed = values[19];
          mSourceSessionNumber = Integer.valueOf(values[18]);

          mSemantic = mDbManager.checkIfActualSourceIdBelongsToASemanticSessionEntry(mSourceSessionSeed, mSourceSessionNumber, mSourcePointNumber);

          if(mSemantic != null)
          {
            mSemanticSessionSeed = mSemantic.mSemanticSessionSeed;
            mSemanticSessionNumber = mSemantic.mSourceSessionNumber;
            mSemanticPointNumberStart = mSourcePointNumber - mSemantic.mPointNumberStart;
          }
          else
          {
            mSemanticSessionSeed = "";
            mSemanticSessionNumber = 0;
            mSemanticPointNumberStart = 0;
          }

          mBoxMacAddr = values[20];          
          if((values[20] != null)&&(values[20].length() == 12))
          {
            mBoxMacAddr = values[20].substring(0, 2)+":"+values[20].substring(2, 4)+":"+
                values[20].substring(4, 6)+":"+values[20].substring(6, 8)+":"+values[20].substring(8, 10)+
                ":"+values[20].substring(10);
          }
          
          try {
            boxAcc = Double.valueOf(values[22]);
          }catch(Exception e){e.printStackTrace();};
          try {
            boxBear = Double.valueOf(values[25]);
          }catch(Exception e){e.printStackTrace();};
          try {
            boxSpeed = Double.valueOf(values[24]);
          }catch(Exception e){e.printStackTrace();};
          try {
            boxAltitude = Double.valueOf(values[22]);
          }catch(Exception e){e.printStackTrace();};
          try {
            boxNumSat = Integer.valueOf(values[21]);
          }catch(Exception e){e.printStackTrace();};
          
          newHistRec = new Record(0, boxTs, fillValues(values), "offline_"+mCurrentHistSessionId, Constants.LOCALIZATION[1], gpsProvider, 0, new double[]{0.0, 0.0, 0.0}, 0, 
              mSourceSessionSeed, mSourceSessionNumber, mSourcePointNumber, mSemanticSessionSeed, mSemanticSessionNumber, mSemanticPointNumberStart, 
              0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 
              Double.valueOf(values[4]), Double.valueOf(values[6]), boxAcc, boxBear, 0.51 * boxSpeed, boxAltitude, boxNumSat, 
              0.0, 0.0, 0.0, 
              mBoxMacAddr);

          newHistRec.mUserData2 = Constants.mFirmwareVersion;
          newHistRec.mUserData3 = Constants.mMacAddress;
          newHistRec.mUniquePhoneId = Constants.mUniquePhoneId;
          newHistRec.mPhoneModel = Constants.mPhoneModel;
          
          mHistoryRecordsSerie.add(newHistRec);  
        }
        else
        {
          Log.d("SaveHistoryTask", "doInBackground()--> History record NOT valid!");
          Log.d("SaveHistoryTask", "doInBackground()--> msg lost: " +msg);
          Utils.lostHR++;
        }
      }
      
      Record[] recordsToSaveArray = new Record[mHistoryRecordsSerie.size()];      
      mHistoryRecordsSerie.toArray(recordsToSaveArray);
      
      int size = recordsToSaveArray.length;
      
      if(mDbManager.saveHistoryRecordsSerie(recordsToSaveArray))
      {
        //save received history records
        Utils.counterHR += size;
        //clear array to avoid duplicated records
        mHistoryRecordsSerie.clear();

        Log.d("SaveHistoryTask", "doInBackground()--> history records saved count: " +Utils.counterHR);
      }
      else
        Log.d("SaveHistoryTask", "doInBackground()--> error saving history records");
      
      return 1;
    }
    
    public double[] fillValues(String[] values) throws NumberFormatException
    {
      double[] valuesArray = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
      
      //lat
      if(!values[4].equals(""))
        valuesArray[0] = Double.valueOf(values[4]);
      
      //lon
      if(!values[6].equals(""))
        valuesArray[1] = Double.valueOf(values[6]);

      //co
      if(!values[8].equals(""))
        valuesArray[2] = Double.valueOf(values[8]);            
      if(!values[9].equals(""))
        valuesArray[3] = Double.valueOf(values[9]);  
      if(!values[10].equals(""))
        valuesArray[4] = Double.valueOf(values[10]);
      if(!values[11].equals(""))
        valuesArray[5] = Double.valueOf(values[11]);

      //no2
      if(!values[12].equals(""))
        valuesArray[6] = Double.valueOf(values[12]);  
      if(!values[13].equals(""))
        valuesArray[7] = Double.valueOf(values[13]);
      
      //voc
      if(!values[14].equals(""))
        valuesArray[8] = Double.valueOf(values[14]);  
      
      //o3
      if(!values[15].equals(""))
        valuesArray[9] = Double.valueOf(values[15]);  
      
      //temp
      if(!values[16].equals(""))
        valuesArray[10] = Double.valueOf(values[16]);
      //hum
      if(!values[17].equals(""))
      {
        //Log.d("BluetootManager", "fillValues()--> " +values[16]);
        
        //to correct a possible bug of substring! do not remove
        int index = values[17].indexOf("<");
        if(index != -1)
          values[17] = values[17].substring(0, index);
        valuesArray[11] = Double.parseDouble(values[17]);
      }
      return valuesArray;
    }
  }
}




Java Source Code List

android.UnusedStub.java
org.csp.everyaware.ColorHelper.java
org.csp.everyaware.Constants.java
org.csp.everyaware.Credits.java
org.csp.everyaware.ExtendedLatLng.java
org.csp.everyaware.Installation.java
org.csp.everyaware.KmlParser.java
org.csp.everyaware.ManageAccount.java
org.csp.everyaware.Options.java
org.csp.everyaware.Start.java
org.csp.everyaware.Utils.java
org.csp.everyaware.bluetooth.BluetoothBroadcastReceiver.java
org.csp.everyaware.bluetooth.BluetoothHistoryManager.java
org.csp.everyaware.bluetooth.BluetoothManager.java
org.csp.everyaware.bluetooth.BluetoothObject.java
org.csp.everyaware.db.AnnotatedRecord.java
org.csp.everyaware.db.DbManager.java
org.csp.everyaware.db.MapCluster.java
org.csp.everyaware.db.MarkerRecord.java
org.csp.everyaware.db.Record.java
org.csp.everyaware.db.SemanticSessionDetails.java
org.csp.everyaware.db.Track.java
org.csp.everyaware.facebooksdk.AsyncFacebookRunner.java
org.csp.everyaware.facebooksdk.DialogError.java
org.csp.everyaware.facebooksdk.FacebookError.java
org.csp.everyaware.facebooksdk.Facebook.java
org.csp.everyaware.facebooksdk.FbDialog.java
org.csp.everyaware.facebooksdk.Util.java
org.csp.everyaware.fragments.FragmentWizardStep0.java
org.csp.everyaware.fragments.FragmentWizardStep1.java
org.csp.everyaware.fragments.FragmentWizardStep2.java
org.csp.everyaware.gps.GpsTrackingService.java
org.csp.everyaware.internet.FacebookManager.java
org.csp.everyaware.internet.StoreAndForwardService.java
org.csp.everyaware.internet.TwitterLogin.java
org.csp.everyaware.internet.TwitterManager.java
org.csp.everyaware.offline.Graph.java
org.csp.everyaware.offline.Map.java
org.csp.everyaware.offline.MyTracks.java
org.csp.everyaware.offline.Tabs.java
org.csp.everyaware.tabactivities.Graph.java
org.csp.everyaware.tabactivities.Map.java
org.csp.everyaware.tabactivities.Monitor.java
org.csp.everyaware.tabactivities.Tabs.java