package org.deviceconnect.android.deviceplugin.hvcp.manager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbManager; import android.os.Handler; import android.support.annotation.NonNull; import android.util.Log; import android.util.SparseArray; import com.hoho.android.usbserial.driver.UsbSerialDriver; import com.hoho.android.usbserial.driver.UsbSerialPort; import com.hoho.android.usbserial.driver.UsbSerialProber; import org.deviceconnect.android.deviceplugin.hvcp.BuildConfig; import org.deviceconnect.android.deviceplugin.hvcp.manager.data.HVCCameraInfo; import org.deviceconnect.android.deviceplugin.hvcp.manager.data.HumanDetectKind; import org.deviceconnect.android.deviceplugin.hvcp.manager.data.OkaoResult; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentHashMap; /** * HVC Manager. * @author NTT DOCOMO, INC. */ public enum HVCManager { /** * Singleton instance. */ INSTANCE; /** TAG. */ private static final String TAG = "HVCManager"; /** Okao Execute Command. */ private static final String OKAO_EXECUTE = "FE040300FF0102"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_EYE = "eye"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_NOSE = "nose"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_MOUTH = "mouth"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_BLINK = "blink"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_AGE = "age"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_GENDER = "gender"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_FACE_DIRECTION = "faceDirection"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_GAZE = "gaze"; /** Option parameter:{@value}. */ public static final String PARAM_OPTIONS_EXPRESSION = "expression"; /** HVC-P body detect threshold initial value. */ private static final int HVC_P_BODY_DETECT_THRESHOLD = 500; //1〜1000 /** HVC-P hand detect threshold initial value. */ private static final int HVC_P_HAND_DETECT_THRESHOLD = 500; //1〜1000 /** HVC-P Pet detect threshold initial value. */ private static final int HVC_P_PET_DETECT_THRESHOLD = 500; //1〜1000 /** HVC-P Face detect threshold initial value. */ private static final int HVC_P_FACE_DETECT_THRESHOLD = 500; //1〜1000 /** HVC-P Face Recognition threshold initial value. */ private static final int HVC_P_RECOGNITION_THRESHOLD = 500; //0〜1000 /** Threshold min. body, hand, pet, face. */ public static final int HVC_P_MIN_THRESHOLD = 1; /** Threshold min. recognition.*/ public static final int HVC_P_MIN_RECOGNITION_THRESHOLD = 0; /** Threshold max.*/ public static final int HVC_P_MAX_THRESHOLD = 1000; /** Confidence max.*/ public static final int HVC_P_MAX_CONFIDENCE = 1000; /** Blink max.*/ public static final int HVC_P_MAX_BLINK = 1000; /** * Neutral<br> * Expression Estimation result value<br> */ public static final int HVC_EX_NEUTRAL = 0; /** * Happiness<br> * Expression Estimation result value<br> */ public static final int HVC_EX_HAPPINESS = 1; /** * Surprise<br> * Expression Estimation result value<br> */ public static final int HVC_EX_SURPRISE = 2; /** * Anger<br> * Expression Estimation result value<br> */ public static final int HVC_EX_ANGER = 3; /** * Sadness<br> * Expression Estimation result value<br> */ public static final int HVC_EX_SADNESS = 4; /** * HVC-C expression unknown. */ public static final String EXPRESSION_UNKNOWN = "unknown"; /** * HVC-C expression smile. */ public static final String EXPRESSION_SMILE = "smile"; /** * HVC-C expression surprise. */ public static final String EXPRESSION_SURPRISE = "surprise"; /** * HVC-C expression mad. */ public static final String EXPRESSION_MAD = "mad"; /** * HVC-C expression sad. */ public static final String EXPRESSION_SAD = "sad"; /** * HVC-C expression score max. */ public static final int EXPRESSION_SCORE_MAX = 100; /** * HVC-P detect camera width[pixels]. */ public static final int HVC_P_CAMERA_WIDTH = 320; /** * HVC-P detect camera height[pixels]. */ public static final int HVC_P_CAMERA_HEIGHT = 240; /** HVC-P body min size. */ private static final int HVC_P_BODY_MIN_SIZE = 30; //20〜8192 /** HVC-P body max size. */ private static final int HVC_P_BODY_MAX_SIZE = 8192; /** HVC-P hand min size. */ private static final int HVC_P_HAND_MIN_SIZE = 40; /** HVC-P hand max size. */ private static final int HVC_P_HAND_MAX_SIZE = 8192; /** HVC-P pet min size. */ private static final int HVC_P_PET_MIN_SIZE = 40; /** HVC-P pet max size. */ private static final int HVC_P_PET_MAX_SIZE = 8192; /** HVC-P face min size. */ private static final int HVC_P_FACE_MIN_SIZE = 64; /** HVC-P face max size. */ private static final int HVC_P_FACE_MAX_SIZE = 8192; /** HVC-P min size. */ public static final int HVC_P_MIN_SIZE = 20; /** HVC-P max size. */ public static final int HVC_P_MAX_SIZE = 8192; /** * HVC interval parameter minimum value. */ public static final long PARAM_INTERVAL_MIN = 3 * 1000; /** * HVC interval parameter maximum value. */ public static final long PARAM_INTERVAL_MAX = 60 * 1000; /** * Male<br> * Gender Estimation result value<br> */ public static final int HVC_GEN_MALE = 1; /** * Female<br> * Gender Estimation result value<br> */ public static final int HVC_GEN_FEMALE = 0; /** * USB Manager. */ private UsbManager mUsbManager; /** * USB Driver. */ private UsbSerialPort mUsbDriver; /** * No Command. */ private final int CMD_UNKNOWN = -1; /** * Get Version. */ private final int CMD_VERSION = 1; /** * Execute Okao. */ private final int CMD_OKAO_EXECUTE = 2; /** * Set Threshold. */ private final int CMD_SET_THRESHOLD = 3; /** * Set Size. */ private final int CMD_SET_SIZE = 4; /** * Command mType. */ private int mType = 0; /** * Now interval. */ private Long mNowInterval = PARAM_INTERVAL_MIN; /** * HVC Cameras. */ private ConcurrentHashMap<String, HVCCameraInfo> mServices; /** Event List. */ private List<String> mEventList; /** One shot response list. */ private List<String> mOneShotList; /** Timer Handler. */ private Handler mTimer; public static final String ACTION_USB_PERMISSION_BASE = "com.serenegiant.USB_PERMISSION."; public final String ACTION_USB_PERMISSION = ACTION_USB_PERMISSION_BASE + hashCode(); private PendingIntent mPermissionIntent; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent == null) { return; } String action = intent.getAction(); if (BuildConfig.DEBUG) { Log.d(TAG, "action:" + action); } UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { HVCCameraInfo camera = new HVCCameraInfo("" + device.getDeviceId() + "_" + device.getProductId() + "_" + device.getVendorId(), "HVC-P:" + "" + device.getDeviceId() + "_" + device.getProductId() + "_" + device.getVendorId()); mServices.put(camera.getID(), camera); // デバイスとの接続完了を通知. notifyOnConnected(camera); HVCManager.INSTANCE.init(context); if (BuildConfig.DEBUG) { Log.d(TAG, "device:true:" + device.getDeviceId()); } } else { if (BuildConfig.DEBUG) { Log.d(TAG, "device:false"); } } } }; private final List<ConnectionListener> mConnectionListeners = new ArrayList<ConnectionListener>(); /** * Constructor. */ private HVCManager() { mServices = new ConcurrentHashMap<String, HVCCameraInfo>(); mEventList = new ArrayList<String>(); mOneShotList = new ArrayList<String>(); mTimer = new Handler(); mType = CMD_UNKNOWN; } /** * Return HVC Cameras. * @return HVC Cameras List */ public ConcurrentHashMap<String, HVCCameraInfo> getHVCDevices() { return mServices; } /** * Initialize. * * @param context Context。 */ public void init(final Context context) { mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0); IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_USB_PERMISSION); context.registerReceiver(mReceiver, filter); } /** * Unregister Intent-Filter. * @param context Context */ public void destroyFilter(final Context context) { context.unregisterReceiver(mReceiver); } /** * Add HVC-P Device. * @param device device */ public void addUSBDevice(final UsbDevice device) { if (!mUsbManager.hasPermission(device)) { mUsbManager.requestPermission(device, mPermissionIntent); } } /** * Delete HVC-P Device. * @param device device */ public void removeUSBDevice(final UsbDevice device) { HVCCameraInfo camera = mServices.remove("" + device.getDeviceId() + "_" + device.getProductId() + "_" + device.getVendorId()); if (camera != null) { // デバイスとの接続切断を通知. notifyOnDisconnected(camera); } } /** * Add Body Detect Event Listener. * @param serviceId ServiceID * @param l Listener * @param interval Interval */ public synchronized void addBodyDetectEventListener(final String serviceId, final HVCCameraInfo.OnBodyEventListener l, final Long interval) { if (!mEventList.contains(serviceId)) { mEventList.add(serviceId); } HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setBodyEvent(l); mType = CMD_OKAO_EXECUTE; if (BuildConfig.DEBUG) { Log.d(TAG, "register body event "); } sendCommand(OKAO_EXECUTE, interval); } /** * Add Hand Detect Event Listener. * @param serviceId Service ID * @param l Listener * @param interval Interval */ public synchronized void addHandDetectEventListener(final String serviceId, final HVCCameraInfo.OnHandEventListener l, final Long interval) { if (!mEventList.contains(serviceId)) { mEventList.add(serviceId); } HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setHandEvent(l); mType = CMD_OKAO_EXECUTE; sendCommand(OKAO_EXECUTE, interval); } /** * Add Face Detect Event Listener. * @param serviceId ServiceID * @param l Listener * @param options Options * @param interval Interval */ public synchronized void addFaceDetectEventListener(final String serviceId, final HVCCameraInfo.OnFaceEventListener l, final List<String> options, final Long interval) { if (!mEventList.contains(serviceId)) { mEventList.add(serviceId); } HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setOptions(options); camera.setFaceEvent(l); mType = CMD_OKAO_EXECUTE; sendCommand(OKAO_EXECUTE, interval); } /** * Okao Execute. * @param serviceId Service ID * @param kind Detect kind * @param l One shot listener */ public synchronized void execute(final String serviceId, final HumanDetectKind kind, final HVCCameraInfo.OneShotOkaoResultResoponseListener l) { mOneShotList.add(serviceId); HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } switch (kind) { case BODY: camera.setBodyGet(l); break; case HAND: camera.setHandGet(l); break; case FACE: camera.setFaceGet(l); break; case HUMAN: camera.setBodyGet(l); camera.setHandGet(l); camera.setFaceGet(l); break; default: } mType = CMD_OKAO_EXECUTE; sendCommand(OKAO_EXECUTE, new Long(1)); } /** * Set Okao Execute's Threshold. * @param body body's threshold * @param hand hand's threshold * @param face face's threshold * @param serviceId Service ID * @param l One Shot SetParameterResoponseListener */ public synchronized void setThreshold(final Double body, final Double hand, final Double face, final String serviceId, final HVCCameraInfo.OneShotSetParameterResoponseListener l) { int b = HVC_P_BODY_DETECT_THRESHOLD; int h = HVC_P_HAND_DETECT_THRESHOLD; int p = HVC_P_PET_DETECT_THRESHOLD; int f = HVC_P_FACE_DETECT_THRESHOLD; int r = HVC_P_RECOGNITION_THRESHOLD; if (body != null) { b = body.intValue() * 1000; } if (hand != null) { h = hand.intValue() * 1000; } if (face != null) { f = face.intValue() * 1000; } StringBuffer cmdThreshold = new StringBuffer(); cmdThreshold.append("FE050800").append(swapLSBandMSB(b)).append(swapLSBandMSB(h)) .append(swapLSBandMSB(f)).append("F401"); mOneShotList.add(serviceId); HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setThresholdSet(l); mType = CMD_SET_THRESHOLD; if (BuildConfig.DEBUG) { Log.d(TAG, "Set threshold cmd:" + cmdThreshold.toString()); } sendCommand(cmdThreshold.toString(), new Long(1)); } /** * Set Okao Execute's Min Max Size. * @param bodyMin body's min size * @param bodyMax body's max size * @param handMin hand's min size * @param handMax hand's max size * @param faceMin face's min size * @param faceMax face's max size * @param serviceId Service ID * @param l One Shot SetParameterResoponseListener */ public synchronized void setMinMaxSize(final Double bodyMin, final Double bodyMax, final Double handMin, final Double handMax, final Double faceMin, final Double faceMax, final String serviceId, final HVCCameraInfo.OneShotSetParameterResoponseListener l) { int bMin = HVC_P_BODY_MIN_SIZE; int bMax = HVC_P_BODY_MAX_SIZE; int hMin = HVC_P_HAND_MIN_SIZE; int hMax = HVC_P_HAND_MAX_SIZE; int fMin = HVC_P_FACE_MIN_SIZE; int fMax = HVC_P_FACE_MAX_SIZE; if (bodyMin != null) { bMin = bodyMin.intValue() * 8192; } if (bodyMax != null) { bMax = bodyMax.intValue() * 8192; } if (handMin != null) { hMin = handMin.intValue() * 8192; } if (handMax != null) { hMax = handMax.intValue() * 8192; } if (faceMin != null) { fMin = faceMin.intValue() * 8192; } if (faceMax != null) { fMax = faceMax.intValue() * 8192; } StringBuffer cmdThreshold = new StringBuffer(); cmdThreshold.append("FE070C00").append(swapLSBandMSB(bMin)).append(swapLSBandMSB(bMax)) .append(swapLSBandMSB(hMin)).append(swapLSBandMSB(hMax)) .append(swapLSBandMSB(fMin)).append(swapLSBandMSB(fMax)); mOneShotList.add(serviceId); HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setSizeSet(l); mType = CMD_SET_SIZE; if (BuildConfig.DEBUG) { Log.d(TAG, "Set size cmd:" + cmdThreshold.toString()); } sendCommand(cmdThreshold.toString(), new Long(50)); } /** * Remove Body Detect Event Listener. * @param serviceId serviceId */ public synchronized void removeBodyDetectEventListener(final String serviceId) { HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setBodyEvent(null); removeEventList(serviceId, camera); } /** * Remove Hand Detect Event Listener * @param serviceId Service ID */ public synchronized void removeHandDetectEventListener(final String serviceId) { HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setHandEvent(null); removeEventList(serviceId, camera); } /** * Remove Face Detect Event Listener. * @param serviceId Service ID */ public synchronized void removeFaceDetectEventListener(final String serviceId) { HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setFaceEvent(null); removeEventList(serviceId, camera); } /** * Remove Face Recognize Event Listener. * @param serviceId ServiceID */ public synchronized void removeFaceRecognizeEventListener(final String serviceId) { HVCCameraInfo camera = mServices.get(serviceId); if (camera == null) { return; } camera.setFaceRecognizeEvent(null); removeEventList(serviceId, camera); } /** * Remove all event listener. */ public void removeAllEventListener() { for (String key : mServices.keySet()) { HVCCameraInfo camera = mServices.get(key); camera.setBodyEvent(null); camera.setFaceEvent(null); camera.setFaceRecognizeEvent(null); camera.setHandEvent(null); mEventList.remove(camera.getID()); } } /** * Start USB binary read thread. */ private synchronized void startReadThread(final String stCommand, final Long interval) { mTimer.removeCallbacksAndMessages(null); mNowInterval = interval; mTimer.postDelayed(new Runnable() { @Override public void run() { try { byte buf[] = new byte[32768]; int num = mUsbDriver.read(buf, buf.length); if (num > 0) { int buf_pos = 0; for (int i = 0; i + buf_pos < num; i++) { //if(i!=0 && (i%62)==0)buf0_pos+=2; buf[i] = buf[i + buf_pos]; if (((i + 63) % 62) == 0) { buf_pos += 2; } } num -= buf_pos; num += 2; } for (String key : mServices.keySet()) { HVCCameraInfo camera = mServices.get(key); if (mType == CMD_OKAO_EXECUTE) { if (buf[0] == (byte) 0xfe) { OkaoResult result = parseOkaoResult(buf); if (camera.getBodyEvent() != null) { camera.getBodyEvent().onNotifyForBodyDetectResult(key, result); } if (camera.getHandEvent() != null) { camera.getHandEvent().onNotifyForHandDetectResult(key, result); } if (camera.getFaceEvent() != null) { camera.getFaceEvent().onNotifyForFaceDetectResult(key, result); } if (camera.getBodyGet() != null) { camera.getBodyGet().onResponse(key, result); camera.setBodyGet(null); mOneShotList.remove(key); } if (camera.getHandGet() != null) { camera.getHandGet().onResponse(key, result); camera.setHandGet(null); mOneShotList.remove(key); } if (camera.getFaceGet() != null) { camera.getFaceGet().onResponse(key, result); camera.setFaceGet(null); mOneShotList.remove(key); } } } else if (mType == CMD_SET_THRESHOLD) { if (buf[0] == (byte) 0xfe && camera.getThresholdSet() != null) { camera.getThresholdSet().onResponse(buf[1]); camera.setThresholdSet(null); mOneShotList.remove(key); if (BuildConfig.DEBUG) { Log.d(TAG, "SET Threshold response"); } } else { if (BuildConfig.DEBUG) { Log.d(TAG, "SET Threshold no response"); } } } else if (mType == CMD_SET_SIZE) { if (buf[0] == (byte) 0xfe && camera.getSizeSet() != null) { camera.getSizeSet().onResponse(buf[1]); camera.setSizeSet(null); mOneShotList.remove(key); if (BuildConfig.DEBUG) { Log.d(TAG, "SET size response"); } } else { if (BuildConfig.DEBUG) { Log.d(TAG, "SET size no response"); } } } } } catch (IOException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } mEventList.clear(); mOneShotList.clear(); return; } if (mEventList.size() > 0 || mOneShotList.size() > 0) { if (mType == CMD_OKAO_EXECUTE) { byte send[] = hex2bin(OKAO_EXECUTE); try { mUsbDriver.write(send, send.length); } catch (IOException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } mEventList.clear(); mOneShotList.clear(); return; } } mTimer.postDelayed(this, mNowInterval); } } }, interval); } @NonNull private OkaoResult parseOkaoResult(final byte[] buf) { OkaoResult result = new OkaoResult(); int header = 2 + buf[2] + 4;//(strBuffer.indexOf("a0007800")+8)/2;//160x120 if (buf[2] > 8) { result.setNumberOfBody(buf[6]); result.setNumberOfHand(buf[7]); result.setNumberOfFace(buf[8]); if (BuildConfig.DEBUG) { Log.d(TAG, "body:" + result.getNumberOfBody()); Log.d(TAG, "hand:" + result.getNumberOfHand()); Log.d(TAG, "face:" + result.getNumberOfFace()); } for (int i = 0; i < result.getNumberOfBody(); i++) { result.getBodyX()[i] = (buf[10 + 11 * i] & 0xff) + ((buf[10 + 11 * i + 1] & 0xff) << 8); result.getBodyY()[i] = (buf[10 + 11 * i + 2] & 0xff) + ((buf[10 + 11 * i + 3] & 0xff) << 8); result.getBodySize()[i] = (buf[10 + 11 * i + 4] & 0xff) + ((buf[10 + 11 * i + 5] & 0xff) << 8); result.getBodyDetectConfidence()[i] = (buf[10 + 11 * i + 6] & 0xff) + ((buf[10 + 11 * i + 7] & 0xff) << 8); if (BuildConfig.DEBUG) { String bodyDebug = "[body" + result.getNumberOfBody() + "]" + "| x:" + result.getBodyX()[i] + "| y:" + result.getBodyY()[i] + "| size:" + result.getBodySize()[i] + "| Confidence:" + result.getBodyDetectConfidence()[i] + "\n"; Log.d(TAG, bodyDebug); } } for (int i = 0; i < result.getNumberOfHand(); i++) { result.getHandX()[i] = (buf[10 + 11 * (result.getNumberOfBody() + i)] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + i) + 1] & 0xff) << 8); result.getHandY()[i] = (buf[10 + 11 * (result.getNumberOfBody() + i) + 2] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + i) + 3] & 0xff) << 8); result.getHandSize()[i] = (buf[10 + 11 * (result.getNumberOfBody() + i) + 4] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + i) + 5] & 0xff) << 8); result.getHandDetectConfidence()[i] = (buf[10 + 11 * (result.getNumberOfBody() + i) + 6] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + i) + 7] & 0xff) << 8); if (BuildConfig.DEBUG) { String handDebug = "[hand" + result.getNumberOfHand() + "]" + "| x:" + result.getHandX()[i] + "| y:" + result.getHandY()[i] + "| size:" + result.getHandSize()[i] + "| Confidence:" + result.getHandDetectConfidence()[i] + "\n"; Log.d(TAG, handDebug); } } for (int i = 0; i < result.getNumberOfFace(); i++) { result.getFaceX()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i)] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 1] & 0xff) << 8); result.getFaceY()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 2] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 3] & 0xff) << 8); result.getFaceSize()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 4] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 5] & 0xff) << 8); result.getFaceDetectConfidence()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 6] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 7] & 0xff) << 8); result.getFaceDirectionLR()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i)] + 8 & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 9] & 0xff) << 8); result.getFaceDirectionUD()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 10] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 11] & 0xff) << 8); result.getFaceDirectionSlope()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 12] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 13] & 0xff) << 8); result.getFaceDirectionConfidence()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 14] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 15] & 0xff) << 8); result.getAge()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 16] & 0xff); result.getAgeConfidence()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 17] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 18] & 0xff) << 8); result.getGender()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 19] & 0xff); result.getGenderConfidence()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 20] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 21] & 0xff) << 8); result.getGazeLR()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 22] & 0xff); result.getGazeUD()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 23] & 0xff); result.getBlinkLeft()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 24] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 25] & 0xff) << 8); result.getBlinkRight()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 26] & 0xff) + ((buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 27] & 0xff) << 8); result.getExpressionUnknown()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 28] & 0xff); result.getExpressionSmile()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 29] & 0xff); result.getExpressionSurprise()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 30] & 0xff); result.getExpressionMad()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 31] & 0xff); result.getExpressionSad()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 32] & 0xff); result.getExpressionConfidence()[i] = (buf[10 + 11 * (result.getNumberOfBody() + result.getNumberOfHand() + i) + 33] & 0xff); } } return result; } /** * Send Command. * * @param stCommand * Command String Example) FF00AE11 * @param interval Interval */ private void sendCommand(final String stCommand, final Long interval) { List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager); if (availableDrivers.isEmpty()) { return; } UsbSerialDriver driver = availableDrivers.get(0); UsbDeviceConnection connection = mUsbManager.openDevice(driver.getDevice()); if (connection == null) { // You probably need to call UsbManager.requestPermission(driver.getDevice(), ..) return; } mUsbDriver = driver.getPorts().get(0); if (mUsbDriver != null) { try { mUsbDriver.open(connection); mUsbDriver.setParameters(921600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); startReadThread(stCommand, interval); byte send[] = hex2bin(stCommand); mUsbDriver.write(send, send.length); } catch (IOException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } } } /** * Check Remove Event list. * @param serviceId ServiceID * @param camera Camera Info * */ private void removeEventList(final String serviceId, final HVCCameraInfo camera) { if (mEventList.contains(serviceId) && camera.getBodyEvent() == null && camera.getHandEvent() == null && camera.getFaceEvent() == null && camera.getFaceRecognizeEvent() == null) { mEventList.remove(camera.getID()); } } /** * convert to normalize expression value. * @param hvcExpression expression(HVC value) * @return normalize expression value. */ public static String convertToNormalizeExpression(final int hvcExpression) { String normalizeExpression = EXPRESSION_UNKNOWN; SparseArray<String> map = new SparseArray<>(); map.put(HVC_EX_NEUTRAL, EXPRESSION_UNKNOWN); map.put(HVC_EX_HAPPINESS, EXPRESSION_SMILE); map.put(HVC_EX_SURPRISE, EXPRESSION_SURPRISE); map.put(HVC_EX_ANGER, EXPRESSION_MAD); map.put(HVC_EX_SADNESS, EXPRESSION_SAD); String exp = map.get(hvcExpression); if (exp != null) { normalizeExpression = exp; } else { normalizeExpression = EXPRESSION_UNKNOWN; } return normalizeExpression; } /** * Convert Byte as it is to the string. * @param data array of byte Example) fee0 <- byte * @return string of remains of the value of the byte Example) fee0 <- String */ private String bin2hex(final byte[] data) { StringBuffer sb = new StringBuffer(); for (byte b : data) { String s = Integer.toHexString(0xff & b); if (s.length() == 1) { sb.append("0"); } sb.append(s); } return sb.toString(); } /** * Convert string as it is to the byte. * @param hex hex <- String * @return Converted byte array of values hex <- String */ private byte[] hex2bin(final String hex) { byte[] bytes = new byte[hex.length() / 2]; for (int index = 0; index < bytes.length; index++) { bytes[index] = (byte) Integer.parseInt( hex.substring(index * 2, (index + 1) * 2), 16); } return bytes; } /** * Swap LSB and MSB. * @param parameter hex * @return swap string */ private String swapLSBandMSB(final int parameter) { String size = String.format("%04X", parameter & 0xFFFF); return size.substring(2, size.length()) + size.substring(0, 2); } public void addConnectionListener(final ConnectionListener listener) { synchronized (mConnectionListeners) { if (!mConnectionListeners.contains(listener)) { mConnectionListeners.add(listener); } } } public void removeConnectionListener(final ConnectionListener listener) { synchronized (mConnectionListeners) { for (Iterator<ConnectionListener> it = mConnectionListeners.iterator(); ; it.hasNext()) { ConnectionListener l = it.next(); if (l == listener) { it.remove(); break; } } } } private void notifyOnConnected(final HVCCameraInfo cameraInfo) { synchronized (mConnectionListeners) { for (Iterator<ConnectionListener> it = mConnectionListeners.iterator(); it.hasNext(); ) { ConnectionListener listener = it.next(); listener.onConnected(cameraInfo); } } } private void notifyOnDisconnected(final HVCCameraInfo cameraInfo) { synchronized (mConnectionListeners) { for (Iterator<ConnectionListener> it = mConnectionListeners.iterator(); it.hasNext(); ) { ConnectionListener listener = it.next(); listener.onDisconnected(cameraInfo); } } } public interface ConnectionListener { void onConnected(HVCCameraInfo camera); void onDisconnected(HVCCameraInfo camera); } }