Loading app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java +83 −88 Original line number Diff line number Diff line Loading @@ -31,15 +31,15 @@ import java.util.UUID; @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) public class BluetoothLeService extends Service { private final static String TAG = BluetoothLeService.class.getSimpleName(); private final static String TAG = "BluetoothLeService"; private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private String mBluetoothDeviceAddress; private BluetoothGatt mBluetoothGatt; private String mRemoteDeviceType; private final HashMap<String, BluetoothGattCharacteristic> subscribedCharacteristics = new HashMap<>(); private final List<BluetoothGattCharacteristic> charsToSubscribeTo = new ArrayList<>(); private BluetoothManager bluetoothManager; private BluetoothAdapter bluetoothAdapter; private String device_address; private BluetoothGatt bluetoothGatt; private String remote_device_type; private final HashMap<String, BluetoothGattCharacteristic> subscribed_characteristics = new HashMap<>(); private final List<BluetoothGattCharacteristic> charsToSubscribe = new ArrayList<>(); private double currentTemp = -1; private double currentDepth = -1; Loading Loading @@ -73,15 +73,12 @@ public class BluetoothLeService extends Service { public final static int COMMAND_UP = 64; public final static int COMMAND_DOWN = 80; public void setRemoteDeviceType(String remoteDeviceType) { public void setRemoteDeviceType(String remote_device_type) { if( MyDebug.LOG ) Log.d(TAG, "Setting remote type: " + remoteDeviceType); mRemoteDeviceType = remoteDeviceType; Log.d(TAG, "Setting remote type: " + remote_device_type); this.remote_device_type = remote_device_type; } // Various callback methods defined by the BLE API. private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { Loading @@ -90,14 +87,14 @@ public class BluetoothLeService extends Service { intentAction = ACTION_GATT_CONNECTED; broadcastUpdate(intentAction); if( MyDebug.LOG ) { Log.d(TAG, "Connected to GATT server."); Log.d(TAG, "Attempting to start service discovery"); Log.d(TAG, "Connected to GATT server, call discoverServices()"); } mBluetoothGatt.discoverServices(); bluetoothGatt.discoverServices(); currentDepth = -1; currentTemp = -1; } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { intentAction = ACTION_GATT_DISCONNECTED; if( MyDebug.LOG ) Log.d(TAG, "Disconnected from GATT server, reattempting every 5 seconds."); Loading @@ -112,7 +109,7 @@ public class BluetoothLeService extends Service { public void run() { if( MyDebug.LOG ) Log.d(TAG, "Attempting to reconnect to remote."); connect(mBluetoothDeviceAddress); connect(device_address); } }, 5000); } Loading @@ -122,37 +119,33 @@ public class BluetoothLeService extends Service { if( status == BluetoothGatt.GATT_SUCCESS ) { broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); subscribeToServices(); } else { } else { if( MyDebug.LOG ) Log.d(TAG, "onServicesDiscovered received: " + status); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if( status == BluetoothGatt.GATT_SUCCESS ) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { if( MyDebug.LOG ) Log.d(TAG,"Got notification"); broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } @Override public void onDescriptorWrite (BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { // We need to wait for this callback before enabling the next notification in case we // have several in our list if (!charsToSubscribeTo.isEmpty()) { setCharacteristicNotification(charsToSubscribeTo.remove(0), true); if( !charsToSubscribe.isEmpty() ) { setCharacteristicNotification(charsToSubscribe.remove(0), true); } } }; Loading @@ -167,7 +160,7 @@ public class BluetoothLeService extends Service { if (gattServices == null) return; List<UUID> mCharacteristicsWanted; switch (mRemoteDeviceType) { switch( remote_device_type ) { case "preference_remote_type_kraken": mCharacteristicsWanted = KrakenGattAttributes.getDesiredCharacteristics(); break; Loading @@ -176,23 +169,19 @@ public class BluetoothLeService extends Service { break; } // Loops through available GATT Services and characteristics, and subscribe to // the ones we want. Today, we just enable notifications since that's all we need. for(BluetoothGattService gattService : gattServices) { List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics(); // Loops through available Characteristics. for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { UUID uuid = gattCharacteristic.getUuid(); if( mCharacteristicsWanted.contains(uuid) ) { if( MyDebug.LOG ) Log.d(TAG, "Found characteristic to subscribe to: " + uuid); charsToSubscribeTo.add(gattCharacteristic); charsToSubscribe.add(gattCharacteristic); } } } // We need to enable notifications asynchronously setCharacteristicNotification(charsToSubscribeTo.remove(0), true); setCharacteristicNotification(charsToSubscribe.remove(0), true); } private void broadcastUpdate(final String action) { Loading @@ -200,8 +189,7 @@ public class BluetoothLeService extends Service { sendBroadcast(intent); } private void broadcastUpdate( String action, final BluetoothGattCharacteristic characteristic) { private void broadcastUpdate(String action, final BluetoothGattCharacteristic characteristic) { UUID uuid = characteristic.getUuid(); final int format_uint8 = BluetoothGattCharacteristic.FORMAT_UINT8; final int format_uint16 = BluetoothGattCharacteristic.FORMAT_UINT16; Loading @@ -222,20 +210,25 @@ public class BluetoothLeService extends Service { if( buttonCode == 32 ) { // Shutter press remoteCommand = COMMAND_SHUTTER; } else if (buttonCode == 16) { } else if( buttonCode == 16 ) { // "Mode" button: either "back" action or "Photo/Camera" switch remoteCommand = COMMAND_MODE; } else if (buttonCode == 48) { } else if( buttonCode == 48 ) { // "Menu" button remoteCommand = COMMAND_MENU; } else if (buttonCode == 97) { } else if( buttonCode == 97 ) { // AF/MF button remoteCommand = COMMAND_AFMF; } else if (buttonCode == 96) { } else if( buttonCode == 96 ) { // Long press on MF/AF button. // Note: the camera issues button code 97 first, then // 96 after one second of continuous press } else if (buttonCode == 64) { } else if( buttonCode == 64 ) { // Up button remoteCommand = COMMAND_UP; } else if (buttonCode == 80) { Loading @@ -248,7 +241,8 @@ public class BluetoothLeService extends Service { intent.putExtra(EXTRA_DATA, remoteCommand); sendBroadcast(intent); } } else if (KrakenGattAttributes.KRAKEN_SENSORS_CHARACTERISTIC.equals(uuid)) { } else if( KrakenGattAttributes.KRAKEN_SENSORS_CHARACTERISTIC.equals(uuid) ) { // The housing returns four bytes. // Byte 0-1: depth = (Byte 0 + Byte 1 << 8) / 10 / density // Byte 2-3: temperature = (Byte 2 + Byte 3 << 8) / 10 Loading Loading @@ -300,16 +294,16 @@ public class BluetoothLeService extends Service { public boolean initialize() { if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { if( bluetoothManager == null ) { bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if( bluetoothManager == null ) { Log.e(TAG, "Unable to initialize BluetoothManager."); return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { bluetoothAdapter = bluetoothManager.getAdapter(); if( bluetoothAdapter == null ) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); return false; } Loading @@ -320,9 +314,9 @@ public class BluetoothLeService extends Service { public boolean connect(final String address) { if( MyDebug.LOG ) Log.d(TAG, "connect: " + address); if( mBluetoothAdapter == null ) { if( bluetoothAdapter == null ) { if( MyDebug.LOG ) Log.d(TAG, "mBluetoothAdapter is null"); Log.d(TAG, "bluetoothAdapter is null"); return false; } else if( address == null ) { Loading @@ -331,13 +325,13 @@ public class BluetoothLeService extends Service { return false; } if( mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null ) { mBluetoothGatt.disconnect(); mBluetoothGatt.close(); mBluetoothGatt = null; if( device_address != null && address.equals(device_address) && bluetoothGatt != null ) { bluetoothGatt.disconnect(); bluetoothGatt.close(); bluetoothGatt = null; } final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); if( device == null ) { if( MyDebug.LOG ) Log.d(TAG, "device not found"); Loading @@ -352,48 +346,49 @@ public class BluetoothLeService extends Service { return false; } mBluetoothGatt = device.connectGatt(this, false, mGattCallback); mBluetoothDeviceAddress = address; bluetoothGatt = device.connectGatt(this, false, mGattCallback); device_address = address; return true; } private void close() { if( mBluetoothGatt == null ) { if( bluetoothGatt == null ) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; bluetoothGatt.close(); bluetoothGatt = null; } private void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { if( mBluetoothAdapter == null ) { private void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { if( bluetoothAdapter == null ) { if( MyDebug.LOG ) Log.d(TAG, "mBluetoothAdapter is null"); Log.d(TAG, "bluetoothAdapter is null"); return; } else if( mBluetoothGatt == null ) { else if( bluetoothGatt == null ) { if( MyDebug.LOG ) Log.d(TAG, "mBluetoothGatt is null"); Log.d(TAG, "bluetoothGatt is null"); return; } String uuid = characteristic.getUuid().toString(); mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); bluetoothGatt.setCharacteristicNotification(characteristic, enabled); if( enabled ) { subscribedCharacteristics.put(uuid, characteristic); } else { subscribedCharacteristics.remove(uuid); subscribed_characteristics.put(uuid, characteristic); } else { subscribed_characteristics.remove(uuid); } BluetoothGattDescriptor descriptor = characteristic.getDescriptor(KrakenGattAttributes.CLIENT_CHARACTERISTIC_CONFIG); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); bluetoothGatt.writeDescriptor(descriptor); } private List<BluetoothGattService> getSupportedGattServices() { if (mBluetoothGatt == null) return null; if( bluetoothGatt == null ) return null; return mBluetoothGatt.getServices(); return bluetoothGatt.getServices(); } } app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothRemoteControl.java +64 −52 Original line number Diff line number Diff line Loading @@ -27,16 +27,16 @@ public class BluetoothRemoteControl { private final MainActivity main_activity; private BluetoothLeService mBluetoothLeService; private String mRemoteDeviceAddress; private String mRemoteDeviceType; private boolean mRemoteConnected; private BluetoothLeService bluetoothLeService; private String remoteDeviceAddress; private String remoteDeviceType; private boolean is_connected; public BluetoothRemoteControl(MainActivity main_activity) { this.main_activity = main_activity; } // Code to manage Service lifecycle for remote control. // class to manage the Service lifecycle for remote control. private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override Loading @@ -45,13 +45,13 @@ public class BluetoothRemoteControl { // BluetoothLeService requires Android 4.3+ return; } mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); if (!mBluetoothLeService.initialize()) { bluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); if( !bluetoothLeService.initialize() ) { Log.e(TAG, "Unable to initialize Bluetooth"); stopRemoteControl(); } // Automatically connects to the device upon successful start-up initialization. mBluetoothLeService.connect(mRemoteDeviceAddress); // connect to the device bluetoothLeService.connect(remoteDeviceAddress); } @Override Loading @@ -61,7 +61,7 @@ public class BluetoothRemoteControl { public void run() { if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 ) { // BluetoothLeService requires Android 4.3+ mBluetoothLeService.connect(mRemoteDeviceAddress); bluetoothLeService.connect(remoteDeviceAddress); } } }, 5000); Loading @@ -88,28 +88,29 @@ public class BluetoothRemoteControl { if( MyDebug.LOG ) Log.d(TAG, "Remote connected"); // Tell the Bluetooth service what type of remote we want to use mBluetoothLeService.setRemoteDeviceType(mRemoteDeviceType); bluetoothLeService.setRemoteDeviceType(remoteDeviceType); main_activity.setBrightnessForCamera(false); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { } else if( BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action) ) { if( MyDebug.LOG ) Log.d(TAG, "Remote disconnected"); mRemoteConnected = false; is_connected = false; applicationInterface.getDrawPreview().onExtraOSDValuesChanged("-- \u00B0C", "-- m"); mainUI.updateRemoteConnectionIcon(); main_activity.setBrightnessToMinimumIfWanted(); if (mainUI.isExposureUIOpen()) mainUI.toggleExposureUI(); } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { } else if( BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action) ) { if( MyDebug.LOG ) Log.d(TAG, "Remote services discovered"); /* We let the BluetoothLEService subscribe to what is relevant, so we do nothing here, but we wait until this is done to update the UI icon */ mRemoteConnected = true; // We let the BluetoothLEService subscribe to what is relevant, so we // do nothing here, but we wait until this is done to update the UI // icon is_connected = true; mainUI.updateRemoteConnectionIcon(); } else if (BluetoothLeService.ACTION_SENSOR_VALUE.equals(action)) { } else if( BluetoothLeService.ACTION_SENSOR_VALUE.equals(action) ) { double temp = intent.getDoubleExtra(BluetoothLeService.SENSOR_TEMPERATURE, -1); double depth = intent.getDoubleExtra(BluetoothLeService.SENSOR_DEPTH, -1) / main_activity.getWaterDensity(); depth = (Math.round(depth* 10)) / 10.0; // Round to 1 decimal Loading @@ -119,7 +120,8 @@ public class BluetoothRemoteControl { String line1 = "" + temp + " \u00B0C"; String line2 = "" + depth + " m"; applicationInterface.getDrawPreview().onExtraOSDValuesChanged(line1, line2); } else if (BluetoothLeService.ACTION_REMOTE_COMMAND.equals(action)) { } else if( BluetoothLeService.ACTION_REMOTE_COMMAND.equals(action) ) { int command = intent.getIntExtra(BluetoothLeService.EXTRA_DATA, -1); // TODO: we could abstract this into a method provided by each remote control model switch( command ) { Loading @@ -132,9 +134,11 @@ public class BluetoothRemoteControl { // closes the settings screen that is currently open if( mainUI.popupIsOpen() ) { mainUI.togglePopupSettings(); } else if (mainUI.isExposureUIOpen()) { } else if( mainUI.isExposureUIOpen() ) { mainUI.toggleExposureUI(); } else { } else { main_activity.clickedSwitchVideo(null); } break; Loading @@ -145,10 +149,12 @@ public class BluetoothRemoteControl { if( !mainUI.popupIsOpen() ) { if( !mainUI.isExposureUIOpen() ) { mainUI.toggleExposureUI(); } else { } else { mainUI.commandMenuExposure(); } } else { } else { mainUI.commandMenuPopup(); } break; Loading @@ -159,7 +165,8 @@ public class BluetoothRemoteControl { // - if we are on autofocus, then adjust zoom. if( main_activity.getPreview().getCurrentFocusValue() != null && main_activity.getPreview().getCurrentFocusValue().equals("focus_mode_manual2") ) { main_activity.changeFocusDistance(-25, false); } else { } else { // Adjust zoom main_activity.zoomIn(); } Loading @@ -169,7 +176,8 @@ public class BluetoothRemoteControl { if( !mainUI.processRemoteDownButton() ) { if( main_activity.getPreview().getCurrentFocusValue() != null && main_activity.getPreview().getCurrentFocusValue().equals("focus_mode_manual2") ) { main_activity.changeFocusDistance(25, false); } else { } else { // Adjust zoom main_activity.zoomOut(); } Loading @@ -186,7 +194,8 @@ public class BluetoothRemoteControl { default: break; } } else { } else { if( MyDebug.LOG ) Log.d(TAG, "Other remote event"); } Loading @@ -196,7 +205,7 @@ public class BluetoothRemoteControl { public boolean remoteConnected() { /*if( true ) return true; // test*/ return mRemoteConnected; return is_connected; } // TODO: refactor for a filter than receives generic remote control intents Loading Loading @@ -228,16 +237,18 @@ public class BluetoothRemoteControl { Log.d(TAG, "Remote enabled, starting service"); main_activity.bindService(gattServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE); main_activity.registerReceiver(remoteControlCommandReceiver, makeRemoteCommandIntentFilter()); } else { } else { if( MyDebug.LOG ) Log.d(TAG, "Remote disabled, stopping service"); // Stop the service if necessary try { main_activity.unregisterReceiver(remoteControlCommandReceiver); main_activity.unbindService(mServiceConnection); mRemoteConnected = false; // Unbinding closes the connection, of course is_connected = false; // Unbinding closes the connection, of course main_activity.getMainUI().updateRemoteConnectionIcon(); } catch (IllegalArgumentException e){ } catch(IllegalArgumentException e){ if( MyDebug.LOG ) Log.d(TAG, "Remote Service was not running, that's fine"); } Loading @@ -252,9 +263,10 @@ public class BluetoothRemoteControl { try { main_activity.unregisterReceiver(remoteControlCommandReceiver); main_activity.unbindService(mServiceConnection); mRemoteConnected = false; // Unbinding closes the connection, of course is_connected = false; // Unbinding closes the connection, of course main_activity.getMainUI().updateRemoteConnectionIcon(); } catch (IllegalArgumentException e){ } catch(IllegalArgumentException e){ Log.e(TAG, "Remote Service was not running, that's strange"); e.printStackTrace(); } Loading @@ -273,8 +285,8 @@ public class BluetoothRemoteControl { } SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(main_activity); boolean remote_enabled = sharedPreferences.getBoolean(PreferenceKeys.EnableRemote, false); mRemoteDeviceType = sharedPreferences.getString(PreferenceKeys.RemoteType, "undefined"); mRemoteDeviceAddress = sharedPreferences.getString(PreferenceKeys.RemoteName, "undefined"); return remote_enabled && !mRemoteDeviceAddress.equals("undefined"); remoteDeviceType = sharedPreferences.getString(PreferenceKeys.RemoteType, "undefined"); remoteDeviceAddress = sharedPreferences.getString(PreferenceKeys.RemoteName, "undefined"); return remote_enabled && !remoteDeviceAddress.equals("undefined"); } } app/src/main/java/net/sourceforge/opencamera/remotecontrol/DeviceScanner.java +48 −62 File changed.Preview size limit exceeded, changes collapsed. Show changes app/src/main/java/net/sourceforge/opencamera/remotecontrol/KrakenGattAttributes.java +0 −3 Original line number Diff line number Diff line Loading @@ -10,9 +10,6 @@ import java.util.UUID; * Bluetooth Low Energy */ public class KrakenGattAttributes { // The Kraken Smart Housing advertises itself as a heart measurement device, talk about // lazy devs... //public static final UUID HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb"); public static final UUID CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); //public static final UUID KRAKEN_SENSORS_SERVICE = UUID.fromString("00001623-1212-efde-1523-785feabcd123"); Loading Loading
app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java +83 −88 Original line number Diff line number Diff line Loading @@ -31,15 +31,15 @@ import java.util.UUID; @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) public class BluetoothLeService extends Service { private final static String TAG = BluetoothLeService.class.getSimpleName(); private final static String TAG = "BluetoothLeService"; private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private String mBluetoothDeviceAddress; private BluetoothGatt mBluetoothGatt; private String mRemoteDeviceType; private final HashMap<String, BluetoothGattCharacteristic> subscribedCharacteristics = new HashMap<>(); private final List<BluetoothGattCharacteristic> charsToSubscribeTo = new ArrayList<>(); private BluetoothManager bluetoothManager; private BluetoothAdapter bluetoothAdapter; private String device_address; private BluetoothGatt bluetoothGatt; private String remote_device_type; private final HashMap<String, BluetoothGattCharacteristic> subscribed_characteristics = new HashMap<>(); private final List<BluetoothGattCharacteristic> charsToSubscribe = new ArrayList<>(); private double currentTemp = -1; private double currentDepth = -1; Loading Loading @@ -73,15 +73,12 @@ public class BluetoothLeService extends Service { public final static int COMMAND_UP = 64; public final static int COMMAND_DOWN = 80; public void setRemoteDeviceType(String remoteDeviceType) { public void setRemoteDeviceType(String remote_device_type) { if( MyDebug.LOG ) Log.d(TAG, "Setting remote type: " + remoteDeviceType); mRemoteDeviceType = remoteDeviceType; Log.d(TAG, "Setting remote type: " + remote_device_type); this.remote_device_type = remote_device_type; } // Various callback methods defined by the BLE API. private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { Loading @@ -90,14 +87,14 @@ public class BluetoothLeService extends Service { intentAction = ACTION_GATT_CONNECTED; broadcastUpdate(intentAction); if( MyDebug.LOG ) { Log.d(TAG, "Connected to GATT server."); Log.d(TAG, "Attempting to start service discovery"); Log.d(TAG, "Connected to GATT server, call discoverServices()"); } mBluetoothGatt.discoverServices(); bluetoothGatt.discoverServices(); currentDepth = -1; currentTemp = -1; } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { intentAction = ACTION_GATT_DISCONNECTED; if( MyDebug.LOG ) Log.d(TAG, "Disconnected from GATT server, reattempting every 5 seconds."); Loading @@ -112,7 +109,7 @@ public class BluetoothLeService extends Service { public void run() { if( MyDebug.LOG ) Log.d(TAG, "Attempting to reconnect to remote."); connect(mBluetoothDeviceAddress); connect(device_address); } }, 5000); } Loading @@ -122,37 +119,33 @@ public class BluetoothLeService extends Service { if( status == BluetoothGatt.GATT_SUCCESS ) { broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); subscribeToServices(); } else { } else { if( MyDebug.LOG ) Log.d(TAG, "onServicesDiscovered received: " + status); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if( status == BluetoothGatt.GATT_SUCCESS ) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { if( MyDebug.LOG ) Log.d(TAG,"Got notification"); broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } @Override public void onDescriptorWrite (BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { // We need to wait for this callback before enabling the next notification in case we // have several in our list if (!charsToSubscribeTo.isEmpty()) { setCharacteristicNotification(charsToSubscribeTo.remove(0), true); if( !charsToSubscribe.isEmpty() ) { setCharacteristicNotification(charsToSubscribe.remove(0), true); } } }; Loading @@ -167,7 +160,7 @@ public class BluetoothLeService extends Service { if (gattServices == null) return; List<UUID> mCharacteristicsWanted; switch (mRemoteDeviceType) { switch( remote_device_type ) { case "preference_remote_type_kraken": mCharacteristicsWanted = KrakenGattAttributes.getDesiredCharacteristics(); break; Loading @@ -176,23 +169,19 @@ public class BluetoothLeService extends Service { break; } // Loops through available GATT Services and characteristics, and subscribe to // the ones we want. Today, we just enable notifications since that's all we need. for(BluetoothGattService gattService : gattServices) { List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics(); // Loops through available Characteristics. for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { UUID uuid = gattCharacteristic.getUuid(); if( mCharacteristicsWanted.contains(uuid) ) { if( MyDebug.LOG ) Log.d(TAG, "Found characteristic to subscribe to: " + uuid); charsToSubscribeTo.add(gattCharacteristic); charsToSubscribe.add(gattCharacteristic); } } } // We need to enable notifications asynchronously setCharacteristicNotification(charsToSubscribeTo.remove(0), true); setCharacteristicNotification(charsToSubscribe.remove(0), true); } private void broadcastUpdate(final String action) { Loading @@ -200,8 +189,7 @@ public class BluetoothLeService extends Service { sendBroadcast(intent); } private void broadcastUpdate( String action, final BluetoothGattCharacteristic characteristic) { private void broadcastUpdate(String action, final BluetoothGattCharacteristic characteristic) { UUID uuid = characteristic.getUuid(); final int format_uint8 = BluetoothGattCharacteristic.FORMAT_UINT8; final int format_uint16 = BluetoothGattCharacteristic.FORMAT_UINT16; Loading @@ -222,20 +210,25 @@ public class BluetoothLeService extends Service { if( buttonCode == 32 ) { // Shutter press remoteCommand = COMMAND_SHUTTER; } else if (buttonCode == 16) { } else if( buttonCode == 16 ) { // "Mode" button: either "back" action or "Photo/Camera" switch remoteCommand = COMMAND_MODE; } else if (buttonCode == 48) { } else if( buttonCode == 48 ) { // "Menu" button remoteCommand = COMMAND_MENU; } else if (buttonCode == 97) { } else if( buttonCode == 97 ) { // AF/MF button remoteCommand = COMMAND_AFMF; } else if (buttonCode == 96) { } else if( buttonCode == 96 ) { // Long press on MF/AF button. // Note: the camera issues button code 97 first, then // 96 after one second of continuous press } else if (buttonCode == 64) { } else if( buttonCode == 64 ) { // Up button remoteCommand = COMMAND_UP; } else if (buttonCode == 80) { Loading @@ -248,7 +241,8 @@ public class BluetoothLeService extends Service { intent.putExtra(EXTRA_DATA, remoteCommand); sendBroadcast(intent); } } else if (KrakenGattAttributes.KRAKEN_SENSORS_CHARACTERISTIC.equals(uuid)) { } else if( KrakenGattAttributes.KRAKEN_SENSORS_CHARACTERISTIC.equals(uuid) ) { // The housing returns four bytes. // Byte 0-1: depth = (Byte 0 + Byte 1 << 8) / 10 / density // Byte 2-3: temperature = (Byte 2 + Byte 3 << 8) / 10 Loading Loading @@ -300,16 +294,16 @@ public class BluetoothLeService extends Service { public boolean initialize() { if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { if( bluetoothManager == null ) { bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if( bluetoothManager == null ) { Log.e(TAG, "Unable to initialize BluetoothManager."); return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { bluetoothAdapter = bluetoothManager.getAdapter(); if( bluetoothAdapter == null ) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); return false; } Loading @@ -320,9 +314,9 @@ public class BluetoothLeService extends Service { public boolean connect(final String address) { if( MyDebug.LOG ) Log.d(TAG, "connect: " + address); if( mBluetoothAdapter == null ) { if( bluetoothAdapter == null ) { if( MyDebug.LOG ) Log.d(TAG, "mBluetoothAdapter is null"); Log.d(TAG, "bluetoothAdapter is null"); return false; } else if( address == null ) { Loading @@ -331,13 +325,13 @@ public class BluetoothLeService extends Service { return false; } if( mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null ) { mBluetoothGatt.disconnect(); mBluetoothGatt.close(); mBluetoothGatt = null; if( device_address != null && address.equals(device_address) && bluetoothGatt != null ) { bluetoothGatt.disconnect(); bluetoothGatt.close(); bluetoothGatt = null; } final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); if( device == null ) { if( MyDebug.LOG ) Log.d(TAG, "device not found"); Loading @@ -352,48 +346,49 @@ public class BluetoothLeService extends Service { return false; } mBluetoothGatt = device.connectGatt(this, false, mGattCallback); mBluetoothDeviceAddress = address; bluetoothGatt = device.connectGatt(this, false, mGattCallback); device_address = address; return true; } private void close() { if( mBluetoothGatt == null ) { if( bluetoothGatt == null ) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; bluetoothGatt.close(); bluetoothGatt = null; } private void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { if( mBluetoothAdapter == null ) { private void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { if( bluetoothAdapter == null ) { if( MyDebug.LOG ) Log.d(TAG, "mBluetoothAdapter is null"); Log.d(TAG, "bluetoothAdapter is null"); return; } else if( mBluetoothGatt == null ) { else if( bluetoothGatt == null ) { if( MyDebug.LOG ) Log.d(TAG, "mBluetoothGatt is null"); Log.d(TAG, "bluetoothGatt is null"); return; } String uuid = characteristic.getUuid().toString(); mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); bluetoothGatt.setCharacteristicNotification(characteristic, enabled); if( enabled ) { subscribedCharacteristics.put(uuid, characteristic); } else { subscribedCharacteristics.remove(uuid); subscribed_characteristics.put(uuid, characteristic); } else { subscribed_characteristics.remove(uuid); } BluetoothGattDescriptor descriptor = characteristic.getDescriptor(KrakenGattAttributes.CLIENT_CHARACTERISTIC_CONFIG); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); bluetoothGatt.writeDescriptor(descriptor); } private List<BluetoothGattService> getSupportedGattServices() { if (mBluetoothGatt == null) return null; if( bluetoothGatt == null ) return null; return mBluetoothGatt.getServices(); return bluetoothGatt.getServices(); } }
app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothRemoteControl.java +64 −52 Original line number Diff line number Diff line Loading @@ -27,16 +27,16 @@ public class BluetoothRemoteControl { private final MainActivity main_activity; private BluetoothLeService mBluetoothLeService; private String mRemoteDeviceAddress; private String mRemoteDeviceType; private boolean mRemoteConnected; private BluetoothLeService bluetoothLeService; private String remoteDeviceAddress; private String remoteDeviceType; private boolean is_connected; public BluetoothRemoteControl(MainActivity main_activity) { this.main_activity = main_activity; } // Code to manage Service lifecycle for remote control. // class to manage the Service lifecycle for remote control. private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override Loading @@ -45,13 +45,13 @@ public class BluetoothRemoteControl { // BluetoothLeService requires Android 4.3+ return; } mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); if (!mBluetoothLeService.initialize()) { bluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); if( !bluetoothLeService.initialize() ) { Log.e(TAG, "Unable to initialize Bluetooth"); stopRemoteControl(); } // Automatically connects to the device upon successful start-up initialization. mBluetoothLeService.connect(mRemoteDeviceAddress); // connect to the device bluetoothLeService.connect(remoteDeviceAddress); } @Override Loading @@ -61,7 +61,7 @@ public class BluetoothRemoteControl { public void run() { if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 ) { // BluetoothLeService requires Android 4.3+ mBluetoothLeService.connect(mRemoteDeviceAddress); bluetoothLeService.connect(remoteDeviceAddress); } } }, 5000); Loading @@ -88,28 +88,29 @@ public class BluetoothRemoteControl { if( MyDebug.LOG ) Log.d(TAG, "Remote connected"); // Tell the Bluetooth service what type of remote we want to use mBluetoothLeService.setRemoteDeviceType(mRemoteDeviceType); bluetoothLeService.setRemoteDeviceType(remoteDeviceType); main_activity.setBrightnessForCamera(false); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { } else if( BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action) ) { if( MyDebug.LOG ) Log.d(TAG, "Remote disconnected"); mRemoteConnected = false; is_connected = false; applicationInterface.getDrawPreview().onExtraOSDValuesChanged("-- \u00B0C", "-- m"); mainUI.updateRemoteConnectionIcon(); main_activity.setBrightnessToMinimumIfWanted(); if (mainUI.isExposureUIOpen()) mainUI.toggleExposureUI(); } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { } else if( BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action) ) { if( MyDebug.LOG ) Log.d(TAG, "Remote services discovered"); /* We let the BluetoothLEService subscribe to what is relevant, so we do nothing here, but we wait until this is done to update the UI icon */ mRemoteConnected = true; // We let the BluetoothLEService subscribe to what is relevant, so we // do nothing here, but we wait until this is done to update the UI // icon is_connected = true; mainUI.updateRemoteConnectionIcon(); } else if (BluetoothLeService.ACTION_SENSOR_VALUE.equals(action)) { } else if( BluetoothLeService.ACTION_SENSOR_VALUE.equals(action) ) { double temp = intent.getDoubleExtra(BluetoothLeService.SENSOR_TEMPERATURE, -1); double depth = intent.getDoubleExtra(BluetoothLeService.SENSOR_DEPTH, -1) / main_activity.getWaterDensity(); depth = (Math.round(depth* 10)) / 10.0; // Round to 1 decimal Loading @@ -119,7 +120,8 @@ public class BluetoothRemoteControl { String line1 = "" + temp + " \u00B0C"; String line2 = "" + depth + " m"; applicationInterface.getDrawPreview().onExtraOSDValuesChanged(line1, line2); } else if (BluetoothLeService.ACTION_REMOTE_COMMAND.equals(action)) { } else if( BluetoothLeService.ACTION_REMOTE_COMMAND.equals(action) ) { int command = intent.getIntExtra(BluetoothLeService.EXTRA_DATA, -1); // TODO: we could abstract this into a method provided by each remote control model switch( command ) { Loading @@ -132,9 +134,11 @@ public class BluetoothRemoteControl { // closes the settings screen that is currently open if( mainUI.popupIsOpen() ) { mainUI.togglePopupSettings(); } else if (mainUI.isExposureUIOpen()) { } else if( mainUI.isExposureUIOpen() ) { mainUI.toggleExposureUI(); } else { } else { main_activity.clickedSwitchVideo(null); } break; Loading @@ -145,10 +149,12 @@ public class BluetoothRemoteControl { if( !mainUI.popupIsOpen() ) { if( !mainUI.isExposureUIOpen() ) { mainUI.toggleExposureUI(); } else { } else { mainUI.commandMenuExposure(); } } else { } else { mainUI.commandMenuPopup(); } break; Loading @@ -159,7 +165,8 @@ public class BluetoothRemoteControl { // - if we are on autofocus, then adjust zoom. if( main_activity.getPreview().getCurrentFocusValue() != null && main_activity.getPreview().getCurrentFocusValue().equals("focus_mode_manual2") ) { main_activity.changeFocusDistance(-25, false); } else { } else { // Adjust zoom main_activity.zoomIn(); } Loading @@ -169,7 +176,8 @@ public class BluetoothRemoteControl { if( !mainUI.processRemoteDownButton() ) { if( main_activity.getPreview().getCurrentFocusValue() != null && main_activity.getPreview().getCurrentFocusValue().equals("focus_mode_manual2") ) { main_activity.changeFocusDistance(25, false); } else { } else { // Adjust zoom main_activity.zoomOut(); } Loading @@ -186,7 +194,8 @@ public class BluetoothRemoteControl { default: break; } } else { } else { if( MyDebug.LOG ) Log.d(TAG, "Other remote event"); } Loading @@ -196,7 +205,7 @@ public class BluetoothRemoteControl { public boolean remoteConnected() { /*if( true ) return true; // test*/ return mRemoteConnected; return is_connected; } // TODO: refactor for a filter than receives generic remote control intents Loading Loading @@ -228,16 +237,18 @@ public class BluetoothRemoteControl { Log.d(TAG, "Remote enabled, starting service"); main_activity.bindService(gattServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE); main_activity.registerReceiver(remoteControlCommandReceiver, makeRemoteCommandIntentFilter()); } else { } else { if( MyDebug.LOG ) Log.d(TAG, "Remote disabled, stopping service"); // Stop the service if necessary try { main_activity.unregisterReceiver(remoteControlCommandReceiver); main_activity.unbindService(mServiceConnection); mRemoteConnected = false; // Unbinding closes the connection, of course is_connected = false; // Unbinding closes the connection, of course main_activity.getMainUI().updateRemoteConnectionIcon(); } catch (IllegalArgumentException e){ } catch(IllegalArgumentException e){ if( MyDebug.LOG ) Log.d(TAG, "Remote Service was not running, that's fine"); } Loading @@ -252,9 +263,10 @@ public class BluetoothRemoteControl { try { main_activity.unregisterReceiver(remoteControlCommandReceiver); main_activity.unbindService(mServiceConnection); mRemoteConnected = false; // Unbinding closes the connection, of course is_connected = false; // Unbinding closes the connection, of course main_activity.getMainUI().updateRemoteConnectionIcon(); } catch (IllegalArgumentException e){ } catch(IllegalArgumentException e){ Log.e(TAG, "Remote Service was not running, that's strange"); e.printStackTrace(); } Loading @@ -273,8 +285,8 @@ public class BluetoothRemoteControl { } SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(main_activity); boolean remote_enabled = sharedPreferences.getBoolean(PreferenceKeys.EnableRemote, false); mRemoteDeviceType = sharedPreferences.getString(PreferenceKeys.RemoteType, "undefined"); mRemoteDeviceAddress = sharedPreferences.getString(PreferenceKeys.RemoteName, "undefined"); return remote_enabled && !mRemoteDeviceAddress.equals("undefined"); remoteDeviceType = sharedPreferences.getString(PreferenceKeys.RemoteType, "undefined"); remoteDeviceAddress = sharedPreferences.getString(PreferenceKeys.RemoteName, "undefined"); return remote_enabled && !remoteDeviceAddress.equals("undefined"); } }
app/src/main/java/net/sourceforge/opencamera/remotecontrol/DeviceScanner.java +48 −62 File changed.Preview size limit exceeded, changes collapsed. Show changes
app/src/main/java/net/sourceforge/opencamera/remotecontrol/KrakenGattAttributes.java +0 −3 Original line number Diff line number Diff line Loading @@ -10,9 +10,6 @@ import java.util.UUID; * Bluetooth Low Energy */ public class KrakenGattAttributes { // The Kraken Smart Housing advertises itself as a heart measurement device, talk about // lazy devs... //public static final UUID HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb"); public static final UUID CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); //public static final UUID KRAKEN_SENSORS_SERVICE = UUID.fromString("00001623-1212-efde-1523-785feabcd123"); Loading