From be2f8aaedce1fa0bdeb12264ac102da84184a65b Mon Sep 17 00:00:00 2001 From: Daniel Dakhno Date: Thu, 15 Oct 2020 22:42:39 +0200 Subject: [PATCH] Fossil Hybrid: added translation handling --- .../fossil_hr/FossilHRWatchAdapter.java | 32 +++++------ .../translation/TranslationData.java | 45 +++++++++++++++ .../translation/TranslationItem.java | 35 ++++++++++++ .../translation/TranslationsGetRequest.java | 57 +++++++++++++++++++ .../translation/TranslationsPutRequest.java | 40 +++++++++++++ 5 files changed, 192 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationData.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationItem.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsGetRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsPutRequest.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java index 4d6e841a9..63d75b90b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java @@ -70,6 +70,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileLookupRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayCallNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayTextNotificationRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.activity.ActivityFilesGetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.async.ConfirmAppStatusRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.authentication.VerifyPrivateKeyRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.buttons.ButtonConfiguration; @@ -88,6 +89,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicInfoSetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationFilterPutHRRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.translation.TranslationData; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.translation.TranslationsGetRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.translation.TranslationsPutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomBackgroundWidgetElement; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomTextWidgetElement; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidget; @@ -836,25 +840,19 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { @Override public void onTestNewFunction() { - /*queueWrite(new ActivityFilesGetRequest(this){ + queueWrite(new TranslationsGetRequest(this){ @Override - public void handleFileData(byte[] fileData) { - super.handleFileData(fileData); - File activityDir = new File(getContext().getExternalFilesDir(null), "activity_hr"); - activityDir.mkdir(); - File f = new File(activityDir, String.valueOf(System.currentTimeMillis())); - try { - f.createNewFile(); - FileOutputStream fos = new FileOutputStream(f); - fos.write(fileData); - fos.close(); - GB.toast("saved file data", Toast.LENGTH_SHORT, GB.INFO); - } catch (IOException e) { - GB.log("activity file error", GB.ERROR, e); - } - queueWrite(new FileDeleteRequest((short) 0x0101)); + public void handleTranslations(TranslationData translationData) { + translationData.replaceByOriginal("ON", "oi m8"); + translationData.replaceByOriginal("OFF", "nah go away"); + translationData.replaceByOriginal("Device is about to reset.", "oh frick no no no"); + translationData.replaceByOriginal("Release button to stop reset.", "please don't let me die like that"); + translationData.replaceByOriginal("Serial number", "Gadgetbridge :)"); + translationData.replaceByOriginal("Dial Info", "Widgets"); + TranslationsPutRequest request = new TranslationsPutRequest(translationData, FossilHRWatchAdapter.this); + queueWrite(request); } - });*/ + }); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationData.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationData.java new file mode 100644 index 000000000..b1b1c352a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationData.java @@ -0,0 +1,45 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.translation; + +import nodomain.freeyourgadget.gadgetbridge.service.btle.Transaction; + +public class TranslationData { + private String locale; + private TranslationItem[] translations; + + public TranslationData(String locale, TranslationItem[] translations) { + this.locale = locale; + this.translations = translations; + } + + public String getLocale() { + return locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public TranslationItem[] getTranslations() { + return translations; + } + + public void setTranslations(TranslationItem[] translations) { + this.translations = translations; + } + + public void replaceByOriginal(String originalKey, String translated){ + for(TranslationItem translationItem : this.translations){ + if(translationItem.getOriginal().equals(originalKey)){ + translationItem.setTranslated(translated); + } + } + } + + public void replaceByTranslated(String translatedOld, String translatedNew){ + for(TranslationItem translationItem : this.translations){ + if(translationItem.getTranslated().equals(translatedOld)){ + translationItem.setTranslated(translatedNew); + } + } + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationItem.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationItem.java new file mode 100644 index 000000000..10d74d231 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationItem.java @@ -0,0 +1,35 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.translation; + +import androidx.annotation.NonNull; + +public class TranslationItem { + private String originalTranslation; + private String translated; + + public TranslationItem(String originalTranslation, String translated) { + this.originalTranslation = originalTranslation; + this.translated = translated; + } + + public String getOriginal() { + return originalTranslation; + } + + public void setOriginalTranslation(String originalTranslation) { + this.originalTranslation = originalTranslation; + } + + public String getTranslated() { + return translated; + } + + public void setTranslated(String translated) { + this.translated = translated; + } + + @NonNull + @Override + public String toString() { + return this.originalTranslation + " => " + this.translated; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsGetRequest.java new file mode 100644 index 000000000..fb3c3f285 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsGetRequest.java @@ -0,0 +1,57 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.translation; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest; + +public abstract class TranslationsGetRequest extends FileGetRequest { + public TranslationsGetRequest(FossilWatchAdapter adapter) { + super((short) 0x0702, adapter); + } + + @Override + public void handleFileData(byte[] fileData) { + ByteBuffer buffer = ByteBuffer.wrap(fileData); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + buffer.position(12); + + byte[] localeBytes = new byte[5]; + buffer.get(localeBytes); + String locale = new String(localeBytes); + + buffer.get(); // locale null byte + + ArrayList translations = new ArrayList<>(); + + while(buffer.remaining() > 4){ + int originalLength = buffer.getShort() - 1; // subtracting null terminator + byte[] originalBytes = new byte[originalLength]; + buffer.get(originalBytes); + buffer.get(); // should always return null terminator + int translatedLength = buffer.getShort() - 1; + byte[] translatedBytes = new byte[translatedLength]; + buffer.get(translatedBytes); + buffer.get(); // should always return null terminator + + String original = new String(originalBytes); + String translated = new String(translatedBytes); + + translations.add(new TranslationItem(original, translated)); + } + + handleTranslations( + new TranslationData( + locale, + translations.toArray(new TranslationItem[0]) + ) + ); + + } + + public abstract void handleTranslations(TranslationData translationDate); +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsPutRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsPutRequest.java new file mode 100644 index 000000000..2adaead8b --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsPutRequest.java @@ -0,0 +1,40 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.translation; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest; + +public class TranslationsPutRequest extends FilePutRequest { + public TranslationsPutRequest(TranslationData translationData, FossilWatchAdapter adapter) { + super((short) 0x0702, createPayload(translationData), (short) 0x0d02, adapter); + } + + private static byte[] createPayload(TranslationData translationData){ + TranslationItem[] translations = translationData.getTranslations(); + int fileLength = 6 + translations.length * 6; // locale + one null-byte per translation + lengths per translation + for(TranslationItem translation : translations){ + fileLength += translation.getOriginal().getBytes().length + translation.getTranslated().getBytes().length; + } + + ByteBuffer buffer = ByteBuffer.allocate(fileLength); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + buffer.put(translationData.getLocale().getBytes()) + .put((byte)0); + + for(TranslationItem translation : translations){ + byte[] originalBytes = translation.getOriginal().getBytes(); + byte[] translatedBytes = translation.getTranslated().getBytes(); + buffer.putShort((short)(originalBytes.length + 1)) + .put(originalBytes) + .put((byte)0) // null terminator + .putShort((short)(translatedBytes.length + 1)) + .put(translatedBytes) + .put((byte)0); // null terminator + } + + return buffer.array(); + } +}