Huawei: watchface upload - more request up to chunked upload

* SendWatchfaceHash (28 03)
* SendWatchfaceAck (28 04)
* WatchfaceNextChunkParams packet (28 05)
* SendWatchfaceChunk; (28 06)
This commit is contained in:
Vitaliy Tomin 2024-03-31 20:38:42 +08:00
parent 8e71487092
commit 00af1c6895
6 changed files with 196 additions and 5 deletions

View File

@ -60,9 +60,7 @@ public class WatchfaceUpload {
public static class Response extends HuaweiPacket {
public Response (ParamsProvider paramsProvider) {
super(paramsProvider);
}
}
@ -70,4 +68,56 @@ public class WatchfaceUpload {
}
public static class WatchfaceSendConsultAck {
public static final byte id = 0x04;
public static class Request extends HuaweiPacket {
public Request(ParamsProvider paramsProvider) {
super(paramsProvider);
this.tlv = new HuaweiTLV()
.put(0x7f, 0x000186A0) //ok
.put(0x01, (byte) 0x01)
.put(0x09, (byte) 0x01);
this.complete = true;
}
}
public static class Response extends HuaweiPacket {
public Response (ParamsProvider paramsProvider) {
super(paramsProvider);
}
}
}
public static class WatchfaceNextChunkParams extends HuaweiPacket {
public static final byte id = 0x05;
public int bytesUploaded = 0;
public int nextchunkSize = 0;
public WatchfaceNextChunkParams(ParamsProvider paramsProvider) {
super(paramsProvider);
this.serviceId = WatchfaceUpload.id;
this.commandId = id;
}
@Override
public void parseTlv() throws HuaweiPacket.ParseException {
if (this.tlv.contains(0x02) && this.tlv.getBytes(0x02).length == 4)
this.bytesUploaded = this.tlv.getInteger(0x02);
if (this.tlv.contains(0x03) && this.tlv.getBytes(0x03).length == 4)
this.nextchunkSize = this.tlv.getInteger(0x03);
}
}
public static class WatchfaceSendNextChunk extends HuaweiPacket {
public static final byte id = 0x06;
public WatchfaceSendNextChunk(ParamsProvider paramsProvider) {
super(paramsProvider);
this.serviceId = WatchfaceUpload.id;
this.commandId = id;
}
}
}

View File

@ -53,6 +53,9 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetPhoneInfoRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendMenstrualModifyTimeRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWatchfaceAck;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWatchfaceChunk;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWatchfaceHash;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherDeviceRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetMusicStatusRequest;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -102,6 +105,7 @@ public class AsynchronousResponse {
handleWeatherCheck(response);
handleGpsRequest(response);
handleWatchfaceHash(response);
handleWatchfaceAck(response);
} catch (Request.ResponseParseException e) {
LOG.error("Response parse exception", e);
}
@ -388,10 +392,45 @@ public class AsynchronousResponse {
private void handleWatchfaceHash(HuaweiPacket response) {
if (response.serviceId == WatchfaceUpload.id && response.commandId == WatchfaceUpload.WatchfaceSendHash.id) {
try {
SendWatchfaceHash sendWatchfaceHash = new SendWatchfaceHash(this.support, this.support.huaweiWatchfaceManager);
sendWatchfaceHash.doPerform();
} catch (IOException e) {
LOG.error("Could not send watchface hash request", e);
}
}
}
private void handleWatchfaceAck(HuaweiPacket response) {
if (response.serviceId == WatchfaceUpload.id && response.commandId == WatchfaceUpload.WatchfaceSendConsultAck.id) {
try {
SendWatchfaceAck sendWatchfaceAck = new SendWatchfaceAck(this.support);
sendWatchfaceAck.doPerform();
} catch (IOException e) {
LOG.error("Could not send watchface ack request", e);
}
}
}
//FIXME: implement sliced raw serialization and add handeWatchfaceNextChunk to handleResponse list
private void handeWatchfaceNextChunk(HuaweiPacket response) throws Request.ResponseParseException {
if (response.serviceId == WatchfaceUpload.id && response.commandId == WatchfaceUpload.WatchfaceNextChunkParams.id) {
if (!(response instanceof WatchfaceUpload.WatchfaceNextChunkParams))
throw new Request.ResponseTypeMismatchException(response, WatchfaceUpload.WatchfaceNextChunkParams.class);
WatchfaceUpload.WatchfaceNextChunkParams resp = (WatchfaceUpload.WatchfaceNextChunkParams) response;
support.huaweiWatchfaceManager.setUploadChunkSize(resp.nextchunkSize);
support.huaweiWatchfaceManager.setCurrentUploadPosition(resp.bytesUploaded);
try {
SendWatchfaceChunk sendWatchfaceChunk = new SendWatchfaceChunk(this.support, this.support.huaweiWatchfaceManager);
sendWatchfaceChunk.doPerform();
} catch (IOException e) {
LOG.error("Could not send watchface next chunk request", e);
}
}
}
private void handleWeatherCheck(HuaweiPacket response) {
if (response.serviceId == Weather.id && response.commandId == 0x04) {
// Send back ok

View File

@ -22,8 +22,11 @@ public class HuaweiWatchfaceManager {
byte[] watchfaceSHA256;
int fileSize = 0;
String watchfaceName = "413493857";
String watchfaceVersion = "1.0.0";
int currentUploadPosition = 0;
int uploudChunkSize =0;
String watchfaceName = "413493857"; //FIXME generate random name
String watchfaceVersion = "1.0.0"; //FIXME generate random version
public HuaweiWatchfaceManager(HuaweiSupportProvider support) {
this.support=support;
}
@ -65,6 +68,8 @@ public class HuaweiWatchfaceManager {
return;
}
currentUploadPosition = 0;
uploudChunkSize = 0;
//TODO: generate random watchfaceName and watchfaceVersion
LOG.info("watchface loaded, SHA256: "+ GB.hexdump(watchfaceSHA256) + " watchfaceName: " + watchfaceName + " watchfaceVersion: "+watchfaceVersion);
@ -82,4 +87,15 @@ public class HuaweiWatchfaceManager {
return watchfaceVersion;
}
public byte[] getWatchfaceSHA256() {
return watchfaceSHA256;
}
public void setUploadChunkSize(int chunkSize) {
uploudChunkSize = chunkSize;
}
public void setCurrentUploadPosition (int pos) {
currentUploadPosition = pos;
}
}

View File

@ -0,0 +1,25 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.WatchfaceUpload;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWatchfaceManager;
public class SendWatchfaceAck extends Request {
public SendWatchfaceAck(HuaweiSupportProvider support) {
super(support);
this.serviceId = WatchfaceUpload.id;
this.commandId = WatchfaceUpload.WatchfaceSendConsultAck.id;
}
@Override
protected List<byte[]> createRequest() throws RequestCreationException {
try {
return new WatchfaceUpload.WatchfaceSendConsultAck.Request(this.paramsProvider ).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new RequestCreationException(e);
}
}
}

View File

@ -0,0 +1,30 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.WatchfaceUpload;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWatchfaceManager;
public class SendWatchfaceChunk extends Request {
HuaweiWatchfaceManager huaweiWatchfaceManager;
public SendWatchfaceChunk(HuaweiSupportProvider support,
HuaweiWatchfaceManager watchfaceManager) {
super(support);
this.huaweiWatchfaceManager = watchfaceManager;
this.serviceId = WatchfaceUpload.id;
this.commandId = WatchfaceUpload.WatchfaceSendNextChunk.id;
}
@Override
protected List<byte[]> createRequest() throws RequestCreationException {
try {
//FIXME need new package type with raw data chunks ?
return new WatchfaceUpload.WatchfaceSendNextChunk(this.paramsProvider).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new RequestCreationException(e);
}
}
}

View File

@ -0,0 +1,31 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.WatchfaceUpload;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWatchfaceManager;
public class SendWatchfaceHash extends Request{
HuaweiWatchfaceManager huaweiWatchfaceManager;
public SendWatchfaceHash(HuaweiSupportProvider support,
HuaweiWatchfaceManager huaweiWatchfaceManager) {
super(support);
this.huaweiWatchfaceManager = huaweiWatchfaceManager;
this.serviceId = WatchfaceUpload.id;
this.commandId = WatchfaceUpload.WatchfaceSendHash.id;
}
@Override
protected List<byte[]> createRequest() throws RequestCreationException {
try {
return new WatchfaceUpload.WatchfaceSendHash.Request(this.paramsProvider,
huaweiWatchfaceManager.getWatchfaceSHA256()
).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new RequestCreationException(e);
}
}
}