diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/waspos/WaspOSConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/waspos/WaspOSConstants.java
new file mode 100644
index 000000000..df5c29378
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/waspos/WaspOSConstants.java
@@ -0,0 +1,28 @@
+/* Copyright (C) 2019-2020 Gordon Williams
+
+ 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.devices.waspos;
+
+import java.util.UUID;
+
+public final class WaspOSConstants {
+
+
+ public static final UUID UUID_SERVICE_NORDIC_UART = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
+ public static final UUID UUID_CHARACTERISTIC_NORDIC_UART_TX = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
+ public static final UUID UUID_CHARACTERISTIC_NORDIC_UART_RX = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
+
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/waspos/WaspOSCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/waspos/WaspOSCoordinator.java
new file mode 100644
index 000000000..772868713
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/waspos/WaspOSCoordinator.java
@@ -0,0 +1,167 @@
+/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele
+ Gobbetti, Gordon Williams, José Rebelo
+
+ 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.devices.waspos;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.bluetooth.le.ScanFilter;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Build;
+import android.os.ParcelUuid;
+
+import androidx.annotation.NonNull;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
+import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
+import nodomain.freeyourgadget.gadgetbridge.devices.waspos.WaspOSConstants;
+import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
+import nodomain.freeyourgadget.gadgetbridge.entities.Device;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
+import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
+
+public class WaspOSCoordinator extends AbstractDeviceCoordinator {
+
+ @Override
+ public DeviceType getDeviceType() {
+ return DeviceType.WASPOS;
+ }
+
+ @Override
+ public String getManufacturer() {
+ return "MicroPython";
+ }
+
+ @NonNull
+ @Override
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public Collection extends ScanFilter> createBLEScanFilters() {
+ // TODO: filter on name beginning Bangle.js? Doesn't appear to be built-in :(
+ // https://developer.android.com/reference/android/bluetooth/le/ScanFilter.Builder.html#setDeviceName(java.lang.String)
+ ParcelUuid hpService = new ParcelUuid(WaspOSConstants.UUID_SERVICE_NORDIC_UART);
+ ScanFilter filter = new ScanFilter.Builder().setServiceUuid(hpService).build();
+ return Collections.singletonList(filter);
+ }
+
+ @NonNull
+ @Override
+ public DeviceType getSupportedType(GBDeviceCandidate candidate) {
+ String name = candidate.getDevice().getName();
+ /* Filter by Espruino devices to avoid getting
+ the device chooser full of spam devices. */
+ if (name != null && (
+ name.startsWith("DS-D6") ||
+ name.startsWith("K9") ||
+ name.startsWith("PineTime") ||
+ name.startsWith("P8")))
+ return DeviceType.WASPOS;
+
+ return DeviceType.UNKNOWN;
+ }
+
+ @Override
+ public int getBondingStyle(){
+ return BONDING_STYLE_NONE;
+ }
+
+ @Override
+ public boolean supportsCalendarEvents() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsRealtimeData() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsWeather() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsFindDevice() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsActivityDataFetching() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsActivityTracking() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsScreenshots() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsSmartWakeup(GBDevice device) {
+ return false;
+ }
+
+ @Override
+ public boolean supportsHeartRateMeasurement(GBDevice device) {
+ return false;
+ }
+
+ @Override
+ public boolean supportsAppsManagement() {
+ return false;
+ }
+
+ @Override
+ public int getAlarmSlotCount() {
+ return 0;
+ }
+
+ @Override
+ public Class extends Activity> getAppsManagementActivity() {
+ return null;
+ }
+
+
+ @Override
+ protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) {
+ }
+
+ @Override
+ public Class extends Activity> getPairingActivity() {
+ return null;
+ }
+
+ @Override
+ public SampleProvider extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
+ return null;//new WaspOSSampleProvider(device, session);
+ }
+
+ @Override
+ public InstallHandler findInstallHandler(Uri uri, Context context) {
+ return null;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
index a71d3980e..7fdb68f14 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
@@ -91,6 +91,7 @@ public enum DeviceType {
VIBRATISSIMO(300, R.drawable.ic_device_lovetoy, R.drawable.ic_device_lovetoy_disabled, R.string.devicetype_vibratissimo),
SONY_SWR12(310, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_sonyswr12),
LIVEVIEW(320, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_liveview),
+ WASPOS(330, R.drawable.ic_device_pebble, R.drawable.ic_device_pebble_disabled, R.string.devicetype_waspos),
TEST(1000, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_test);
private final int key;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java
index bdf0a947a..95cb6c3f5 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java
@@ -81,6 +81,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.roidmi.RoidmiSupport
import nodomain.freeyourgadget.gadgetbridge.service.devices.sonyswr12.SonySWR12DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.tlw64.TLW64Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.vibratissimo.VibratissimoSupport;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.waspos.WaspOSDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.watch9.Watch9DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.xwatch.XWatchSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppe.ZeppESupport;
@@ -320,6 +321,8 @@ public class DeviceSupportFactory {
break;
case SONY_SWR12:
deviceSupport = new ServiceDeviceSupport(new SonySWR12DeviceSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
+ case WASPOS:
+ deviceSupport = new ServiceDeviceSupport(new WaspOSDeviceSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
}
if (deviceSupport != null) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/waspos/WaspOSDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/waspos/WaspOSDeviceSupport.java
new file mode 100644
index 000000000..39fbde24f
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/waspos/WaspOSDeviceSupport.java
@@ -0,0 +1,507 @@
+/* Copyright (C) 2019-2020 Andreas Shimokawa, Gordon Williams
+
+ 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.waspos;
+
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.content.Context;
+import android.net.Uri;
+import android.widget.Toast;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.SimpleTimeZone;
+import java.util.UUID;
+
+import nodomain.freeyourgadget.gadgetbridge.GBApplication;
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl;
+import nodomain.freeyourgadget.gadgetbridge.devices.waspos.WaspOSConstants;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
+import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
+import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
+import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
+import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
+import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
+import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
+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;
+import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
+
+public class WaspOSDeviceSupport extends AbstractBTLEDeviceSupport {
+ private static final Logger LOG = LoggerFactory.getLogger(WaspOSDeviceSupport.class);
+ private BluetoothGattCharacteristic rxCharacteristic = null;
+ private BluetoothGattCharacteristic txCharacteristic = null;
+
+ private String receivedLine = "";
+
+ public WaspOSDeviceSupport() {
+ super(LOG);
+ addSupportedService(WaspOSConstants.UUID_SERVICE_NORDIC_UART);
+ }
+
+ @Override
+ protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
+ LOG.info("Initializing");
+
+ gbDevice.setState(GBDevice.State.INITIALIZING);
+ gbDevice.sendDeviceUpdateIntent(getContext());
+
+ rxCharacteristic = getCharacteristic(WaspOSConstants.UUID_CHARACTERISTIC_NORDIC_UART_RX);
+ txCharacteristic = getCharacteristic(WaspOSConstants.UUID_CHARACTERISTIC_NORDIC_UART_TX);
+ builder.setGattCallback(this);
+ builder.notify(rxCharacteristic, true);
+
+ uartTx(builder, " \u0003"); // clear active line
+
+ Prefs prefs = GBApplication.getPrefs();
+ if (prefs.getBoolean("datetime_synconconnect", true))
+ setTime(builder);
+ //sendSettings(builder);
+
+ // get version
+
+ gbDevice.setState(GBDevice.State.INITIALIZED);
+ gbDevice.sendDeviceUpdateIntent(getContext());
+
+ LOG.info("Initialization Done");
+
+ return builder;
+ }
+
+ /// Write a string of data, and chunk it up
+ private void uartTx(TransactionBuilder builder, String str) {
+ LOG.info("UART TX: " + str);
+ byte[] bytes;
+ bytes = str.getBytes(StandardCharsets.ISO_8859_1);
+ for (int i=0;i8) l=8;
+ byte[] packet = new byte[l];
+ System.arraycopy(bytes, i, packet, 0, l);
+ builder.write(txCharacteristic, packet);
+ }
+ }
+
+ /// Write a string of data, and chunk it up
+ private void uartTxJSON(String taskName, JSONObject json) {
+ try {
+ TransactionBuilder builder = performInitialized(taskName);
+ uartTx(builder, "\u0010GB("+json.toString()+")\n");
+ builder.queue(getQueue());
+ } catch (IOException e) {
+ GB.toast(getContext(), "Error in "+taskName+": " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
+ }
+ }
+
+ private void handleUartRxLine(String line) {
+ LOG.info("UART RX LINE: " + line);
+
+ if (">Uncaught ReferenceError: \"gb\" is not defined".equals(line))
+ GB.toast(getContext(), "Gadgetbridge plugin not installed on Bangle.js", Toast.LENGTH_LONG, GB.ERROR);
+ else if (line.charAt(0)=='{') {
+ // JSON - we hope!
+ try {
+ JSONObject json = new JSONObject(line);
+ handleUartRxJSON(json);
+ } catch (JSONException e) {
+ GB.toast(getContext(), "Malformed JSON from Bangle.js: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
+ }
+ }
+ }
+
+ private void handleUartRxJSON(JSONObject json) throws JSONException {
+ switch (json.getString("t")) {
+ case "info":
+ GB.toast(getContext(), "Bangle.js: " + json.getString("msg"), Toast.LENGTH_LONG, GB.INFO);
+ break;
+ case "warn":
+ GB.toast(getContext(), "Bangle.js: " + json.getString("msg"), Toast.LENGTH_LONG, GB.WARN);
+ break;
+ case "error":
+ GB.toast(getContext(), "Bangle.js: " + json.getString("msg"), Toast.LENGTH_LONG, GB.ERROR);
+ break;
+ case "status": {
+ Context context = getContext();
+ if (json.has("bat")) {
+ int b = json.getInt("bat");
+ if (b<0) b=0;
+ if (b>100) b=100;
+ gbDevice.setBatteryLevel((short)b);
+ if (b < 30) {
+ gbDevice.setBatteryState(BatteryState.BATTERY_LOW);
+ GB.updateBatteryNotification(context.getString(R.string.notif_battery_low_percent, gbDevice.getName(), String.valueOf(b)), "", context);
+ } else {
+ gbDevice.setBatteryState(BatteryState.BATTERY_NORMAL);
+ GB.removeBatteryNotification(context);
+ }
+ }
+ if (json.has("volt"))
+ gbDevice.setBatteryVoltage((float)json.getDouble("volt"));
+ gbDevice.sendDeviceUpdateIntent(context);
+ } break;
+ case "findPhone": {
+ boolean start = json.has("n") && json.getBoolean("n");
+ GBDeviceEventFindPhone deviceEventFindPhone = new GBDeviceEventFindPhone();
+ deviceEventFindPhone.event = start ? GBDeviceEventFindPhone.Event.START : GBDeviceEventFindPhone.Event.STOP;
+ evaluateGBDeviceEvent(deviceEventFindPhone);
+ } break;
+ case "music": {
+ GBDeviceEventMusicControl deviceEventMusicControl = new GBDeviceEventMusicControl();
+ deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.valueOf(json.getString("n").toUpperCase());
+ evaluateGBDeviceEvent(deviceEventMusicControl);
+ } break;
+ case "call": {
+ GBDeviceEventCallControl deviceEventCallControl = new GBDeviceEventCallControl();
+ deviceEventCallControl.event = GBDeviceEventCallControl.Event.valueOf(json.getString("n").toUpperCase());
+ evaluateGBDeviceEvent(deviceEventCallControl);
+ } break;
+ case "notify" : {
+ GBDeviceEventNotificationControl deviceEvtNotificationControl = new GBDeviceEventNotificationControl();
+ // .title appears unused
+ deviceEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.valueOf(json.getString("n").toUpperCase());
+ if (json.has("id"))
+ deviceEvtNotificationControl.handle = json.getInt("id");
+ if (json.has("tel"))
+ deviceEvtNotificationControl.phoneNumber = json.getString("tel");
+ if (json.has("msg"))
+ deviceEvtNotificationControl.reply = json.getString("msg");
+ evaluateGBDeviceEvent(deviceEvtNotificationControl);
+ } break;
+ /*case "activity": {
+ WaspOSActivitySample sample = new WaspOSActivitySample();
+ sample.setTimestamp((int) (GregorianCalendar.getInstance().getTimeInMillis() / 1000L));
+ sample.setHeartRate(json.getInteger("hrm"));
+ try (DBHandler dbHandler = GBApplication.acquireDB()) {
+ Long userId = DBHelper.getUser(dbHandler.getDaoSession()).getId();
+ Long deviceId = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()).getId();
+ WaspOSSampleProvider provider = new WaspOSSampleProvider(getDevice(), dbHandler.getDaoSession());
+ sample.setDeviceId(deviceId);
+ sample.setUserId(userId);
+ provider.addGBActivitySample(sample);
+ } catch (Exception ex) {
+ LOG.warn("Error saving current heart rate: " + ex.getLocalizedMessage());
+ }
+ } break;*/
+ }
+ }
+
+ @Override
+ public boolean onCharacteristicChanged(BluetoothGatt gatt,
+ BluetoothGattCharacteristic characteristic) {
+ if (super.onCharacteristicChanged(gatt, characteristic)) {
+ return true;
+ }
+ if (WaspOSConstants.UUID_CHARACTERISTIC_NORDIC_UART_RX.equals(characteristic.getUuid())) {
+ byte[] chars = characteristic.getValue();
+ String packetStr = new String(chars);
+ LOG.info("RX: " + packetStr);
+ receivedLine += packetStr;
+ while (receivedLine.contains("\n")) {
+ int p = receivedLine.indexOf("\n");
+ String line = receivedLine.substring(0,p-1);
+ receivedLine = receivedLine.substring(p+1);
+ handleUartRxLine(line);
+ }
+ }
+ return false;
+ }
+
+
+ void setTime(TransactionBuilder builder) {
+ DateTimeFormatter dtf = DateTimeFormatter.ofPattern("(yyyy, MM, dd, HH, mm, ss)");
+ LocalDateTime now = LocalDateTime.now();
+ String cmd = "\u0010watch.rtc.set_localtime("+dtf.format(now)+")\n";
+ uartTx(builder, cmd+"\n");
+ }
+
+ @Override
+ public boolean useAutoConnect() {
+ return true;
+ }
+
+ @Override
+ public void onNotification(NotificationSpec notificationSpec) {
+ try {
+ 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);
+ uartTxJSON("onNotification", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public void onDeleteNotification(int id) {
+ try {
+ JSONObject o = new JSONObject();
+ o.put("t", "notify-");
+ o.put("id", id);
+ uartTxJSON("onDeleteNotification", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+ }
+
+ @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 extends Alarm> alarms) {
+ try {
+ 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());
+ }
+ uartTxJSON("onSetAlarms", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public void onSetCallState(CallSpec callSpec) {
+ try {
+ 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);
+ uartTxJSON("onSetCallState", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+}
+
+ @Override
+ public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) {
+
+ }
+
+ @Override
+ public void onSetMusicState(MusicStateSpec stateSpec) {
+ try {
+ 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);
+ uartTxJSON("onSetMusicState", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public void onSetMusicInfo(MusicSpec musicSpec) {
+ try {
+ 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);
+ uartTxJSON("onSetMusicInfo", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public void onEnableRealtimeSteps(boolean enable) {
+
+ }
+
+ @Override
+ public void onInstallApp(Uri uri) {
+
+ }
+
+ @Override
+ public void onAppInfoReq() {
+
+ }
+
+ @Override
+ public void onAppStart(UUID uuid, boolean start) {
+
+ }
+
+ @Override
+ public void onAppDelete(UUID uuid) {
+
+ }
+
+ @Override
+ public void onAppConfiguration(UUID appUuid, String config, Integer id) {
+
+ }
+
+ @Override
+ public void onAppReorder(UUID[] uuids) {
+
+ }
+
+ @Override
+ public void onFetchRecordedData(int dataTypes) {
+
+ }
+
+ @Override
+ public void onReset(int flags) {
+
+ }
+
+ @Override
+ public void onHeartRateTest() {
+
+ }
+
+ @Override
+ public void onEnableRealtimeHeartRateMeasurement(boolean enable) {
+
+ }
+
+ @Override
+ public void onFindDevice(boolean start) {
+ try {
+ JSONObject o = new JSONObject();
+ o.put("t", "find");
+ o.put("n", start);
+ uartTxJSON("onFindDevice", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public void onSetConstantVibration(int integer) {
+ try {
+ JSONObject o = new JSONObject();
+ o.put("t", "vibrate");
+ o.put("n", integer);
+ uartTxJSON("onSetConstantVibration", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public void onScreenshotReq() {
+
+ }
+
+ @Override
+ public void onEnableHeartRateSleepSupport(boolean enable) {
+
+ }
+
+ @Override
+ public void onSetHeartRateMeasurementInterval(int seconds) {
+
+ }
+
+ @Override
+ public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) {
+
+ }
+
+ @Override
+ public void onDeleteCalendarEvent(byte type, long id) {
+
+ }
+
+ @Override
+ public void onSendConfiguration(String config) {
+
+ }
+
+ @Override
+ public void onReadConfiguration(String config) {
+
+ }
+
+ @Override
+ public void onTestNewFunction() {
+
+ }
+
+ @Override
+ public void onSendWeather(WeatherSpec weatherSpec) {
+ try {
+ 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);
+ uartTxJSON("onSendWeather", o);
+ } catch (JSONException e) {
+ LOG.info("JSONException: " + e.getLocalizedMessage());
+ }
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java
index 1fa421504..1662253bd 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java
@@ -99,6 +99,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.roidmi.Roidmi3Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sonyswr12.SonySWR12DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.tlw64.TLW64Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.vibratissimo.VibratissimoCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.waspos.WaspOSCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.watch9.Watch9DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.zetime.ZeTimeCoordinator;
@@ -286,6 +287,7 @@ public class DeviceHelper {
result.add(new SG2Coordinator());
result.add(new LefunDeviceCoordinator());
result.add(new SonySWR12DeviceCoordinator());
+ result.add(new WaspOSCoordinator());
return result;
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f61bc75a3..2884bdd53 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -837,6 +837,7 @@
TLW64
PineTime (JF Firmware)
Sony SWR12
+ Wasp OS
Choose export location
Gadgetbridge notifications
Gadgetbridge notifications high priority