From fad2c908878a34ca76cd9d94e7d019995e77e4f4 Mon Sep 17 00:00:00 2001 From: rusEfi Date: Fri, 6 Mar 2015 20:06:33 -0600 Subject: [PATCH] auto-sync --- .../io/src/com/rusefi/ConfigurationImage.java | 34 +++++ .../rusefi/binaryprotocol/BinaryProtocol.java | 116 ++++++++++++++++-- .../binaryprotocol/BinaryProtocolCmd.java | 46 ++----- java_console/io/src/etch/util/ByteBuffer.java | 4 +- 4 files changed, 151 insertions(+), 49 deletions(-) create mode 100644 java_console/io/src/com/rusefi/ConfigurationImage.java diff --git a/java_console/io/src/com/rusefi/ConfigurationImage.java b/java_console/io/src/com/rusefi/ConfigurationImage.java new file mode 100644 index 0000000000..be3a65cff6 --- /dev/null +++ b/java_console/io/src/com/rusefi/ConfigurationImage.java @@ -0,0 +1,34 @@ +package com.rusefi; + +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * (c) Andrey Belomutskiy + * 3/6/2015 + */ +public class ConfigurationImage { + private final static String BIN_HEADER = "RUSEFI0.1"; + private final int size; + private byte content[]; + + public ConfigurationImage(int size) { + this.size = size; + content = new byte[size]; + } + + public int getSize() { + return size; + } + + public void saveToFile(String fileName) throws IOException { + FileOutputStream fos = new FileOutputStream(fileName); + byte[] bytes = BIN_HEADER.getBytes(); + if (bytes.length != BIN_HEADER.length()) + throw new IllegalStateException("Encoding issue"); + fos.write(bytes); + fos.write(content); + fos.close(); + System.out.println("Saved to " + fileName); + } +} diff --git a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java index 73e5f7e687..2daa42a593 100644 --- a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java +++ b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java @@ -1,22 +1,48 @@ package com.rusefi.binaryprotocol; +import com.rusefi.ConfigurationImage; +import com.rusefi.io.DataListener; +import com.rusefi.io.serial.SerialPortReader; import etch.util.CircularByteBuffer; import jssc.SerialPort; import jssc.SerialPortException; +import java.io.EOFException; +import java.util.Arrays; + /** * (c) Andrey Belomutskiy * 3/6/2015 */ public class BinaryProtocol { + private static final int BLOCKING_FACTOR = 256; + private static final byte RESPONSE_OK = 0; private final SerialPort serialPort; + private static final int BUFFER_SIZE = 10000; + final CircularByteBuffer cbb; - public BinaryProtocol(SerialPort serialPort) { - + public BinaryProtocol(SerialPort serialPort) throws SerialPortException { this.serialPort = serialPort; + + cbb = new CircularByteBuffer(BUFFER_SIZE); + DataListener listener = new DataListener() { + @Override + public void onDataArrived(byte[] freshData) { + System.out.println(freshData.length + " byte(s) arrived"); + synchronized (cbb) { + if (cbb.size() - cbb.length() < freshData.length) { + System.out.println("buffer overflow not expected"); + cbb.clear(); + } + cbb.put(freshData); + cbb.notifyAll(); + } + } + }; + serialPort.addEventListener(new SerialPortReader(serialPort, listener)); } - static void waitForBytes(CircularByteBuffer cbb, int count) throws InterruptedException { + private void waitForBytes(int count) throws InterruptedException { System.out.println("Waiting for " + count + " byte(s)"); synchronized (cbb) { while (cbb.length() < count) @@ -24,23 +50,38 @@ public class BinaryProtocol { } } + /** + * this method adds two bytes for packet size before and four bytes for CRC after + */ public static byte[] makePacket(byte[] command) { byte[] packet = new byte[command.length + 6]; packet[0] = (byte) (command.length / 256); packet[1] = (byte) command.length; - int index = packet.length - 1; System.arraycopy(command, 0, packet, 2, command.length); int crc = CRC.crc32(command); - for (int i = 0; i < 4; i++) { - packet[index--] = (byte) crc; - crc >>= 8; - } + putInt(packet, packet.length - 4, crc); return packet; } + private static void putInt(byte[] packet, int offset, int value) { + int index = offset + 3; + for (int i = 0; i < 4; i++) { + packet[index--] = (byte) value; + value >>= 8; + } + } + + private static void putShort(byte[] packet, int offset, int value) { + int index = offset + 1; + for (int i = 0; i < 2; i++) { + packet[index--] = (byte) value; + value >>= 8; + } + } + public void sendQueryCommand() throws SerialPortException { byte[] command = {'S'}; sendCrcPacket(command); @@ -49,6 +90,7 @@ public class BinaryProtocol { public void sendCrcPacket(byte[] command) throws SerialPortException { byte[] packet = makePacket(command); + System.out.println("Sending " + Arrays.toString(packet)); serialPort.writeBytes(packet); } @@ -59,4 +101,62 @@ public class BinaryProtocol { public static int swap32(int x) { return (((x) >> 24) & 0xff) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) | (((x) << 24) & 0xff000000); } + + public byte[] receivePacket() throws InterruptedException, EOFException { + synchronized (cbb) { + waitForBytes(2); + + int packetSize = BinaryProtocol.swap16(cbb.getShort()); + System.out.println("Got packet size " + packetSize); + if (packetSize < 0 || packetSize > 300) { + // invalid packet size + return null; + } + waitForBytes(packetSize + 4); + + byte[] packet = new byte[packetSize]; + int packetCrc; + synchronized (cbb) { + cbb.get(packet); + packetCrc = BinaryProtocol.swap32(cbb.getInt()); + } + int actualCrc = CRC.crc32(packet); + + boolean isCrcOk = actualCrc == packetCrc; + if (!isCrcOk) { + System.out.println(String.format("%x", actualCrc) + " vs " + String.format("%x", packetCrc)); + return null; + } + System.out.println("packet " + Arrays.toString(packet) + ": crc OK"); + + return packet; + } + } + + public void readImage(ConfigurationImage image) throws SerialPortException, EOFException, InterruptedException { + int offset = 0; + + while (offset < image.getSize()) { + int remainingSize = image.getSize() - offset; + int requestSize = Math.min(remainingSize, BLOCKING_FACTOR); + + byte packet[] = new byte[7]; + packet[0] = 'R'; + putShort(packet, 1, 0); // page + putShort(packet, 3, swap16(offset)); + putShort(packet, 5, swap16(requestSize)); + + sendCrcPacket(packet); + + byte[] response = receivePacket(); + if (response == null || response.length == 0 || response[0] != RESPONSE_OK || response.length != requestSize + 1) { + System.out.println("Something is wrong, retrying..."); + continue; + } + + + offset += requestSize; + } + System.out.println("Got image!"); + } } diff --git a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocolCmd.java b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocolCmd.java index 5c79c2028f..843ed8432f 100644 --- a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocolCmd.java +++ b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocolCmd.java @@ -1,5 +1,6 @@ package com.rusefi.binaryprotocol; +import com.rusefi.ConfigurationImage; import com.rusefi.io.DataListener; import com.rusefi.io.serial.PortHolder; import com.rusefi.io.serial.SerialPortReader; @@ -8,6 +9,7 @@ import jssc.SerialPort; import jssc.SerialPortException; import java.io.EOFException; +import java.io.IOException; import java.util.Arrays; /** @@ -15,10 +17,9 @@ import java.util.Arrays; * 3/6/2015 */ public class BinaryProtocolCmd { - private static final int BUFFER_SIZE = 10000; private static SerialPort serialPort; - public static void main(String[] args) throws SerialPortException, InterruptedException, EOFException { + public static void main(String[] args) throws SerialPortException, InterruptedException, IOException { if (args.length != 1) { System.out.println("Exactly one parameter expected"); return; @@ -35,49 +36,16 @@ public class BinaryProtocolCmd { BinaryProtocol bp = new BinaryProtocol(serialPort); - final CircularByteBuffer cbb = new CircularByteBuffer(BUFFER_SIZE); - DataListener listener = new DataListener() { - @Override - public void onDataArrived(byte[] freshData) { - System.out.println(freshData.length + " byte(s) arrived"); - synchronized (cbb) { - if (cbb.size() - cbb.length() < freshData.length) { - System.out.println("buffer overflow not expected"); - cbb.clear(); - } - cbb.put(freshData); - cbb.notifyAll(); - } - } - }; - serialPort.addEventListener(new SerialPortReader(serialPort, listener)); PortHolder.setupPort(serialPort, 38400); System.out.println("Looks good"); bp.sendQueryCommand(); + bp.receivePacket(); + ConfigurationImage image = new ConfigurationImage(14008); - synchronized (cbb) { - BinaryProtocol.waitForBytes(cbb, 2); - - int packetSize = BinaryProtocol.swap16(cbb.getShort()); - System.out.println("Got packet size " + packetSize); - BinaryProtocol.waitForBytes(cbb, packetSize + 4); - byte[] packet = new byte[packetSize]; - int packetCrc; - synchronized (cbb) { - cbb.get(packet); - packetCrc = BinaryProtocol.swap32(cbb.getInt()); - } - int actualCrc = CRC.crc32(packet); - - boolean isCrcOk = actualCrc == packetCrc; - if(!isCrcOk) { - System.out.println(String.format("%x", actualCrc) + " vs " + String.format("%x", packetCrc)); - } - - System.out.println("packet " + Arrays.toString(packet) + ": crc ok=" + isCrcOk); - } + bp.readImage(image); + image.saveToFile("rusefi_configuration.bin"); } diff --git a/java_console/io/src/etch/util/ByteBuffer.java b/java_console/io/src/etch/util/ByteBuffer.java index 3cacf072be..2101341de2 100644 --- a/java_console/io/src/etch/util/ByteBuffer.java +++ b/java_console/io/src/etch/util/ByteBuffer.java @@ -172,10 +172,10 @@ abstract public class ByteBuffer { return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); } - public short getShort() throws EOFException { + public int getShort() throws EOFException { int b0 = get() & 255; int b1 = get() & 255; - return (short) (b0 | (b1 << 8)); + return (b0 | (b1 << 8)); } /**