package org.oobd.ui.android.bus;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.oobd.base.bus.OobdBus;
import org.oobd.base.port.OOBDPort;
import org.oobd.base.port.PortInfo;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Looper;
import android.util.Log;
import org.oobd.base.support.Onion;
import org.oobd.ui.android.application.OOBDApp;
public class ComPort implements OOBDPort {
InputStream inputStream;
OutputStream outputStream;
static ComPort myInstance = null;
Activity callingActivity;
BluetoothAdapter mBluetoothAdapter;
BluetoothDevice obdDevice;
BluetoothSocket serialPort;
String BTAddress = null;
Thread myThread;
OobdBus msgReceiver;
public static final UUID MY_UUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
// public InputStream getInputStream() {
// if (serialPort != null) {
// return inputStream;
// } else {
// return null;
// }
// }
//
// public OutputStream getOutputStream() {
// if (serialPort != null) {
// return outputStream;
// } else {
// return null;
// }
// }
public ComPort(Activity callingActivity, String BTAddress) {
myInstance = this;
this.BTAddress = BTAddress;
this.callingActivity = callingActivity;
// Looper.prepare();
}
public boolean connect(Onion options, OobdBus receiveListener) {
msgReceiver = receiveListener;
System.out.println("Starting Bluetooth Detection and Device Pairing");
if (mBluetoothAdapter == null) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Log.w(this.getClass().getSimpleName(),
"Bluetooth not supported.");
return false;
}
if (!mBluetoothAdapter.isEnabled()) {
Log.w(this.getClass().getSimpleName(),
"Bluetooth switched off.");
return false;
}
}
obdDevice = mBluetoothAdapter.getRemoteDevice(BTAddress);
if (obdDevice != null) { // Get a BluetoothSocket to connect
// with the given BluetoothDevice
try {
Log.v(this.getClass().getSimpleName(),
"Device " + obdDevice.getName());
java.lang.reflect.Method m = obdDevice.getClass().getMethod(
"createRfcommSocket", new Class[] { int.class });
// "createInsecureRfcommSocket", new Class[] { int.class });
serialPort = null;
serialPort = (BluetoothSocket) m.invoke(obdDevice, 1);
if (serialPort != null) {
try {
//mBluetoothAdapter.cancelDiscovery();
serialPort.connect();
Log.d("OOBD:Bluetooth", "Bluetooth connected");
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
OOBDApp.getInstance().displayToast(
"Bluetooth connected");
myThread = new Thread() {
@Override
public void run() {
byte[] buffer = new byte[1024]; // buffer store
// for the
// stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an
// exception occurs
Log.d("OOBD:Bluetooth", "receiver task runs");
while (!isInterrupted()) {
if (inputStream != null) {
try {
//first we need to make this call not blocking, otherways we could not end the thread in case of no incoming data..
if (inputStream.available()>0){
// Read from the InputStream
bytes = inputStream.read(buffer);
if (bytes > 0) {
Log.v(this.getClass().getSimpleName(),
"Debug: received something");
String recString=new String(buffer);
recString=recString.substring(0, bytes);
msgReceiver
.receiveString(recString);
}
}else{
try {
Thread.sleep(10);
} catch (InterruptedException e) {
break;
}
}
} catch (IOException e) {
}
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
}
Log.d("OOBD:Bluetooth", "receiver task interupted");
}
};
myThread.start();
return true;
} catch (IOException ex) {
Log.e(this.getClass().getSimpleName(),
"Error: Could not connect to socket.", ex);
OOBDApp.getInstance().displayToast(
"Bluetooth NOT connected!");
}
} else {
Log.e("OOBD:Bluetooth", "Bluetooth NOT connected!");
OOBDApp.getInstance().displayToast(
"Bluetooth NOT connected!");
if (serialPort != null) {
try {
serialPort.close();
} catch (IOException closeEx) {
}
}
return false;
}
// do not yet connect. Connect before calling the
// socket.
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
// public boolean available() {
// try {
// return inputStream != null && inputStream.available() > 0;
// } catch (IOException ex) {
// // broken socket: Close it..
// close();
// return false;
// }
// }
public String connectInfo(){
if (inputStream != null){
return "BT Connect to "+BTAddress;
}else{
return null;
}
}
public void close() {
Log.d("BT Socket", "Try to close socket");
if (myThread!=null){
myThread.interrupt();
try {
myThread.join();
} catch (InterruptedException e) {
}
myThread=null;
}
if (serialPort != null) {
try {
inputStream.close();
inputStream = null;
} catch (Exception e) {
e.printStackTrace();
}
try {
outputStream.close();
outputStream = null;
} catch (Exception e) {
e.printStackTrace();
}
// add delay between closing streams and socket itself
// appears as very helpful to avoid reconnection fault because of not properly
// closed previous connection
// found at http://stackoverflow.com/a/22769260
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
}
try {
serialPort.close();
serialPort = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static String getUrlFormat() {
return "bt://{connectid}";
}
public static PortInfo[] getPorts() {
System.out.println("Starting Bluetooth Detection and Device Pairing");
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter
.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Log.w("ComPort", "Bluetooth not supported.");
PortInfo[] BTDeviceSet = new PortInfo[1];
BTDeviceSet[0] = new PortInfo("", "No Devices paired :-(");
return BTDeviceSet;
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter
.getBondedDevices();
PortInfo[] BTDeviceSet = new PortInfo[pairedDevices.size()];
Log.v("ComPort", "Anzahl paired devices: "
+ pairedDevices.size());
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
int i = 0;
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a
// ListView
Log.d("OOBD:BluetoothIntiWorker", "Found Bluetooth Device: "
+ device.getName() + "=" + device.getAddress());
BTDeviceSet[i] = new PortInfo(device.getAddress(),
device.getName());
i++;
}
}
return BTDeviceSet;
}
public void attachShutDownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Inside Add Shutdown Hook");
close();
System.out.println("Serial line closed");
}
});
System.out.println("Shut Down Hook Attached.");
}
public synchronized void write(String s) {
Log.d("OOBD:Comport", "Write something ");
if (serialPort != null) {
try {
serialPort.getOutputStream().write(s.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.err.println("NO comhandle:" + s);
}
}
public int adjustTimeOut(int originalTimeout) {
// leave the original timeout unchanged
return originalTimeout;
}
}