/* Copyright (C) 2013 Isak Eriksson
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/ */
package bgsep.bluetooth;
import java.nio.ByteBuffer;
import bgsep.bluetooth.BluetoothHandler;
import bgsep.communication.Sender;
import lib.Protocol;
/**
* @author Isak Eriksson (isak.eriksson@mail.com)
* This class implements Sender using bluetooth.
*
*/
public class SenderImpl implements Sender {
private BluetoothHandler bh;
@Override
public void send(byte id, boolean pressed) {
byte[] data = new byte[2];
data[0] = id;
data[1] = (byte) (pressed ? 0x01 : 0x00);
send(data, Protocol.MESSAGE_TYPE_BUTTON);
}
public SenderImpl(BluetoothHandler bh) {
this.bh = bh;
}
@Override
public void send(byte id, float value) {
byte[] data = new byte[5];
data[0] = id;
byte[] floatArray = ByteBuffer.allocate(4).putFloat(value).array();
System.arraycopy(floatArray, 0, data, 1, 4);
send(data, Protocol.MESSAGE_TYPE_JOYSTICK);
}
@Override
public void sendCloseMessage(String message) {
byte[] data = message.getBytes();
send(data, Protocol.MESSAGE_TYPE_CLOSE);
}
@Override
public void sendNameMessage(String name) {
byte[] data = name.getBytes();
send(data, Protocol.MESSAGE_TYPE_NAME);
}
public void poll() {
send(new byte[0], Protocol.MESSAGE_TYPE_POLL);
}
private boolean shouldBeEscaped(byte b) {
return b == Protocol.ESCAPE || b == Protocol.START || b == Protocol.STOP;
}
/**
* This method takes a byte array and inserts the ESCAPE byte
* before all occurrences of START, STOP and ESCAPE except from
* the first and last byte.
* @param data the unescaped array
* @return the escaped aray
*/
private byte[] insertEscapeBytes(byte[] data) {
byte[] escapingBytes = new byte[lib.Constants.MESSAGE_MAX_SIZE];
int offset = 0;
for (int i = 0; i < data.length; i++) {
if (shouldBeEscaped(data[i]) && i > 0 && i < data.length - 1) { //the first and last byte should not be escaped
escapingBytes[i + offset] = Protocol.ESCAPE; //prefix the byte with the ESCAPE byte
offset++;
}
escapingBytes[i + offset] = data[i];
}
byte[] escapedBytes = new byte[data.length + offset];
System.arraycopy(escapingBytes, 0, escapedBytes, 0, escapedBytes.length);
return escapedBytes;
}
private synchronized void send(byte[] data, byte type) {
byte[] allData = new byte[data.length + 3];
allData[0] = Protocol.START;
allData[1] = type;
System.arraycopy(data, 0, allData, 2, data.length);
allData[data.length + 2] = Protocol.STOP;
bh.send(insertEscapeBytes(allData));
}
@Override
public boolean isConnected() {
return bh.isConnected();
}
}