diff --git a/Banglejs.md b/Banglejs.md new file mode 100644 index 000000000..f5621a002 --- /dev/null +++ b/Banglejs.md @@ -0,0 +1,12 @@ + +adb install app/build/outputs/apk/debug/app-debug.apk + +`t:"notify", id:id, src,title,subject,body,sender,tel` - new notification +`t:"notify-", id:id` - delete notification +`t:"alarm", d:[{h,m},...]` - set alarms +`t:"find", n:bool` - findDevice +`t:"vibrate", n:int` - vibrate +`t:"weather", temp,hum,txt,wind,loc` - weather report + +"musicstate", state,position,shuffle,repeat +"musicinfo", artist,album,track,dur,c(track count),n(track num) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java index bee2f3e5d..1bcbb39d0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java @@ -49,11 +49,12 @@ public class BangleJSCoordinator extends AbstractDeviceCoordinator { @Override public DeviceType getSupportedType(GBDeviceCandidate candidate) { String name = candidate.getDevice().getName(); - if (name != null && name.startsWith("Bangle.js")) { + // FIXME - disabled for debug + //if (name != null && name.startsWith("Bangle.js")) { return DeviceType.BANGLEJS; - } + //} - return DeviceType.UNKNOWN; + //return DeviceType.UNKNOWN; } @Override @@ -74,12 +75,12 @@ public class BangleJSCoordinator extends AbstractDeviceCoordinator { @Override public boolean supportsWeather() { - return false; + return true; } @Override public boolean supportsFindDevice() { - return false; + return true; } @Override @@ -114,7 +115,7 @@ public class BangleJSCoordinator extends AbstractDeviceCoordinator { @Override public int getAlarmSlotCount() { - return 0; + return 10; } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java index 77b5086a2..80fd5fae5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java @@ -3,6 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.banglejs; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.List; import java.util.TimeZone; import java.util.UUID; @@ -11,14 +12,18 @@ import java.util.UUID; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.net.Uri; +import android.widget.Toast; import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.json.JSONObject; +import org.json.JSONArray; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo; import nodomain.freeyourgadget.gadgetbridge.devices.banglejs.BangleJSConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1Constants; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.Alarm; import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; @@ -30,6 +35,8 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; +import nodomain.freeyourgadget.gadgetbridge.util.GB; public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { private static final Logger LOG = LoggerFactory.getLogger(BangleJSDeviceSupport.class); @@ -37,6 +44,8 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { public BluetoothGattCharacteristic rxCharacteristic = null; public BluetoothGattCharacteristic txCharacteristic = null; + private String receivedLine = ""; + public BangleJSDeviceSupport() { super(LOG); addSupportedService(BangleJSConstants.UUID_SERVICE_NORDIC_UART); @@ -94,8 +103,16 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { } if (BangleJSConstants.UUID_CHARACTERISTIC_NORDIC_UART_RX.equals(characteristic.getUuid())) { byte chars[] = characteristic.getValue(); - - LOG.info("RX: " + chars); + String packetStr = new String(chars); + LOG.info("RX: " + packetStr); + receivedLine += packetStr; + while (receivedLine.indexOf("\n")>=0) { + int p = receivedLine.indexOf("\n"); + String line = receivedLine.substring(0,p-1); + receivedLine = receivedLine.substring(p+1); + LOG.info("RX LINE: " + line); + // TODO: parse this into JSON and handle it + } } return false; } @@ -113,27 +130,92 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onNotification(NotificationSpec notificationSpec) { + try { + TransactionBuilder builder = performInitialized("onNotification"); + JSONObject o = new JSONObject(); + o.put("t", "notify"); + o.put("id", notificationSpec.getId()); + o.put("src", notificationSpec.sourceName); + o.put("title", notificationSpec.title); + o.put("subject", notificationSpec.subject); + o.put("body", notificationSpec.body); + o.put("sender", notificationSpec.sender); + o.put("tel", notificationSpec.phoneNumber); + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error setting notification: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override public void onDeleteNotification(int id) { - + try { + TransactionBuilder builder = performInitialized("onDeleteNotification"); + JSONObject o = new JSONObject(); + o.put("t", "notify-"); + o.put("id", id); + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error deleting notification: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override public void onSetTime() { - + try { + TransactionBuilder builder = performInitialized("setTime"); + setTime(builder); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error setting time: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override public void onSetAlarms(ArrayList alarms) { + try { + TransactionBuilder builder = performInitialized("onSetAlarms"); + JSONObject o = new JSONObject(); + o.put("t", "alarm"); + JSONArray jsonalarms = new JSONArray(); + o.put("d", jsonalarms); + for (Alarm alarm : alarms) { + if (!alarm.getEnabled()) continue; + JSONObject jsonalarm = new JSONObject(); + jsonalarms.put(jsonalarm); + + Calendar calendar = AlarmUtils.toCalendar(alarm); + // TODO: getRepetition to ensure it only happens on correct day? + jsonalarm.put("h", alarm.getHour()); + jsonalarm.put("m", alarm.getMinute()); + } + + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error setting alarms: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override public void onSetCallState(CallSpec callSpec) { - + try { + TransactionBuilder builder = performInitialized("onSetCallState"); + JSONObject o = new JSONObject(); + o.put("t", "call"); + String cmdString[] = {"","undefined","accept","incoming","outgoing","reject","start","end"}; + o.put("cmd", cmdString[callSpec.command]); + o.put("name", callSpec.name); + o.put("number", callSpec.number); + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error setting call state: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override @@ -143,12 +225,39 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onSetMusicState(MusicStateSpec stateSpec) { - + try { + TransactionBuilder builder = performInitialized("onSetMusicState"); + JSONObject o = new JSONObject(); + o.put("t", "musicstate"); + String musicStates[] = {"play","pause","stop",""}; + o.put("state", musicStates[stateSpec.state]); + o.put("position", stateSpec.position); + o.put("shuffle", stateSpec.shuffle); + o.put("repeat", stateSpec.repeat); + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error setting Music state: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override public void onSetMusicInfo(MusicSpec musicSpec) { - + try { + TransactionBuilder builder = performInitialized("onSetMusicInfo"); + JSONObject o = new JSONObject(); + o.put("t", "musicinfo"); + o.put("artist", musicSpec.artist); + o.put("album", musicSpec.album); + o.put("track", musicSpec.track); + o.put("dur", musicSpec.duration); + o.put("c", musicSpec.trackCount); + o.put("n", musicSpec.trackNr); + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error setting Music info: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override @@ -208,12 +317,30 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onFindDevice(boolean start) { - + try { + TransactionBuilder builder = performInitialized("onFindDevice"); + JSONObject o = new JSONObject(); + o.put("t", "find"); + o.put("n", start); + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error finding device: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override public void onSetConstantVibration(int integer) { - + try { + TransactionBuilder builder = performInitialized("onSetConstantVibration"); + JSONObject o = new JSONObject(); + o.put("t", "vibrate"); + o.put("n", integer); + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error vibrating: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override @@ -258,6 +385,19 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onSendWeather(WeatherSpec weatherSpec) { - + try { + TransactionBuilder builder = performInitialized("onSendWeather"); + JSONObject o = new JSONObject(); + o.put("t", "weather"); + o.put("temp", weatherSpec.currentTemp); + o.put("hum", weatherSpec.currentHumidity); + o.put("txt", weatherSpec.currentCondition); + o.put("wind", weatherSpec.windSpeed); + o.put("loc", weatherSpec.location); + uartTx(builder, "\u0010gb("+o.toString()+")\n"); + builder.queue(getQueue()); + } catch (Exception e) { + GB.toast(getContext(), "Error showing weather: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } }