mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-02-16 12:26:47 +01:00
Lefun: Implement notification support
This commit is contained in:
parent
a1737c39fb
commit
c2375f95f4
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
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<NotificationCommand> 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;
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
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;
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user