Skip to content

Commit

Permalink
Merge pull request #2 from kurtisnelson/ble
Browse files Browse the repository at this point in the history
BLE
  • Loading branch information
scottgwald committed Jul 30, 2014
2 parents 470c0ec + 3d55360 commit 004254d
Show file tree
Hide file tree
Showing 12 changed files with 226 additions and 58 deletions.
2 changes: 1 addition & 1 deletion WearScript/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ android {
buildToolsVersion "19.1.0"

defaultConfig {
minSdkVersion 15
minSdkVersion 19
targetSdkVersion 19
}
}
Expand Down
3 changes: 3 additions & 0 deletions WearScript/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
<uses-feature
android:name="android.hardware.camera.front.autofocus"
android:required="false" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false"/>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Expand Down
14 changes: 12 additions & 2 deletions WearScript/src/main/assets/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -1016,9 +1016,19 @@ function WearScript() {
this.group = function () {
return WSRAW.group();
}
this.bluetoothList = function (callback) {
this.beacon = function (rangeCb, enterCb, exitCb) {
rangeCb = this._funcfix(rangeCb);
enterCb = this._funcfix(enterCb);
exitCb = this._funcfix(exitCb);
WSRAW.beacon(this._funcwrap(rangeCb), this._funcwrap(enterCb), this._funcwrap(exitCb));
}
this.bluetoothList = function (callback, btle) {
callback = this._funcfix(callback);
WSRAW.bluetoothList(this._funcwrap(function (x) {callback(JSON.parse(x))}));
if(btle) {
WSRAW.bluetoothList(this._funcwrap(callback), true);
} else {
WSRAW.bluetoothList(this._funcwrap(function (x) {callback(JSON.parse(x))}), false);
}
}
this.bluetoothRead = function (address, callback) {
callback = this._funcfix(callback);
Expand Down
7 changes: 4 additions & 3 deletions WearScript/src/main/assets/init.js.min
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ WSRAW.warpGlassToPreviewH(this._funcwrap(function(c){a(JSON.parse(c))}))};this.w
h?(h=this._funcfix(h),WSRAW.cameraOn(a,c,b,!1,this._funcwrap(h))):WSRAW.cameraOn(a,c,b,!1)};this.cameraOnBackgroundUnsafe=function(a,c,b,h){c||(c=0);b||(maxwidth=0);h?(h=this._funcfix(h),WSRAW.cameraOn(a,c,b,!0,this._funcwrap(h))):WSRAW.cameraOn(a,c,b,!0)};this.cameraPhoto=function(a){a?(a=this._funcfix(a),WSRAW.cameraPhoto(this._funcwrap(a))):WSRAW.cameraPhoto()};this.cameraPhotoData=function(a){a?(a=this._funcfix(a),WSRAW.cameraPhotoData(this._funcwrap(a))):WSRAW.cameraPhoto()};this.cameraVideo=
function(a){a?(a=this._funcfix(a),WSRAW.cameraVideo(this._funcwrap(a))):WSRAW.cameraVideo()};this.cameraOff=function(){WSRAW.cameraOff()};this.activityCreate=function(){WSRAW.activityCreate()};this.activityDestroy=function(){WSRAW.activityDestroy()};this.wifiOn=function(a){a=this._funcfix(a);WSRAW.wifiOn(this._funcwrap(a))};this.wifiOff=function(){WSRAW.wifiOff()};this.wifiScan=function(){WSRAW.wifiScan()};this.serverConnect=function(a,c){c=this._funcfix(c);WSRAW.serverConnect(a,this._funcwrap(c))};
this.wake=function(){WSRAW.wake()};this.sound=function(a){WSRAW.sound(a)};this.gestureCallback=function(a,c){c=this._funcfix(c);WSRAW.gestureCallback(a,this._funcwrap(c))};this.speechRecognize=function(a,c){c=this._funcfix(c);WSRAW.speechRecognize(a,this._funcwrap(function(a){c(atob(a))}))};this.liveCardCreate=function(a,c){var b=[],h=Array.prototype.slice.call(arguments).slice(2);0==h.length&&(h.push("Open"),h.push(function(){WS.activityCreate()}),h.push("Shutdown"),h.push(function(){WS.shutdown()}));
for(var k=0;k<h.length;k+=2)b.push({label:h[k],callback:this._funcwrap(this._funcfix(h[k+1]))});WSRAW.liveCardCreate(a,c,JSON.stringify(b))};this.liveCardDestroy=function(){WSRAW.liveCardDestroy()};this.device=function(){return WSRAW.device()};this.groupDevice=function(){return WSRAW.groupDevice()};this.group=function(){return WSRAW.group()};this.bluetoothList=function(a){a=this._funcfix(a);WSRAW.bluetoothList(this._funcwrap(function(c){a(JSON.parse(c))}))};this.bluetoothRead=function(a,c){c=this._funcfix(c);
WSRAW.bluetoothRead(a,this._funcwrap(function(a){c(atob(a))}))};this.bluetoothWrite=function(a,c){WSRAW.bluetoothWrite(a,btoa(c))};this.bluetoothEnable=function(){WSRAW.bluetoothEnable()};this.bluetoothDisable=function(){WSRAW.bluetoothDisable()};this.bluetoothBond=function(a,c){WSRAW.bluetoothBond(a,c)};this.bluetoothDiscover=function(a){a=this._funcfix(a);WSRAW.bluetoothDiscover(this._funcwrap(function(c){a(JSON.parse(c))}))};this.pebbleSetTitle=function(a,c){WSRAW.pebbleSetTitle(a,c)};this.pebbleSetSubtitle=
function(a,c){WSRAW.pebbleSetSubtitle(a,c)};this.pebbleSetBody=function(a,c){WSRAW.pebbleSetBody(a,c)};this.pebbleVibe=function(a){WSRAW.pebbleVibe(a)};this.control=function(a,c){c||(c=!1);WSRAW.control(a,c)};this.picarus=function(a,c,b){b=this._funcfix(b);WSRAW.picarus(a,c,this._funcwrap(function(a){b(atob(a))}))};this.picarusStream=function(a,c){c=this._funcfix(c);WSRAW.picarusStream(a,this._funcwrap(function(a){c(atob(a))}))}}WS=new WearScript;
for(var k=0;k<h.length;k+=2)b.push({label:h[k],callback:this._funcwrap(this._funcfix(h[k+1]))});WSRAW.liveCardCreate(a,c,JSON.stringify(b))};this.liveCardDestroy=function(){WSRAW.liveCardDestroy()};this.device=function(){return WSRAW.device()};this.groupDevice=function(){return WSRAW.groupDevice()};this.group=function(){return WSRAW.group()};this.beacon=function(a,c,b){a=this._funcfix(a);c=this._funcfix(c);b=this._funcfix(b);WSRAW.beacon(this._funcwrap(a),this._funcwrap(c),this._funcwrap(b))};this.bluetoothList=
function(a,c){a=this._funcfix(a);c?WSRAW.bluetoothList(this._funcwrap(a),!0):WSRAW.bluetoothList(this._funcwrap(function(b){a(JSON.parse(b))}),!1)};this.bluetoothRead=function(a,c){c=this._funcfix(c);WSRAW.bluetoothRead(a,this._funcwrap(function(a){c(atob(a))}))};this.bluetoothWrite=function(a,c){WSRAW.bluetoothWrite(a,btoa(c))};this.bluetoothEnable=function(){WSRAW.bluetoothEnable()};this.bluetoothDisable=function(){WSRAW.bluetoothDisable()};this.bluetoothBond=function(a,c){WSRAW.bluetoothBond(a,
c)};this.bluetoothDiscover=function(a){a=this._funcfix(a);WSRAW.bluetoothDiscover(this._funcwrap(function(c){a(JSON.parse(c))}))};this.pebbleSetTitle=function(a,c){WSRAW.pebbleSetTitle(a,c)};this.pebbleSetSubtitle=function(a,c){WSRAW.pebbleSetSubtitle(a,c)};this.pebbleSetBody=function(a,c){WSRAW.pebbleSetBody(a,c)};this.pebbleVibe=function(a){WSRAW.pebbleVibe(a)};this.control=function(a,c){c||(c=!1);WSRAW.control(a,c)};this.picarus=function(a,c,b){b=this._funcfix(b);WSRAW.picarus(a,c,this._funcwrap(function(a){b(atob(a))}))};
this.picarusStream=function(a,c){c=this._funcfix(c);WSRAW.picarusStream(a,this._funcwrap(function(a){c(atob(a))}))}}WS=new WearScript;
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class ScriptView extends WebView implements SurfaceHolder.Callback, Direc
setWebChromeClient(new WebChromeClient() {
public boolean onConsoleMessage(ConsoleMessage cm) {
String msg = cm.message() + " -- From line " + cm.lineNumber() + " of " + cm.sourceId();
Log.w("WearScriptWebView", msg);
Log.w(TAG, msg);
Utils.eventBusPost(new SendEvent("log", "WebView: " + msg));
return true;
}
Expand Down Expand Up @@ -156,6 +156,12 @@ public void draw2() {
}
}

@Override
public void loadUrl(String url) {
//Log.d(TAG, url); //really useful when writing new initjs stuff
super.loadUrl(url);
}

@Override
public void renderingPaused(SurfaceHolder surfaceHolder, boolean b) {
this.paused = b;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@
import com.dappervision.wearscript.events.WifiEvent;
import com.dappervision.wearscript.events.WifiScanEvent;
import com.dappervision.wearscript.managers.BarcodeManager;
import com.dappervision.wearscript.managers.BluetoothLEManager;
import com.dappervision.wearscript.managers.BluetoothManager;
import com.dappervision.wearscript.managers.CameraManager;
import com.dappervision.wearscript.managers.ConnectionManager;
import com.dappervision.wearscript.managers.EyeManager;
import com.dappervision.wearscript.managers.GestureManager;
import com.dappervision.wearscript.managers.IBeaconManager;
import com.dappervision.wearscript.managers.OpenCVManager;
import com.dappervision.wearscript.managers.PicarusManager;
import com.dappervision.wearscript.managers.WarpManager;
Expand Down Expand Up @@ -481,8 +483,22 @@ public void cardTree(String treeJS) {
}

@JavascriptInterface
public void bluetoothList(String callback) {
Utils.eventBusPost(new CallbackRegistration(BluetoothManager.class, callback).setEvent(BluetoothManager.LIST));
public void beacon(String range, String enter, String exit) {
if(range != "null")
Utils.eventBusPost(new CallbackRegistration(IBeaconManager.class, range).setEvent(IBeaconManager.RANGE_NOTIFICATION));
if(enter != "null")
Utils.eventBusPost(new CallbackRegistration(IBeaconManager.class, enter).setEvent(IBeaconManager.ENTER_REGION));
if(exit != "null")
Utils.eventBusPost(new CallbackRegistration(IBeaconManager.class, exit).setEvent(IBeaconManager.EXIT_REGION));
}

@JavascriptInterface
public void bluetoothList(String callback, boolean btle) {
if(!btle) {
Utils.eventBusPost(new CallbackRegistration(BluetoothManager.class, callback).setEvent(BluetoothManager.LIST));
}else{
Utils.eventBusPost(new CallbackRegistration(BluetoothLEManager.class, callback).setEvent(BluetoothLEManager.LIST));
}
}

@JavascriptInterface
Expand All @@ -500,6 +516,11 @@ public void bluetoothRead(String device, String callback) {
Utils.eventBusPost(new CallbackRegistration(BluetoothManager.class, callback).setEvent(BluetoothManager.READ + device));
}

@JavascriptInterface
public void bluetoothLeRead(String device, String callback) {
Utils.eventBusPost(new CallbackRegistration(BluetoothLEManager.class, callback).setEvent(BluetoothLEManager.READ + device));
}

@JavascriptInterface
public void bluetoothWrite(String address, String data) {
Utils.eventBusPost(new BluetoothWriteEvent(address, data));
Expand Down Expand Up @@ -588,7 +609,6 @@ private void requiresGDK() {
}

public static enum SENSOR {
IBEACON("ibeacon", -8),
PEBBLE_ACCELEROMETER("pebbleAccelerometer", -7),
BATTERY("battery", -3),
PUPIL("pupil", -2),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package com.dappervision.wearscript.managers;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;

import com.dappervision.wearscript.BackgroundService;

import java.util.concurrent.ConcurrentHashMap;

public class BluetoothLEManager extends Manager {
public static final String READ = "READ:";
public static final String LIST = "LESCAN";
static String TAG = "BluetoothManager";
private BluetoothAdapter mBluetoothAdapter;
protected ConcurrentHashMap<String, GattConnection> gatts;

public BluetoothLEManager(BackgroundService bs) {
super(bs);
gatts = new ConcurrentHashMap<String, GattConnection>();
BluetoothManager bluetoothManager = (BluetoothManager) service.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}

@Override
public void reset() {
super.reset();
scanOff();
}

@Override
public void shutdown() {
super.shutdown();
scanOff();
for(GattConnection connection : gatts.values()){
connection.close();
}
gatts.clear();
}


@Override
protected void registerCallback(String type, String jsFunction) {
super.registerCallback(type, jsFunction);
if (type.startsWith(READ)) {
scanOff();
String address = type.substring(READ.length());
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if(!gatts.containsKey(address)){
gatts.put(address, new GattConnection(jsFunction));
}
device.connectGatt(service, true, gatts.get(address));
}else if(type.equals(LIST)){
scanOn();
}

}

private void scanOff() {
if(mBluetoothAdapter != null)
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}

public void scanOn() {
mBluetoothAdapter.startLeScan(mLeScanCallback);
}

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
makeCall(LIST, bluetoothDevice.getAddress(), bluetoothDevice.getName());
}
};

private class GattConnection extends BluetoothGattCallback {
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;

private final String mCallback;
private int mConnectionState = STATE_DISCONNECTED;
private BluetoothGatt mGatt;

GattConnection(String callback) {
super();
mCallback = callback;
}

@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
mGatt = gatt;
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
gatt.discoverServices();

} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mConnectionState = STATE_DISCONNECTED;
}
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
mGatt = gatt;
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
makeCall(mCallback, stringBuilder.toString());
}
}

public void close() {
if(mGatt != null)
mGatt.close();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.dappervision.wearscript.dataproviders.DataPoint;
import com.dappervision.wearscript.dataproviders.DataProvider;
import com.dappervision.wearscript.dataproviders.GPSDataProvider;
import com.dappervision.wearscript.dataproviders.IBeaconDataProvider;
import com.dappervision.wearscript.dataproviders.NativeDataProvider;
import com.dappervision.wearscript.dataproviders.PebbleDataProvider;
import com.dappervision.wearscript.dataproviders.RemoteDataProvider;
Expand Down Expand Up @@ -54,8 +53,6 @@ else if (type == WearScript.SENSOR.BATTERY.id())
dp = new BatteryDataProvider(this, samplePeriod);
else if (type == WearScript.SENSOR.PEBBLE_ACCELEROMETER.id())
dp = new PebbleDataProvider(this, samplePeriod, type);
else if (type == WearScript.SENSOR.IBEACON.id())
dp = new IBeaconDataProvider(this, samplePeriod);
else
throw new RuntimeException("Invalid type: " + type);
registerProvider(type, dp);
Expand Down
Loading

0 comments on commit 004254d

Please sign in to comment.