package org.squidy.nodes.reactivision.remote.control;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import org.squidy.nodes.reactivision.remote.Util;
/**
* byte 0: OpCode
* bytes 1-4: payload length in bytes (unsigned integer)
* bytes 5-... payload (optional)
*
* @author Andreas Ergenzinger
*
*/
public final class ControlMessage {
private byte[] header;
private ByteBuffer payload;
private ControlMessage() {
}
public ControlMessage(OpCode opCode) {
header = new byte[5];
header[0] = opCode.value();
}
public ControlMessage(OpCode opCode, byte[] payload) {
this(opCode);
setPayloadLength(payload.length);
this.payload = ByteBuffer.wrap(payload);
}
public static ControlMessage createSetFiducialSetControlMessage(FiducialSet fiducialSet) {
final int fiducialSetID = fiducialSet.ordinal();
final byte[] bytes = new byte[4];
Util.writeIntToByteArray(fiducialSetID, bytes, 0);
return new ControlMessage(OpCode.SET_FIDUCIAL_SET, bytes);
}
public static ControlMessage createSettingsControlMessage(OpCode opCode, int value) {
byte[] bytes = new byte[4];
Util.writeIntToByteArray(value, bytes, 0);
return new ControlMessage(opCode, bytes);
}
public static ControlMessage createSettingsControlMessage(OpCode opCode, float value) {
byte[] bytes = new byte[4];
Util.writeFloatToByteArray(value, bytes, 0);
return new ControlMessage(opCode, bytes);
}
public OpCode getOpCode() {
return OpCode.valueOf(header[0]);
}
public ByteBuffer getPayload() {
return payload;
}
public int getPayloadLength() {
return ((header[1] & 255) << 24) | ((header[2] & 255) << 16) | ((header[3] & 255) << 8) | (header[4] & 255);
}
public void send(SocketChannel socketChannel) throws IOException{
socketChannel.write(serialize());
}
/**
* Returns a ByteBuffer filled with the byte representation of this message,
* which has been
* @return
*/
private ByteBuffer serialize() {
int payloadLength = getPayloadLength();
final ByteBuffer buffer = ByteBuffer.allocate(5 + payloadLength);
buffer.put(header);
if (payloadLength > 0)
buffer.put(payload);
buffer.flip();
return buffer;
}
private void setPayloadLength(int length) {
header[1] = (byte)(length >> 24);
header[2] = (byte)(length >> 16);
header[3] = (byte)(length >> 8);
header[4] = (byte) length;
}
public static ControlMessage read(SocketChannel socketChannel)
throws IOException {
ControlMessage message = new ControlMessage();
//read header
final ByteBuffer headerBB = ByteBuffer.allocate(5);
socketChannel.read(headerBB);
message.header = headerBB.array();
final int length = message.getPayloadLength();
if (length > 0) {
//read payload
message.payload = ByteBuffer.allocate(length);
socketChannel.read(message.payload);
}
return message;
}
public String toString() {
final StringBuilder s = new StringBuilder();
final OpCode operationCode = OpCode.valueOf(header[0]);
s.append(operationCode.toString());
switch (operationCode) {
case SEND_CAMERA_SETTINGS:
s.append("\n");
s.append(CameraSettingsContainer.deserialize(payload).toString());
break;
case SET_CAMERA_SETTINGS_FRAMERATE:
s.append(" framerate: " + Util.readFloatFromBytes(payload.array(), 0));
break;
case SET_CAMERA_SETTINGS_EXPOSURE_TIME:
s.append(" exposure time: " + Util.readFloatFromBytes(payload.array(), 0));
break;
case SET_CAMERA_SETTINGS_PIXEL_CLOCK:
s.append(" pixel clock: " + Util.readFourByteInt(payload, 0));
break;
case SET_CAMERA_SETTINGS_HARDWARE_GAIN:
s.append(" hardware gain: " + Util.readFourByteInt(payload, 0));
break;
case SET_CAMERA_SETTINGS_EDGE_ENHANCEMENT:
final int edgeEnhancement = Util.readFourByteInt(payload, 0);
String inWords = " (none)";
if (edgeEnhancement == 1)
inWords = " (weak)";
else if (edgeEnhancement == 2)
inWords = " (strong)";
s.append(" edge enhancement: " + edgeEnhancement + inWords);
break;
case SET_CAMERA_SETTINGS_GAMMA:
s.append(" gamma: " + Util.readFourByteInt(payload, 0));
break;
default:
s.append(" <payload length: ");
s.append(Util.readFourByteInt(header, 1));
s.append("> ");
if (payload != null)
s.append(java.util.Arrays.toString(payload.array()));
}
return s.toString();
}
}