/*---------------------------------------------------------------------------------------------------------------- * CupCarbon: OSM based Wireless Sensor Network design and simulation tool * www.cupcarbon.com * ---------------------------------------------------------------------------------------------------------------- * Copyright (C) 2013 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.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Polygon; import java.awt.Stroke; import java.awt.geom.Point2D; import java.util.LinkedList; import java.util.List; import java.util.Random; import org.jdesktop.swingx.mapviewer.GeoPosition; import battery.Battery; import geo_objects.GeoZoneList; import map.MapLayer; import map.NetworkParameters; import radio_module.RadioDetection; import radio_module.RadioModule; import utilities.MapCalc; import utilities.UColor; import wisen_simulation.SimulationInputs; /** * @author Ahcene Bounceur * @author Lounis Massinissa * @version 1.0 */ public abstract class DeviceWithRadio extends DeviceWithWithoutRadio { protected double porteeErr = .4 ; protected Random random = new Random() ; protected LinkedList<RadioModule> radioModuleList = new LinkedList<RadioModule>(); protected RadioModule currentRadioModule = null; protected LinkedList<SensorNode> neighbors = new LinkedList<SensorNode> () ; protected int nPoint = 30; protected double deg = 2.*Math.PI/nPoint; protected int [] polyX = new int [nPoint]; protected int [] polyY = new int [nPoint]; protected int numberOfNeighbors = 0; protected boolean ackReceived = false; protected boolean ackWaiting = false; /** * */ public DeviceWithRadio() { this(0, 0, 0, 0, 0, -1); } /** * @param x * @param y * @param z * @param radius * @param radioRangeRadius */ public DeviceWithRadio(double x, double y, double z, double radius, double radioRangeRadius, int id) { super(x, y, z, radius, id); initGeoZoneList(); } public void setGeoZoneList(GeoZoneList geoZoneList) { this.geoZoneList = geoZoneList ; } public void initGeoZoneList() { geoZoneList = new GeoZoneList(); } public Polygon getRadioPolygon() { return new Polygon(polyX, polyY, nPoint); } public boolean contains(Point2D p) { if(nPoint>0) return (getRadioPolygon().contains(p)); return (geoZoneList.contains((Point) p)); } public boolean contains(DeviceWithRadio device) { GeoPosition gp = new GeoPosition(device.getLatitude(), device.getLongitude()); Point2D p = MapLayer.mapViewer.getTileFactory().geoToPixel(gp, MapLayer.mapViewer.getZoom()); if(nPoint>0) return ((new Polygon(polyX, polyY, nPoint)).contains(p)); return (geoZoneList.contains(p)); } @Override public Battery getBattery() { return battery; } public double getRadioRadiusOri() { return currentRadioModule.getRadioRangeRadiusOri() ; } public void setRadioRadius(double radioRadius) { currentRadioModule.setRadioRangeRadius(radioRadius) ; } @Override public void initSelection() { super.initSelection() ; } /** * @param x * @param y * @param r * @param g */ public void drawRadioRadius(int x, int y, int r, Graphics g) { this.getCurrentRadioModule().drawRadioRadius(x, y, r, g); } @Override public void drawMarked(Graphics g2) { if (!isDead()) { Graphics2D g = (Graphics2D) g2; g.setStroke(new BasicStroke(0.4f)); if (ledColor==1) { int[] coord = MapCalc.geoToPixelMapA(latitude, longitude); int x = coord[0]; int y = coord[1]; g.setColor(Color.ORANGE); int r2 = 8; g.setColor(UColor.GREEND_TRANSPARENT); g.fillOval(x-(r2+1), y-(r2+1), (r2+1)*2, (r2+1)*2); g.setColor(Color.GRAY); g.drawOval(x-(r2+1), y-(r2+1), (r2+1)*2, (r2+1)*2); } if(ledColor>1) { int[] coord = MapCalc.geoToPixelMapA(latitude, longitude); int x = coord[0]; int y = coord[1]; g.setColor(Color.ORANGE); int r2 = 8; g.setColor(UColor.colorTab[ledColor-1]); g.fillOval(x-(r2+1), y-(r2+1), (r2+1)*2, (r2+1)*2); g.setColor(Color.GRAY); g.drawOval(x-(r2+1), y-(r2+1), (r2+1)*2, (r2+1)*2); } } } public List<SensorNode> getNeighbors() { if(DeviceList.propagationsCalculated) return neighbors; else { List<SensorNode> neighnodes = new LinkedList<SensorNode>(); for(SensorNode sensorNode : DeviceList.sensors) { if(radioDetect(sensorNode) && this!=sensorNode && !isDead() && !sensorNode.isDead()) { neighnodes.add(sensorNode); } } return neighnodes; } } public List<SensorNode> getActiveNodes() { List<SensorNode> neighActiveNodes = new LinkedList<SensorNode>(); for(SensorNode sensorNode : getNeighbors()) { if(sensorNode.isSending()) neighActiveNodes.add(sensorNode); } return neighActiveNodes; } public int getPerActiveNodes() { int n = getNeighbors().size(); int p = 0; for(SensorNode sensorNode : getNeighbors()) { if(sensorNode.isSending()) p++; } return (p/n); } public void displayNeighbors() { System.out.print(id+" : "); for (int i = 0; i < DeviceList.sensors.size(); i++) { if(this != DeviceList.sensors.get(i)) if((DeviceList.sensors.get(i).radioDetect(this)) || (radioDetect((DeviceWithRadio)DeviceList.sensors.get(i)))) { System.out.print(DeviceList.sensors.get(i)+" "); } } System.out.println(); } public void drawRadioLinks2(Graphics g) { numberOfNeighbors = 0; for(SensorNode sensor : DeviceList.sensors) { if(this!=sensor) { if(radioDetect(sensor) && !isDead() && !sensor.isDead()) { drawRadioLink(sensor, g, 1); numberOfNeighbors++; if (NetworkParameters.displayRLDistance) { MapLayer.drawDistance(longitude, latitude, elevation, sensor.getLongitude(), sensor.getLatitude(), sensor.getElevation(), g); } } } } } public void drawRadioLinks(int k1, Graphics g) { numberOfNeighbors = 0; //int k2 = 0; for(SensorNode sensor : DeviceList.sensors) { //if(k2>k1) { if(this!=sensor) { if(radioDetect(sensor) && !isDead() && !sensor.isDead()) { drawRadioLink(sensor, g, 1); numberOfNeighbors++; if (NetworkParameters.displayRLDistance) { MapLayer.drawDistance(longitude, latitude, elevation, sensor.getLongitude(), sensor.getLatitude(), sensor.getElevation(), g); } } } //} //k2++; } } public void drawRadioLinkArrows(Graphics g) { for(SensorNode sensor : DeviceList.sensors) { if(this!=sensor) { if(radioDetect(sensor) && !isDead() && !sensor.isDead()) { drawRadioLinkArrows(sensor, g, 1); } } } } public void drawRadioPropagations(Graphics g) { Device device; for(int i=0; i<neighbors.size(); i++) { device = neighbors.get(i); drawRadioLink(device, g, 0); if (NetworkParameters.displayRLDistance) { MapLayer.drawDistance(longitude, latitude, elevation, device.getLongitude(), device.getLatitude(), device.getElevation(), g); } } } /** * Draw the (line) radio link * * @param device * Device * @param g * Graphics */ public void drawRadioLink(Device device, Graphics g, int type) { if(NetworkParameters.drawRadioLinks) { int[] coord = MapCalc.geoToPixelMapA(latitude, longitude); int lx1 = coord[0]; int ly1 = coord[1]; coord = MapCalc.geoToPixelMapA(device.getLatitude(), device.getLongitude()); int lx2 = coord[0]; int ly2 = coord[1]; setColor(g, NetworkParameters.radioLinksColor); Graphics2D g2 = (Graphics2D) g; Stroke dashed = new BasicStroke(0.4f); if(type==1) dashed = new BasicStroke(0.6f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{3,3}, 0); g2.setStroke(dashed); g2.drawLine(lx1, ly1, lx2, ly2); } } /** * Draw the (line) radio link * * @param device * Device * @param g * Graphics */ public void drawRadioLinkArrows(Device device, Graphics g, int type) { if(NetworkParameters.drawRadioLinks) { int[] coord = MapCalc.geoToPixelMapA(latitude, longitude); int lx1 = coord[0]; int ly1 = coord[1]; coord = MapCalc.geoToPixelMapA(device.getLatitude(), device.getLongitude()); int lx2 = coord[0]; int ly2 = coord[1]; setColor(g, NetworkParameters.radioLinksColor); if(NetworkParameters.drawSensorArrows) { double dx = 0; double dy = 0; double alpha = 0; coord = MapCalc.geoToPixelMapA(latitude, longitude); lx1 = coord[0]; ly1 = coord[1]; coord = MapCalc.geoToPixelMapA(device.getLatitude(), device.getLongitude()); lx2 = coord[0]; ly2 = coord[1]; dx = lx2 - lx1; dy = ly2 - ly1; alpha = Math.atan(dy / dx); alpha = 180 * alpha / Math.PI; int as = 11; if (dx >= 0) g.fillArc((int) lx2 - as, (int) ly2 - as, as*2, as*2,180 - (int) alpha - as, as*2); else g.fillArc((int) lx2 - as, (int) ly2 - as, as*2, as*2, -(int) alpha - as, as*2); } } } public void setColor(Graphics g, int intColor) { switch(intColor) { case 0 : g.setColor(Color.DARK_GRAY); if(MapLayer.dark) g.setColor(Color.LIGHT_GRAY); break; case 1 : g.setColor(Color.BLACK); if(MapLayer.dark) g.setColor(Color.DARK_GRAY); break; case 2 : g.setColor(Color.GRAY); if(MapLayer.dark) g.setColor(UColor.DWHITE); break; case 3 : g.setColor(UColor.RED); break; case 4 : g.setColor(UColor.BLUE); break; case 5 : g.setColor(UColor.ORANGE); if(MapLayer.dark) g.setColor(Color.ORANGE); break; } } /** * 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) { if(r>0 && displayRadius) { g.setColor(UColor.WHITE_TRANSPARENT); int lr2 = (int) (r*Math.cos(Math.PI/4.)); g.drawLine(x,y,x-lr2,y-lr2); g.drawString(""+r,x-lr2,y-lr2); } } /** * @param device * @return if a neighbor device is in the radio area of the current device */ public boolean radioDetect(DeviceWithRadio device) { if (!DeviceList.propagationsCalculated) return RadioDetection.simpleDetection(this, device); else { if (SimulationInputs.radioDetectionType == RadioDetection.POWER_RECEPTION_DETECTION) return RadioDetection.powerReceptionDetection(this, device); if (SimulationInputs.radioDetectionType == RadioDetection.THREED_DETECTION) return RadioDetection.threeDDetection(this, device); } return true; } /** * @param device * @return if a neighbor device is in the propagation area of the current device */ public boolean propagationDetect(DeviceWithRadio device) { if (DeviceList.propagationsCalculated) return neighbors.contains(device); else return radioDetect(device); } public void calculatePropagations() { SimulationInputs.radioDetectionType = RadioDetection.POWER_RECEPTION_DETECTION; neighbors = new LinkedList<SensorNode> () ; for(SensorNode device : DeviceList.sensors) { if(this!=device) { if(radioDetect(device) && !isDead() && !device.isDead()) { neighbors.add(device); } } } } public void resetPropagations() { SimulationInputs.radioDetectionType = RadioDetection.SIMPLE_DETECTION; neighbors = new LinkedList<SensorNode> () ; } public double getRequiredQuality() { return this.getCurrentRadioModule().getRequiredQuality(); } public void setRequiredQuality(double requiredQuality) { this.getCurrentRadioModule().setRequiredQuality(requiredQuality); } public double getTransmitPower() { return this.getCurrentRadioModule().getTransmitPower(); } public void setTransmitPower(double transmitPower) { this.getCurrentRadioModule().setTransmitPower(transmitPower); } /** * Draw the ID of the device * * @param x * Longitude * @param y * Latitude * @param g * Graphics */ @Override public void drawId(int x, int y, Graphics g) { if (NetworkParameters.displayDetails) { g.setColor(UColor.PURPLE); if(MapLayer.dark) g.setColor(new Color(198,232,106)); g.drawString(getName()+" ["+currentRadioModule.getMy()+"]", (int) (x + 10), (int) (y + 5)); } if(!scriptFileName.equals("") && NetworkParameters.drawScriptFileName) { g.setColor(Color.DARK_GRAY); if(MapLayer.dark) g.setColor(Color.LIGHT_GRAY); g.drawString(scriptFileName.substring(0, scriptFileName.indexOf('.')), (int) (x + 10), (int) (y - 6)); // g.drawString("S : "+this.isSending(), (int) (x + 10), (int) (y + 26)); // g.drawString("R : "+this.isReceiving(), (int) (x + 10), (int) (y + 36)); // g.drawString("AW: "+this.isAckWaiting(), (int) (x + 10), (int) (y + 46)); // g.drawString("AR: "+this.isAckReceived(), (int) (x + 10), (int) (y + 56)); } if(NetworkParameters.displayPrintMessage) { g.setColor(new Color(28,64,123)); if(MapLayer.dark) g.setColor(new Color(116,186,209)); if(!message.equals("")) { g.drawString(message, (int) (x + 10), (int) (y + 15)); } else g.drawString(">", (int) (x + 10), (int) (y + 15)); } } public void setMy(int my) { this.getCurrentRadioModule().setMy(my); } public void setPl(int pl) { this.getCurrentRadioModule().setPl(pl); } public RadioModule getCurrentRadioModule() { return currentRadioModule; } public int getAttempts() { return currentRadioModule.getAttempts(); } public void setAttempts(int attempts) { currentRadioModule.setAttempts(attempts); } public void incAttempts() { currentRadioModule.incAttempts(); } public int getStandard() { return getCurrentRadioModule().getStandard(); } public void selectCurrentRadioModule(String name) { for(RadioModule rm : radioModuleList) { if(rm.getName().equals(name)) { currentRadioModule = rm; return; } } } public void removeRadioModule(String name) { for(RadioModule rm : radioModuleList) { if(rm.getName().equals(name) && rm!=this.getCurrentRadioModule()) { radioModuleList.remove(rm); return; } } } public void removeRadioModule(RadioModule radioModule) { for(RadioModule rm : radioModuleList) { if(rm.getName().equals(radioModule.getName()) && rm!=this.getCurrentRadioModule()) { radioModuleList.remove(rm); return; } } } public double getTimeToResend() { return getCurrentRadioModule().getTimeToResend(); } public void setTimeToResend(double timeToResend) { getCurrentRadioModule().setTimeToResend(timeToResend); } public int getNumberOfSends() { return getCurrentRadioModule().getNumberOfSends(); } public void setNumberOfSends(int numberOfSends) { getCurrentRadioModule().setNumberOfSends(numberOfSends); } /** * consumeTx * * @param v */ public void consumeTx(int v) { this.getCurrentRadioModule().consumeTx(v); } /** * consumeRx * * @param v */ public void consumeRx(int v) { getBattery().consume(v * getCurrentRadioModule().getERx()); } public double getETx() { return getCurrentRadioModule().getETx(); } public void setETx(double eTx) { getCurrentRadioModule().setETx(eTx); } public double getERx() { return getCurrentRadioModule().getERx(); } public void setERx(double eRx) { getCurrentRadioModule().setERx(eRx); } public double getEL() { return getCurrentRadioModule().getEListen(); } public void setEL(double eL) { getCurrentRadioModule().setEListen(eL); } public void initRadioModule(){ radioModuleList = new LinkedList<RadioModule>(); } public double getCurrentRadioRangeRadius() { return currentRadioModule.getRadioRangeRadius(); } /** * @return the informations about the device */ public String[][] getInfos() { super.getInfos(); infos[2][1] = ""+ getCurrentRadioModule().getMy(); infos[3][1] = ""+ getCurrentRadioModule().getNId()+" ("+Integer.toHexString(getCurrentRadioModule().getNId()).toUpperCase()+")"; infos[4][1] = ""+ getCurrentRadioModule().getCh()+" ("+Integer.toHexString(getCurrentRadioModule().getCh()).toUpperCase()+")"; return infos; } @Override public void initForSimulation() { super.initForSimulation(); //initRadioModule(); } public boolean canCommunicateWith(DeviceWithRadio device) { return ( !isDead() && !device.isDead() && sameCh(device) && sameNId(device) && sameStandard(device) ); } public boolean sameCh(DeviceWithRadio device) { return (this.getCurrentRadioModule().getCh() == device.getCurrentRadioModule().getCh()); } public boolean sameNId(DeviceWithRadio device) { return (this.getCurrentRadioModule().getNId() == device.getCurrentRadioModule().getNId()); } public boolean sameStandard(DeviceWithRadio device) { return (getStandard() == device.getStandard()); } public int getNumberOfNeighbors() { return numberOfNeighbors; } public boolean isAckReceived() { return ackReceived; } public void setAckReceived(boolean ackReceived) { this.ackReceived = ackReceived; } public boolean isAckWaiting() { return ackWaiting; } public void setAckWaiting(boolean b) { this.ackWaiting = b; } }