From e6ac9d91a55f5d95665f8daec9f3238e2b91e1e2 Mon Sep 17 00:00:00 2001 From: Daniel Dakhno Date: Tue, 26 Nov 2019 02:10:03 +0100 Subject: [PATCH] added some fun and useless requests --- .../fossil/microapp/MicroAppCommand.java | 160 ++++++++++++++++++ .../fossil/microapp/PlayCrazyShitRequest.java | 59 +++++++ 2 files changed, 219 insertions(+) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/microapp/MicroAppCommand.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/microapp/PlayCrazyShitRequest.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/microapp/MicroAppCommand.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/microapp/MicroAppCommand.java new file mode 100644 index 000000000..fb3298487 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/microapp/MicroAppCommand.java @@ -0,0 +1,160 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.microapp; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public interface MicroAppCommand { + byte[] getData(); +} + +class StartCriticalCommand implements MicroAppCommand{ + @Override + public byte[] getData() { + return new byte[]{(byte) 0x03, (byte) 0x00}; + } +} + +class CloseCommand implements MicroAppCommand{ + @Override + public byte[] getData() { + return new byte[]{(byte) 0x01, (byte) 0x00}; + } +} + +class DelayCommand implements MicroAppCommand{ + private double delayInSeconds; + + public DelayCommand(double delayInSeconds) { + this.delayInSeconds = delayInSeconds; + } + + @Override + public byte[] getData() { + return ByteBuffer.wrap(new byte[]{0x08, 0x01, 0x00, 0x00}) + .order(ByteOrder.LITTLE_ENDIAN) + .putShort(2, (short)(delayInSeconds * 10f)) + .array(); + } +} + +enum VibrationType{ + NORMAL((byte) 0x04); + + private byte value; + + VibrationType(byte value){ + this.value = value; + } + + public byte getValue(){ return this.value; } +} + +class VibrateCommand implements MicroAppCommand{ + private VibrationType vibrationType; + + public VibrateCommand(VibrationType vibrationType) { + this.vibrationType = vibrationType; + } + + @Override + public byte[] getData() { + return ByteBuffer.wrap(new byte[]{(byte) 0x93, 0x00, 0x00}) + .put(2, vibrationType.getValue()) + .array(); + } +} + +enum MovingDirection{ + CLOCKWISE((byte) 0x00), + COUNTER_CLOCKWISE((byte) 0x01), + SHORTEST((byte) 0x02), + ; + private byte value; + + MovingDirection(byte value){ this.value = value; } + + public byte getValue() { + return value; + } +} + +enum MovingSpeed{ + MAX((byte) 0x00), + HALF((byte) 0x01), + QUARTER((byte) 0x02), + EIGHTH((byte) 0x03), + SIXTEENTH((byte) 0x04), + ; + private byte value; + + MovingSpeed(byte value){ this.value = value; } + + public byte getValue() { + return value; + } +} + +class StreamCommand implements MicroAppCommand{ + private byte type; + + public StreamCommand(byte type) { + this.type = type; + } + + + @Override + public byte[] getData() { + return new byte[]{(byte) 0x8B, (byte) 0x00, this.type}; + } +} + +class RepeatStartCommand implements MicroAppCommand{ + private byte count; + + public RepeatStartCommand(byte count) { + this.count = count; + } + + + @Override + public byte[] getData() { + return new byte[]{(byte) 0x86, (byte) 0x00, this.count}; + } +} + +class RepeatStopCommand implements MicroAppCommand{ + @Override + public byte[] getData() { + return new byte[]{(byte) 0x07, (byte) 0x00}; + } +} + +class AnimationCommand implements MicroAppCommand{ + private short hour, minute; + private MovingDirection direction; + private MovingSpeed speed; + private byte absoluteMovementFlag; + + public AnimationCommand(short hour, short minute) { + this.hour = hour; + this.minute = minute; + this.speed = MovingSpeed.MAX; + this.direction = MovingDirection.SHORTEST; + this.absoluteMovementFlag = 1; + } + + @Override + public byte[] getData() { + return ByteBuffer.allocate(10) + .order(ByteOrder.LITTLE_ENDIAN) + .put((byte) 0x09) + .put((byte) 0x04) + .put((byte) 0x01) + .put((byte) 0x03) + .put((byte) ((direction.getValue() << 6) | (byte)(absoluteMovementFlag << 5) | this.speed.getValue())) + .putShort(this.hour) + .put((byte) ((direction.getValue() << 6) | (byte)(absoluteMovementFlag << 5) | this.speed.getValue())) + .putShort(this.minute) + .array(); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/microapp/PlayCrazyShitRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/microapp/PlayCrazyShitRequest.java new file mode 100644 index 000000000..c67d27d83 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/microapp/PlayCrazyShitRequest.java @@ -0,0 +1,59 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.microapp; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.CRC32; + +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest; + +public class PlayCrazyShitRequest extends FilePutRequest { + public PlayCrazyShitRequest(byte[] appData, FossilWatchAdapter adapter) { + super((short) 0x0600, createPayload(appData), adapter); + } + + private static byte[] createPayload(byte[] appData) { + List commands = new ArrayList<>(); + + commands.add(new StartCriticalCommand()); + // commands.add(new RepeatStartCommand((byte) 10)); + commands.add(new VibrateCommand(VibrationType.NORMAL)); + commands.add(new DelayCommand(1)); + // commands.add(new RepeatStopCommand()); + // commands.add(new StreamCommand((byte) 0b11111111)); + // commands.add(new AnimationCommand((short) 300, (short) 60)); + // commands.add(new DelayCommand(2)); + commands.add(new CloseCommand()); + + int length = 0; + + for (MicroAppCommand command : commands) length += command.getData().length; + + ByteBuffer buffer = ByteBuffer.allocate( + 3 /* magic bytes */ + + 8 /* button header copy */ + + 1 /* 0xFF */ + + 2 /* payload length */ + + length + + 4 /* crc */ + ); + buffer.order(ByteOrder.LITTLE_ENDIAN); + buffer.put((byte) 0x01); + buffer.put((byte) 0x00); + buffer.put((byte) 0x08); + buffer.put(appData, 3, 8); + buffer.put((byte) 0xFF); + buffer.putShort((short)(length + 3)); + + for(MicroAppCommand command : commands) buffer.put(command.getData()); + + CRC32 crc = new CRC32(); + crc.update(buffer.array(), 0, buffer.position()); + + buffer.putInt((int) crc.getValue()); + + return buffer.array(); + } +}