/**
*
* Copyright (c) 2009-2016 Freedomotic team http://freedomotic.com
*
* This file is part of Freedomotic
*
* This Program 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 2, or (at your option) any later version.
*
* This Program 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.
*
* You should have received a copy of the GNU General Public License along with
* Freedomotic; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
package com.freedomotic.plugins.devices.btspeechrecognition;
/*
* EchoServer is a threaded RFCOMM service with the specified UUID and name.
*/
import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.bluetooth.*;
/**
* @author Mauro Cicolella
*Adapted from original code by Andrew Davison
* ad@fivedots.coe.psu.ac.th, February 2011
*/
public class BTServer
extends Thread {
BTSpeechRecognition pluginRef;
// UUID and name of the echo service
private static final String UUID_STRING = "11111111111111111111111111111111";
// 32 hex digits which will become a 128 bit ID
private static final String SERVICE_NAME = "speechRecognition"; // use lowercase
private StreamConnectionNotifier server;
private ArrayList<ThreadedBTClientHandler> handlers;
private volatile boolean isRunning = false;
/**
*
* @param pluginRef
*/
public BTServer(BTSpeechRecognition pluginRef) {
this.pluginRef = pluginRef;
handlers = new ArrayList<ThreadedBTClientHandler>();
}
public void run() {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
closeDown();
}
});
try {
initDevice();
} catch (BluetoothStateException ex) {
// throws the exception to BTSpeechRecognition to raise a PluginStartupException
throw new RuntimeException();
}
createRFCOMMConnection();
processClients();
} // end of EchoServer()
private void initDevice() throws BluetoothStateException {
try { // make the server's device discoverable
LocalDevice local = LocalDevice.getLocalDevice();
pluginRef.pluginLog().info("Found local device: {}", local.getFriendlyName() + " with Bluetooth Address: " + local.getBluetoothAddress());
boolean res = local.setDiscoverable(DiscoveryAgent.GIAC);
pluginRef.pluginLog().info("Discoverability set: '{}'", res);
} catch (BluetoothStateException ex) {
// throws the exception to caller thread run()
throw ex;
}
} // end of initDevice()
private void createRFCOMMConnection() /*
* Create a RFCOMM connection notifier for the server, with the given UUID
* and name. This also creates a service record.
*/ {
try {
pluginRef.pluginLog().info("Start advertising ''{}'' service ...", SERVICE_NAME);
server = (StreamConnectionNotifier) Connector.open(
"btspp://localhost:" + UUID_STRING
+ ";name=" + SERVICE_NAME + ";authenticate=false");
/*
* for most devices, with authenticate=false there should be no need
* for pin pairing
*/
} catch (IOException e) {
pluginRef.pluginLog().error("Error creating RFCOMM connection for ", e);
}
} // end of createRFCOMMConnection()
/*
* Wait for client connections, creating a handler for each one
*
*/
private void processClients() {
isRunning = true;
try {
while (isRunning) {
pluginRef.pluginLog().info("Waiting for incoming connection...");
StreamConnection conn = server.acceptAndOpen();
/*
* wait for a client connection acceptAndOpen() also adds the
* service record to the device's SDDB, making the service
* visible to clients
*/
pluginRef.pluginLog().info("Connection requested...");
ThreadedBTClientHandler hand = new ThreadedBTClientHandler(conn, pluginRef);
// create client handler
handlers.add(hand);
hand.start();
}
} catch (IOException e) {
pluginRef.pluginLog().error(" ", e);
}
} // end of processClients()
/*
* Stop accepting any further client connections, and close down all the
* handlers.
*/
private void closeDown() {
pluginRef.pluginLog().info("Closing down server");
if (isRunning) {
isRunning = false;
try {
// close connection, and remove service record from SDDB
server.close();
} catch (IOException e) {
pluginRef.pluginLog().error(" ", e);
}
// close down all the handlers
for (ThreadedBTClientHandler hand : handlers) {
hand.closeDown();
}
handlers.clear();
}
}
}