/*---------------------------------------------------------------------------------------------------------------- * CupCarbon: OSM based Wireless Sensor Network design and simulation tool * www.cupcarbon.com * ---------------------------------------------------------------------------------------------------------------- * Copyright (C) 2015 Ahcene Bounceur * ---------------------------------------------------------------------------------------------------------------- * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *----------------------------------------------------------------------------------------------------------------*/ package device; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Polygon; import java.util.LinkedList; import java.util.Random; import battery.Battery; //import cupcarbon.RadioModuleWindow; import map.MapLayer; import map.NetworkParameters; import senscript.SenScript; import utilities.MapCalc; import utilities.UColor; import utilities._Constantes; import visibility.VisibilityZones; import wisen_simulation.SimulationInputs; /** * @author Ahcene Bounceur * @author Lounis Massinissa * @version 1.0 */ public abstract class Device extends MapObject implements Runnable, _Constantes, Cloneable { public static final boolean DEAD = false; public static final boolean ALIVE = true; public static final boolean SLEEP = false; protected double sigmaOfDriftTime = 0.00003; protected double driftTime = 1.0; public static int moveSpeed = 100; protected int idm = 0; protected Battery battery ; protected long uartDataRate = 9600;//1000000000; //38400; protected boolean underSimulation = false; protected boolean withRadio = false; protected boolean withSensor = false; protected boolean mobile = false; protected boolean displayRadius = false; protected boolean visited = false; protected boolean drawBatteryLevel = false; protected String [][] infos = {{"SENSOR: ",""},{"ID: ",""},{"MY: ",""},{"Network ID: ",""},{"Channel: ",""},{"Script: ",""},{"GPS: ",""},{"Battery: ",""}}; protected boolean displayInfos = false; protected String scriptFileName = ""; protected String gpsFileName = ""; protected String gpsFileName_ori = ""; protected String nateventFileName = ""; protected SenScript script = null; protected String targetName = ""; protected int ledColor = 0; protected Color radioLinkColor = new Color(221,0,0,190); protected boolean receiving = false; protected boolean sending = false; protected boolean writing = false; protected long distanceModeDelay = 2000 ; protected boolean state = ALIVE; //---------------------------------- // For Algorithms //---------------------------------- protected boolean marked = false; protected double value = 0; protected LinkedList<Double> valueList; //---------------------------------- protected double event = Double.MAX_VALUE; // Event relied to actions = sending/receiving protected double event2 = Double.MAX_VALUE; // Event relied to mobility protected double event3 = Double.MAX_VALUE; // Event relied to natural events protected Thread thread; protected String message = ""; private Random random = new Random(); /** * Empty constructor */ public Device() { super(); } public Device(double x, double y, double z, double radius, int id) { super(x, y, z, radius, id); } /** * Set the GPS file path of the device * * @param gpsFileName */ public void setGPSFileName(String gpsFileName) { if(gpsFileName.endsWith(".gps")) this.gpsFileName = gpsFileName; else this.gpsFileName = ""; } /** * @return the GPS file name */ public String getGPSFileName() { return gpsFileName; } /** * @return the Natural Event file name */ public String getNatEventFileName() { return nateventFileName; } /** * Set the GPS file path of the device * * @param gpsFileName */ public void setNatEventFileName(String nateventFileName) { if(nateventFileName.endsWith(".evt")) { this.nateventFileName = nateventFileName; } else { this.nateventFileName = ""; } } /** * This method draw the sensor with another look in order to view if an * algorithm has marked them or not * * @param g * Graphics */ public void drawMarked(Graphics g) { } public void drawSensorUnit(Graphics g) { } public void drawRadioRange(Graphics g) { } /** * @return the user ID */ public String getUserId() { return userId; } /** * Set the user ID * * @param userId */ public void setUserId(String userId) { this.userId = userId; } /** * Set a path and name for the script file * * @param scriptFileName */ public void setScriptFileName(String scriptFileName) { this.scriptFileName = scriptFileName; } /** * @return the path of the communication script file */ public String getScriptFileName() { return scriptFileName; } /** * Set the informations of a device * * @param infos */ public void setInfos(String[][] infos) { this.infos = infos; } /** * @return the informations about the device */ public String[][] getInfos() { infos[0][1] = "S"+id; infos[1][1] = ""+id; infos[5][1] = scriptFileName; infos[6][1] = gpsFileName; infos[7][1] = getBatteryLevelInPercent()+" % ["+(int)getBatteryConsumption()+"]"; return infos; } /** * An algorithm can select or not a device * * @param b * Yes/No (to select the device by algorithms) */ public void setMarked(boolean b) { if(b) ledColor = 1; else ledColor = 0; this.marked = b; } /** * Returns if the node is selected by the algorithm (yellow color) * @return marked */ public boolean isMarked() { return marked; } public void setVisited(boolean visited) { this.visited = visited ; } /** * Returns if the node is visited by the algorithm * This parameter is used to simplify * algorithms programming * @return visited */ public boolean isVisited() { return visited; } /** * Set if the device is dead or not * * @param dead */ public void setDead(boolean dead) { if(dead) { this.marked = false; this.getBattery().setLevel(0); } } public boolean isDead() { if(getBatteryLevel()<=0) return true; return false; } /** * @return if the device is with or without radio */ public boolean withRadio() { return withRadio; } /** * @return radius */ public double getMaxRadius() { return radius; } /** * @param device * A device * @return the distance in pixels between the current device and the one * given as a parameter */ public double distanceInPixel(Device device) { double x2 = device.getLongitude(); double y2 = device.getLatitude(); return MapCalc.distanceInPixels(longitude, latitude, x2, y2); } /** * @param point * @return the distance in meters between the current device and the point * given as parameters (x,y) */ public double distance(double x, double y) { return MapCalc.distance(longitude, latitude, x, y); } /** * @param device * @return the distance in meters between the current device and the one * given as a parameter */ public double distance(Device device) { double x2 = device.getLongitude(); double y2 = device.getLatitude(); return MapCalc.distance(longitude, latitude, x2, y2); } /** * @param id * @return the distance in meters between the current device and the one * having the id given as a parameter */ public double distance(int id) { DeviceWithRadio device = (DeviceWithRadio) DeviceList.getNodeById(id); if (!radioDetect(device)) return -1; double x2 = device.getLongitude(); double y2 = device.getLatitude(); return MapCalc.distance(longitude, latitude, x2, y2); } /** * @param device * @return the horizontal distance in meters between the current design and * the one given as a parameter */ public double distanceX(Device device) { double x2 = device.getLongitude(); return MapCalc.distance(longitude, latitude, x2, latitude); } /** * @param device * @return the vertical distance in meters between the current design and * the one given as a parameter */ public double distanceY(Device device) { double y2 = device.getLatitude(); return MapCalc.distance(longitude, latitude, longitude, y2); } /** * Set the ID number */ public void setId() { id = DeviceList.number++; } /** * Stop the simulation */ @SuppressWarnings("deprecation") public void stopAgentSimulation() { if (thread != null) { thread.stop(); longitude = longitude_ori; latitude = latitude_ori; } thread = null; underSimulation = false; MapLayer.repaint(); } public void stopSimByAlgo() { thread = null; underSimulation = false; MapLayer.repaint(); } /** * Start the simulation */ public void agentSimulation() { if (selected) { selected = false; start(); } } /** * Draw the radius * * @param x * Longitude * @param y * Latitude * @param r * Radius * @param g * Graphics */ public void drawRadius(int x, int y, int r, Graphics g) { } public boolean displayInfos() { return displayInfos; } /** * Draw the informations of the device * * @param device * Device * @param g * Graphics */ public void drawInfos(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setStroke(new BasicStroke(0.6f)); int[] coord; if (displayInfos && selected && infos != null) { g.setFont(new Font("arial", 1, 10)); coord = MapCalc.geoToPixelMapA(latitude, longitude); int lx1 = coord[0]; int ly1 = coord[1]; g.setColor(UColor.WHITE_TRANSPARENT); g.fillRect(lx1 + 20, ly1 - 25, 150, 90); g.setColor(UColor.BLACK_TRANSPARENT); g.drawRect(lx1 + 20, ly1 - 25, 150, 90); g.setColor(Color.black); g.drawString(getInfos()[0][0] + getInfos()[0][1], lx1 + 30, ly1 - 10); g.drawString(getInfos()[1][0] + getInfos()[1][1], lx1 + 30, ly1); g.drawString(getInfos()[2][0] + getInfos()[2][1], lx1 + 30, ly1 + 10); g.drawString(getInfos()[3][0] + getInfos()[3][1], lx1 + 30, ly1 + 20); g.drawString(getInfos()[4][0] + getInfos()[4][1], lx1 + 30, ly1 + 30); g.drawString(getInfos()[5][0] + getInfos()[5][1], lx1 + 30, ly1 + 40); g.drawString(getInfos()[6][0] + getInfos()[6][1], lx1 + 30, ly1 + 50); g.drawString(getInfos()[7][0] + getInfos()[7][1], lx1 + 30, ly1 + 60); } } // public Device duplicate() { // try { // DeviceList.add(clone()); // } catch (CloneNotSupportedException e) { // e.printStackTrace(); // } // } public Device duplicateByConsole() throws CloneNotSupportedException { Device newNode = (Device) super.clone(); newNode.setId(); newNode.setScriptFileName(scriptFileName); newNode.setGPSFileName(gpsFileName); newNode.setLongitude(this.getLongitude()+0.0001); newNode.setLatitude(this.getLatitude()+0.0001); newNode.setElevation(this.getElevation()); return newNode; } @Override public Device clone() throws CloneNotSupportedException { Device newNode = (Device) super.clone(); newNode.setId(); newNode.setScriptFileName(scriptFileName); newNode.setGPSFileName(gpsFileName); return newNode; } /** * Start simulation thread */ public void start() { if (thread == null) { thread = new Thread(this); thread.start(); } else { System.out.println("Simulation is running for node " + getName()); } } /** * @return the battery level */ public double getBatteryLevel() { if(getBattery() != null) return getBattery().getLevel(); return 0; } /** * Set the battery level */ public void setBatteryLevel(double level) { if(getBattery() != null) getBattery().setLevel(level); } /** * @return the battery level in percent */ public int getBatteryLevelInPercent() { return getBattery().getLevelInPercent(); } public double getBatteryConsumption() { return getBattery().getBatteryConsumption(); } /** * @return the battery object */ public Battery getBattery() { return battery; } /** * @return the state of the device */ public boolean getState() { return state; } /** * Set the state value * * @param state */ public void setState(boolean state) { this.state = state; } /** * @return if the device is visible */ public boolean isVisible() { return visible; } public Thread getThread() { return thread; } public static void initNumber() { DeviceList.number = 1; } public static void incNumber() { DeviceList.number++; } public void fixori() { longitude_ori = longitude; latitude_ori = latitude; elevation_ori = elevation; gpsFileName_ori = gpsFileName; if (SimulationInputs.visibility) { if(getType()==Device.SENSOR || getType()==Device.MEDIA_SENSOR) { VisibilityZones vz = new VisibilityZones((SensorNode) this); vz.run(); } } } public void toOri() { longitude = longitude_ori; latitude = latitude_ori; elevation = elevation_ori; gpsFileName = gpsFileName_ori; if (SimulationInputs.visibility) { if(getType()==Device.SENSOR || getType()==Device.MEDIA_SENSOR) { VisibilityZones vz = new VisibilityZones((SensorNode) this); vz.run(); } } } public int getHide() { return hide; } public abstract double getNextTime(); public abstract void loadRouteFromFile(); public abstract void moveToNext(boolean visual, int visualDelay); public abstract boolean hasNext() ; public abstract double getNextValueTime(); public abstract void generateNextValue(); public void setLedColor(int ledColor) { this.ledColor = ledColor; } public int getLedColor() { return ledColor; } public void setTrgetName(String targetName) { this.targetName = targetName; } public String getTargetName() { return targetName ; } public double getValue() { return value; } public void setValue(double value) { this.value = value; } @Override public String toString() { return ""+id; } //------ public void creatValueList() { valueList = new LinkedList<Double>(); } public Double getIthValue(int i) { return valueList.get(i); } public void addValue(Double value) { valueList.add(value); } // Remove the first occurence public void removeValue(Double value) { valueList.remove(value); } public void removeIthValue(int i) { valueList.remove(i); } public SenScript getScript() { return script; } public void setEvent(double event) { this.event = event ; } public void setEvent(String event) { this.event = Double.parseDouble(event) ; } public double getEvent() { return event; } public void setEvent2(double event) { this.event2 = event ; } public double getEvent2() { return event2; } public void setEvent3(double event) { this.event3 = event ; } public double getEvent3() { return event3; } public abstract void loadScript(); public abstract void initBuffer() ; public abstract void initForSimulation(); public Device cloneWithSameId() throws CloneNotSupportedException { Device newNode = (Device) super.clone(); newNode.setScriptFileName(scriptFileName); newNode.setGPSFileName(gpsFileName); return newNode; } public Device cloneDeviceWithId() throws CloneNotSupportedException { Device newNode = (Device) super.clone(); newNode.setScriptFileName(scriptFileName); newNode.setGPSFileName(gpsFileName); return newNode; } public void init() { message = ""; setMarked(false); setVisited(false); setDead(false); setLedColor(0); initBattery(); initBuffer(); } public abstract void initBattery() ; public boolean isSending() { return sending; } public boolean isWriting() { return writing; } public boolean isReceiving() { return receiving; } public void setSending(boolean b) { sending = b; } public void setWriting(boolean b) { writing = b; } public void setReceiving(boolean b) { receiving = b; } public Color getRadioLinkColor() { return radioLinkColor; } public void setRadioLinkColor(Color radioLinkColor) { this.radioLinkColor = radioLinkColor; } public void gotoTheNextInstruction() { if(!script.getCurrent().isExecuting()) { script.next(); } } public void gotoTheNextEvent(double min) { if(event != Double.MAX_VALUE) event = event - min; } public long getDistanceModeDelay() { return distanceModeDelay; } public void setDistanceModeDelay(long distanceModeDelay) { this.distanceModeDelay = distanceModeDelay; } public void setMessage(String message) { this.message = message; } public String getMessage() { return message; } public long getUartDataRate() { return uartDataRate; } public void setUartDataRate(long uartDataRate) { this.uartDataRate = uartDataRate; } public void drift() { double d = random.nextGaussian() * sigmaOfDriftTime; if (d > (3.0*sigmaOfDriftTime)) d = 3.0*sigmaOfDriftTime; if (d < (-3.0*sigmaOfDriftTime)) d = -3.0*sigmaOfDriftTime; System.out.println(d); driftTime = 1 - d; } public double getDriftTime() { return driftTime; } public double getSigmaOfDriftTime() { return sigmaOfDriftTime; } public abstract Polygon getRadioPolygon(); public abstract void execute(); public abstract void drawRadioLinks(int k, Graphics g) ; public abstract void calculatePropagations(); public abstract void resetPropagations(); public abstract void drawRadioPropagations(Graphics g) ; public abstract boolean radioDetect(DeviceWithRadio device) ; public void setSigmaOfDriftTime(double sigmaOfDriftTime) { this.sigmaOfDriftTime = sigmaOfDriftTime; } public boolean isMobile() { return !gpsFileName.equals(""); } public boolean getDisplaydRadius() { return displayRadius; } public void setDisplaydRadius(boolean b) { displayRadius = b; } public boolean getDisplaydInfos() { return displayInfos; } public void setDisplaydInfos(boolean b) { displayInfos = b; } public void setHide(int hide) { this.hide = hide ; } public boolean getDrawBatteryLevel() { return drawBatteryLevel; } public void setDrawBatteryLevel(boolean b) { drawBatteryLevel = b; } /** * Draw the ID of the device * * @param x * Longitude * @param y * Latitude * @param g * Graphics */ public void drawId(int x, int y, Graphics g) { if (NetworkParameters.displayDetails) { g.setColor(Color.BLACK); if(MapLayer.dark) g.setColor(new Color(179, 221, 67)); g.drawString(getName(), (int) (x + 10), (int) (y + 6)); } } public void increaseRadius(int d) { radius += d ; } public abstract double getSensorUnitRadius(); public abstract double getESensing(); public void invertDrawBatteryLevel() { drawBatteryLevel = !drawBatteryLevel; } public abstract Device duplicate() ; public abstract Device duplicateWithShift(double sh1, double sh2, double sh3) ; public abstract void save(String fileName) ; }