/* Copyright (C) 2019-2024 Andreas Shimokawa, Arjan Schrijver, Daniel Dakhno
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.qhybrid.requests.fossil_hr.notification;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public class NotificationFilterPutHRRequest extends FilePutRequest {
public NotificationFilterPutHRRequest(NotificationHRConfiguration[] configs, FossilWatchAdapter adapter) {
super(FileHandle.NOTIFICATION_FILTER, createFile(configs), adapter);
}
public NotificationFilterPutHRRequest(ArrayList configs, FossilWatchAdapter adapter) {
super(FileHandle.NOTIFICATION_FILTER, createFile(configs.toArray(new NotificationHRConfiguration[0])), adapter);
}
private static byte[] createFile(NotificationHRConfiguration[] configs) {
int payloadLength = 0;
for (NotificationHRConfiguration config : configs) {
if (config.getIconName().equals("")) {
// Notification filters without icon are possible
payloadLength += 14;
} else {
payloadLength += config.getIconName().length() + 20;
}
if (config.getPackageName().equals("call")) {
// Extra payload space needed for call notifications due to multi-icon
payloadLength += 44;
}
}
ByteBuffer buffer = ByteBuffer.allocate(payloadLength);
buffer.order(ByteOrder.LITTLE_ENDIAN);
for (NotificationHRConfiguration config : configs) {
if (config.getIconName().equals("")) {
payloadLength = 12;
} else {
payloadLength = config.getIconName().length() + 18;
}
if (config.getPackageName().equals("call")) {
payloadLength += 44;
}
buffer.putShort((short) payloadLength); // current filter config length
// 6 bytes
buffer.put(PacketID.PACKAGE_NAME_CRC.id)
.put((byte) 4) // crc length
.put(config.getPackageCrc());
// 3 bytes
buffer.put(PacketID.GROUP_ID.id)
.put((byte) 1)
.put((byte) 0);
// 3 bytes
buffer.put(PacketID.PRIORITY.id)
.put((byte) 1)
.put((byte) 0xFF);
if (config.getPackageName().equals("call")) {
// Call notifications have a specific multi-icon filter config
buffer.put(PacketID.ICON.id)
.put((byte) ("icIncomingCall.icon".length() + 4))
.put((byte) 0x02)
.put((byte) 0x00)
.put((byte) ("icIncomingCall.icon".length() + 1))
.put("icIncomingCall.icon".getBytes())
.put((byte) 0x00)
.put((byte) 0x40)
.put((byte) 0x00)
.put((byte) ("icMissedCall.icon".length() + 1))
.put("icMissedCall.icon".getBytes())
.put((byte) 0x00)
.put((byte) 0xbd)
.put((byte) 0x00)
.put((byte) ("icIncomingCall.icon".length() + 1))
.put("icIncomingCall.icon".getBytes())
.put((byte) 0x00);
} else if (!config.getIconName().equals("")) {
// 6 bytes + icon name
buffer.put(PacketID.ICON.id)
.put((byte) (config.getIconName().length() + 4))
.put((byte) 0xFF)
.put((byte) 0x00)
.put((byte) (config.getIconName().length() + 1))
.put(config.getIconName().getBytes())
.put((byte) 0x00);
}
}
return buffer.array();
}
enum PacketID {
PACKAGE_NAME((byte) 0x01),
SENDER_NAME((byte) 0x02),
PACKAGE_NAME_CRC((byte) 0x04),
GROUP_ID((byte) 0x80),
APP_DISPLAY_NAME((byte) 0x81),
ICON((byte) 0x82),
PRIORITY((byte) 0xC1),
MOVEMENT((byte) 0xC2),
VIBRATION((byte) 0xC3);
byte id;
PacketID(byte id) {
this.id = id;
}
}
enum VibrationType {
SINGLE_SHORT((byte) 5),
DOUBLE_SHORT((byte) 6),
TRIPLE_SHORT((byte) 7),
SINGLE_LONG((byte) 8),
SILENT((byte) 9);
byte id;
VibrationType(byte id) {
this.id = id;
}
}
}