/** * Mazilu Sinziana * * EZCab Car Entity */ package vnsim.applications.ezcab; import java.io.IOException; import java.io.Serializable; import java.nio.ByteBuffer; import java.util.ArrayList; import vnsim.network.dsrc.*; import vnsim.core.*; import vnsim.core.events.SendEvent; import vnsim.map.object.Globals; public class EzcabCar extends CarRunningDSRC{ private int entityType = EzcabGlobals.CAB; /* type of entity: client or cab */ private int state; /* state of cab */ private int newState = EzcabGlobals.FREE_STATE; /* future state of cab */ private EzcabMessage newMessage; /* next message to be prepared */ private ArrayList waitingMessages = new ArrayList(); private long changeInWaitingState = 0; private int clientID; private int timeOfsending = 0; public EzcabCar(int state, int vehicleId, byte lane, double speed, short roadIdx, short pointIdx, byte direction,double offset) { super(vehicleId, lane, speed, roadIdx, pointIdx, direction, offset); this.entityType = EzcabGlobals.CAB; this.state = state; } /* this should be used */ public EzcabCar(int vehicleId, byte lane, double speed, short roadIdx, short pointIdx, byte direction,double offset) { super(vehicleId, lane, speed, roadIdx, pointIdx, direction, offset); this.entityType = EzcabGlobals.CAB; this.state = EzcabGlobals.FREE_STATE; } public void onReceive(byte[] bytesReceived, Serializable message, Communicator sender){ if (!isEquipped) return; if(bytesReceived == null){ processMessage(message); return; } byte header = bytesReceived[0]; switch(header) { case Globals.PROT_EZCAB: processMessage(message); break; default: super.onReceive(bytesReceived, message, sender); } } public void processMessage(Serializable message) { int idClient; int noHops; int ts; if(message == null){ return; } if(message instanceof EzcabRequest){ EzcabRequest req = (EzcabRequest)message; noHops = req.getNoHops(); idClient = req.getIdClient(); ts = req.getTimeOfSending(); /* verify if cab doesn't wait too long */ //if( ((int)(currentTime - this.changeInWaitingState)/Globals.SECOND) > EzcabGlobals.TIMEOUT){ if( ((long)(Globals.engine.getCrtTime() - this.timeOfsending)/Globals.SECOND * 1000) > EzcabGlobals.TIMEOUT ){ this.changeInWaitingState = 0; this.timeOfsending = 0; this.clientID = -1; this.state = EzcabGlobals.FREE_STATE; this.newMessage = null; this.newState = EzcabGlobals.FREE_STATE; } if(this.state == EzcabGlobals.WAITING_STATE){ /* if message is not expired */ if((noHops - 1) > 0){ /* add message to my waiting queue */ updateWaitingQueue(); if(((long)(Globals.engine.getCrtTime() - ts)/Globals.SECOND * 1000) < EzcabGlobals.TIMEOUT ){ this.newMessage = new EzcabRequest(Globals.PROT_EZCAB, EzcabGlobals.REQUEST, idClient, (noHops -1), ts); this.waitingMessages.add(req); } else{ this.newMessage = null; } /* prepare to forward message in next event handler */ } else{ this.newMessage = null; } /* in this case, state is the same */ this.newState = EzcabGlobals.WAITING_STATE; } if(this.state == EzcabGlobals.FREE_STATE){ EzcabRequest requestFromQueue = this.getMessageMaxSendTime(); if(requestFromQueue != null){ if(requestFromQueue.getTimeOfSending() > ts){ this.newMessage = requestFromQueue; this.timeOfsending = requestFromQueue.getTimeOfSending(); this.clientID = requestFromQueue.getIdClient(); this.waitingMessages.add(req); } else{ /* make a next message with the response */ this.newMessage = new EzcabResponse(Globals.PROT_EZCAB, EzcabGlobals.RESPONSE, this.vehicleId, idClient, EzcabGlobals.MAX_HOPS); //this.changeInWaitingState = System.currentTimeMillis(); this.timeOfsending = ts; this.clientID = idClient; } } else{ /* make a next message with the response */ this.newMessage = new EzcabResponse(Globals.PROT_EZCAB, EzcabGlobals.RESPONSE, this.vehicleId, idClient, EzcabGlobals.MAX_HOPS); //this.changeInWaitingState = System.currentTimeMillis(); this.timeOfsending = ts; this.clientID = idClient; } /* change next state */ this.newState = EzcabGlobals.WAITING_STATE; } if(this.state == EzcabGlobals.BUSY_STATE){ if((noHops -1) > 0){ this.newMessage = new EzcabRequest(Globals.PROT_EZCAB, EzcabGlobals.REQUEST, idClient, (noHops -1), ts); } else{ this.newMessage = null; } this.newState = EzcabGlobals.BUSY_STATE; } }//end ezcabRequest if(message instanceof EzcabAck){ EzcabAck ack = (EzcabAck)message; noHops = ack.getNoHops(); idClient = ack.getIdClient(); int idCab = ack.getIdCab(); if(this.state == EzcabGlobals.WAITING_STATE){ //if( ((currentTime - this.changeInWaitingState)%Globals.SECOND) > EzcabGlobals.TIMEOUT){ if( ((long)(Globals.engine.getCrtTime() - this.timeOfsending)/Globals.SECOND * 1000) > EzcabGlobals.TIMEOUT ){ this.changeInWaitingState = 0; this.timeOfsending = 0; this.clientID = -1; this.state = EzcabGlobals.FREE_STATE; //don't know if is necessary this.newMessage = null; this.newState = EzcabGlobals.FREE_STATE; } else{ if(this.vehicleId == idCab){//that means is for me yeeeeeyyyy! try { Engine.bwCab.write(idClient + " " + this.vehicleId + " " + (long)((float)Globals.engine.crtTime)/Globals.SECOND * 1000L + " " + (long)((float)(Globals.engine.crtTime - this.timeOfsending)/Globals.SECOND * 1000L) + "\n"); Engine.bwCab.flush(); } catch (IOException e1) { e1.printStackTrace(); } this.newMessage = null; this.newState = EzcabGlobals.BUSY_STATE; } else{ if((noHops -1) > 0){ this.newMessage = new EzcabAck(Globals.PROT_EZCAB, EzcabGlobals.ACK, idClient, idCab, (noHops - 1)); } else this.newMessage = null; this.newState = EzcabGlobals.WAITING_STATE; } } } if( (this.state == EzcabGlobals.FREE_STATE) || (this.state == EzcabGlobals.BUSY_STATE) ){ if((noHops -1) > 0){ this.newMessage = new EzcabAck(Globals.PROT_EZCAB, EzcabGlobals.ACK, idClient, idCab, (noHops - 1)); } else this.newMessage = null; this.newState = this.state; } }// end ezcabAck if(message instanceof EzcabResponse){ EzcabResponse res = (EzcabResponse)message; int idFreeCab = res.getIdFreeCab(); idClient = res.getIdClient(); noHops = res.getNoHops(); /* dosn't matter the state of the cab - he only forwards the message */ if((noHops -1) > 0){ this.newMessage = new EzcabResponse(Globals.PROT_EZCAB, EzcabGlobals.RESPONSE, idFreeCab, idClient, (noHops - 1)); } else{ this.newMessage = null; } this.newState = this.state; }// end ezcabResponse SendEvent e = new SendEvent(Globals.engine.crtTime, this, Globals.TYPE_EZCAB); e.setMessageObject(this.newMessage); Globals.engine.schedEvent(e); this.state = this.newState; } public byte[] prepareMessage(int messageType){ byte[] bytesToSend=null; /* update state */ this.state = this.newState; if ( (!isEquipped) || (this.newMessage == null) ) return null; if(messageType == Globals.TYPE_EZCAB){ /* if is a request message */ if(this.newMessage instanceof EzcabRequest){ EzcabRequest request = (EzcabRequest)this.newMessage; ByteBuffer bb = ByteBuffer.allocate(17); bb.put(request.getProtType()); //bb.put(Globals.PROT_EZCAB); bb.putInt(request.getMessageType()); //bb.putInt(EzcabGlobals.REQUEST); bb.putInt(request.getIdClient()); bb.putInt(request.getNoHops()); bb.putInt(request.getTimeOfSending()); bytesToSend = bb.array(); } /* if is a response message */ if(this.newMessage instanceof EzcabResponse){ EzcabResponse response = (EzcabResponse)this.newMessage; ByteBuffer bb = ByteBuffer.allocate(17); bb.put(response.getProtType()); //bb.put(Globals.PROT_EZCAB); bb.putInt(response.getMessageType()); //bb.putInt(EzcabGlobals.RESPONSE); bb.putInt(response.getIdFreeCab()); bb.putInt(response.getIdClient()); bb.putInt(response.getNoHops()); bytesToSend = bb.array(); } /* if is an ack message */ if(this.newMessage instanceof EzcabAck){ EzcabAck ack = (EzcabAck)this.newMessage; ByteBuffer bb = ByteBuffer.allocate(17); bb.put(ack.getProtType()); //bb.put(Globals.PROT_EZCAB); bb.putInt(ack.getMessageType()); //bb.putInt(EzcabGlobals.ACK); bb.putInt(ack.getIdClient()); bb.putInt(ack.getIdCab()); bb.putInt(ack.getNoHops()); bytesToSend = bb.array(); } return bytesToSend; } else{ return super.prepareMessage(messageType); } } /* remove from waiting queue expired messages */ public void updateWaitingQueue(){ int messageTime; for(int i = 0; i < this.waitingMessages.size(); i++){ messageTime = (int)(this.waitingMessages.get(i)).getTimeOfSending(); if( ((long)(Globals.engine.getCrtTime() - messageTime) / Globals.SECOND * 1000) > EzcabGlobals.TIMEOUT) this.waitingMessages.remove(i); } } public EzcabRequest getMessageMaxSendTime(){ int messageTime, maxTime = 0; EzcabRequest message = null; for(int i = 0; i < this.waitingMessages.size(); i++){ messageTime = (int)(this.waitingMessages.get(i)).getTimeOfSending(); if(messageTime > maxTime){ maxTime = messageTime; message = this.waitingMessages.get(i); } } return message; } }