/*
* 作成日: 2008/06/29
*/
package jp.ac.fit.asura.nao.communication;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import jp.ac.fit.asura.nao.DatagramService;
import jp.ac.fit.asura.nao.RobotContext;
import jp.ac.fit.asura.nao.VisualCycle;
import jp.ac.fit.asura.nao.VisualFrameContext;
import jp.ac.fit.asura.nao.event.RoboCupMessageListener;
import jp.ac.fit.asura.nao.strategy.StrategyContext;
import org.apache.log4j.Logger;
/**
* @author $Author: sey $
*
* @version $Id: MessageManager.java 713 2008-11-24 06:27:48Z sey $
*
*/
public class MessageManager implements VisualCycle {
private Logger log = Logger.getLogger(MessageManager.class);
private RobotContext robotContext;
private StrategyContext strategyContext;
private DatagramService ds;
private AsuraLink link;
private ByteBuffer dsbuf = ByteBuffer.allocate(2048);
private List<RoboCupMessageListener> roboCupListeners;
private RoboCupGameControlData gameData;
private AsuraLinkStrategySendData strategySendData;
private AsuraLinkStrategyReceiveData strategyReceiveData;
boolean flg;
public MessageManager() {
roboCupListeners = new CopyOnWriteArrayList<RoboCupMessageListener>();
gameData = new RoboCupGameControlData();
}
@Override
public void init(RobotContext rctx) {
log.info("init Communication.");
robotContext = rctx;
ds = robotContext.getDatagramService();
link = new AsuraLink(rctx);
}
@Override
public void start() {
strategyContext = robotContext.getStrategy().getContext();
strategySendData = new AsuraLinkStrategySendData(strategyContext);
strategyReceiveData = new AsuraLinkStrategyReceiveData(strategyContext);
strategySendData.init(robotContext);
log.info("start communication.");
}
@Override
public void step(VisualFrameContext context) {
// 自分のWorldObjectデータを送信.
// 1フレーム目はなぜかgetTime(...)で止まるので,2フレーム目から送信する.
if (!flg) {
flg = true;
} else {
strategySendData.send();
// 受信部に古い情報が残っていないかチェック
strategyReceiveData.checkData();
}
while (true) {
dsbuf.clear();
ds.receive(dsbuf);
dsbuf.flip();
if (!dsbuf.hasRemaining()) {
return;
}
byte[] buf = dsbuf.array();
log.trace("received packet. size:" + buf.length);
try {
if (buf.length >= 4
&& RoboCupGameControlData.hasValidHeader(buf)) {
gameData.update(buf);
log.trace("update game control data:" + gameData.toString());
fireUpdateGameData(gameData);
} else if (link.hasValidHeader(buf)) {
log.trace("received asura link packet.");
log.trace("asura link packet. size:" + dsbuf.remaining());
link.parse(buf);
} else {
log.warn("frame:" + context.getFrame()
+ "received unknown packet.");
}
} catch (IndexOutOfBoundsException e) {
log.error("frame:" + context.getFrame(), e);
}
}
}
@Override
public void stop() {
}
private void fireUpdateGameData(RoboCupGameControlData gameData) {
for (RoboCupMessageListener listener : roboCupListeners)
listener.update(gameData);
}
public void addMessageListener(RoboCupMessageListener listener) {
roboCupListeners.add(listener);
}
public void removeListener(RoboCupMessageListener listener) {
roboCupListeners.remove(listener);
}
public AsuraLinkStrategySendData getStrategySendData() {
return strategySendData;
}
public AsuraLinkStrategyReceiveData getStrategyReceiveData() {
return strategyReceiveData;
}
}