/* Copyright (C) 2024 Damien Gaignon, Martin.JM
|
|
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 <https://www.gnu.org/licenses/>. */
|
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets;
|
|
import java.nio.ByteBuffer;
|
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
|
public class Notifications {
|
public static final byte id = 0x02;
|
public static final byte[] defaultConstraints = new byte[]{
|
0x00, 0x02, 0x00, 0x0F,
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x1E,
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x1E,
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x1E
|
};
|
|
public static class NotificationActionRequest extends HuaweiPacket {
|
public static final byte id = 0x01;
|
|
// TODO: support other types of notifications
|
// public static final int send = 0x01;
|
// public static final int notificationId = 0x01;
|
// public static final int notificationType = 0x02;
|
// public static final int vibrate = 0x03;
|
// public static final int payloadEmpty = 0x04;
|
// public static final int imageHeight = 0x08;
|
// public static final int imageWidth = 0x09;
|
// public static final int imageColor = 0x0A;
|
// public static final int imageData = 0x0B;
|
// public static final int textType = 0x0E;
|
// public static final int textEncoding = 0x0F;
|
// public static final int textContent = 0x10;
|
// public static final int sourceAppId = 0x11;
|
// public static final int payloadText = 0x84;
|
// public static final int payloadImage = 0x86;
|
// public static final int textList = 0x8C;
|
// public static final int textItem = 0x8D;
|
|
public NotificationActionRequest(
|
ParamsProvider paramsProvider,
|
short notificationId,
|
byte notificationType,
|
int encoding,
|
String titleContent,
|
String senderContent,
|
String bodyContent,
|
String sourceAppId
|
) {
|
super(paramsProvider);
|
|
this.serviceId = Notifications.id;
|
this.commandId = id;
|
|
// TODO: Add notification information per type if necessary
|
|
this.tlv = new HuaweiTLV()
|
.put(0x01, notificationId)
|
.put(0x02, notificationType)
|
.put(0x03, true); // This used to be vibrate, but doesn't work
|
|
HuaweiTLV subTlv = new HuaweiTLV();
|
if (titleContent != null && !titleContent.isEmpty())
|
subTlv.put(0x8D, new HuaweiTLV()
|
.put(0x0E, (byte) TextType.title)
|
.put(0x0F, (byte) encoding)
|
.put(0x10, titleContent)
|
);
|
|
if (senderContent != null && !senderContent.isEmpty())
|
subTlv.put(0x8D, new HuaweiTLV()
|
.put(0x0E, (byte) TextType.sender)
|
.put(0x0F, (byte) encoding)
|
.put(0x10, senderContent)
|
);
|
|
if (bodyContent != null && !bodyContent.isEmpty())
|
subTlv.put(0x8D, new HuaweiTLV()
|
.put(0x0E, (byte) TextType.text)
|
.put(0x0F, (byte) encoding)
|
.put(0x10, bodyContent)
|
);
|
|
if (subTlv.length() != 0) {
|
this.tlv.put(0x84, new HuaweiTLV().put(0x8C, subTlv));
|
} else {
|
this.tlv.put(0x04);
|
}
|
|
if (sourceAppId != null)
|
this.tlv.put(0x11, sourceAppId);
|
|
this.complete = true;
|
}
|
}
|
|
public static class NotificationConstraints {
|
public static final byte id = 0x02;
|
|
public static class Request extends HuaweiPacket {
|
public Request(ParamsProvider paramsProvider) {
|
super(paramsProvider);
|
this.serviceId = Notifications.id;
|
this.commandId = id;
|
this.tlv = new HuaweiTLV()
|
.put(0x01);
|
this.complete = true;
|
}
|
}
|
|
public static class Response extends HuaweiPacket {
|
public ByteBuffer constraints;
|
|
public Response(ParamsProvider paramsProvider) {
|
super(paramsProvider);
|
this.serviceId = Notifications.id;
|
this.commandId = id;
|
this.complete = true;
|
}
|
|
private void putByteBuffer(ByteBuffer bBuffer, byte position, byte[] value) {
|
ByteBuffer bValue = ByteBuffer.wrap(value);
|
if (bValue.capacity() == 4) {
|
short highbytes = bValue.getShort();
|
if (highbytes != 0) {
|
throw new RuntimeException("This should not happen until very large messages allowed");
|
}
|
bBuffer.putShort(position, bValue.getShort());
|
} else if (bValue.capacity() == 2) {
|
bBuffer.putShort(position, bValue.getShort());
|
} else {
|
bBuffer.put(position, (byte) 0x00);
|
bBuffer.put(position + 1, bValue.get());
|
}
|
}
|
|
@Override
|
public void parseTlv() throws ParseException {
|
this.constraints = ByteBuffer.allocate(22);
|
HuaweiTLV container = this.tlv
|
.getObject(0x81)
|
.getObject(0x82)
|
.getObject(0x90);
|
for (HuaweiTLV subContainer : container.getObjects(0x91)) {
|
if (subContainer.getByte(0x12) == 0x01) {
|
putByteBuffer(constraints, NotificationConstraintsType.contentFormat, new byte[] {0x02}); //Always 0x02 even if gadget report 0x03
|
putByteBuffer(constraints, NotificationConstraintsType.contentLength, subContainer.getBytes(0x14));
|
}
|
if (subContainer.getByte(0x12) == 0x05) {
|
constraints.putShort(NotificationConstraintsType.yellowPagesSupport,(short)0x01);
|
putByteBuffer(constraints, NotificationConstraintsType.yellowPagesFormat,subContainer.getBytes(0x13));
|
putByteBuffer(constraints, NotificationConstraintsType.yellowPagesLength,subContainer.getBytes(0x14));
|
}
|
if (subContainer.getByte(0x12) == 0x06) {
|
constraints.putShort(NotificationConstraintsType.contentSignSupport,(short)0x01);
|
putByteBuffer(constraints, NotificationConstraintsType.contentSignFormat,subContainer.getBytes(0x13));
|
putByteBuffer(constraints, NotificationConstraintsType.contentSignLength,subContainer.getBytes(0x14));
|
}
|
if (subContainer.getByte(0x12) == 0x07 ) {
|
constraints.putShort(NotificationConstraintsType.incomingNumberSupport,(short)0x01);
|
putByteBuffer(constraints, NotificationConstraintsType.incomingNumberFormat,subContainer.getBytes(0x13));
|
putByteBuffer(constraints, NotificationConstraintsType.incomingNumberLength,subContainer.getBytes(0x14));
|
}
|
}
|
constraints.rewind();
|
}
|
}
|
}
|
|
public static class NotificationConstraintsType {
|
// TODO: enum?
|
public static final byte contentFormat = 0x00;
|
public static final byte contentLength = 0x02;
|
public static final byte yellowPagesSupport = 0x04;
|
public static final byte yellowPagesFormat = 0x06;
|
public static final byte yellowPagesLength = 0x08;
|
public static final byte contentSignSupport = 0x0A;
|
public static final byte contentSignFormat = 0x0C;
|
public static final byte contentSignLength = 0x0E;
|
public static final byte incomingNumberSupport = 0x10;
|
public static final byte incomingNumberFormat = 0x12;
|
public static final byte incomingNumberLength = 0x14;
|
}
|
|
public static class NotificationType {
|
// TODO: enum?
|
public static final byte call = 0x01;
|
public static final byte sms = 0x02;
|
public static final byte weChat = 0x03;
|
public static final byte qq = 0x0B;
|
public static final byte stopNotification = 0x0C; // To stop showing a (call) notification
|
public static final byte missedCall = 0x0E;
|
public static final byte email = 0x0F;
|
public static final byte generic = 0x7F;
|
}
|
|
public static class TextType {
|
// TODO: enum?
|
public static final int text = 0x01;
|
public static final int sender = 0x02;
|
public static final int title = 0x03;
|
public static final int yellowPage = 0x05;
|
public static final int contentSign = 0x06;
|
public static final int flight = 0x07;
|
public static final int train = 0x08;
|
public static final int warmRemind = 0x09;
|
public static final int weather = 0x0A;
|
}
|
|
public static class NotificationStateRequest extends HuaweiPacket {
|
public static final byte id = 0x04;
|
|
public NotificationStateRequest(
|
ParamsProvider paramsProvider,
|
boolean status
|
) {
|
super(paramsProvider);
|
|
this.serviceId = Notifications.id;
|
this.commandId = id;
|
|
this.tlv = new HuaweiTLV()
|
.put(0x81, new HuaweiTLV()
|
.put(0x02, status)
|
.put(0x03, status)
|
);
|
|
this.complete = true;
|
}
|
}
|
|
public static class NotificationCapabilities {
|
public static final byte id = 0x05;
|
|
public static class Request extends HuaweiPacket {
|
public Request(
|
ParamsProvider paramsProvider
|
){
|
super(paramsProvider);
|
this.serviceId = Notifications.id;
|
this.commandId = id;
|
this.tlv = new HuaweiTLV()
|
.put(0x01);
|
|
this.complete = true;
|
}
|
}
|
|
public static class Response extends HuaweiPacket {
|
public byte capabilities = 0x00;
|
|
public Response(ParamsProvider paramsProvider) {
|
super(paramsProvider);
|
this.serviceId = DeviceConfig.id;
|
this.commandId = id;
|
}
|
|
@Override
|
public void parseTlv() throws ParseException {
|
if (this.tlv.contains(0x01))
|
this.capabilities = this.tlv.getByte(0x01);
|
}
|
}
|
}
|
|
public static class WearMessagePushRequest extends HuaweiPacket {
|
public static final byte id = 0x08;
|
|
public WearMessagePushRequest(
|
ParamsProvider paramsProvider,
|
boolean status
|
) {
|
super(paramsProvider);
|
|
this.serviceId = Notifications.id;
|
this.commandId = id;
|
|
/* Value sent is the opposite of the switch status */
|
this.tlv = new HuaweiTLV()
|
.put(0x01, !status);
|
|
this.complete = true;
|
}
|
}
|
}
|