Skip to content

Commit

Permalink
Initial add of files for plugin.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Musyj committed Mar 8, 2014
1 parent 301dd62 commit f9ecd62
Show file tree
Hide file tree
Showing 5 changed files with 300 additions and 0 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,24 @@ phonegap-estimote-plugin
========================

PhoneGap plugin to interface with Estimote SDK

Installation
------------
Check out PhoneGap CLI [docs](http://docs.phonegap.com/en/3.0.0/guide_cli_index.md.html#The%20Command-line%20Interface) before starting out.

To install this plugin on 3.0.0, use the phonegap CLI.

```
phonegap local plugin add https://github.com/jmusyj/phonegap-estimote-plugin.git
```

Remember to build the project afterwards.

Usage
-----

The plugin is accessible from `window.estimote`.

License
-------
TODO
40 changes: 40 additions & 0 deletions plugin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="com.phonegap.plugins.estimote"
version="0.9">

<name>Estimote</name>

<description>
Allows access to Estimote API via JavaScript.
</description>

<engines>
<engine name="cordova" version=">=2.6.0" />
</engines>

<platform name="android">

<config-file target="res/xml/config.xml" parent="/*">
<feature name="Estimote">
<param name="android-package" value="org.apache.cordova.estimote.EstimotePlugin" />
</feature>
</config-file>

<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<service android:name="com.estimote.sdk.service.BeaconService" android:exported="false"/>
</config-file>

<js-module src="www/estimote.js" name="estimote">
<clobbers target="estimote" />
</js-module>

<source-file src="src/android/EstimotePlugin.java" target-dir="src/org/apache/cordova/estimote" />
<source-file src="src/android/BluetoothError.java" target-dir="src/org/apache/cordova/estimote" />

</platform>

</plugin>
26 changes: 26 additions & 0 deletions src/android/BluetoothError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.apache.cordova.bluetooth;

/**
* Container class for different error codes for Bluetooth.
* These are the codes passed to the JavaScript API's onError
* callback under <b>error.code</b>.
*
*/
public class BluetoothError
{
public static final int ERR_UNKNOWN = 0;
public static final int ERR_DISCOVERY_CANCELED = 1;
public static final int ERR_DISCOVERY_RESTARTED = 2;
public static final int ERR_PAIRING_IN_PROGRESS = 3;
public static final int ERR_UUID_FETCHING_IN_PROGRESS = 4;
public static final int ERR_CONNECTION_ALREADY_EXISTS = 5;
public static final int ERR_CONNECTING_IN_PROGRESS = 6;
public static final int ERR_CONNECTION_DOESNT_EXIST = 7;
public static final int ERR_CONNECTION_LOST = 8;
public static final int ERR_CONNECTING_FAILED = 9;
public static final int ERR_PAIRING_FAILED = 10;
public static final int ERR_UUID_FETCH_FAILED = 11;
public static final int ERR_BLUETOOTH_LOST = 12;
public static final int ERR_MANAGED_CONNECTION_LOST = 13;
public static final int ERR_DISCONNECTED = 14;
}
159 changes: 159 additions & 0 deletions src/android/EstimotePlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package org.apache.cordova.estimote;

import java.util.ArrayList;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import android.util.Log;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.annotation.TargetApi;

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class EstimotePlugin extends CordovaPlugin
{
private static final String LOG_TAG = "EstimotePlugin";

private static final String ACTION_START_RANGING = "startRanging";

/**
* Callback context for device ranging actions.
*/
private CallbackContext rangingCallback;

/**
* Is set to true when a ranging process is cancelled or a new one is started when
* there is a ranging process still in progress (cancels the old one).
*/
private boolean wasRangingCancelled;


/**
* Initialize the Plugin, Cordova handles this.
*
* @param cordova Used to get register Handler with the Context accessible from this interface
* @param view Passed straight to super's initialization.
*/
public void initialize(CordovaInterface cordova, CordovaWebView view)
{
super.initialize(cordova, view);
wasRangingCancelled = false;
}

/**
* Executes the given action.
*
* @param action The action to execute.
* @param args Potential arguments.
* @param callbackCtx Babby call home.
*/
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackCtx)
{
if(ACTION_START_RANGING.equals(action))
{
startRanging(args, callbackCtx);
}
else
{
Log.e(LOG_TAG, "Invalid Action[" + action + "]");
callbackCtx.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
}

return true;
}

private void startRanging(JSONArray args, final CallbackContext callbackCtx)
{
Log.d(LOG_TAG, "startRanging-method called");

try
{
BeaconManager beaconManager = new BeaconManager(cordova.getActivity().getBaseContext());
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
@Override
public void onBeaconsDiscovered(Region region, List<Beacon> beacons) {
Log.d(TAG, "Ranged beacons: " + beacons);
for(Beacon b: beacons) {
try {
String name = b.getName();
String address = b.getMacAddress();
String proximityUUID = b.getProximityUUID();
JSONObject device = new JSONObject();
device.put("name", name);
device.put("address", address);
device.put("proximityUUID", proximityUUID);

// Send one device at a time, keeping callback to be used again
if(callbackCtx != null) {
PluginResult result = new PluginResult(PluginResult.Status.OK, device);
result.setKeepCallback(true);
callbackCtx.sendPluginResult(result);
} else {
Log.e(LOG_TAG, "CallbackContext for discovery doesn't exist.");
}
} catch(JSONException e) {
if(callbackCtx != null) {
EstimotePlugin.this.error(callbackCtx,
e.getMessage(),
BluetoothError.ERR_UNKNOWN
);
callbackCtx = null;
}
}
}
}
});

beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
@Override
public void onServiceReady() {
try {
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS);
} catch (RemoteException e) {
Log.e(TAG, "Cannot start ranging", e);
}
}
});
}
catch(Exception e)
{
this.error(callbackCtx, e.getMessage(), BluetoothError.ERR_UNKNOWN);
}
}

/**
* Send an error to given CallbackContext containing the error code and message.
*
* @param ctx Where to send the error.
* @param msg What seems to be the problem.
* @param code Integer value as a an error "code"
*/
private void error(CallbackContext ctx, String msg, int code)
{
try
{
JSONObject result = new JSONObject();
result.put("message", msg);
result.put("code", code);

ctx.error(result);
}
catch(Exception e)
{
Log.e(LOG_TAG, "Error with... error raising, " + e.getMessage());
}
}

}
54 changes: 54 additions & 0 deletions www/estimote.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
var exec = require('cordova/exec');

/**
* Create a new instance of Estimote(Plugin).
*
* @class Estimote
* @classdesc EstimotePlugin for cordova 3.0.0+ (PhoneGap).
*/
var Estimote = function()
{
this.platforms = [ "android" ];
};

/**
* Start the device discovery process.
*
* @memberOf Estimote
*
* @param {Estimote~onDeviceDiscovered} onDeviceDiscovered Invoked when a device is found.
* @param {Estimote~onSuccess} onDiscoveryFinished Invoked when discovery finishes succesfully.
* @param {Estimote~onError} onError Invoked if there is an error, or the discovery finishes prematurely.
*/
Estimote.prototype.startRanging = function(onDeviceDiscovered, onRangingFinished, onError)
{
var timeout = function()
{
onError({ code: 9001, message: "Request timed out" });
}

this.timeout = setTimeout(timeout, 15000);

var self = this;
exec(function(result)
{
if(result === false)
{
clearTimeout(self.timeout);
onRangingFinished();
}
else
{
onDeviceDiscovered(result);
}
},
function(error)
{
clearTimeout(self.timeout);
onError(error);
},
"Estimote", "startRanging", []);
}

var bluetooth = new Bluetooth();
module.exports = bluetooth;

0 comments on commit f9ecd62

Please sign in to comment.