mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-29 13:26:50 +01:00
Zepp OS: Add support for compressed file transfer
This commit is contained in:
parent
d29e092ce7
commit
55cecceb38
@ -25,6 +25,9 @@ import java.nio.ByteOrder;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.zip.DataFormatException;
|
||||||
|
import java.util.zip.Deflater;
|
||||||
|
import java.util.zip.Inflater;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
@ -152,10 +155,23 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
|
|||||||
final int length = BLETypeConversions.toUint32(payload, pos);
|
final int length = BLETypeConversions.toUint32(payload, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
final int crc32 = BLETypeConversions.toUint32(payload, pos);
|
final int crc32 = BLETypeConversions.toUint32(payload, pos);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
LOG.info("Got transfer request: session={}, url={}, filename={}, length={}", session, url, filename, length);
|
final boolean compressed;
|
||||||
|
if (pos < payload.length) {
|
||||||
|
final Boolean compressedBoolean = booleanFromByte(payload[pos]);
|
||||||
|
if (compressedBoolean == null) {
|
||||||
|
LOG.warn("Unknown compression type {}", payload[pos]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
compressed = compressedBoolean;
|
||||||
|
} else {
|
||||||
|
compressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
final FileTransferRequest request = new FileTransferRequest(url, filename, new byte[length], getSupport());
|
LOG.info("Got transfer request: session={}, url={}, filename={}, length={}, compressed={}", session, url, filename, length, compressed);
|
||||||
|
|
||||||
|
final FileTransferRequest request = new FileTransferRequest(url, filename, new byte[length], compressed, getSupport());
|
||||||
request.setCrc32(crc32);
|
request.setCrc32(crc32);
|
||||||
|
|
||||||
final ByteBuffer buf = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN);
|
final ByteBuffer buf = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
@ -212,21 +228,43 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
|
|||||||
if (lastPacket) {
|
if (lastPacket) {
|
||||||
mSessionRequests.remove(session);
|
mSessionRequests.remove(session);
|
||||||
|
|
||||||
if (request.getProgress() != request.getSize()) {
|
final byte[] data;
|
||||||
LOG.warn("Request not finished: {}/{}", request.getProgress(), request.getSize());
|
if (request.isCompressed()) {
|
||||||
return;
|
data = decompress(request.getBytes());
|
||||||
|
if (data == null) {
|
||||||
|
LOG.error("Failed to decompress bytes for session={}", session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = request.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
final int checksum = CheckSums.getCRC32(request.getBytes());
|
final int checksum = CheckSums.getCRC32(data);
|
||||||
if (checksum != request.getCrc32()) {
|
if (checksum != request.getCrc32()) {
|
||||||
LOG.warn("Checksum mismatch: expected {}, got {}", request.getCrc32(), checksum);
|
LOG.warn("Checksum mismatch: expected {}, got {}", request.getCrc32(), checksum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.getCallback().onFileDownloadFinish(request.getUrl(), request.getFilename(), request.getBytes());
|
request.getCallback().onFileDownloadFinish(request.getUrl(), request.getFilename(), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] decompress(final byte[] data) {
|
||||||
|
final Inflater inflater = new Inflater();
|
||||||
|
final byte[] output = new byte[data.length];
|
||||||
|
inflater.setInput(data);
|
||||||
|
try {
|
||||||
|
inflater.inflate(output);
|
||||||
|
} catch (final DataFormatException e) {
|
||||||
|
LOG.error("Failed to decompress data", e);
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
inflater.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
public void sendFile(final String url, final String filename, final byte[] bytes, final Callback callback) {
|
public void sendFile(final String url, final String filename, final byte[] bytes, final Callback callback) {
|
||||||
if (mChunkSize < 0) {
|
if (mChunkSize < 0) {
|
||||||
LOG.error("Service not initialized, refusing to send {}", url);
|
LOG.error("Service not initialized, refusing to send {}", url);
|
||||||
@ -236,7 +274,7 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
|
|||||||
|
|
||||||
LOG.info("Sending {} bytes to {}", bytes.length, url);
|
LOG.info("Sending {} bytes to {}", bytes.length, url);
|
||||||
|
|
||||||
final FileTransferRequest request = new FileTransferRequest(url, filename, bytes, callback);
|
final FileTransferRequest request = new FileTransferRequest(url, filename, bytes, false, callback);
|
||||||
|
|
||||||
byte session = (byte) mSessionRequests.size();
|
byte session = (byte) mSessionRequests.size();
|
||||||
while (mSessionRequests.containsKey(session)) {
|
while (mSessionRequests.containsKey(session)) {
|
||||||
@ -331,15 +369,17 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
|
|||||||
private final String url;
|
private final String url;
|
||||||
private final String filename;
|
private final String filename;
|
||||||
private final byte[] bytes;
|
private final byte[] bytes;
|
||||||
|
private final boolean compressed;
|
||||||
private final Callback callback;
|
private final Callback callback;
|
||||||
private int progress = 0;
|
private int progress = 0;
|
||||||
private byte index = 0;
|
private byte index = 0;
|
||||||
private int crc32;
|
private int crc32;
|
||||||
|
|
||||||
public FileTransferRequest(final String url, final String filename, final byte[] bytes, final Callback callback) {
|
public FileTransferRequest(final String url, final String filename, final byte[] bytes, boolean compressed, final Callback callback) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
this.bytes = bytes;
|
this.bytes = bytes;
|
||||||
|
this.compressed = compressed;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.crc32 = CheckSums.getCRC32(bytes);
|
this.crc32 = CheckSums.getCRC32(bytes);
|
||||||
}
|
}
|
||||||
@ -360,6 +400,10 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
|
|||||||
return bytes.length;
|
return bytes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCompressed() {
|
||||||
|
return compressed;
|
||||||
|
}
|
||||||
|
|
||||||
public Callback getCallback() {
|
public Callback getCallback() {
|
||||||
return callback;
|
return callback;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user