/* Copyright (C) 2023-2024 Frank Ertl 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.withingssteelhr.communication.message; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import nodomain.freeyourgadget.gadgetbridge.service.devices.withingssteelhr.communication.datastructures.WithingsStructure; import nodomain.freeyourgadget.gadgetbridge.util.GB; public abstract class AbstractMessage implements Message { /** * The header consist of the first byte 0x01 (probably the message format identifier), * two bytes for the message type and 2 bytes for the actual datalength. */ private static final int HEADER_SIZE = 5; protected final static short EOM_SIZE = 4; private List dataStructures = new ArrayList(); public List getDataStructures() { return Collections.unmodifiableList(dataStructures); } @Override public void addDataStructure(WithingsStructure data) { dataStructures.add(data); } @Override public byte[] getRawData() { short structureLength = 0; boolean setEndOfMessage = false; for (WithingsStructure structure : dataStructures) { if (structure.withEndOfMessage()) { setEndOfMessage = true; } structureLength += (short)(structure.getLength()); } if (setEndOfMessage) { structureLength += EOM_SIZE; } ByteBuffer rawDataBuffer = ByteBuffer.allocate(HEADER_SIZE + structureLength); rawDataBuffer.put((byte)0x01); // <= This seems to be always 0x01 for all commands rawDataBuffer.putShort(getType()); rawDataBuffer.putShort(structureLength); for (WithingsStructure structure : dataStructures) { rawDataBuffer.put(structure.getRawData()); } if (setEndOfMessage) { addEndOfMessageBytes(rawDataBuffer); } return rawDataBuffer.array(); } @Override public T getStructureByType(Class type) { for (WithingsStructure structure : this.getDataStructures()) { if (type.isInstance(structure)) { return (T)structure; } } return null; } private void addEndOfMessageBytes(ByteBuffer buffer) { buffer.putShort((short)256); buffer.putShort((short)0); } public String toString() { return GB.hexdump(this.getRawData()).toLowerCase(Locale.ROOT); } }