/*
* Copyright (C) 2014 OMRON Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package omron.HVC;
import java.util.ArrayList;
import org.deviceconnect.android.deviceplugin.hvc.BuildConfig;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.util.Log;
interface BleInterface {
abstract void connect(Context context, BluetoothDevice device);
abstract void disconnect();
abstract int setDeviceName(byte[] value);
abstract int getDeviceName(byte[] value);
}
/**
* HVC-C BLE Model<br>
* [Description]<br>
* HVC subclass, connects HVC to Bluetooth<br>
*
*/
public class HVC_BLE extends HVC implements BleInterface
{
/**
* DebugLog.
*/
static final boolean DEBUG_LOG = BuildConfig.DEBUG;
public static final int STATE_DISCONNECTED = 0;
public static final int STATE_CONNECTING = 1;
public static final int STATE_CONNECTED = 2;
public static final int STATE_BUSY = 3;
private int mStatus = STATE_DISCONNECTED;
private byte[] mtxName = null;
private ArrayList<Byte> mtxValue = null;
private HVCBleCallback mCallback = null;
private BluetoothDevice mBtDevice = null;
private BleDeviceService mService = null;
private static final String TAG = "HVC_BLE";
/**
* HVC_BLE constructor<br>
* [Description]<br>
* Set HVC_BLE to new to automatically connect to Bluetooth device specified with btDevice<br>
* @param mainAct Activity object<br>
*/
public HVC_BLE()
{
super();
mStatus = STATE_DISCONNECTED;
mtxValue = new ArrayList<Byte>();
}
/**
* HVC_BLE finalizer<br>
* [Description]<br>
* MUST be called when ending<br>
* @throws Throwable
*/
@Override
public void finalize() throws Throwable {
mStatus = STATE_DISCONNECTED;
if ( mService != null ) {
mService.close();
}
mService = null;
super.finalize();
}
/**
* HVC_BLE verify status<br>
* [Description]<br>
* Verify HVC_BLE device status<br>
* @return boolean true:function executable, false:function non-executable<br>
*/
@Override
public boolean IsBusy() {
// TODO Auto-generated method stub
if ( mStatus != STATE_CONNECTED ) {
return true;
}
return false;
}
/**
* Execute HVC functions<br>
* [Description]<br>
* Execute each HVC function. Store results in HVC_BLE.Result<br>
* @param inExec execution flag<br>
* @param outStatus HVC execution result status<br>
* @return int execution result error code <br>
*/
@Override
public int execute(final int inExec, final HVC_RES res)
{
if ( mBtDevice == null ) {
if (DEBUG_LOG) {
Log.d(TAG, "execute() : HVC_ERROR_NODEVICES");
}
return HVC_ERROR_NODEVICES;
}
if ( mService == null || mService.getmConnectionState() != BleDeviceService.STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "execute() : HVC_ERROR_DISCONNECTED");
}
return HVC_ERROR_DISCONNECTED;
}
if ( mStatus > STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "execute() : HVC_ERROR_BUSY");
}
return HVC_ERROR_BUSY;
}
mStatus = STATE_BUSY;
Thread t = new Thread() {
public void run() {
int nRet = HVC_NORMAL;
byte[] outStatus = new byte[1];
nRet = Execute(30000, inExec, outStatus, res);
if ( mStatus == STATE_BUSY ) {
mStatus = STATE_CONNECTED;
}
if ( mCallback != null ) {
mCallback.onPostExecute(nRet, outStatus[0]);
}
}
};
t.start();
if (DEBUG_LOG) {
Log.d(TAG, "execute() : HVC_NORMAL");
}
return HVC_NORMAL;
}
@Override
public int setParam(final HVC_PRM prm)
{
if ( mBtDevice == null ) {
if (DEBUG_LOG) {
Log.d(TAG, "setParam() : HVC_ERROR_NODEVICES");
}
return HVC_ERROR_NODEVICES;
}
if ( mService == null || mService.getmConnectionState() != BleDeviceService.STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "setParam() : HVC_ERROR_DISCONNECTED");
}
return HVC_ERROR_DISCONNECTED;
}
if ( mStatus > STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "setParam() : HVC_ERROR_BUSY");
}
return HVC_ERROR_BUSY;
}
mStatus = STATE_BUSY;
Thread t = new Thread() {
public void run() {
int nRet = HVC_NORMAL;
byte[] outStatus = new byte[1];
nRet = SetCameraAngle(10000, outStatus, prm);
if ( nRet == HVC_NORMAL && outStatus[0] == 0 ) {
nRet = SetThreshold(10000, outStatus, prm);
}
if ( nRet == HVC_NORMAL && outStatus[0] == 0 ) {
nRet = SetSizeRange(10000, outStatus, prm);
}
if ( nRet == HVC_NORMAL && outStatus[0] == 0 ) {
nRet = SetFaceDetectionAngle(10000, outStatus, prm);
}
if ( mStatus == STATE_BUSY ) {
mStatus = STATE_CONNECTED;
}
if ( mCallback != null ) {
mCallback.onPostSetParam(nRet, outStatus[0]);
}
}
};
t.start();
if (DEBUG_LOG) {
Log.d(TAG, "setParam() : HVC_NORMAL");
}
return HVC_NORMAL;
}
public int getParam(final HVC_PRM prm) {
if ( mBtDevice == null ) {
if (DEBUG_LOG) {
Log.d(TAG, "getParam() : HVC_ERROR_NODEVICES");
}
return HVC_ERROR_NODEVICES;
}
if ( mService == null || mService.getmConnectionState() != BleDeviceService.STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "getParam() : HVC_ERROR_DISCONNECTED");
}
return HVC_ERROR_DISCONNECTED;
}
if ( mStatus > STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "getParam() : HVC_ERROR_BUSY");
}
return HVC_ERROR_BUSY;
}
mStatus = STATE_BUSY;
Thread t = new Thread() {
public void run() {
int nRet = HVC_NORMAL;
byte[] outStatus = new byte[1];
if ( nRet == HVC_NORMAL ) {
nRet = GetCameraAngle(10000, outStatus, prm);
}
if ( nRet == HVC_NORMAL ) {
nRet = GetThreshold(10000, outStatus, prm);
}
if ( nRet == HVC_NORMAL ) {
nRet = GetSizeRange(10000, outStatus, prm);
}
if ( nRet == HVC_NORMAL ) {
nRet = GetFaceDetectionAngle(10000, outStatus, prm);
}
if ( mCallback != null ) {
mCallback.onPostGetParam(nRet, outStatus[0]);
}
if ( mStatus == STATE_BUSY ) {
mStatus = STATE_CONNECTED;
}
}
};
t.start();
if (DEBUG_LOG) {
Log.d(TAG, "getParam() : HVC_NORMAL");
}
return HVC_NORMAL;
}
@Override
public int getVersion(final HVC_VER ver) {
if ( mBtDevice == null ) {
if (DEBUG_LOG) {
Log.d(TAG, "getParam() : HVC_ERROR_NODEVICES");
}
return HVC_ERROR_NODEVICES;
}
if ( mService == null || mService.getmConnectionState() != BleDeviceService.STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "getParam() : HVC_ERROR_DISCONNECTED");
}
return HVC_ERROR_DISCONNECTED;
}
if ( mStatus > STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "getParam() : HVC_ERROR_BUSY");
}
return HVC_ERROR_BUSY;
}
mStatus = STATE_BUSY;
Thread t = new Thread() {
public void run() {
int nRet = HVC_NORMAL;
byte[] outStatus = new byte[1];
if ( nRet == HVC_NORMAL ) {
nRet = GetVersion(10000, outStatus, ver);
}
if ( mCallback != null ) {
mCallback.onPostGetVersion(nRet, outStatus[0]);
}
if ( mStatus == STATE_BUSY ) {
mStatus = STATE_CONNECTED;
}
}
};
t.start();
if (DEBUG_LOG) {
Log.d(TAG, "getVersion() : HVC_NORMAL");
}
return HVC_NORMAL;
}
private final BleCallback gattCallback = new BleCallback() {
@Override
public void callbackMethod(String action) {
//*********************//
if (action.equals(BleDeviceService.ACTION_GATT_CONNECTED)) {
if (DEBUG_LOG) {
Log.d(TAG, "UART_CONNECT_MSG");
}
mStatus = STATE_CONNECTING;
}
//*********************//
if (action.equals(BleDeviceService.ACTION_GATT_DISCONNECTED)) {
if (DEBUG_LOG) {
Log.d(TAG, "UART_DISCONNECT_MSG");
}
mService.close();
mStatus = STATE_DISCONNECTED;
if ( mCallback != null ) {
mCallback.onDisconnected();
}
}
//*********************//
if (action.equals(BleDeviceService.ACTION_GATT_SERVICES_DISCOVERED)) {
if (DEBUG_LOG) {
Log.d(TAG, "UART_DISCOVERED_MSG");
}
mStatus = STATE_CONNECTED;
if ( mCallback != null ) {
mCallback.onConnected();
}
}
//*********************//
if (action.equals(BleDeviceService.DEVICE_DOES_NOT_SUPPORT_UART)){
if (DEBUG_LOG) {
Log.d(TAG, "DEVICE_DOES_NOT_SUPPORT_UART");
}
mService.disconnect();
mStatus = STATE_DISCONNECTED;
}
}
@Override
public void callbackMethod(String action, byte[] byText) {
//*********************//
if (action.equals(BleDeviceService.ACTION_DATA_AVAILABLE+BleDeviceService.EXTRA_DATA)) {
if ( byText != null ) {
String deviceInfo = "DATA_AVAILABLE: " + String.valueOf(byText.length) + " byte";
synchronized (mtxValue) {
for ( int i=0; i<byText.length; i++ ) {
mtxValue.add(byText[i]);
//deviceInfo += String.valueOf(byText[i]) + " ";
}
}
if (DEBUG_LOG) {
Log.d(TAG, deviceInfo);
}
sleep(1);
}
}
//*********************//
if (action.equals(BleDeviceService.ACTION_DATA_AVAILABLE+BleDeviceService.NAME_DATA)) {
if ( byText != null && mtxName != null ) {
String deviceInfo = "NAME_AVAILABLE: " + String.valueOf(byText.length) + " byte";
synchronized (mtxName) {
for ( int i=0; i<byText.length; i++ ) {
mtxName[i] = byText[i];
//deviceInfo += String.valueOf(mtxName[i]) + " ";
}
}
if (DEBUG_LOG) {
Log.d(TAG, deviceInfo);
}
if ( mCallback != null ) {
mCallback.onPostGetDeviceName(mtxName);
}
}
}
}
};
/**
* Bt send signal<br>
* [Description]<br>
* none<br>
* [Notes]<br>
* @param inDataSize send signal data size<br>
* @param inData send signal data<br>
* @return int send signal complete data number<br>
*/
@Override
protected int Send(byte[] inData)
{
do {
if ( mStatus < STATE_CONNECTED ) {
return 0;
}
synchronized(mtxValue){
int readLength = mtxValue.size();
if ( readLength <= 0 ) break;
mtxValue.clear();
}
} while ( true );
mService.writeTXCharacteristic(inData);
String deviceInfo = "Send: " + inData.length + " byte";
if (DEBUG_LOG) {
Log.d(TAG, deviceInfo);
}
return inData.length;
}
/**
* Bt receive signalg<br>
* [Description]<br>
* none<br>
* [Notes]<br>
* @param inDataSize receive signal data size<br>
* @param outResult receive signal data<br>
* @return int receive signal complete data number<br>
*/
@Override
protected int Receive(int inTimeOutTime, int inDataSize, byte[] outResult)
{
long maxTimeMillis = System.currentTimeMillis() + inTimeOutTime;
while (System.currentTimeMillis() < maxTimeMillis) {
if ( mStatus < STATE_CONNECTED ) {
return 0;
}
int readLength = mtxValue.size();
if ( readLength >= inDataSize ) {
break;
} else {
sleep(1);
}
}
int readLength = 0;
synchronized(mtxValue){
readLength = java.lang.Math.min(mtxValue.size(),inDataSize);
for ( int i=0; i<readLength; i++ ) {
outResult[i] = mtxValue.get(i);
}
for ( int i=0; i<readLength; i++ ) {
mtxValue.remove(0);
}
}
String deviceInfo = "Receive: " + String.valueOf(readLength) + " byte";
if (DEBUG_LOG) {
Log.d(TAG, deviceInfo);
}
return readLength;
}
protected synchronized void sleep(long msec) {
//Method to stop execution after set number of msec
try {
wait(msec);
} catch(InterruptedException e){}
}
public void setCallBack(HVCBleCallback hvcCallback) {
// TODO Auto-generated method stub
mCallback = hvcCallback;
if (DEBUG_LOG) {
Log.d(TAG, "Set CallBack");
}
}
/**
* HVC_BLE connect<br>
* [Description]<br>
* Connect with HVC_BLE device<br>
*/
@Override
public void connect(Context context, BluetoothDevice device) {
// TODO Auto-generated method stub
mStatus = STATE_DISCONNECTED;
if ( mService != null ) {
if (DEBUG_LOG) {
Log.d(TAG, "DisConnect Device = " + mBtDevice.getName() + " (" + mBtDevice.getAddress() + ")");
}
mService.close();
}
mBtDevice = device;
if ( mBtDevice == null ) {
return;
}
mService = new BleDeviceService(gattCallback);
mService.connect(context, mBtDevice);
if (DEBUG_LOG) {
Log.d(TAG, "Connect Device = " + mBtDevice.getName() + " (" + mBtDevice.getAddress() + ")");
}
}
/**
* HVC_BLE disconnect<br>
* [Description]<br>
* Disconnect HVC_BLE device<br>
*/
@Override
public void disconnect() {
// TODO Auto-generated method stub
mStatus = STATE_DISCONNECTED;
if ( mService != null ) {
if (DEBUG_LOG) {
Log.d(TAG, "DisConnect Device = " + mBtDevice.getName() + " (" + mBtDevice.getAddress() + ")");
}
mService.close();
}
mService = null;
if ( mCallback != null ) {
mCallback.onDisconnected();
}
}
@Override
public int setDeviceName(byte[] value) {
// TODO Auto-generated method stub
if ( mBtDevice == null ) {
if (DEBUG_LOG) {
Log.d(TAG, "setDeviceName() : HVC_ERROR_NODEVICES");
}
return HVC_ERROR_NODEVICES;
}
if ( mService == null || mService.getmConnectionState() != BleDeviceService.STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "setDeviceName() : HVC_ERROR_DISCONNECTED");
}
return HVC_ERROR_DISCONNECTED;
}
if ( mStatus > STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "setDeviceName() : HVC_ERROR_BUSY");
}
return HVC_ERROR_BUSY;
}
mService.writeNameCharacteristic(value);
if (DEBUG_LOG) {
Log.d(TAG, "getDeviceName() : HVC_NORMAL");
}
return HVC_NORMAL;
}
@Override
public int getDeviceName(byte[] value) {
// TODO Auto-generated method stub
if ( mBtDevice == null ) {
if (DEBUG_LOG) {
Log.d(TAG, "getDeviceName() : HVC_ERROR_NODEVICES");
}
return HVC_ERROR_NODEVICES;
}
if ( mService == null || mService.getmConnectionState() != BleDeviceService.STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "getDeviceName() : HVC_ERROR_DISCONNECTED");
}
return HVC_ERROR_DISCONNECTED;
}
if ( mStatus > STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "getDeviceName() : HVC_ERROR_BUSY");
}
return HVC_ERROR_BUSY;
}
mtxName = value;
mService.readNameCharacteristic();
if (DEBUG_LOG) {
Log.d(TAG, "getDeviceName() : HVC_NORMAL");
}
return HVC_NORMAL;
}
/**
* get status.
* @return status(STATE_DISCONNECTED / STATE_CONNECTING / STATE_CONNECTED / STATE_BUSY)
*/
public int getStatus() {
return mStatus;
}
/**
* get comm status.
* @return status.
*/
public int getCommStatus() {
if ( mBtDevice == null ) {
if (DEBUG_LOG) {
Log.d(TAG, "getStatus() : HVC_ERROR_NODEVICES");
}
return HVC_ERROR_NODEVICES;
}
if ( mService == null || mService.getmConnectionState() != BleDeviceService.STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "getStatus() : HVC_ERROR_DISCONNECTED");
}
return HVC_ERROR_DISCONNECTED;
}
if ( mStatus > STATE_CONNECTED ) {
if (DEBUG_LOG) {
Log.d(TAG, "getStatus() : HVC_ERROR_BUSY");
}
return HVC_ERROR_BUSY;
}
if (DEBUG_LOG) {
Log.d(TAG, "getStatus() : HVC_NORMAL - mStatus:" + mStatus);
}
return HVC_NORMAL;
}
}