Skip to content

Commit c11c511

Browse files
committed
First commit
0 parents  commit c11c511

File tree

7 files changed

+403
-0
lines changed

7 files changed

+403
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License
2+
3+
Copyright (c) 2013 Stereolux. http://www.stereolux.org
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
## Cordovarduino
2+
3+
Cordovarduino is a Cordova/Phonegap plugin that enable you to use serial communication from an Android device to a serial over USB capable one.
4+
5+
### Context
6+
This work was made during an art residency hosted at the [Stereolux, Laboratoire Arts et Technologies](http://www.stereolux.org/laboratoire-arts-et-technologies/archives) with [Coup de foudre](https://www.facebook.com/coup.defoudre.716) and [Xavier Seignard](http://drangies.fr).
7+
8+
The goal was to create a tablet app to control a [tesla coil](http://www.youtube.com/watch?v=X2elQ6RR7lw) with an [Arduino](http://arduino.cc). The chosen technology ([Cordova](http://cordova.io)) had no capabilities to handle such serial over usb communication.
9+
10+
### Install it
11+
From the root folder of your cordova project, run :
12+
```
13+
cordova plugin add https://github.com/xseignard/cordovarduino
14+
```
15+
16+
### How to use it
17+
Thanks to [usb-serial-for-android](https://github.com/mik3y/usb-serial-for-android) library, you can communicate with CDC, FTDI, Arduino and other devices. Here is the Cordova plugin API.
18+
19+
Because you're polite, first request the permission to use the serial port to the system:
20+
```js
21+
serial.requestPermission(function success(), function error());
22+
```
23+
You can now open the serial port:
24+
```js
25+
serial.open(opts, function success(), function error());
26+
```
27+
`opts` is a JSON object with the following properties:
28+
29+
- baudRate: defaults to 9600
30+
- dataBits: defaults to 8
31+
- stopBits: defaults to 1
32+
- parity: defaults to 0
33+
34+
You're now able to read and write:
35+
```js
36+
serial.write(function success(), function error());
37+
serial.read(data, function success(), function error());
38+
```
39+
`data` is the string representation to be written to the serial port.
40+
41+
And finally close the port:
42+
```js
43+
serial.close(function success(), function error())
44+
```
45+
46+
### Example
47+
48+
A callback-ish example.
49+
50+
```js
51+
var errorCallback = function(message) {
52+
alert('Error: ' + message);
53+
};
54+
55+
serial.requestPermission(
56+
function(successMessage) {
57+
serial.open(
58+
{baudRate: 9600},
59+
function(successMessage) {
60+
serial.write(
61+
'1',
62+
function(successMessage) {
63+
alert(successMessage);
64+
},
65+
errorCallback
66+
);
67+
},
68+
errorCallback
69+
);
70+
},
71+
errorCallback
72+
);
73+
```

lib/cordova-3.1.0.jar

286 KB
Binary file not shown.

lib/usbseriallibrary.jar

38.2 KB
Binary file not shown.

plugin.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
4+
id="org.stereolux.cordova.serial"
5+
version="0.0.1">
6+
<name>Serial</name>
7+
<description>Cordova plugin to communicate with the android USB serial port</description>
8+
<license>MIT</license>
9+
<keywords>serial,arduino</keywords>
10+
11+
<!-- js module -->
12+
<js-module src="www/serial.js" name="Serial">
13+
<clobbers target="window.serial" />
14+
</js-module>
15+
16+
<!-- android -->
17+
<platform name="android">
18+
<config-file target="res/xml/config.xml" parent="/*">
19+
<feature name="Serial">
20+
<param name="android-package" value="org.stereolux.cordova.serial.Serial"/>
21+
</feature>
22+
</config-file>
23+
<source-file src="src/android/org/stereolux/cordova/serial/Serial.java" target-dir="src/org/stereolux/cordova/serial" />
24+
</platform>
25+
</plugin>
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
package org.stereolux.cordova.serial;
2+
3+
import java.io.IOException;
4+
import java.util.List;
5+
6+
import org.apache.cordova.CallbackContext;
7+
import org.apache.cordova.CordovaPlugin;
8+
import org.json.JSONArray;
9+
import org.json.JSONException;
10+
import org.json.JSONObject;
11+
12+
import android.app.PendingIntent;
13+
import android.content.Context;
14+
import android.content.Intent;
15+
import android.hardware.usb.UsbDevice;
16+
import android.hardware.usb.UsbDeviceConnection;
17+
import android.hardware.usb.UsbManager;
18+
import android.util.Log;
19+
20+
import com.hoho.android.usbserial.driver.UsbSerialDriver;
21+
import com.hoho.android.usbserial.driver.UsbSerialPort;
22+
import com.hoho.android.usbserial.driver.UsbSerialProber;
23+
24+
/**
25+
* Cordova plugin to communicate with the android serial port
26+
* @author Xavier Seignard <[email protected]>
27+
* @version 0.0.1
28+
*/
29+
public class Serial extends CordovaPlugin {
30+
// logging tag
31+
private final String TAG = Serial.class.getSimpleName();
32+
// actions definitions
33+
public static final String ACTION_REQUEST_PERMISSION = "requestPermission";
34+
public static final String ACTION_OPEN = "openSerial";
35+
public static final String ACTION_READ = "readSerial";
36+
public static final String ACTION_WRITE = "writeSerial";
37+
public static final String ACTION_CLOSE = "closeSerial";
38+
// flag to check if the user has permitted to use the USB/serial port
39+
private boolean permitted = false;
40+
// UsbManager instance to deal with permission and opening
41+
private UsbManager manager;
42+
// The current driver that handle the serial port
43+
private UsbSerialDriver driver;
44+
// The serial port that will be used in this plugin
45+
private UsbSerialPort port;
46+
47+
/**
48+
* Overridden execute method
49+
* @param action the string representation of the action to execute
50+
* @param args
51+
* @param callbackContext the cordova {@link CallbackContext}
52+
* @return true if the action exists, false otherwise
53+
* @throws JSONException if the args parsing fails
54+
*/
55+
@Override
56+
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
57+
Log.d(TAG, "Action: " + action);
58+
JSONObject arg_object = args.optJSONObject(0);
59+
// request permission
60+
if (ACTION_REQUEST_PERMISSION.equals(action)) {
61+
requestPermission(callbackContext);
62+
return true;
63+
}
64+
// open serial port
65+
else if (ACTION_OPEN.equals(action)) {
66+
JSONObject opts = arg_object.has("opts")? arg_object.getJSONObject("opts") : new JSONObject();
67+
openSerial(opts, callbackContext);
68+
return true;
69+
}
70+
// write to the serial port
71+
else if (ACTION_WRITE.equals(action)) {
72+
String data = arg_object.getString("data");
73+
writeSerial(data, callbackContext);
74+
return true;
75+
}
76+
// read on the serial port
77+
else if (ACTION_READ.equals(action)) {
78+
readSerial(callbackContext);
79+
return true;
80+
}
81+
// close the serial port
82+
else if (ACTION_CLOSE.equals(action)) {
83+
closeSerial(callbackContext);
84+
return true;
85+
}
86+
// the action doesn't exist
87+
return false;
88+
}
89+
90+
/**
91+
* Request permission the the user for the app to use the USB/serial port
92+
* @param callbackContext the cordova {@link CallbackContext}
93+
*/
94+
private void requestPermission(final CallbackContext callbackContext) {
95+
cordova.getThreadPool().execute(new Runnable() {
96+
public void run() {
97+
// get UsbManager from Android
98+
manager = (UsbManager) cordova.getActivity().getSystemService(Context.USB_SERVICE);
99+
// find all available drivers from attached devices.
100+
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
101+
if (!availableDrivers.isEmpty()) {
102+
// get the first one as there is a high chance that there is no more than one usb device attached to your android
103+
driver = availableDrivers.get(0);
104+
UsbDevice device = driver.getDevice();
105+
// create the intent that will be used to get the permission
106+
PendingIntent pendingIntent = PendingIntent.getBroadcast(cordova.getActivity(), 0, new Intent("USB_PERMISSION"), 0);
107+
manager.requestPermission(device, pendingIntent);
108+
if (manager.hasPermission(device)) {
109+
permitted = true;
110+
Log.d(TAG, "Permission to connect to the device was accepted!");
111+
callbackContext.success("Permission to connect to the device was accepted!");
112+
}
113+
else {
114+
Log.d(TAG, "Permission to connect to the device was denied!");
115+
callbackContext.error("Permission to connect to the device was denied!");
116+
}
117+
}
118+
else {
119+
// no available drivers
120+
Log.d(TAG, "No device found!");
121+
callbackContext.error("No device found!");
122+
}
123+
}
124+
});
125+
}
126+
127+
/**
128+
* Open the serial port
129+
* @param opts a {@link JSONObject} containing the connection paramters
130+
* @param callbackContext the cordova {@link CallbackContext}
131+
*/
132+
private void openSerial(final JSONObject opts, final CallbackContext callbackContext) {
133+
cordova.getThreadPool().execute(new Runnable() {
134+
public void run() {
135+
if (permitted) {
136+
UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
137+
if (connection != null) {
138+
// get first port and open it
139+
port = driver.getPorts().get(0);
140+
try {
141+
port.open(connection);
142+
// get connection params or the default values
143+
int baudRate = opts.has("baudRate") ? opts.getInt("baudRate") : 9600;
144+
int dataBits = opts.has("dataBits") ? opts.getInt("dataBits") : UsbSerialPort.DATABITS_8;
145+
int stopBits = opts.has("stopBits") ? opts.getInt("stopBits") : UsbSerialPort.STOPBITS_1;
146+
int parity = opts.has("parity") ? opts.getInt("parity") : UsbSerialPort.PARITY_NONE;
147+
port.setParameters(baudRate, dataBits, stopBits, parity);
148+
}
149+
catch (IOException e) {
150+
// deal with error
151+
Log.d(TAG, e.getMessage());
152+
callbackContext.error(e.getMessage());
153+
}
154+
catch (JSONException e) {
155+
// deal with error
156+
Log.d(TAG, e.getMessage());
157+
callbackContext.error(e.getMessage());
158+
}
159+
Log.d(TAG, "Serial port opened!");
160+
callbackContext.success("Serial port opened!");
161+
}
162+
else {
163+
Log.d(TAG, "Cannot connect to the device!");
164+
callbackContext.error("Cannot connect to the device!");
165+
}
166+
}
167+
else {
168+
Log.d(TAG, "Permission to connect to the device was denied!");
169+
callbackContext.error("Permission to connect to the device was denied!");
170+
}
171+
}
172+
});
173+
}
174+
175+
/**
176+
* Write on the serial port
177+
* @param data the {@link String} representation of the data to be written on the port
178+
* @param callbackContext the cordova {@link CallbackContext}
179+
*/
180+
private void writeSerial(final String data, final CallbackContext callbackContext) {
181+
cordova.getThreadPool().execute(new Runnable() {
182+
public void run() {
183+
Log.d(TAG, data);
184+
try {
185+
byte[] buffer = data.getBytes();
186+
port.write(buffer, 1000);
187+
callbackContext.success();
188+
} catch (IOException e) {
189+
// deal with error
190+
Log.d(TAG, e.getMessage());
191+
callbackContext.error(e.getMessage());
192+
}
193+
}
194+
});
195+
}
196+
197+
/**
198+
* Read on the serial port
199+
* @param callbackContext the {@link CallbackContext}
200+
*/
201+
private void readSerial(final CallbackContext callbackContext) {
202+
cordova.getThreadPool().execute(new Runnable() {
203+
public void run() {
204+
try {
205+
byte buffer[] = new byte[16];
206+
int numBytesRead = port.read(buffer, 1000);
207+
callbackContext.success(numBytesRead);
208+
}
209+
catch (IOException e) {
210+
// deal with error
211+
Log.d(TAG, e.getMessage());
212+
callbackContext.error(e.getMessage());
213+
}
214+
}
215+
});
216+
}
217+
218+
/**
219+
* Close the serial port
220+
* @param callbackContext the cordova {@link CallbackContext}
221+
*/
222+
private void closeSerial(final CallbackContext callbackContext) {
223+
cordova.getThreadPool().execute(new Runnable() {
224+
public void run() {
225+
try {
226+
port.close();
227+
callbackContext.success();
228+
} catch (IOException e) {
229+
// deal with error
230+
Log.d(TAG, e.getMessage());
231+
callbackContext.error(e.getMessage());
232+
}
233+
}
234+
});
235+
}
236+
}

0 commit comments

Comments
 (0)