/* 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 . */ package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets; import java.util.ArrayList; import java.util.List; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket.ParseException; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV; // TODO: complete responses public class Alarms { public static class EventAlarm { public byte index; public boolean status = false; public byte startHour = -1; public byte startMinute = -1; public byte repeat = 0; public String name = "Alarm"; public EventAlarm(HuaweiTLV tlv) throws ParseException { this.index = tlv.getByte(0x03); if (tlv.contains(0x04)) this.status = tlv.getBoolean(0x04); if (this.status || tlv.contains(0x05)) { // I think we should refuse to set the alarm to a default time if it's enabled. // If it is enabled, it should have the time set. this.startHour = (byte) ((tlv.getShort(0x05) >> 8) & 0xFF); this.startMinute = (byte) (tlv.getShort(0x05) & 0xFF); } if (tlv.contains(0x06)) this.repeat = tlv.getByte(0x06); if (tlv.contains(0x07)) this.name = tlv.getString(0x07); } public EventAlarm(byte index, boolean status, byte startHour, byte startMinute, byte repeat, String name) { this.index = index; this.status = status; this.startHour = startHour; this.startMinute = startMinute; this.repeat = repeat; this.name = name; } public HuaweiTLV asTlv() { return new HuaweiTLV() .put(0x03, index) .put(0x04, status) .put(0x05, (short) ((startHour << 8) | (startMinute & 0xFF))) .put(0x06, repeat) .put(0x07, name); } @Override public String toString() { return "EventAlarm{" + "index=" + index + ", status=" + status + ", startHour=" + startHour + ", startMinute=" + startMinute + ", repeat=" + repeat + ", name='" + name + '\'' + '}'; } } public static class SmartAlarm { public byte index; public boolean status; public byte startHour; public byte startMinute; public byte repeat; public byte aheadTime; public SmartAlarm(HuaweiTLV tlv) throws ParseException { this.index = tlv.getByte(0x03); this.status = tlv.getBoolean(0x04, false); this.startHour = (byte) ((tlv.getShort(0x05, (short) 0) >> 8) & 0xFF); this.startMinute = (byte) (tlv.getShort(0x05, (short) 0) & 0xFF); this.repeat = tlv.getByte(0x06, (byte) 0); this.aheadTime = tlv.getByte(0x07, (byte) 0); } public SmartAlarm(boolean status, byte startHour, byte startMinute, byte repeat, byte aheadTime) { this.index = 1; this.status = status; this.startHour = startHour; this.startMinute = startMinute; this.repeat = repeat; this.aheadTime = aheadTime; } public HuaweiTLV asTlv() { return new HuaweiTLV() .put(0x03, index) .put(0x04, status) .put(0x05, (short) ((startHour << 8) | (startMinute & 0xFF))) .put(0x06, repeat) .put(0x07, aheadTime); } @Override public String toString() { return "SmartAlarm{" + "index=" + index + ", status=" + status + ", startHour=" + startHour + ", startMinute=" + startMinute + ", repeat=" + repeat + ", aheadTime=" + aheadTime + '}'; } } public static final byte id = 0x08; public static class EventAlarmsRequest extends HuaweiPacket { public static final byte id = 0x01; // TODO: move to list private final HuaweiTLV alarms; public EventAlarmsRequest(ParamsProvider paramsProvider) { super(paramsProvider); this.serviceId = Alarms.id; this.commandId = id; alarms = new HuaweiTLV(); } public void addEventAlarm(EventAlarm alarm) { // TODO: 5 is a max and we may need to check for that and throw an exception if passed alarms.put(0x82, alarm.asTlv()); } @Override public List serialize() throws CryptoException { if (this.alarms.get().size() == 0) { // Empty alarms - this will disable them all this.alarms.put(0x82, new HuaweiTLV().put(0x03, (byte) 0x01)); } this.tlv = new HuaweiTLV().put(0x81, this.alarms); this.complete = true; return super.serialize(); } } public static class SmartAlarmRequest extends HuaweiPacket { public static final int id = 0x02; public SmartAlarmRequest( ParamsProvider paramsProvider, SmartAlarm smartAlarm ) { super(paramsProvider); this.serviceId = Alarms.id; this.commandId = id; this.tlv = new HuaweiTLV() .put(0x81, new HuaweiTLV() .put(0x82, smartAlarm.asTlv()) ); this.complete = true; } } public static class EventAlarmsList { public static final int id = 0x03; public static class Request extends HuaweiPacket { public Request(ParamsProvider paramsProvider) { super(paramsProvider); this.serviceId = Alarms.id; this.commandId = id; this.tlv = new HuaweiTLV().put(0x01); this.complete = true; } } public static class Response extends HuaweiPacket { public List eventAlarms; public Response(ParamsProvider paramsProvider) { super(paramsProvider); } @Override public void parseTlv() throws ParseException { eventAlarms = new ArrayList<>(); HuaweiTLV tlv = this.tlv.getObject(0x81); for (HuaweiTLV subTlv : tlv.getObjects(0x82)) { eventAlarms.add(new EventAlarm(subTlv)); } } } } public static class SmartAlarmList { public static final int id = 0x04; public static class Request extends HuaweiPacket { public Request(ParamsProvider paramsProvider) { super(paramsProvider); this.serviceId = Alarms.id; this.commandId = id; this.tlv = new HuaweiTLV().put(0x01); this.complete = true; } } public static class Response extends HuaweiPacket { public SmartAlarm smartAlarm; public Response(ParamsProvider paramsProvider) { super(paramsProvider); } @Override public void parseTlv() throws ParseException { HuaweiTLV tlv = this.tlv.getObject(0x81); if (tlv.contains(0x82)) { this.smartAlarm = new SmartAlarm(tlv.getObject(0x82)); } else { this.smartAlarm = null; } } } } }