diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGATTServer.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGATTServer.java deleted file mode 100644 index 3820ab398..000000000 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGATTServer.java +++ /dev/null @@ -1,228 +0,0 @@ -/* Copyright (C) 2018-2019 Andreas Böhler, Daniele Gobbetti - based on code from BlueWatcher, https://github.com/masterjc/bluewatcher - - This file is part of Gadgetbridge. - - Gadgetbridge is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Gadgetbridge 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . */ -package nodomain.freeyourgadget.gadgetbridge.service.devices.casiogb6900; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; -import android.bluetooth.BluetoothGattServer; -import android.bluetooth.BluetoothGattServerCallback; -import android.bluetooth.BluetoothGattService; -import android.bluetooth.BluetoothManager; -import android.content.Context; -import android.content.Intent; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import androidx.localbroadcastmanager.content.LocalBroadcastManager; -import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl; -import nodomain.freeyourgadget.gadgetbridge.devices.casiogb6900.CasioGB6900Constants; -import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; -import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; -import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService; - -class CasioGATTServer extends BluetoothGattServerCallback { - private static final Logger LOG = LoggerFactory.getLogger(CasioGATTServer.class); - - private Context mContext; - private BluetoothGattServer mBluetoothGattServer; - private CasioGB6900DeviceSupport mDeviceSupport = null; - private final GBDeviceEventMusicControl musicCmd = new GBDeviceEventMusicControl(); - - CasioGATTServer(Context context, CasioGB6900DeviceSupport deviceSupport) { - mContext = context; - mDeviceSupport = deviceSupport; - } - - public void setContext(Context ctx) { - mContext = ctx; - } - - boolean initialize() { - if(mContext == null) { - return false; - } - - BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); - if (bluetoothManager == null) { - return false; - } - mBluetoothGattServer = bluetoothManager.openGattServer(mContext, this); - if (mBluetoothGattServer == null) { - return false; - } - - BluetoothGattService casioGATTService = new BluetoothGattService(CasioGB6900Constants.WATCH_CTRL_SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY); - BluetoothGattCharacteristic bluetoothgGATTCharacteristic = new BluetoothGattCharacteristic(CasioGB6900Constants.KEY_CONTAINER_CHARACTERISTIC_UUID, BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, BluetoothGattCharacteristic.PERMISSION_WRITE); - bluetoothgGATTCharacteristic.setValue(new byte[0]); - - BluetoothGattCharacteristic bluetoothgGATTCharacteristic2 = new BluetoothGattCharacteristic(CasioGB6900Constants.NAME_OF_APP_CHARACTERISTIC_UUID, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED); - bluetoothgGATTCharacteristic2.setValue(CasioGB6900Constants.MUSIC_MESSAGE.getBytes()); - - BluetoothGattDescriptor bluetoothGattDescriptor = new BluetoothGattDescriptor(CasioGB6900Constants.CCC_DESCRIPTOR_UUID, BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE); - bluetoothGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); - - bluetoothgGATTCharacteristic2.addDescriptor(bluetoothGattDescriptor); - - casioGATTService.addCharacteristic(bluetoothgGATTCharacteristic); - casioGATTService.addCharacteristic(bluetoothgGATTCharacteristic2); - mBluetoothGattServer.addService(casioGATTService); - - return true; - } - - @Override - public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) { - - if (!characteristic.getUuid().equals(CasioGB6900Constants.NAME_OF_APP_CHARACTERISTIC_UUID)) { - LOG.warn("unexpected read request"); - return; - } - - LOG.info("will send response to read request from device: " + device.getAddress()); - - if (!this.mBluetoothGattServer.sendResponse(device, requestId, 0, offset, CasioGB6900Constants.MUSIC_MESSAGE.getBytes())) { - LOG.warn("error sending response"); - } - } - private GBDeviceEventMusicControl.Event parse3Button(int button) { - GBDeviceEventMusicControl.Event event; - switch(button) { - case 3: - event = GBDeviceEventMusicControl.Event.NEXT; - break; - case 2: - event = GBDeviceEventMusicControl.Event.PREVIOUS; - break; - case 1: - event = GBDeviceEventMusicControl.Event.PLAYPAUSE; - break; - default: - LOG.warn("Unhandled button received: " + button); - event = GBDeviceEventMusicControl.Event.UNKNOWN; - } - return event; - } - - private GBDeviceEventMusicControl.Event parse2Button(int button) { - GBDeviceEventMusicControl.Event event; - switch(button) { - case 2: - event = GBDeviceEventMusicControl.Event.PLAYPAUSE; - break; - case 1: - event = GBDeviceEventMusicControl.Event.NEXT; - break; - default: - LOG.warn("Unhandled button received: " + button); - event = GBDeviceEventMusicControl.Event.UNKNOWN; - } - return event; - } - - @Override - public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, - boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { - - if (!characteristic.getUuid().equals(CasioGB6900Constants.KEY_CONTAINER_CHARACTERISTIC_UUID)) { - LOG.warn("unexpected write request"); - return; - } - - if(mDeviceSupport == null) { - LOG.warn("mDeviceSupport is null, did initialization complete?"); - return; - } - - if((value[0] & 0x03) == 0) { - int button = value[1] & 0x0f; - LOG.info("Button pressed: " + button); - switch(mDeviceSupport.getModel()) - { - case MODEL_CASIO_5600B: - musicCmd.event = parse2Button(button); - break; - case MODEL_CASIO_6900B: - musicCmd.event = parse3Button(button); - break; - case MODEL_CASIO_GENERIC: - musicCmd.event = parse3Button(button); - break; - default: - LOG.warn("Unhandled device"); - return; - } - mDeviceSupport.evaluateGBDeviceEvent(musicCmd); - mDeviceSupport.evaluateGBDeviceEvent(musicCmd); - } - else { - LOG.info("received from device: " + value.toString()); - } - } - - @Override - public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { - - LOG.info("Connection state change for device: " + device.getAddress() + " status = " + status + " newState = " + newState); - if (newState == BluetoothGattServer.STATE_DISCONNECTED) { - LOG.info("CASIO GATT server noticed disconnect."); - } - if (newState == BluetoothGattServer.STATE_CONNECTED) { - GBDevice.State devState = mDeviceSupport.getDevice().getState(); - Intent deviceCommunicationServiceIntent = new Intent(mContext, DeviceCommunicationService.class); - if (devState.equals(GBDevice.State.WAITING_FOR_RECONNECT) || devState.equals(GBDevice.State.NOT_CONNECTED)) { - LOG.info("Forcing re-connect because GATT server has been reconnected."); - deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_CONNECT); - deviceCommunicationServiceIntent.putExtra(GBDevice.EXTRA_DEVICE, device); - LocalBroadcastManager.getInstance(mContext).sendBroadcast(deviceCommunicationServiceIntent); - //PendingIntent reconnectPendingIntent = PendingIntent.getService(mContext, 2, deviceCommunicationServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT); - //builder.addAction(R.drawable.ic_notification, context.getString(R.string.controlcenter_connect), reconnectPendingIntent); - } - } - } - - @Override - public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, - boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { - - LOG.info("onDescriptorWriteRequest() notifications enabled = " + (value[0] == 1)); - if (!this.mBluetoothGattServer.sendResponse(device, requestId, 0, offset, value)) { - LOG.warn("onDescriptorWriteRequest() error sending response!"); - } - } - - @Override - public void onServiceAdded(int status, BluetoothGattService service) { - LOG.info("onServiceAdded() status = " + status + " service = " + service.getUuid()); - } - - @Override - public void onNotificationSent(BluetoothDevice bluetoothDevice, int status) { - LOG.info("onNotificationSent() status = " + status + " to device " + bluetoothDevice.getAddress()); - } - - void close() { - if (mBluetoothGattServer != null) { - mBluetoothGattServer.clearServices(); - mBluetoothGattServer.close(); - mBluetoothGattServer = null; - } - } - -} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGATTThread.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGATTThread.java deleted file mode 100644 index 97f3c4401..000000000 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGATTThread.java +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (C) 2018-2019 Andreas Böhler - based on code from BlueWatcher, https://github.com/masterjc/bluewatcher - - This file is part of Gadgetbridge. - - Gadgetbridge is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Gadgetbridge 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . */ -package nodomain.freeyourgadget.gadgetbridge.service.devices.casiogb6900; -import android.content.Context; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CasioGATTThread extends Thread { - CasioGATTServer mServer = null; - private static final Logger LOG = LoggerFactory.getLogger(CasioGATTThread.class); - private boolean mStopFlag = false; - private final Object waitObject = new Object(); - - public CasioGATTThread(Context context, CasioGB6900DeviceSupport deviceSupport) - { - mServer = new CasioGATTServer(context, deviceSupport); - } - - public void setContext(Context ctx) { - mServer.setContext(ctx); - } - - @Override - public void run() { - if (!mServer.initialize()) { - LOG.error("Error initializing CasioGATTServer. Has the context been set?"); - return; - } - - long waitTime = 60 * 1000; - - while (!mStopFlag) { - synchronized (waitObject) { - try { - waitObject.wait(waitTime); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - if (mStopFlag) { - break; - } - } - mServer.close(); - } - - public void quit() { - mStopFlag = true; - synchronized (waitObject) { - waitObject.notify(); - } - } - - -} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGB6900DeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGB6900DeviceSupport.java index 6b1d5c7e4..877f7c170 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGB6900DeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casiogb6900/CasioGB6900DeviceSupport.java @@ -17,12 +17,13 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.casiogb6900; -import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; -import android.content.Context; import android.net.Uri; +import android.widget.Toast; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +36,7 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone; +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl; import nodomain.freeyourgadget.gadgetbridge.devices.casiogb6900.CasioGB6900Constants; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.Alarm; @@ -48,22 +50,24 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService; +import nodomain.freeyourgadget.gadgetbridge.service.btle.ServerTransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.casiogb6900.operations.InitOperation; +import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { private static final Logger LOG = LoggerFactory.getLogger(CasioGB6900DeviceSupport.class); private ArrayList mCasioCharacteristics = new ArrayList(); - private CasioGATTThread mThread; private CasioHandlerThread mHandlerThread = null; private MusicSpec mBufferMusicSpec = null; private MusicStateSpec mBufferMusicStateSpec = null; private BluetoothGatt mBtGatt = null; private CasioGB6900Constants.Model mModel = CasioGB6900Constants.Model.MODEL_CASIO_GENERIC; - private byte[] mBleSettings = null; + private boolean mFirstConnect = false; - private static final int mCasioSleepTime = 80; + private static final int mCasioSleepTime = 50; public CasioGB6900DeviceSupport() { super(LOG); @@ -79,14 +83,30 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { addSupportedService(CasioGB6900Constants.TX_POWER_SERVICE_UUID); addSupportedService(CasioGB6900Constants.LINK_LOSS_SERVICE); addSupportedService(CasioGB6900Constants.IMMEDIATE_ALERT_SERVICE_UUID); - mThread = new CasioGATTThread(getContext(), this); + + BluetoothGattService casioGATTService = new BluetoothGattService(CasioGB6900Constants.WATCH_CTRL_SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY); + BluetoothGattCharacteristic bluetoothGATTCharacteristic = new BluetoothGattCharacteristic(CasioGB6900Constants.KEY_CONTAINER_CHARACTERISTIC_UUID, BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, BluetoothGattCharacteristic.PERMISSION_WRITE); + bluetoothGATTCharacteristic.setValue(new byte[0]); + + BluetoothGattCharacteristic bluetoothGATTCharacteristic2 = new BluetoothGattCharacteristic(CasioGB6900Constants.NAME_OF_APP_CHARACTERISTIC_UUID, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED); + bluetoothGATTCharacteristic2.setValue(CasioGB6900Constants.MUSIC_MESSAGE.getBytes()); + + BluetoothGattDescriptor bluetoothGattDescriptor = new BluetoothGattDescriptor(CasioGB6900Constants.CCC_DESCRIPTOR_UUID, BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE); + bluetoothGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); + + bluetoothGATTCharacteristic2.addDescriptor(bluetoothGattDescriptor); + + casioGATTService.addCharacteristic(bluetoothGATTCharacteristic); + casioGATTService.addCharacteristic(bluetoothGATTCharacteristic2); + + addSupportedServerService(casioGATTService); } @Override - public void setContext(GBDevice gbDevice, BluetoothAdapter btAdapter, Context context) { - super.setContext(gbDevice, btAdapter, context); - mThread.setContext(context); - mThread.start(); + public boolean connectFirstTime() { + GB.toast(getContext(), "After first connect, disable and enable bluetooth on your Casio watch to really connect", Toast.LENGTH_SHORT, GB.INFO); + mFirstConnect = true; + return super.connect(); } @Override @@ -103,12 +123,6 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { mHandlerThread.interrupt(); mHandlerThread = null; } - - if(mThread != null) { - mThread.quit(); - mThread.interrupt(); - mThread = null; - } } @Override @@ -121,6 +135,14 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { protected TransactionBuilder initializeDevice(TransactionBuilder builder) { LOG.info("Initializing"); + if(mFirstConnect) { + gbDevice.setState(GBDevice.State.INITIALIZED); + gbDevice.sendDeviceUpdateIntent(getContext()); + getDevice().setFirmwareVersion("N/A"); + getDevice().setFirmwareVersion2("N/A"); + return builder; + } + String name = gbDevice.getName(); if(name.contains("5600B")) { @@ -131,17 +153,27 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { mModel = CasioGB6900Constants.Model.MODEL_CASIO_GENERIC; } + try { + new InitOperation(this, builder).perform(); + } catch (IOException e) { + GB.toast(getContext(), "Initializing Casio watch failed", Toast.LENGTH_SHORT, GB.ERROR, e); + } + /* gbDevice.setState(GBDevice.State.INITIALIZING); gbDevice.sendDeviceUpdateIntent(getContext()); + */ + + getDevice().setFirmwareVersion("N/A"); + getDevice().setFirmwareVersion2("N/A"); - addCharacteristics(); builder.setGattCallback(this); - enableNotifications(builder, true); - configureWatch(builder); + addCharacteristics(); + enableNotifications(builder, true); + LOG.info("Initialization Done"); return builder; @@ -251,52 +283,22 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { } } - private void readBleSettings() { - try { - TransactionBuilder builder = performInitialized("readBleSettings"); - builder.read(getCharacteristic(CasioGB6900Constants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID)); - builder.queue(getQueue()); - } catch(IOException e) { - LOG.error("Error reading BLE settings: " + e.getMessage()); - } - } - - private void configureBleSettings() { - // These values seem to improve connection stability _on my phone_ - // Maybe they should be configurable? - int slaveLatency = 2; - int connInterval = 300; - - mBleSettings[5] = (byte)(connInterval & 0xff); - mBleSettings[6] = (byte)((connInterval >> 8) & 0xff); - mBleSettings[7] = (byte)(slaveLatency & 0xff); - mBleSettings[8] = (byte)((slaveLatency >> 8) & 0xff); - - mBleSettings[9] = 0; // Setting for Disconnect!? - } - - private void writeBleSettings() { - try { - TransactionBuilder builder = performInitialized("writeBleSettings"); - builder.write(getCharacteristic(CasioGB6900Constants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID), mBleSettings); - builder.queue(getQueue()); - } catch(IOException e) { - LOG.error("Error writing BLE settings: " + e.getMessage()); - } - } private boolean handleInitResponse(byte data) { boolean handled = false; switch(data) { case (byte) 1: LOG.info("Initialization done, setting state to INITIALIZED"); - if(mHandlerThread == null) { - mHandlerThread = new CasioHandlerThread(getDevice(), getContext(), this); + if(mHandlerThread != null) { + if(mHandlerThread.isAlive()) { + mHandlerThread.quit(); + mHandlerThread.interrupt(); + } } + mHandlerThread = new CasioHandlerThread(getDevice(), getContext(), this); mHandlerThread.start(); gbDevice.setState(GBDevice.State.INITIALIZED); gbDevice.sendDeviceUpdateIntent(getContext()); - readBleSettings(); handled = true; break; default: @@ -351,7 +353,7 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { return true; } - private boolean handleCasioCom(byte[] data) { + private boolean handleCasioCom(byte[] data, boolean handleTime) { boolean handled = false; if(data.length < 3) { @@ -365,7 +367,11 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { handled = handleInitResponse(data[2]); break; case 2: - handled = handleTimeRequests(data[2]); + if(handleTime) { + handled = handleTimeRequests(data[2]); + } else { + handled = true; + } break; case 7: handled = handleServerFeatureRequests(data[2]); @@ -376,7 +382,7 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { @Override public boolean onCharacteristicRead(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic, int status) { + BluetoothGattCharacteristic characteristic, int status) { UUID characteristicUUID = characteristic.getUuid(); byte[] data = characteristic.getValue(); @@ -391,63 +397,6 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { } LOG.info(str); } - else if(characteristicUUID.equals(CasioGB6900Constants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID)) { - mBleSettings = data; - String str = "Read Casio Setting for BLE: "; - for(int i=0; i> 6) & 0x03; - //LOG.info("Call Alert: " + callAlert); - //int mailAlert = (data[0] >> 2) & 0x03; - //LOG.info("Mail Alert: " + mailAlert); - //int snsAlert = (data[2] >> 4) & 0x03; - //LOG.info("SNS Alert: " + snsAlert); - //int calAlert = (data[1] >> 6) & 0x03; - //LOG.info("Calendart Alert: " + calAlert); - //int otherAlert = (data[0] & 0x03); - //LOG.info("Other Alert: " + otherAlert); - //int vibrationValue = (data[3] & 0x0f); - //LOG.info("Vibration Value: " + vibrationValue); - //int alarmValue = (data[3] >> 4) & 0x0f; - // Vibration pattern; A = 0, B = 1, C = 2 - //LOG.info("Alarm Value: " + alarmValue); - //int animationValue = data[4] & 0x40; - // Length of Alarm, only 2, 5 and 10 possible - //LOG.info("Animation Value: " + animationValue); - // 0 = on - // 64 = off - //int useDisableMtuReqBit = data[4] & 0x08; - // 8 = on - // 0 = off!? - //LOG.info("useDisableMtuReqBit: " + useDisableMtuReqBit); - - //int slaveLatency = ((data[7] & 0xff) | ((data[8] & 0xff) << 8)); - //int connInterval = ((data[5] & 0xff) | ((data[6] & 0xff) << 8)); - //LOG.info("Slave Latency: " + slaveLatency); - //LOG.info("Connection Interval: " + connInterval); - //LOG.info(str); - - configureBleSettings(); - writeBleSettings(); - } else { return super.onCharacteristicRead(gatt, characteristic, status); } @@ -466,11 +415,11 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { return true; if(characteristicUUID.equals(CasioGB6900Constants.CASIO_A_NOT_W_REQ_NOT)) { - handled = handleCasioCom(data); + handled = handleCasioCom(data, true); } if(characteristicUUID.equals(CasioGB6900Constants.CASIO_A_NOT_COM_SET_NOT)) { - handled = handleCasioCom(data); + handled = handleCasioCom(data, false); } if(characteristicUUID.equals(CasioGB6900Constants.ALERT_LEVEL_CHARACTERISTIC_UUID)) { @@ -481,7 +430,7 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { else { findPhoneEvent.event = GBDeviceEventFindPhone.Event.STOP; } - evaluateGBDeviceEvent(findPhoneEvent); + evaluateGBDeviceEvent(findPhoneEvent); handled = true; } @@ -501,6 +450,8 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { } private void showNotification(byte icon, String title, String message) { + if(!isConnected()) + return; try { TransactionBuilder builder = performInitialized("showNotification"); int len; @@ -558,6 +509,10 @@ public class CasioGB6900DeviceSupport extends AbstractBTLEDeviceSupport { public void onSetAlarms(ArrayList alarms) { int alarmOffset = 4; byte[] data = new byte[20]; + + if(!isConnected()) + return; + for(int i=0; i. */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.casiogb6900.operations; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.UUID; + +import nodomain.freeyourgadget.gadgetbridge.devices.casiogb6900.CasioGB6900Constants; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; +import nodomain.freeyourgadget.gadgetbridge.service.devices.casiogb6900.CasioGB6900DeviceSupport; + +public class InitOperation extends AbstractBTLEOperation { + private static final Logger LOG = LoggerFactory.getLogger(InitOperation.class); + + private final TransactionBuilder builder; + private byte[] mBleSettings = null; + + + public InitOperation(CasioGB6900DeviceSupport support, TransactionBuilder builder) { + super(support); + this.builder = builder; + builder.setGattCallback(this); + } + + @Override + protected void doPerform() throws IOException { + builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext())); + TransactionBuilder builder = getSupport().createTransactionBuilder("readBleSettings"); + builder.setGattCallback(this); + builder.read(getCharacteristic(CasioGB6900Constants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID)); + getSupport().performImmediately(builder); + } + + @Override + public TransactionBuilder performInitialized(String taskName) throws IOException { + throw new UnsupportedOperationException("This IS the initialization class, you cannot call this method"); + } + + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic) { + UUID characteristicUUID = characteristic.getUuid(); + LOG.info("Unhandled characteristic changed: " + characteristicUUID); + return super.onCharacteristicChanged(gatt, characteristic); + } + + private void configureBleSettings() { + // These values seem to improve connection stability _on my phone_ + // Maybe they should be configurable? + int slaveLatency = 2; + int connInterval = 300; + + mBleSettings[5] = (byte)(connInterval & 0xff); + mBleSettings[6] = (byte)((connInterval >> 8) & 0xff); + mBleSettings[7] = (byte)(slaveLatency & 0xff); + mBleSettings[8] = (byte)((slaveLatency >> 8) & 0xff); + + mBleSettings[9] = 0; // Setting for Disconnect!? + } + + private void writeBleSettings() { + try { + TransactionBuilder builder = getSupport().createTransactionBuilder("writeBleInit"); + builder.setGattCallback(this); + builder.write(getCharacteristic(CasioGB6900Constants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID), mBleSettings); + getSupport().performImmediately(builder); + } catch(IOException e) { + LOG.error("Error writing BLE settings: " + e.getMessage()); + } + } + + @Override + public boolean onCharacteristicRead(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic, int status) { + + UUID characteristicUUID = characteristic.getUuid(); + byte[] data = characteristic.getValue(); + + if(data.length == 0) + return true; + + if(characteristicUUID.equals(CasioGB6900Constants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID)) { + mBleSettings = data; + String str = "Read Casio Setting for BLE: "; + for(int i=0; i> 6) & 0x03; + //LOG.info("Call Alert: " + callAlert); + //int mailAlert = (data[0] >> 2) & 0x03; + //LOG.info("Mail Alert: " + mailAlert); + //int snsAlert = (data[2] >> 4) & 0x03; + //LOG.info("SNS Alert: " + snsAlert); + //int calAlert = (data[1] >> 6) & 0x03; + //LOG.info("Calendart Alert: " + calAlert); + //int otherAlert = (data[0] & 0x03); + //LOG.info("Other Alert: " + otherAlert); + //int vibrationValue = (data[3] & 0x0f); + //LOG.info("Vibration Value: " + vibrationValue); + //int alarmValue = (data[3] >> 4) & 0x0f; + // Vibration pattern; A = 0, B = 1, C = 2 + //LOG.info("Alarm Value: " + alarmValue); + //int animationValue = data[4] & 0x40; + // Length of Alarm, only 2, 5 and 10 possible + //LOG.info("Animation Value: " + animationValue); + // 0 = on + // 64 = off + //int useDisableMtuReqBit = data[4] & 0x08; + // 8 = on + // 0 = off!? + //LOG.info("useDisableMtuReqBit: " + useDisableMtuReqBit); + + //int slaveLatency = ((data[7] & 0xff) | ((data[8] & 0xff) << 8)); + //int connInterval = ((data[5] & 0xff) | ((data[6] & 0xff) << 8)); + //LOG.info("Slave Latency: " + slaveLatency); + //LOG.info("Connection Interval: " + connInterval); + //LOG.info(str); + + configureBleSettings(); + writeBleSettings(); + } + else { + return super.onCharacteristicRead(gatt, characteristic, status); + } + + return true; + } +}