diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/commands/NotificationCommand.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/commands/NotificationCommand.java
index 6335c8f40..bde32b448 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/commands/NotificationCommand.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/commands/NotificationCommand.java
@@ -36,6 +36,8 @@ public class NotificationCommand extends BaseCommand {
public static final byte EXTENDED_SERVICE_TYPE_LINE = 5;
public static final byte EXTENDED_SERVICE_TYPE_KAKAOTALK = 6;
+ public static final int MAX_PAYLOAD_LENGTH = 13;
+
private byte serviceType;
private byte totalPieces;
private byte currentPiece;
@@ -49,7 +51,7 @@ public class NotificationCommand extends BaseCommand {
public void setServiceType(int type) {
if (type < 0 || type > 4)
throw new IllegalArgumentException("Invalid service type");
- this.serviceType = (byte)(1 << type);
+ this.serviceType = (byte) (1 << type);
}
public byte getTotalPieces() {
@@ -103,8 +105,9 @@ public class NotificationCommand extends BaseCommand {
@Override
protected byte serializeParams(ByteBuffer params) {
boolean hasExtendedServiceType = (serviceType & (1 << SERVICE_TYPE_EXTENDED)) != 0
- && (extendedServiceType & 0x0f) != 0 ;
- int maxPayloadLength = hasExtendedServiceType ? 12 : 13;
+ && (extendedServiceType & 0x0f) != 0;
+ int maxPayloadLength = MAX_PAYLOAD_LENGTH;
+ if (hasExtendedServiceType) maxPayloadLength -= 1;
if (payload.length > maxPayloadLength)
throw new IllegalStateException("Payload is too long");
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/LefunDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/LefunDeviceSupport.java
index 427622a87..a39b63c75 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/LefunDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/LefunDeviceSupport.java
@@ -71,6 +71,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetFi
import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetPpgDataRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetSleepDataRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.Request;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.AbstractSendNotificationRequest;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SendCallNotificationRequest;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SendNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetAlarmRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetTimeRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.StartPpgRequest;
@@ -126,7 +129,16 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
@Override
public void onNotification(NotificationSpec notificationSpec) {
-
+ try {
+ TransactionBuilder builder = performInitialized(SetTimeRequest.class.getSimpleName());
+ SendNotificationRequest request = new SendNotificationRequest(this, builder);
+ request.setNotification(notificationSpec);
+ request.perform();
+ performConnected(builder.getTransaction());
+ } catch (IOException e) {
+ GB.toast(getContext(), "Failed to send notification", Toast.LENGTH_SHORT,
+ GB.ERROR, e);
+ }
}
@Override
@@ -173,7 +185,20 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
@Override
public void onSetCallState(CallSpec callSpec) {
-
+ switch (callSpec.command) {
+ case CallSpec.CALL_INCOMING:
+ try {
+ TransactionBuilder builder = performInitialized(SetTimeRequest.class.getSimpleName());
+ SendCallNotificationRequest request = new SendCallNotificationRequest(this, builder);
+ request.setCallNotification(callSpec);
+ request.perform();
+ performConnected(builder.getTransaction());
+ } catch (IOException e) {
+ GB.toast(getContext(), "Failed to send call notification", Toast.LENGTH_SHORT,
+ GB.ERROR, e);
+ }
+ break;
+ }
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/AbstractSendNotificationRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/AbstractSendNotificationRequest.java
new file mode 100644
index 000000000..acfb01935
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/AbstractSendNotificationRequest.java
@@ -0,0 +1,98 @@
+/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele
+ Gobbetti
+ Copyright (C) 2020 Yukai Li
+
+ 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.lefun.requests;
+
+import android.bluetooth.BluetoothGattCharacteristic;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants;
+import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.NotificationCommand;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport;
+
+public abstract class AbstractSendNotificationRequest extends Request {
+ protected AbstractSendNotificationRequest(LefunDeviceSupport support, TransactionBuilder builder) {
+ super(support, builder);
+ }
+
+ protected abstract String getMessage();
+
+ protected abstract byte getNotificationType();
+
+ protected abstract byte getExtendedNotificationType();
+
+ @Override
+ public byte[] createRequest() {
+ return new byte[0];
+ }
+
+ @Override
+ protected void doPerform() throws IOException {
+ byte notificationType = getNotificationType();
+ byte extendedNotificationType = getExtendedNotificationType();
+ boolean reserveSpaceForExtended = notificationType == NotificationCommand.SERVICE_TYPE_EXTENDED;
+ byte[] encoded = getMessage().getBytes(StandardCharsets.UTF_8);
+ ByteBuffer buffer = ByteBuffer.wrap(encoded);
+
+ BluetoothGattCharacteristic characteristic = getSupport()
+ .getCharacteristic(LefunConstants.UUID_CHARACTERISTIC_LEFUN_WRITE);
+
+ List commandList = new ArrayList<>();
+ for (int i = 0; i < 0xff; ++i) {
+ NotificationCommand cmd = new NotificationCommand();
+ cmd.setServiceType(notificationType);
+ cmd.setExtendedServiceType(extendedNotificationType);
+ cmd.setCurrentPiece((byte) (i + 1));
+
+ int maxPayloadLength = NotificationCommand.MAX_PAYLOAD_LENGTH;
+ if (reserveSpaceForExtended) maxPayloadLength -= 1;
+ maxPayloadLength = Math.min(maxPayloadLength, buffer.limit() - buffer.position());
+ if (maxPayloadLength == 0) break;
+
+ byte[] payload = new byte[maxPayloadLength];
+ buffer.get(payload);
+ cmd.setPayload(payload);
+
+ commandList.add(cmd);
+ }
+
+ for (NotificationCommand cmd : commandList) {
+ cmd.setTotalPieces((byte) commandList.size());
+ builder.write(characteristic, cmd.serialize());
+ }
+
+ if (isSelfQueue())
+ getSupport().performConnected(builder.getTransaction());
+ }
+
+ @Override
+ public int getCommandId() {
+ return LefunConstants.CMD_NOTIFICATION;
+ }
+
+ @Override
+ public boolean expectsResponse() {
+ return false;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SendCallNotificationRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SendCallNotificationRequest.java
new file mode 100644
index 000000000..bd572f62a
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SendCallNotificationRequest.java
@@ -0,0 +1,67 @@
+/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele
+ Gobbetti
+ Copyright (C) 2020 Yukai Li
+
+ 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.lefun.requests;
+
+import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.NotificationCommand;
+import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport;
+
+public class SendCallNotificationRequest extends AbstractSendNotificationRequest {
+ public SendCallNotificationRequest(LefunDeviceSupport support, TransactionBuilder builder) {
+ super(support, builder);
+ }
+
+ private CallSpec callNotification;
+
+ public CallSpec getCallNotification() {
+ return callNotification;
+ }
+
+ public void setCallNotification(CallSpec callNotification) {
+ this.callNotification = callNotification;
+ }
+
+ @Override
+ protected String getMessage() {
+ String message = "";
+ if (callNotification.number != null) {
+ message = callNotification.number;
+ }
+
+ if (callNotification.name != null) {
+ if (message.length() > 0) {
+ message += " - ";
+ }
+ message += callNotification.name;
+ }
+
+ return message;
+ }
+
+ @Override
+ protected byte getNotificationType() {
+ return NotificationCommand.SERVICE_TYPE_CALL;
+ }
+
+ @Override
+ protected byte getExtendedNotificationType() {
+ return 0;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SendNotificationRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SendNotificationRequest.java
new file mode 100644
index 000000000..98405d0bc
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SendNotificationRequest.java
@@ -0,0 +1,111 @@
+/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele
+ Gobbetti
+ Copyright (C) 2020 Yukai Li
+
+ 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.lefun.requests;
+
+import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.NotificationCommand;
+import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport;
+
+public class SendNotificationRequest extends AbstractSendNotificationRequest {
+ NotificationSpec notification;
+
+ public SendNotificationRequest(LefunDeviceSupport support, TransactionBuilder builder) {
+ super(support, builder);
+ }
+
+ @Override
+ protected byte getNotificationType() {
+ switch (notification.type) {
+ case GENERIC_PHONE:
+ return NotificationCommand.SERVICE_TYPE_CALL;
+ case GENERIC_SMS:
+ case GENERIC_EMAIL:
+ default:
+ return NotificationCommand.SERVICE_TYPE_TEXT;
+ case WECHAT:
+ return NotificationCommand.SERVICE_TYPE_WECHAT;
+ case FACEBOOK:
+ case FACEBOOK_MESSENGER:
+ case TWITTER:
+ case LINKEDIN:
+ case WHATSAPP:
+ case LINE:
+ case KAKAO_TALK:
+ return NotificationCommand.SERVICE_TYPE_EXTENDED;
+ }
+ }
+
+ @Override
+ protected byte getExtendedNotificationType() {
+ switch (notification.type) {
+ case GENERIC_PHONE:
+ case GENERIC_SMS:
+ case GENERIC_EMAIL:
+ default:
+ case WECHAT:
+ return 0;
+ case FACEBOOK:
+ case FACEBOOK_MESSENGER:
+ return NotificationCommand.EXTENDED_SERVICE_TYPE_FACEBOOK;
+ case TWITTER:
+ return NotificationCommand.EXTENDED_SERVICE_TYPE_TWITTER;
+ case LINKEDIN:
+ return NotificationCommand.EXTENDED_SERVICE_TYPE_LINKEDIN;
+ case WHATSAPP:
+ return NotificationCommand.EXTENDED_SERVICE_TYPE_WHATSAPP;
+ case LINE:
+ return NotificationCommand.EXTENDED_SERVICE_TYPE_LINE;
+ case KAKAO_TALK:
+ return NotificationCommand.EXTENDED_SERVICE_TYPE_KAKAOTALK;
+ }
+ }
+
+ public NotificationSpec getNotification() {
+ return notification;
+ }
+
+ public void setNotification(NotificationSpec notification) {
+ this.notification = notification;
+ }
+
+ @Override
+ protected String getMessage() {
+ // Based on nodomain.freeyourgadget.gadgetbridge.service.devices.id115.SendNotificationOperation
+ String message = "";
+
+ if (notification.phoneNumber != null) {
+ message += notification.phoneNumber + ": ";
+ }
+
+ if (notification.sender != null) {
+ message += notification.sender + " - ";
+ } else if (notification.title != null) {
+ message += notification.title + " - ";
+ } else if (notification.subject != null) {
+ message += notification.subject + " - ";
+ }
+
+ if (notification.body != null) {
+ message += notification.body;
+ }
+
+ return message;
+ }
+}