package org.openiot.qos;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openiot.cupus.artefact.HashtablePublication;
import org.openiot.cupus.artefact.Subscription;
import org.openiot.cupus.util.LogWriter;
public class QoSLogic {
private volatile HashMap<String, ArrayList<Double>> sensorBattery = new HashMap<String, ArrayList<Double>>();
private volatile HashMap<String, Integer> sensorPriority = new HashMap<String, Integer>();
private LogWriter log;
private double highBatteryLevel;
private double lowBatteryLevel;
private int numOfActiveSensors;
public QoSLogic(LogWriter log, int initialNumOfActiveSensors, double initialHighBatteryLevel, double initialLowBatteryLevel){
this.log = log;
this.highBatteryLevel = initialHighBatteryLevel;
this.lowBatteryLevel = initialLowBatteryLevel;
this.numOfActiveSensors = initialNumOfActiveSensors;
}
public void setBatteryLevels (double hBatteryLevel, double lBatteryLevel){
this.highBatteryLevel = hBatteryLevel;
this.lowBatteryLevel = lBatteryLevel;
}
public void setNumberOfActiveSensors (int numOfActiveSensors){
this.numOfActiveSensors = numOfActiveSensors;
}
public Set<String> findBestSensors(Set<String> activeSensors, Set<String> possibleSensors) {
Set<String> bestK = new HashSet<String>();
Map<String, Integer> unsortedSensorPriorityMap = new HashMap<String, Integer>();
String sensor;
Set<String> sensorsToRemove = new HashSet<String>();
if(possibleSensors!=null){
if(numOfActiveSensors != 0){
if (activeSensors.size()<numOfActiveSensors){
//check reputation for every possible sensor
for(String s : possibleSensors){
if(sensorPriority.containsKey(s))
unsortedSensorPriorityMap.put(s, sensorPriority.get(s));
}
@SuppressWarnings("unchecked")
Map<String, Integer> sortedMap = sortByValue(unsortedSensorPriorityMap);
ArrayList<String> newSensors = new ArrayList<String>();
for(String s : sortedMap.keySet()){
newSensors.add(s);
}
for(int i=0; i<(numOfActiveSensors-activeSensors.size());i++){
if(newSensors.size()-i>0 && sensorPriority.get(newSensors.get(i))!=3){
bestK.add(newSensors.get(i));
}
}
if (activeSensors.size()==0 && bestK.size()==0)
bestK.add(newSensors.get(0));
//if there is already enough active sensors check if some of active has low battery and try to replace it with better sensor
for(String s : activeSensors){
if(sensorPriority.containsKey(s) && sensorPriority.get(s)==3){
sensor = searchBetterSensor(possibleSensors, bestK);
if (sensor!=null){
bestK.add(sensor);
sensorsToRemove.add(s);
}else if(sensor==null && possibleSensors.size()==1)
log.writeToLog("Active sensor that needs to be replaced : "+s+" Replacement sensor: "+sensor, true);
}
}
for (String s : sensorsToRemove){
activeSensors.remove(s);
}
bestK.addAll(activeSensors);
}else if (activeSensors.size() == numOfActiveSensors){
//if there is already enough active sensors check if some of active has low battery and try to replace it with better sensor
for(String s : activeSensors){
if(sensorPriority.containsKey(s) && sensorPriority.get(s)==3){
sensor = searchBetterSensor(possibleSensors, bestK);
if (sensor!=null){
bestK.add(sensor);
sensorsToRemove.add(s);
}
log.writeToLog("Active sensor that needs to be replaced : "+s+" Replacement sensor: "+sensor, true);
}
}
for (String s : sensorsToRemove){
activeSensors.remove(s);
}
bestK.addAll(activeSensors);
}else if ((activeSensors.size() - numOfActiveSensors) > 0){
System.out.println("Treba ugasit neke senzore");
//nadji senzore koji se gase
for(String s : activeSensors){
if(sensorPriority.containsKey(s))
unsortedSensorPriorityMap.put(s, sensorPriority.get(s));
}
for(String s : possibleSensors){
if(sensorPriority.containsKey(s))
unsortedSensorPriorityMap.put(s, sensorPriority.get(s));
}
@SuppressWarnings("unchecked")
Map<String, Integer> sortedMap = sortByValue(unsortedSensorPriorityMap);
ArrayList<String> newSensors = new ArrayList<String>();
for(String s : sortedMap.keySet()){
newSensors.add(s);
}
for (int i=0; i<numOfActiveSensors;i++){
bestK.add(newSensors.get(i));
}
System.out.println(bestK);
}
}
}else {
if(numOfActiveSensors==0){
}else if ((activeSensors.size() - numOfActiveSensors) > 0){
System.out.println("Treba ugasit neke senzore");
//nadji senzore koji se gase
for(String s : activeSensors){
if(sensorPriority.containsKey(s))
unsortedSensorPriorityMap.put(s, sensorPriority.get(s));
}
@SuppressWarnings("unchecked")
Map<String, Integer> sortedMap = sortByValue(unsortedSensorPriorityMap);
ArrayList<String> newSensors = new ArrayList<String>();
for(String s : sortedMap.keySet()){
newSensors.add(s);
}
for (int i=0; i<numOfActiveSensors;i++){
bestK.add(newSensors.get(i));
}
System.out.println(bestK);
}else
bestK.addAll(activeSensors);
}
return bestK;
}
private String searchBetterSensor(Set<String> possibleSensors, Set<String> bestK) {
String betterSensor = null;
for(String s : possibleSensors){
if(!bestK.contains(s) && sensorPriority.get(s)==1){
betterSensor=s;
break;
}
else if(!bestK.contains(s) && sensorPriority.get(s)==2 && betterSensor == null)
betterSensor=s;
else if(bestK.contains(s) && possibleSensors.size()==1 && betterSensor == null)
betterSensor=s;
}
return betterSensor;
}
public boolean deactivateSensor(Subscription sub, Set<String> activeSensors, String newSensorID) {
//ako ne smije bit aktivnih senzora ugasi ga
if (numOfActiveSensors==0)
return true;
//ako treba 1 aktivan i do sad nema aktivnih upali ga kakav god bio
else if (numOfActiveSensors==1 && activeSensors.size()<numOfActiveSensors)
return false;
//ako treba 1 aktivan i vec ima aktivnih ugasi ga
else if (numOfActiveSensors==1 && activeSensors.size()>=numOfActiveSensors)
return true;
//ako ima vec aktivnih, al ih nije dosta al kandidat ima losu bateriju ugasi ga
else if (numOfActiveSensors>1 && activeSensors.size()>=1 && activeSensors.size()<numOfActiveSensors && sensorPriority.get(newSensorID)==3)
return true;
//ako ima vec aktivnih, al ih nije dosta a kandidat ima dobru bateriju upali ga
else if (numOfActiveSensors>1 && activeSensors.size()>=1&& activeSensors.size()<numOfActiveSensors && (sensorPriority.get(newSensorID)==2 || sensorPriority.get(newSensorID)==1))
return false;
//ako nema aktivnih upali ga kakv god bio
else if(numOfActiveSensors>1 && activeSensors.size()==0)
return false;
else
return true;
}
public Set<String> newActiveSensors(Set<String> activeSensors, String newSensorID) {
Set<String> set = new HashSet<String>();
set.add(newSensorID);
Set<String> sensors = findBestSensors(activeSensors,set);
return sensors;
}
public String activateBestCandidate(Set<String> setOfCandidates) {
String sensor;
Map<String, Integer> unsortedSensorPriorityMap = new HashMap<String, Integer>();
for(String s : setOfCandidates){
if(sensorBattery.containsKey(s))
unsortedSensorPriorityMap.put(s, sensorPriority.get(s));
}
@SuppressWarnings("unchecked")
Map<String, Integer> sortedMap = sortByValue(unsortedSensorPriorityMap);ArrayList<String> newSensors = new ArrayList<String>();
for(String s : sortedMap.keySet()){
newSensors.add(s);
}
sensor = newSensors.get(0);
log.writeToLog("Sensor that is going to be activated : "+sensor, true);
return sensor;
}
public void setBattery(HashtablePublication sensorAnnouncement) {
ArrayList<Double> battery = new ArrayList<Double>();
battery.add(new Double((Short)sensorAnnouncement.getProperties().get("batterys")));
battery.add(new Double((Float)sensorAnnouncement.getProperties().get("batterymp")));
sensorBattery.put((String)sensorAnnouncement.getProperties().get("SensorID"), battery);
if(((Short)sensorAnnouncement.getProperties().get("batterys")).doubleValue() > highBatteryLevel && ((Float)sensorAnnouncement.getProperties().get("batterymp")).doubleValue() > highBatteryLevel){
sensorPriority.put((String)sensorAnnouncement.getProperties().get("SensorID"),1);
}else if(((Short)sensorAnnouncement.getProperties().get("batterys")).doubleValue() > lowBatteryLevel && ((Float)sensorAnnouncement.getProperties().get("batterymp")).doubleValue() > lowBatteryLevel){
sensorPriority.put((String)sensorAnnouncement.getProperties().get("SensorID"),2);
}else
sensorPriority.put((String)sensorAnnouncement.getProperties().get("SensorID"),3);
log.writeToLog("Sensor battery: "+sensorBattery.get((String)sensorAnnouncement.getProperties().get("SensorID")), true);
log.writeToLog("Priority level: "+sensorPriority.get((String)sensorAnnouncement.getProperties().get("SensorID")), true);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static Map sortByValue(Map unsortMap) {
List list = new LinkedList(unsortMap.entrySet());
// sort list based on comparator
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Comparable) ((Map.Entry) (o1)).getValue()).compareTo(((Map.Entry) (o2)).getValue());
}
});
// put sorted list into map again
Map sortedMap = new LinkedHashMap();
for (Iterator it = list.iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
public HashtablePublication calculateAverageSensorReadings(String area, Set<HashtablePublication> publicationsInArea) {
ArrayList<Object> temp = new ArrayList<Object>();
ArrayList<Object> humid = new ArrayList<Object>();
ArrayList<Object> pressure = new ArrayList<Object>();
ArrayList<Object> co = new ArrayList<Object>();
ArrayList<Object> no2 = new ArrayList<Object>();
ArrayList<Object> so2 = new ArrayList<Object>();
for(HashtablePublication pubInArea : publicationsInArea){
for(String property : pubInArea.getProperties().keySet()){
if (property.equals("temperature"))
temp.add(pubInArea.getProperties().get(property));
else if (property.equals("humidity"))
humid.add(pubInArea.getProperties().get(property));
else if (property.equals("pressure"))
pressure.add(pubInArea.getProperties().get(property));
else if (property.equals("co"))
co.add(pubInArea.getProperties().get(property));
else if (property.equals("no2"))
no2.add(pubInArea.getProperties().get(property));
else if (property.equals("so2"))
so2.add(pubInArea.getProperties().get(property));
}
}
HashtablePublication pub = new HashtablePublication (System.currentTimeMillis()+900000, System.currentTimeMillis());
pub.setProperty("Timestamp", pub.getStartTime());
pub.setProperty("Type", "AverageReading");
pub.setProperty("Area", area);
Double tempValue = average(temp);
if (tempValue!=Double.POSITIVE_INFINITY && tempValue!=Double.NEGATIVE_INFINITY)
pub.setProperty("temperature", tempValue);
Double humidValue = average(humid);
if (humidValue!=Double.POSITIVE_INFINITY && humidValue!=Double.NEGATIVE_INFINITY)
pub.setProperty("humidity", humidValue.intValue());
Double pressureValue = average(pressure);
if (pressureValue!=Double.POSITIVE_INFINITY && pressureValue!=Double.NEGATIVE_INFINITY)
pub.setProperty("pressure", pressureValue.intValue());
Double coValue = average(co);
if (coValue!=Double.POSITIVE_INFINITY && coValue!=Double.NEGATIVE_INFINITY)
pub.setProperty("co", coValue);
Double no2Value = average(no2);
if (no2Value!=Double.POSITIVE_INFINITY && no2Value!=Double.NEGATIVE_INFINITY)
pub.setProperty("no2", no2Value);
Double so2Value = average(so2);
if (so2Value!=Double.POSITIVE_INFINITY && so2Value!=Double.NEGATIVE_INFINITY)
pub.setProperty("so2", so2Value);
return pub;
}
private Double average(ArrayList<Object> list) {
Double average=Double.MIN_VALUE;
for (Object o : list){
if ( o instanceof Double)
average+=(Double)o;
else if (o instanceof Float)
average+=((Float)o).doubleValue();
else if (o instanceof Long)
average+=((Long)o).doubleValue();
else if (o instanceof Integer)
average+=((Integer)o).doubleValue();
else if (o instanceof Short)
average += ((Short) o).doubleValue();
}
return average/list.size();
}
}