/**
* Global Sensor Networks (GSN) Source Code
* Copyright (c) 2006-2014, Ecole Polytechnique Federale de Lausanne (EPFL)
* <p/>
* This file is part of GSN.
* <p/>
* GSN 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.
* <p/>
* GSN 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.
* <p/>
* You should have received a copy of the GNU General Public License
* along with GSN. If not, see <http://www.gnu.org/licenses/>.
* <p/>
* File: gsn-tiny/src/tinygsn/model/wrappers/USBplugO3Wrapper.java
*
* @author Do Ngoc Hoan
*/
package com.nordicsemi.nrfUARTv2;
//import java.io.Serializable;
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;
import tinygsn.model.utils.WritableBT;
import tinygsn.model.wrappers.AbstractWrapper;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import tinygsn.beans.DataField;
import tinygsn.beans.DataTypes;
import tinygsn.beans.StaticData;
import tinygsn.beans.StreamElement;
import tinygsn.beans.WrapperConfig;
import tinygsn.model.wrappers.utils.AbstractSerialProtocol;
import tinygsn.model.wrappers.utils.OpenSWISSensor;
import tinygsn.services.WrapperService;
import tinygsn.utils.ToastUtils;
@TargetApi(18)
public class SerialBLEWrapper extends AbstractWrapper {
public SerialBLEWrapper(WrapperConfig wc) {
super(wc);
}
public SerialBLEWrapper() {
}
public static final String TAG = "SerialBLEWrapper";
public static final String[] FIELD_NAMES = new String[]{ "sensor", "modality", "measure"};
public static final Byte[] FIELD_TYPES = new Byte[]{DataTypes.VARCHAR, DataTypes.VARCHAR, DataTypes.DOUBLE};
private static final String[] FIELD_DESCRIPTION = new String[]{"sensor", "modality", "measure"};
private static final String[] FIELD_TYPES_STRING = new String[]{"varchar(20)", "varchar(32)", "double"};
public final Class<? extends WrapperService> getSERVICE() {
return SerialBLEService.class;
}
@Override
public DataField[] getOutputStructure() {
ArrayList<DataField> output = new ArrayList<DataField>();
for (int i = 0; i < FIELD_NAMES.length; i++)
output.add(new DataField(FIELD_NAMES[i], FIELD_TYPES_STRING[i],
FIELD_DESCRIPTION[i]));
return output.toArray(new DataField[]{});
}
@Override
public String[] getFieldList() {
return FIELD_NAMES;
}
@Override
public Byte[] getFieldType() {
return FIELD_TYPES;
}
@Override
public void runOnce() { }
public static class SerialBLEService extends WrapperService implements WritableBT {
public SerialBLEService() {
super("serialBTService");
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle b = intent.getBundleExtra("tinygsn.beans.config");
config = b.getParcelable("tinygsn.beans.config");
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
if (!config.isRunning()) {
am.cancel(PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
return;
}
long interval = 10;
try {
w = StaticData.getWrapperByName(config.getWrapperName());
w.updateWrapperInfo();
if (w.getDcDuration() > 0) {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter != null) {
if (!mBluetoothAdapter.isEnabled()) {
ToastUtils.showToastInUiThread(StaticData.globalContext, "The Bluetooth wrapper needs Bluetooth to be enabled.", Toast.LENGTH_LONG);
} else {
service_init();
mBluetoothAdapter.cancelDiscovery();
mLeDeviceListAdapter = new ArrayList<>();
mBluetoothAdapter.startLeScan(mLeScanCallback);
try { Thread.sleep(10*1000); } catch (InterruptedException e) {}
mBluetoothAdapter.stopLeScan(mLeScanCallback);
for (BluetoothDevice device : mLeDeviceListAdapter) {
mService.connect(device.getAddress());
cdl = new CountDownLatch(1);
cdl.await(60, TimeUnit.SECONDS);
mService.disconnect();
}
try {
LocalBroadcastManager.getInstance(this).unregisterReceiver(UARTStatusChangeReceiver);
} catch (Exception ignore) {
Log.e(TAG, ignore.toString());
}
unbindService(mServiceConnection);
mService.stopSelf();
mService = null;
}
}
}
interval = w.getDcInterval();
} catch (Exception e) {
Log.e("WrapperService["+this.getClass().getName()+"]", e.getMessage());
}
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000 * interval, PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
private CountDownLatch cdl;
private AbstractSerialProtocol sensor;
private ArrayList<BluetoothDevice> mLeDeviceListAdapter;
private UartService mService = null;
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
if (!mLeDeviceListAdapter.contains(device)) {
mLeDeviceListAdapter.add(device);
Log.i(TAG, "Found device: " + device.getAddress());
}
}
};
//UART service connected/disconnected
private ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder rawBinder) {
mService = ((UartService.LocalBinder) rawBinder).getService();
Log.d(TAG, "onServiceConnected mService= " + mService);
if (!mService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
}
}
public void onServiceDisconnected(ComponentName classname) {
//// mService.disconnect(mDevice);
mService = null;
}
};
private final BroadcastReceiver UARTStatusChangeReceiver = new BroadcastReceiver() {
private String buffer = "";
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
final Intent mIntent = intent;
//*********************//
if (action.equals(UartService.ACTION_GATT_CONNECTED)) {
Log.d(TAG, "UART_CONNECT_MSG");
}
//*********************//
if (action.equals(UartService.ACTION_GATT_DISCONNECTED)) {
Log.d(TAG, "UART_DISCONNECT_MSG");
cdl.countDown();
//mService.close();
}
//*********************//
if (action.equals(UartService.ACTION_GATT_SERVICES_DISCOVERED)) {
mService.enableTXNotification();
sensor = new OpenSWISSensor(SerialBLEService.this, mService.getAddress().replace(":","_"));
sensor.getMeasurements();
}
//*********************//
if (action.equals(UartService.ACTION_DATA_AVAILABLE)) {
final byte[] txValue = intent.getByteArrayExtra(UartService.EXTRA_DATA);
try {
buffer += new String(txValue, "UTF-8");
if (buffer.contains("\n")) {
String[] st = buffer.split("\n");
for (String s:st){
if (s.trim().isEmpty()) continue;
sensor.received(s);
}
}
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
//*********************//
if (action.equals(UartService.DEVICE_DOES_NOT_SUPPORT_UART)){
//"Device doesn't support UART. Disconnecting");
cdl.countDown();
// mService.disconnect();
}
}
};
private void service_init() {
Intent bindIntent = new Intent(this, UartService.class);
bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
LocalBroadcastManager.getInstance(this).registerReceiver(UARTStatusChangeReceiver, makeGattUpdateIntentFilter());
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(UartService.ACTION_GATT_CONNECTED);
intentFilter.addAction(UartService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(UartService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(UartService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(UartService.DEVICE_DOES_NOT_SUPPORT_UART);
return intentFilter;
}
@Override
public void write(byte[] b) {
mService.writeRXCharacteristic(b);
}
@Override
public void done() {
cdl.countDown();
}
@Override
public void publish(StreamElement se){
w.postStreamElement(se);
}
}
}