mercoledì 7 maggio 2014

Bluetooth ed Android

Questa piccola applicazione interfaccia i sensori di Android  con un PC mediante Bluetooth.
In pratica viene avviata una connessione BT tra PC ed telefono e vengono passati i valori di azimuth, pitch e roll del telefono; dopo aver inviato la prima terna di valore il socket viene interrotto

Importanti: i due dispositivi devono essere gia' stati accoppiati in precedenza ed il BT deve essere gia' abilitato sul telefono


Lato Android
-------------------------------------------------
package com.luca.innocenti.btsensors;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import android.support.v7.app.ActionBarActivity;
import android.support.v4.app.Fragment;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.SensorEvent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.TextView;

@SuppressLint("NewApi")
public class MainActivity extends ActionBarActivity {

private static final String TAG = "BT";

//Bluetooth
public BluetoothAdapter mBluetoothAdapter;
public  BluetoothDevice mmDevice;
public BluetoothSocket mmSocket;
public OutputStream mmOutputStream;

//Sensori
public SensorManager mSensorManager;
    public Sensor mSensor;
    public double azimuth;
    public double pitch;
    public double roll;
    



@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);


setContentView(R.layout.activity_main);

if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}

//Ricerca BT
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
   if(mBluetoothAdapter == null) {
     Log.d(TAG,"No bluetooth adapter available");
   }

   if(!mBluetoothAdapter.isEnabled()) {
     startActivityForResult( new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 0);
   }

   Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
   if(pairedDevices.size() > 0) {
     for(BluetoothDevice device : pairedDevices) {
       if(device.getName().equals("debian-x40-0")) { //qui si deve mettere il nome BT del PC
        Log.d(TAG,device.getName()+" "+device.getAddress() );
       
         mmDevice = device;
         break;
       }
     }
   }
//apre connessione
   UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard //SerialPortService ID
   try {
mmSocket = mmDevice.createInsecureRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}    
   try {
mmSocket.connect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
   try {
mmOutputStream = mmSocket.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
   
   //sensori
    mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);  
   
    
}


private void send_string(final String dati)
{
for (int t=0;t<dati.length();t++)
{
try {
mmOutputStream.write(dati.charAt(t));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

private final SensorEventListener mListener = new SensorEventListener() {
//manda una terna di valori pitch,roll ed azimuth e poi termina l'applicazione
public void onSensorChanged(SensorEvent event) {
   azimuth = event.values[0];
           pitch = event.values[1];
           roll = event.values[2];
              
           send_string(Double.toString(azimuth));
           send_string("A");
           send_string(Double.toString(pitch));
           send_string("A");
           send_string(Double.toString(roll));
           send_string("A");
           
           try {
mmSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
           //termina l'applicazione dopo la prima lettura
           finish();
           moveTaskToBack(true);
           android.os.Process.killProcess(android.os.Process.myPid());

           
           }

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub

}
};
 
    @Override
   protected void onResume()
   {
       super.onResume();
       mSensorManager.registerListener(mListener, mSensor,SensorManager.SENSOR_DELAY_GAME);
   }

   @Override
   protected void onStop()
   {
       mSensorManager.unregisterListener(mListener);
       super.onStop();
   }

   @Override
   protected void onDestroy()
   {
       mSensorManager.unregisterListener(mListener);
       super.onDestroy();
   }

   @Override
public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {


public PlaceholderFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}


}
----------------------------------------------------

Lato PC (Python)
-----------------------------------------------------
from bluetooth import *

server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",PORT_ANY))
server_sock.listen(1)

port = server_sock.getsockname()[1]

uuid = "00001101-0000-1000-8000-00805F9B34FB"

advertise_service( server_sock, "SampleServer",
    service_id = uuid,
    service_classes = [ uuid, SERIAL_PORT_CLASS ],
    profiles = [ SERIAL_PORT_PROFILE ]
)


client_sock, client_info = server_sock.accept()
misura = ""

try:
    while True:
        data = client_sock.recv(1024)
        if len(data) == 0: break
        if data == 'A':
print misura
misura = ""
else:
misura = misura + data

except IOError:
    pass

client_sock.close()
server_sock.close()