Java tutorial
/* Copyright 2011-2013 Google Inc. * Copyright 2013 mike wakerly <opensource@hoho.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * Project home page: https://github.com/mik3y/usb-serial-for-android */ package com.hoho.android.usbserial.examples; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.AssetManager; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbManager; import android.os.Bundle; import android.util.Log; import android.widget.ArrayAdapter; import android.widget.ScrollView; import android.widget.TextView; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.wearable.MessageApi; import com.google.android.gms.wearable.Node; import com.google.android.gms.wearable.NodeApi; import com.google.android.gms.wearable.Wearable; import com.hoho.android.usbserial.driver.UsbSerialPort; import com.hoho.android.usbserial.util.SerialInputOutputManager; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.lang.reflect.Array; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.TreeSet; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import src.com.hoho.android.usbserial.examples.SVMGestureRecognition; import src.com.hoho.android.usbserial.examples.SVMLevelRecognition; import src.com.hoho.android.usbserial.examples.SVMRecognition; import weka.classifiers.Classifier; import weka.core.SerializationHelper; /** * @Author :Akshika Wijesundara */ public class SerialConsoleActivity extends Activity implements GoogleApiClient.ConnectionCallbacks { private static final String START_ACTIVITY = "/start_activity"; private static final String WEAR_MESSAGE_PATH = "/message"; static int g; private GoogleApiClient mApiClient; private ArrayAdapter<String> mAdapter; public static byte[] publicB; public static JSONObject configJson, varJson, mainConfig, devicesObject, deviceObject; public static int s; public static String deviceConfigPath, device_Name; private static int constellationNumber; int zeroCount = 0; String message = ""; public static Classifier getClassifierSVMG() { return classifierSVMG; } public static void setClassifierSVMG(Classifier classifierSVMG) { SerialConsoleActivity.classifierSVMG = classifierSVMG; } public static Classifier getClassifierSVMH() { return classifierSVMH; } public static void setClassifierSVMH(Classifier classifierSVMH) { SerialConsoleActivity.classifierSVMH = classifierSVMH; } public static Classifier getClassifierSVML() { return classifierSVML; } public static void setClassifierSVML(Classifier classifierSVML) { SerialConsoleActivity.classifierSVML = classifierSVML; } public static Classifier classifierSVMG; public static Classifier classifierSVMH; public static Classifier classifierSVML; public static int counter; // size of the queue passed to recognize the gesture static int numberOfGuestureInputs; // extrapolated to this amount static boolean updateGesture; public static SVMRecognition svm; public static SVMLevelRecognition svml; public static SVMGestureRecognition svmg; static PrintWriter out; static ArrayList<Integer> gestureRaw, gestureParse, gestureToWrite; static int stopSize; static int gestureSize; public static int gestureF; // These parameters are set based on the constellationNumber public static int NUMBER_OF_STATES_F1; public static int NUMBER_OF_STATES_F2; public static int NUMBER_OF_STATES_F3; // These parameters are set based on the flags set // Select training mode; static boolean levelTraining; static boolean horizontalTraining; static boolean gestureTraining; static String filenameFinal; // step2 train for levels & 2,3 fingers filenameFinal="VisualisationV1/level.csv"; // step3 train for horizontal filenameFinal="VisualisationV1/horizontal.csv"; static boolean daq; // true for daq static int numStates; // 0th state for background static int getDataForState; // current training state static int numOfDataItems; // number of training data per state static int numOfAquiredData; static int datai; static int numberOfdataperState; // number of training data per state static int currentGesture, acquiredData; static boolean recognize = !gestureTraining; // step 4 training for gestures static boolean acquireData; static int numberOfGestures; // max number of gestures //following are file names static String filenameIntermid; static int tempCount = 0; static String csvPathH; static String modelPathH; static String csvPathG; static String modelPathG; static String csvPathL; static String modelPathL; public static String mainConfigPath = "config"; public static String[] deviceNames; // Serial read // Serial read end private static int NUMBER_OF_INPUTS = 4; public int bufferInt[] = new int[24]; //change this number when necessary, this is a hard coded value( this has to be 2^E*S where number of E0) public int count = 0; public int bufferFilled; int[] bufferSerial = new int[NUMBER_OF_INPUTS]; private final String TAG = SerialConsoleActivity.class.getSimpleName(); /** * Driver instance, passed in statically via * {@link #show(Context, UsbSerialPort)}. * <p/> * <p/> * This is a devious hack; it'd be cleaner to re-create the driver using * arguments passed in with the {@link #startActivity(Intent)} intent. We * can get away with it because both activities will run in the same * process, and this is a simple demo. */ private static UsbSerialPort sPort = null; private TextView mTitleTextView; private TextView mDumpTextView; private ScrollView mScrollView; // private String message; private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); private SerialInputOutputManager mSerialIoManager; final SerialInputOutputManager.Listener mListener = new SerialInputOutputManager.Listener() { @Override public void onRunError(Exception e) { Log.d(TAG, "Runner stopped."); } @Override public void onNewData(final byte[] data) { SerialConsoleActivity.this.runOnUiThread(new Runnable() { @Override public void run() { try { SerialConsoleActivity.this.updateReceivedData(data); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }); } }; @Override public void onCreate(Bundle savedInstanceState) { try { initVariables(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } try { setAbsolutePath(); } catch (JSONException e) { e.printStackTrace(); } try { setConstellation(); } catch (JSONException e) { e.printStackTrace(); } try { setTraininginfo(); } catch (JSONException e) { e.printStackTrace(); } try { initGesture(); } catch (IOException e) { e.printStackTrace(); } try { svmInit(); } catch (Exception e) { e.printStackTrace(); } for (int i = 0; i < bufferInt.length; i++) { bufferInt[i] = 0; } initGoogleApiClient(); super.onCreate(savedInstanceState); setContentView(R.layout.serial_console); mTitleTextView = (TextView) findViewById(R.id.demoTitle); mDumpTextView = (TextView) findViewById(R.id.consoleText); mScrollView = (ScrollView) findViewById(R.id.demoScroller); } @Override protected void onPause() { super.onPause(); stopIoManager(); if (sPort != null) { try { sPort.close(); } catch (IOException e) { } sPort = null; } finish(); } @Override protected void onResume() { super.onResume(); Log.d(TAG, "Resumed, port=" + sPort); if (sPort == null) { mTitleTextView.setText("No serial device."); } else { final UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); UsbDeviceConnection connection = usbManager.openDevice(sPort.getDriver().getDevice()); if (connection == null) { mTitleTextView.setText("Opening device failed"); return; } try { sPort.open(connection); sPort.setParameters(57600, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); } catch (IOException e) { Log.e(TAG, "Error setting up device: " + e.getMessage(), e); mTitleTextView.setText("Error opening device: " + e.getMessage()); try { sPort.close(); } catch (IOException e2) { // Ignore. } sPort = null; return; } mTitleTextView.setText("Serial device: " + sPort.getClass().getSimpleName()); } onDeviceStateChange(); } private void stopIoManager() { if (mSerialIoManager != null) { Log.i(TAG, "Stopping io manager .."); mSerialIoManager.stop(); mSerialIoManager = null; } } private void startIoManager() { if (sPort != null) { Log.i(TAG, "Starting io manager .."); mSerialIoManager = new SerialInputOutputManager(sPort, mListener); mExecutor.submit(mSerialIoManager); } } private void onDeviceStateChange() { stopIoManager(); startIoManager(); } private void predict() throws InterruptedException { int[] data = new int[SVMRecognition.numberOfDataitems]; for (int i = 0; i < bufferSerial.length; i++) { data[i] = bufferSerial[i]; if (i < bufferSerial.length - 1) data[i + bufferSerial.length] = bufferSerial[i + 1] - bufferSerial[i]; } int horizontal = svm.getPrediction(data); int level = svml.getPrediction(data); // recognize gesture int state = level * 10 + horizontal; if (horizontal == 0) state = 0; gestureRaw.add(state); parseGesture(); if (updateGesture) { updateGesture = false; String text = "not initialized"; switch (g) { case 0: text = "ONE FINGER RIGHT SWIPE"; break; case 1: text = "ONE FINGER LEFT SWIPE"; break; case 2: text = "THREE FINGER SWIPE "; break; case 3: text = "TWO FINGER CUT"; break; case 4: text = "CURVE SWIPE"; break; } ; mDumpTextView.append(text + "\n"); mScrollView.smoothScrollTo(0, mDumpTextView.getBottom()); return; } } private void updateReceivedData(byte[] data) throws IOException, InterruptedException { int i = 0; int ct = 0; //varaible used in the serial data reading sendMessage(WEAR_MESSAGE_PATH, data); for (; i < data.length; i++) { int nn = new Byte(data[i]).intValue() & 0xFF; ; if (nn == 0) { zeroCount++; bufferFilled = 0; predict(); } else if (bufferFilled >= NUMBER_OF_INPUTS) { continue; } else { int k = ct / 3; if ((k & 2) == 0 && ct % 3 == 1) { bufferSerial[bufferFilled++] = nn; } ct++; } } } /** * Starts the activity, using the supplied driver instance. * * @param context */ static void show(Context context, UsbSerialPort port) { sPort = port; final Intent intent = new Intent(context, SerialConsoleActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY); context.startActivity(intent); } void svmInit() throws Exception { SVMRecognition.numberOfDataitems = 2 * NUMBER_OF_INPUTS - 1; SVMLevelRecognition.numberOfDataitems = 2 * NUMBER_OF_INPUTS - 1; svml = new SVMLevelRecognition(); AssetManager assetManager = getAssets(); classifierSVML = (Classifier) SerializationHelper.read(assetManager.open(SVMLevelRecognition.modelPath)); svml.init(); svm = new SVMRecognition(); classifierSVMH = (Classifier) SerializationHelper.read(assetManager.open(SVMRecognition.modelPath)); svm.init(); if (recognize) { SVMGestureRecognition.numberOfStates = numberOfGestures; SVMGestureRecognition.numberOfDataitems = numberOfGuestureInputs; svmg = new SVMGestureRecognition(); classifierSVMG = (Classifier) SerializationHelper .read(assetManager.open(SVMGestureRecognition.modelPath)); // should be called after training generation svmg.init(); } } static void initGesture() throws IOException { // Gesture Training output if (acquireData) { out = new PrintWriter((new FileWriter(filenameIntermid))); if (currentGesture == 0) { for (int i = 0; i < numberOfGuestureInputs; i++) { out.print("data" + i + ","); } out.println("gesture"); } // Gesture Training output end } // initKey(); gestureRaw = new ArrayList<Integer>(); gestureParse = new ArrayList<Integer>(); gestureToWrite = new ArrayList<Integer>(); } static void setConstellation() throws JSONException { JSONObject ports = configJson.getJSONObject("ConstellationConfig"); NUMBER_OF_INPUTS = ports.getInt("NUMBER_OF_INPUTS"); NUMBER_OF_STATES_F1 = ports.getInt("NUMBER_OF_STATES_F1"); NUMBER_OF_STATES_F2 = ports.getInt("NUMBER_OF_STATES_F2"); NUMBER_OF_STATES_F3 = ports.getInt("NUMBER_OF_STATES_F3"); numberOfGestures = ports.getInt("numberOfGestures"); } static void setTraininginfo() throws JSONException { if (levelTraining) { filenameFinal = csvPathL; numStates = configJson.getInt("ConstellationNumStatesL"); } if (horizontalTraining) { filenameFinal = csvPathH; numStates = configJson.getInt("ConstellationNumStatesH"); } if (gestureTraining) { filenameFinal = csvPathG; } } static void parseGesture() { int len = gestureRaw.size(); if (len >= stopSize) { boolean check = true; int finalState = gestureRaw.get(len - 1); for (int i = 0; i < stopSize; i++) { if (gestureRaw.get(len - 1 - i) != finalState) { check = false; break; } } if (check) { gestureParse.clear(); int c1 = 1, pstate = gestureRaw.get(0); if (pstate != 0) gestureParse.add(pstate); for (Integer state : gestureRaw) { if (c1 == 1 && state == pstate) continue; else { if (state != 0) gestureParse.add(state); pstate = state; c1 = 0; } } gestureRaw.clear(); while (gestureParse.size() >= 2 && gestureParse.get(gestureParse.size() - 1) == gestureParse.get(gestureParse.size() - 2)) { gestureParse.remove(gestureParse.size() - 1); } TreeSet<Integer> size = new TreeSet<Integer>(); for (Integer integer : gestureParse) { size.add(integer); } if (gestureParse.size() >= gestureSize && size.size() > 2) { System.err.println(gestureParse); gestureToWrite.clear(); int length = gestureParse.size(); // gestureToWrite size is always numberOfGuestureInputs int filled = 0; for (int i = 1; i <= length; i++) { int upto = (numberOfGuestureInputs - 1) * i / length; for (; filled <= upto; filled++) { gestureToWrite.add(gestureParse.get(i - 1)); } } if (recognize) { g = svmg.getPrediction(gestureToWrite); gestureF = g + 1; updateGesture = true; System.out.println("gesture: " + g); } } } } } public void initVariables() throws IOException, JSONException, java.text.ParseException { /*following code will read a json object and assign the values to the variables in the code. if you want to change some value. please open json file named configuration.json in data folder. Then it will be assigned in to the working code */ BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(getAssets().open("config/mainConfig.json"))); if (reader != null) Log.d(TAG, "Main Config file was open"); } catch (IOException e) { e.printStackTrace(); } String line = reader.readLine(); String temp = ""; while (line != null) { temp = temp + line; line = reader.readLine(); } mainConfig = new JSONObject(temp); devicesObject = mainConfig.getJSONObject("devices"); //devicesObject gets the JSON object which has the device names and the relative paths to the device config file(many devices) JSONArray s = devicesObject.names(); deviceNames = new String[s.length()]; for (int i = 0; i < s.length(); i++) { deviceNames[i] = s.getString(i); } device_Name = "ring"; deviceObject = devicesObject.getJSONObject(device_Name); //deviceObject gets the JSON object which has the device name and the relative path to the device config file(Single device) deviceConfigPath = deviceObject.getString("path"); //getting the path to the device config files deviceConfigPath = mainConfigPath + "/" + deviceConfigPath; //adding the relative path to the configuration folder's path try { reader = new BufferedReader(new InputStreamReader( getAssets().open("config/devices/" + device_Name + "/json/variables.json"))); if (reader != null) Log.d(TAG, "Config file was open"); } catch (IOException e) { e.printStackTrace(); } line = reader.readLine(); temp = ""; while (line != null) { temp = temp + line; line = reader.readLine(); } //getting the JsonObject and assigning it to the configJson varJson = new JSONObject(temp); filenameFinal = varJson.getString("filenameFinal"); filenameIntermid = varJson.getString("filenameIntermid"); csvPathG = varJson.getString("csvPathG"); csvPathH = varJson.getString("csvPathH"); csvPathL = varJson.getString("csvPathL"); modelPathG = varJson.getString("modelPathG"); modelPathH = varJson.getString("modelPathH"); modelPathL = varJson.getString("modelPathL"); //following is making the path to work properly depending on the constellation number numStates = varJson.getInt("numStates"); // 0th state for background acquiredData = varJson.getInt("acquiredData"); try { reader = new BufferedReader(new InputStreamReader(getAssets().open(deviceConfigPath))); if (reader != null) Log.d(TAG, "It worked!"); } catch (IOException e) { e.printStackTrace(); } line = reader.readLine(); temp = ""; while (line != null) { temp = temp + line; line = reader.readLine(); } //getting the JsonObject and assigning it to the configJson configJson = new JSONObject(temp); //below the variables will be assigned by the values saved in the Json Object constellationNumber = configJson.getInt("constellationNumber"); numberOfGuestureInputs = configJson.getInt("numberOfGuestureInputs"); updateGesture = configJson.getBoolean("updateGesture"); stopSize = configJson.getInt("stopSize"); gestureSize = configJson.getInt("gestureSize"); gestureF = configJson.getInt("gestureF"); levelTraining = configJson.getBoolean("levelTraining"); horizontalTraining = configJson.getBoolean("horizontalTraining"); gestureTraining = configJson.getBoolean("gestureTraining"); getDataForState = configJson.getInt("getDataForState"); // current training state numOfDataItems = configJson.getInt("numOfDataItems"); // number of training data per state numOfAquiredData = configJson.getInt("numOfAquiredData"); datai = configJson.getInt("datai"); numberOfdataperState = configJson.getInt("numberOfdataperState"); // number of training data per state currentGesture = configJson.getInt("currentGesture"); } private static void setAbsolutePath() throws JSONException { //here are the absolute path values for the models and csv files filenameIntermid = "config/devices/" + device_Name + "/csv/" + filenameIntermid; csvPathH = "config/devices/" + device_Name + "/csv/" + csvPathH; csvPathL = "config/devices/" + device_Name + "/csv/" + csvPathL; csvPathG = "config/devices/" + device_Name + "/csv/" + csvPathG; modelPathH = "config/devices/" + device_Name + "/models/" + modelPathH; modelPathL = "config/devices/" + device_Name + "/models/" + modelPathL; modelPathG = "config/devices/" + device_Name + "/models/" + modelPathG; } private void initGoogleApiClient() { mApiClient = new GoogleApiClient.Builder(this).addApi(Wearable.API).build(); mApiClient.connect(); } @Override protected void onDestroy() { super.onDestroy(); mApiClient.disconnect(); } private void sendMessage(final String path, final byte[] text) throws InterruptedException { new Thread(new Runnable() { @Override public void run() { NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mApiClient).await(); for (Node node : nodes.getNodes()) { // MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage( // mApiClient, node.getId(), path, text.getBytes() ).await(); MessageApi.SendMessageResult result = Wearable.MessageApi .sendMessage(mApiClient, node.getId(), path, text).await(); if (!result.getStatus().isSuccess()) { Log.e("test", "error"); } else { Log.i("test", "success!! sent to: " + node.getDisplayName()); } } } }).start(); // Thread.sleep(50); } @Override public void onConnected(Bundle bundle) { try { sendMessage(START_ACTIVITY, "Start".getBytes()); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void onConnectionSuspended(int i) { } }