package com.pekall.smartplug.codec;
import com.pekall.smartplug.message.BaseMessage;
import com.pekall.smartplug.message.GetStatusRequest;
import com.pekall.smartplug.message.GetStatusResponse;
import com.pekall.smartplug.message.Heartbeat;
import com.pekall.smartplug.message.HelloRequest;
import com.pekall.smartplug.message.HelloResponse;
import com.pekall.smartplug.message.ReportStatusRequest;
import com.pekall.smartplug.message.ReportStatusResponse;
import com.pekall.smartplug.message.SetStatusRequest;
import com.pekall.smartplug.message.SetStatusResponse;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class SmartPlugEncoder extends OneToOneEncoder {
private static final int HEADER_SIZE = 4; // msg_type: short, msg_length: short
private static final int STRING_MAX_BYTES = 31;
@Override
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
if (msg instanceof BaseMessage) {
BaseMessage baseMessage = (BaseMessage) msg;
switch (baseMessage.getMessageType()) {
case MSG_HELLO_REQ:
return encodeHelloRequest((HelloRequest) baseMessage);
case MSG_HELLO_RES:
return encodeHelloResponse((HelloResponse) baseMessage);
case MSG_REPORT_STATUS_REQ:
return encodeReportStatusRequest((ReportStatusRequest) baseMessage);
case MSG_REPORT_STATUS_RES:
return encodeReportStatusResponse((ReportStatusResponse) baseMessage);
case MSG_HEARTBEAT:
return encodeHeartbeat((Heartbeat) baseMessage);
case MSG_GET_STATUS_REQ:
return encodeGetStatusRequest((GetStatusRequest) baseMessage);
case MSG_GET_STATUS_RES:
return encodeGetStatusResponse((GetStatusResponse) baseMessage);
case MSG_SET_STATUS_REQ:
return encodeSetStatusRequest((SetStatusRequest) baseMessage);
case MSG_SET_STATUS_RES:
return encodeSetStatusResponse((SetStatusResponse) baseMessage);
default:
throw new IllegalArgumentException("unknown MessageType");
}
} else {
throw new IllegalArgumentException("not BaseMessage instance");
}
}
private Object encodeHeartbeat(Heartbeat request) {
ChannelBuffer buffer = prepareBuffer(request);
buffer.writeShort(request.getStatus());
return buffer;
}
private Object encodeSetStatusRequest(SetStatusRequest request) {
ChannelBuffer buffer = prepareBuffer(request);
buffer.writeShort(request.getStatus());
return buffer;
}
private Object encodeSetStatusResponse(SetStatusResponse response) {
ChannelBuffer buffer = prepareBuffer(response);
buffer.writeShort(response.getResultCode());
return buffer;
}
private Object encodeGetStatusRequest(GetStatusRequest request) {
ChannelBuffer buffer = prepareBuffer(request);
return buffer;
}
private Object encodeGetStatusResponse(GetStatusResponse response) {
ChannelBuffer buffer = prepareBuffer(response);
buffer.writeShort(response.getStatus());
return buffer;
}
private Object encodeReportStatusRequest(ReportStatusRequest request) {
ChannelBuffer buffer = prepareBuffer(request);
buffer.writeShort(request.getStatus());
return buffer;
}
private Object encodeReportStatusResponse(ReportStatusResponse response) {
ChannelBuffer buffer = prepareBuffer(response);
return buffer;
}
private Object encodeHelloRequest(HelloRequest request) throws UnsupportedEncodingException {
ChannelBuffer buffer = prepareBuffer(request);
writeStringUTF(buffer, request.getDeviceId()); // deviceId
writeStringUTF(buffer, request.getDeviceMode());// deviceMode
return buffer;
}
private Object encodeHelloResponse(HelloResponse response) throws UnsupportedEncodingException {
ChannelBuffer buffer = prepareBuffer(response);
buffer.writeShort(response.getResultCode());
writeStringUTF(buffer, response.getServerName());
return buffer;
}
private static ChannelBuffer prepareBuffer(BaseMessage message) {
ChannelBuffer buffer = ChannelBuffers.buffer(getChannelBufferSize(message));
writeHeader(buffer, message);
writeMessageId(buffer, message);
return buffer;
}
private static int getChannelBufferSize(BaseMessage message) {
return HEADER_SIZE + message.size();
}
private static void writeHeader(ChannelBuffer buffer, BaseMessage baseMessage) {
buffer.writeShort(baseMessage.getMessageType().getValue()); // type
buffer.writeShort(baseMessage.size()); // length
}
private static void writeMessageId(ChannelBuffer buffer, BaseMessage baseMessage) {
buffer.writeInt(baseMessage.getMessageId()); // message id
}
private static void writeStringUTF(ChannelBuffer buffer, String str) throws UnsupportedEncodingException {
byte[] bytes = str.getBytes("utf-8");
int writeLength = Math.min(bytes.length, STRING_MAX_BYTES);
buffer.writeBytes(bytes, 0, writeLength);
int fillCount = (STRING_MAX_BYTES + 1) - writeLength;
for (int i = 0; i < fillCount; i++) {
buffer.writeByte(0);
}
}
}