package de.tu_darmstadt.tk.SmartHomeNetworkSim.core; import java.util.Collection; import java.util.Random; import org.apache.commons.math3.distribution.AbstractRealDistribution; import org.apache.commons.math3.distribution.LaplaceDistribution; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.distributionHandler.ConstantValueDistributionHandler; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.scheduler.Schedulable; /** * Representation of connection EndPoints, which allows configuration of timings * and if it reacts to incoming traffic or even triggers new connections. * * @author Andreas T. Meyer-Berg */ public class Port implements Schedulable { /** * A closed Port which does not react to incoming traffic */ public static final short CLOSED = 0; /** * Open Port which reacts to incoming traffic */ public static final short OPEN = 1; /** * Open Port which reacts to incoming traffic and sends packets every * triggerInterval */ public static final short SENDING = 2; /** * Status of the Port, whether it is CLOSED, OPEN or SENDING */ private short status; /** * SmartDevice which owns the port */ private SmartDevice owner; /** * Connection this Port listens to */ private Connection connection; /** * Last timestep traffic was triggered */ private long lastTrigger; /** * Time in milliseconds needed for responds to incoming */ private short responseTime; /** * Jitter of the connection of this port. Random fluctuation of delivery times. */ private short jitter; /** * Current Jitter, updated after every simulation */ private short currentJitter; /** * Port number of this Port. */ private short portNumber; /** * Constant time interval, which triggers new traffic every * {@code triggerInterval} milliseconds. */ private long triggerInterval; /** * Probability Distribution for calculating the next Trigger */ private ProbabilityDistributionHandler triggerIntervalStat; /** * Creates a new Port for the given Device with the specified PortNumber * @param device SmartDevice this port listens on * @param portNumber Number of the Port */ public Port(SmartDevice device, short portNumber){ status = SENDING; owner = device; connection = null; triggerIntervalStat = new ConstantValueDistributionHandler(new Random().nextInt(1000)+1); triggerInterval = Math.max(1, triggerIntervalStat.sampleNextValue()); //setTriggerInterval(new Random().nextInt(1000)+1); lastTrigger = 0; jitter = (short)(new Random().nextInt(5)+1); currentJitter = (short)Math.round(Math.random()*jitter); responseTime = 0; this.portNumber = portNumber; } /** * Creates a new Port for the given Device with the specified PortNumber * @param device SmartDevice this port listens on * @param portNumber Number of the Port * @param triggerInterval frequency the port should trigger */ public Port(SmartDevice device, short portNumber, long triggerInterval){ status = SENDING; owner = device; connection = null; triggerIntervalStat = new ConstantValueDistributionHandler(triggerInterval); this.triggerInterval = Math.max(1, triggerIntervalStat.sampleNextValue()); lastTrigger = 0; jitter = 0; currentJitter = (short)Math.round(Math.random()*jitter); responseTime = 0; this.portNumber = portNumber; } /** * Creates a new Port for the given Device with the specified PortNumber * @param device SmartDevice this port listens on * @param portNumber Number of the Port * @param triggerInterval frequency the port should trigger * @param jitter Jitter * @param lastTrigger last time a packet was sent * @param responseTime response time */ public Port(SmartDevice device, short portNumber, long triggerInterval, short jitter, long lastTrigger, short responseTime){ status = SENDING; owner = device; connection = null; triggerIntervalStat = new ConstantValueDistributionHandler(triggerInterval); this.triggerInterval = Math.max(1, triggerIntervalStat.sampleNextValue()); this.lastTrigger = lastTrigger; this.jitter = jitter; currentJitter = (short)Math.round(Math.random()*jitter); this.responseTime = responseTime; this.portNumber = portNumber; } /** * @return the status */ public short getStatus() { return status; } /** * @param status * the status to set */ public void setStatus(short status) { this.status = status; } /** * @return the owner */ public SmartDevice getOwner() { return owner; } /** * @param owner * the owner to set */ public void setOwner(SmartDevice owner) { this.owner = owner; } /** * TriggerInterval is sampled from distribution after previous simulation * @return the triggerInterval */ public long getTriggerInterval() { return triggerInterval; } /** * Returns the Probability Handler for the trigger interval, which allows configuration of the Distribution * @return Distribution Handler for configuration */ public ProbabilityDistributionHandler getTriggerHandler(){ return triggerIntervalStat; } /** * Set a new Probability Distribution Handler to sample the trigger interval * @param triggerHandler Sets the Probability Distribution to generate the trigger interval */ public void setTriggerHandler(ProbabilityDistributionHandler triggerHandler){ this.triggerIntervalStat = triggerHandler; boolean removed = SimulationManager.removeEvent(this); this.triggerInterval = Math.max(1, triggerHandler.sampleNextValue()); if(removed) SimulationManager.scheduleEvent(this); } /** * Samples a new Value for the TriggerInterval */ public void resampleTriggerInterval(){ boolean removed = SimulationManager.removeEvent(this); this.triggerInterval = Math.max(triggerIntervalStat.sampleNextValue(),1); if(removed) SimulationManager.scheduleEvent(this); } /** * @return the responseTime */ public short getResponseTime() { return responseTime; } /** * @param responseTime * the responseTime to set */ public void setResponseTime(short responseTime) { if(responseTime<=0) this.responseTime = 0; else this.responseTime = responseTime; } /** * @return the portNumber */ public short getPortNumber() { return portNumber; } /** * @param portNumber * the portNumber to set */ public void setPortNumber(short portNumber) { this.portNumber = portNumber; } /** * @return the last timestep the port sent a package */ public long getLastTrigger() { return lastTrigger; } /** * @param lastTrigger the last timestep the port sent */ public void setLastTrigger(long lastTrigger) { this.lastTrigger = lastTrigger; } /** * @return the connection */ public Connection getConnection() { return connection; } /** * @param connection the connection to set */ public void setConnection(Connection connection) { this.connection = connection; } /** * Return the Jitter of the port, which represents random fluctuations of the delivery times * @return the Jitter */ public short getJitter() { return jitter; } /** * Set Jitter of the port, which represents random fluctuations of the delivery times * @param jitter the Jitter to set */ public void setJitter(short jitter) { this.jitter = jitter; } /** * Returns a String representation for the status byte * Returns 0:closed, 1:open, 2:sending * * @param s as specified by {@link Port} * @return textual representation of the status */ public static String statusToString(short s){ switch (s) { case CLOSED: return "closed"; case OPEN: return "open"; case SENDING: return "sending"; default: return "unknown"; } } @Override public String toString() { String protocol = ""; if(connection!=null&&connection.getProtocol()!=null) protocol=connection.getProtocol().getName(); return "Port: " + portNumber + protocol + " Status:" + statusToString(status) + " " + "TriggerInterval:"+triggerInterval+" "+(owner == null ? "" : " on " + owner.getName()); } /** * Returns the transmission delay in milliseconds to the other port, which is specified in the Link of the Connection. * @param to Port, which should receive the transmission * @return delay between this port and the to Port. */ public long getTransmissionDelayTo(Port to){ if(connection != null && connection.getLink() != null) if(owner != null && to != null && to.getOwner()!=null) return connection.getLink().getTransmissionDelayFrom(owner, to.getOwner()); return Long.MAX_VALUE; } @Override public long getEventTime() { return lastTrigger+triggerInterval+currentJitter; } @Override public void simulateEvent(long time) { if(connection==null || connection.getProtocol()==null || connection.getLink()==null || owner == null) return; /** * Packets of the transfer initiated by this port */ Collection packets = connection.getProtocol().generateNextPackets(this, time, false); //Packets encapsulated by Connection packets = connection.encapsulatePackages(packets); //Encapsulate packets in Links packets = connection.getLink().encapsulatePackages(packets); connection.getLink().addPackets(packets); //TODO: Sample next game triggerInterval = Math.max(1,triggerIntervalStat.sampleNextValue()); if(status==Port.SENDING && connection.getStatus()==Connection.ACTIVE) SimulationManager.scheduleEvent(this); } }