auto-sync
This commit is contained in:
parent
2d8ed8cce2
commit
93120c4d60
|
@ -0,0 +1,62 @@
|
|||
package com.rusefi.binaryprotocol;
|
||||
|
||||
import etch.util.CircularByteBuffer;
|
||||
import jssc.SerialPort;
|
||||
import jssc.SerialPortException;
|
||||
|
||||
/**
|
||||
* (c) Andrey Belomutskiy
|
||||
* 3/6/2015
|
||||
*/
|
||||
public class BinaryProtocol {
|
||||
private final SerialPort serialPort;
|
||||
|
||||
public BinaryProtocol(SerialPort serialPort) {
|
||||
|
||||
this.serialPort = serialPort;
|
||||
}
|
||||
|
||||
static void waitForBytes(CircularByteBuffer cbb, int count) throws InterruptedException {
|
||||
System.out.println("Waiting for " + count + " byte(s)");
|
||||
synchronized (cbb) {
|
||||
while (cbb.length() < count)
|
||||
cbb.wait();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
public void sendQueryCommand() throws SerialPortException {
|
||||
byte[] command = {'S'};
|
||||
sendCrcPacket(command);
|
||||
}
|
||||
|
||||
public void sendCrcPacket(byte[] command) throws SerialPortException {
|
||||
byte[] packet = makePacket(command);
|
||||
|
||||
serialPort.writeBytes(packet);
|
||||
}
|
||||
|
||||
public static int swap16(int x) {
|
||||
return (((x & 0xFF) << 8) | ((x) >> 8));
|
||||
}
|
||||
|
||||
public static int swap32(int x) {
|
||||
return (((x) >> 24) & 0xff) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) | (((x) << 24) & 0xff000000);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package com.rusefi.binaryprotocol;
|
||||
|
||||
import com.rusefi.io.DataListener;
|
||||
import com.rusefi.io.serial.PortHolder;
|
||||
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 BinaryProtocolCmd {
|
||||
private static final int BUFFER_SIZE = 10000;
|
||||
private static SerialPort serialPort;
|
||||
|
||||
public static void main(String[] args) throws SerialPortException, InterruptedException, EOFException {
|
||||
if (args.length != 1) {
|
||||
System.out.println("Exactly one parameter expected");
|
||||
return;
|
||||
}
|
||||
|
||||
String port = args[0];
|
||||
|
||||
|
||||
serialPort = new SerialPort(port);
|
||||
boolean opened = serialPort.openPort();
|
||||
if (!opened) {
|
||||
System.out.println("failed to open " + port);
|
||||
}
|
||||
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();
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -12,4 +12,8 @@ public class CRC {
|
|||
c.update(buf, 0, size);
|
||||
return (int) c.getValue();
|
||||
}
|
||||
|
||||
public static int crc32(byte[] packet) {
|
||||
return crc32(packet, packet.length);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package com.rusefi.binaryprotocol.test;
|
||||
|
||||
import com.rusefi.binaryprotocol.BinaryProtocol;
|
||||
import com.rusefi.binaryprotocol.CRC;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* (c) Andrey Belomutskiy
|
||||
|
@ -14,11 +18,20 @@ public class CRCTest {
|
|||
public void testCrc() {
|
||||
{
|
||||
byte[] a = {'A'};
|
||||
assertEquals(0xD3D99E8B, CRC.crc32(a, a.length));
|
||||
assertEquals(0xD3D99E8B, CRC.crc32(a));
|
||||
}
|
||||
{
|
||||
byte[] a = {'S'};
|
||||
assertEquals(0x2060EFC3, CRC.crc32(a, a.length));
|
||||
assertEquals(0x2060EFC3, CRC.crc32(a));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackPacket() {
|
||||
byte[] command = {'S'};
|
||||
byte[] expected = {0, 1, 0x53, 0x20, 0x60, -17, -61};
|
||||
byte[] actual = BinaryProtocol.makePacket(command);
|
||||
assertTrue(Arrays.toString(expected) + " vs " + Arrays.toString(actual),
|
||||
Arrays.equals(expected, actual));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class PortHolder {
|
|||
boolean opened = serialPort.openPort();//Open serial port
|
||||
if (!opened)
|
||||
FileLog.MAIN.logLine("not opened!");
|
||||
setupPort(serialPort);
|
||||
setupPort(serialPort, BAUD_RATE);
|
||||
serialPort.addEventListener(new SerialPortReader(serialPort, listener));
|
||||
} catch (SerialPortException e) {
|
||||
FileLog.rlog("ERROR " + e.getMessage());
|
||||
|
@ -81,8 +81,8 @@ public class PortHolder {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static void setupPort(SerialPort serialPort) throws SerialPortException {
|
||||
serialPort.setParams(BAUD_RATE, 8, 1, 0);//Set params.
|
||||
public static void setupPort(SerialPort serialPort, int baudRate) throws SerialPortException {
|
||||
serialPort.setParams(baudRate, 8, 1, 0);//Set params.
|
||||
int mask = SerialPort.MASK_RXCHAR;
|
||||
//Set the prepared mask
|
||||
serialPort.setEventsMask(mask);
|
||||
|
|
|
@ -11,7 +11,7 @@ import jssc.SerialPortException;
|
|||
* Date: 12/25/12
|
||||
* (c) Andrey Belomutskiy
|
||||
*/
|
||||
class SerialPortReader implements SerialPortEventListener {
|
||||
public class SerialPortReader implements SerialPortEventListener {
|
||||
private SerialPort serialPort;
|
||||
private DataListener listener;
|
||||
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Copyright 2007-2008 Cisco Systems Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package etch.util;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.nio.BufferOverflowException;
|
||||
|
||||
/**
|
||||
* Byte buffer with operation to support getting and putting
|
||||
* bytes.
|
||||
*/
|
||||
abstract public class ByteBuffer {
|
||||
/**
|
||||
* @return true if the buffer is empty.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return length() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the buffer is full.
|
||||
*/
|
||||
public boolean isFull() {
|
||||
return length() == size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the amount of data the buffer can hold.
|
||||
*/
|
||||
abstract public int size();
|
||||
|
||||
/**
|
||||
* @return the amount of data in the buffer.
|
||||
*/
|
||||
abstract public int length();
|
||||
|
||||
/**
|
||||
* @return the next byte from the buffer.
|
||||
* @throws EOFException if the buffer is empty.
|
||||
*/
|
||||
abstract public byte get() throws EOFException;
|
||||
|
||||
/**
|
||||
* Gets bytes from the buffer to fill buf.
|
||||
*
|
||||
* @param buf
|
||||
* @return the length of data put into buf.
|
||||
*/
|
||||
public int get(byte[] buf) {
|
||||
return get(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets bytes from the buffer to fill buf, starting at the specified
|
||||
* position for the specified length.
|
||||
*
|
||||
* @param buf
|
||||
* @param off
|
||||
* @param len
|
||||
* @return the length of data put into buf.
|
||||
*/
|
||||
public int get(byte[] buf, int off, int len) {
|
||||
if (off < 0)
|
||||
throw new IllegalArgumentException("off < 0");
|
||||
|
||||
if (len < 0)
|
||||
throw new IllegalArgumentException("len < 0");
|
||||
|
||||
if (off + len > buf.length)
|
||||
throw new IllegalArgumentException("off+len > buf.length");
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
int count = 0;
|
||||
try {
|
||||
while (len > 0) {
|
||||
buf[off] = get();
|
||||
count++;
|
||||
off++;
|
||||
len--;
|
||||
}
|
||||
} catch (EOFException e) {
|
||||
// nothing to do.
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a byte into the buffer.
|
||||
*
|
||||
* @param b
|
||||
* @throws BufferOverflowException if the buffer is full
|
||||
*/
|
||||
abstract public void put(byte b) throws BufferOverflowException;
|
||||
|
||||
/**
|
||||
* Puts the bytes from buf into the buffer.
|
||||
*
|
||||
* @param buf
|
||||
* @return the amount of data copied into the buffer.
|
||||
*/
|
||||
public int put(byte[] buf) {
|
||||
return put(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the bytes from buf into the buffer, starting at the specified
|
||||
* position for the specified length;
|
||||
*
|
||||
* @param buf
|
||||
* @param off
|
||||
* @param len
|
||||
* @return the amount of data copied into the buffer.
|
||||
*/
|
||||
public int put(byte[] buf, int off, int len) {
|
||||
if (off < 0)
|
||||
throw new IllegalArgumentException("off < 0");
|
||||
|
||||
if (len < 0)
|
||||
throw new IllegalArgumentException("len < 0");
|
||||
|
||||
if (off + len > buf.length)
|
||||
throw new IllegalArgumentException("off+len > buf.length");
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
int count = 0;
|
||||
try {
|
||||
while (len > 0) {
|
||||
put(buf[off]);
|
||||
count++;
|
||||
off++;
|
||||
len--;
|
||||
}
|
||||
} catch (BufferOverflowException e) {
|
||||
// nothing to do.
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the buffer.
|
||||
*/
|
||||
abstract public void clear();
|
||||
|
||||
/**
|
||||
* @return a little-endian 32-bit integer from the buffer.
|
||||
* @throws EOFException
|
||||
*/
|
||||
public int getInt() throws EOFException {
|
||||
int b0 = get() & 255;
|
||||
int b1 = get() & 255;
|
||||
int b2 = get() & 255;
|
||||
int b3 = get() & 255;
|
||||
return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
|
||||
}
|
||||
|
||||
public short getShort() throws EOFException {
|
||||
int b0 = get() & 255;
|
||||
int b1 = get() & 255;
|
||||
return (short) (b0 | (b1 << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a little-endian 32-bit integer into the buffer.
|
||||
*
|
||||
* @param x
|
||||
*/
|
||||
public void putInt(int x) {
|
||||
put((byte) x);
|
||||
put((byte) (x >>> 8));
|
||||
put((byte) (x >>> 16));
|
||||
put((byte) (x >>> 24));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Copyright 2007-2008 Cisco Systems Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package etch.util;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.nio.BufferOverflowException;
|
||||
|
||||
/**
|
||||
* Description of CircularByteBuffer.
|
||||
*/
|
||||
public class CircularByteBuffer extends ByteBuffer {
|
||||
/**
|
||||
* Constructs the CircularByteBuffer.
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
public CircularByteBuffer(int size) {
|
||||
this.size = size;
|
||||
buf = new byte[size];
|
||||
}
|
||||
|
||||
private final int size;
|
||||
|
||||
private final byte[] buf;
|
||||
|
||||
private int length;
|
||||
|
||||
private int nextGet;
|
||||
|
||||
private int nextPut;
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
length = 0;
|
||||
nextGet = 0;
|
||||
nextPut = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte get() throws EOFException {
|
||||
if (isEmpty())
|
||||
throw new EOFException();
|
||||
|
||||
length--;
|
||||
byte b = buf[nextGet++];
|
||||
if (nextGet >= size)
|
||||
nextGet = 0;
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte b) throws BufferOverflowException {
|
||||
if (isFull())
|
||||
throw new BufferOverflowException();
|
||||
|
||||
length++;
|
||||
buf[nextPut++] = b;
|
||||
if (nextPut >= size)
|
||||
nextPut = 0;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue