package org.openiot.qos;
import com.bbn.openmap.proj.coords.LatLonPoint;
import com.bbn.openmap.proj.coords.MGRSPoint;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openiot.cupus.artefact.HashtablePublication;
import org.openiot.cupus.artefact.TripletSubscription;
import org.openiot.cupus.common.Triplet;
import org.openiot.cupus.common.enums.Operator;
import org.openiot.cupus.entity.mobilebroker.MobileBroker;
import org.openiot.cupus.util.LogWriter;
import org.openiot.integration.VirtualSensor;
public class MonitoringAndManagement {
//GSN parameters
private String gsnAddress;
private int wrapperPort;
private HashMap<String, Long> batteryTime = new HashMap<String, Long>();
private volatile HashMap<String, Integer> virtualSensors = new HashMap<String, Integer>();
private volatile HashMap<String, Set<HashtablePublication>> publicationsInArea = new HashMap<String, Set<HashtablePublication>>();
private volatile HashMap<String, Set<String>> sensorsInArea = new HashMap<String, Set<String>>();
private volatile HashMap<String, Set<String>> activeSensorsInArea = new HashMap<String, Set<String>>();
private volatile HashMap<String, HashtablePublication> announcedSensors = new HashMap<String, HashtablePublication>();
private volatile HashMap<String, ArrayList<TripletSubscription>> subscriptionsInArea = new HashMap<String, ArrayList<TripletSubscription>>();
private volatile HashMap<String, ArrayList<TripletSubscription>> sensorActiveSubs = new HashMap<String, ArrayList<TripletSubscription>>();
private volatile HashMap<TripletSubscription, Set<String>> subCandidates = new HashMap<TripletSubscription, Set<String>>();
private Object mutexPublicationsInArea = new Object();
private Object mutexSensorsInArea = new Object();
private Object mutexActiveSensorsInArea = new Object();
private Object mutexAnnouncedSensors = new Object();
private Object mutexSubscriptionsInArea = new Object();
private Object mutexSensorActiveSubs = new Object();
private Object mutexSubCandidates = new Object();
private Object mutexVirtualSensors = new Object();
protected LogWriter log;
protected QoSLogic qosLogic;
private MobileBroker qosMB;
private List<String> sensorParameters;
private List<String> sensorTypes;
private List<String> lsmProperty;
private List<String> lsmUnit;
public MonitoringAndManagement(LogWriter logger, MobileBroker mb, QoSLogic appLogic, List<String> param, List<String> paramTypes, List<String> lsmProp, List<String> lsmUnits, String gsn, int port) throws SQLException {
this.log = logger;
this.qosMB = mb;
this.qosLogic = appLogic;
this.sensorParameters = param;
this.sensorTypes = paramTypes;
this.lsmProperty = lsmProp;
this.lsmUnit = lsmUnits;
this.gsnAddress = gsn;
this.wrapperPort = port;
this.startTimer();
}
public Set<String> getAllSensorsInArea(String area) {
synchronized (sensorsInArea) {
return sensorsInArea.get(area);
}
}
public Set<String> getActiveSensorsInArea(String area) {
synchronized (activeSensorsInArea) {
return activeSensorsInArea.get(area);
}
}
public Set<String> getAllCurrentlyKnownSensors() {
synchronized (announcedSensors) {
return announcedSensors.keySet();
}
}
public List<TripletSubscription> getAllSubscriptionsInArea(String area) {
synchronized (subscriptionsInArea) {
return subscriptionsInArea.get(area);
}
}
public void notify(HashtablePublication sensorPublication) {
log.writeToLog("--------------------------------------", true);
if (((String) sensorPublication.getProperties().get("Type")).equalsIgnoreCase("SensorReading")) {
String area = (String) sensorPublication.getProperties().get("Area");
String sensorID = (String) sensorPublication.getProperties().get("SensorID");
// this sensor was already announced in the system
if (announcedSensors.containsKey(sensorID)) {
if (!announcedSensors.get(sensorID).getProperties().get("Area").equals(area)) {
log.writeToLog("Sensor has sent new announcement. " + sensorPublication + " Remove old announcement in area " + (String) announcedSensors.get(sensorID).getProperties().get("Area") + " and all active subscriptions of a sensor. Remove sensor " + sensorID + " from list of candidates for other subscriptions in the system. ", true);
// remove sensor from previous area and check if sensor had active subs in that area, if had remove them
synchronized (mutexSensorsInArea) {
sensorsInArea.get((String) announcedSensors.get(sensorID).getProperties().get("Area")).remove(sensorID);
}
removeSensorActiveSubsInPreviousArea((String) announcedSensors.get(sensorID).getProperties().get("Area"), sensorID);
batteryTime.put(sensorID, System.currentTimeMillis());
qosLogic.setBattery(sensorPublication);
// add sensor
addSensorInArea(area, sensorID);
} else if (System.currentTimeMillis() - batteryTime.get(sensorID) > 600000) {
log.writeToLog("Refresh sensor battery!", true);
batteryTime.put(sensorID, System.currentTimeMillis());
qosLogic.setBattery(sensorPublication);
}
} else {
// add sensor
addSensorInArea(area, sensorID);
batteryTime.put(sensorID, System.currentTimeMillis());
qosLogic.setBattery(sensorPublication);
}
//refresh sensor announcement
synchronized (mutexAnnouncedSensors) {
announcedSensors.put((String) sensorPublication.getProperties().get("SensorID"), sensorPublication);
}
//search possible subscriptions in that area
matchWithSubscriptionsInArea(sensorPublication, area);
addPublicationInArea(sensorPublication);
//send publication to X-GSN
synchronized(mutexVirtualSensors){
if (!virtualSensors.containsKey(area)) {
try {
registerVirtualSensor(area);
Thread.sleep(1500);
} catch (IOException ex) {
Logger.getLogger(MonitoringAndManagement.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(MonitoringAndManagement.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
sendToXGSN(virtualSensors.get(area), sensorPublication);
} else if (((String) sensorPublication.getProperties().get("Type")).equalsIgnoreCase("LowBattery")) {
//napravi nesto s tim
}
log.writeToLog("--------------------------------------", true);
}
public void notify(TripletSubscription subscription) {
log.writeToLog("--------------------------------------", true);
Set<Triplet> type = subscription.attributePredicates("Type");
for (Triplet t : type) {
if (t.getValue().equals("AverageReading")) {
log.writeToLog("Aggregate subscription arrived!", true);
Set<Triplet> areas = subscription.attributePredicates("Area");
//new aggregate subscription arrived; subscribe on all readings in all areas it contains
for (Triplet area : areas) {
subscribeOnIndividualReadingsInArea(area.getValue().toString());
HashtablePublication pub = getAverageSensorReadingsInArea(area.getValue().toString());
if (pub.getProperties().size() != 3) {
qosMB.publish(pub);
} else {
log.writeToLog("No pubs in the system!", true);
}
}
} else if (t.getValue().equals("SensorReading")) {
Set<Triplet> areas = subscription.attributePredicates("Area");
//new subscription arrived; put subscription in all areas it contains
if (areas != null) {
for (Triplet area : areas) {
addSubscriptionInArea(area.getValue().toString(), subscription);
//search possible sensors in the area
matchWithSensorsInArea(subscription, area.getValue().toString());
}
log.writeToLog("All subscriptions in the system by areas: " + subscriptionsInArea, true);
log.writeToLog("All sensors in the system by areas: " + sensorsInArea, true);
log.writeToLog("Active sensors by areas: " + activeSensorsInArea, true);
} else {
log.writeToLog("New subscription: " + subscription.toString(), true);
}
} else {
log.writeToLog(subscription.toString(), true);
}
}
log.writeToLog("--------------------------------------", true);
}
public HashtablePublication getAverageSensorReadingsInArea(String area) {
log.writeToLog("--------------------------------------", true);
log.writeToLog("Calculate average sensor readings in last 30 minutes in specified area", true);
Set<HashtablePublication> pubsInArea = new HashSet<HashtablePublication>();
synchronized (mutexPublicationsInArea) {
if (publicationsInArea.get(area) != null) {
for (HashtablePublication p : publicationsInArea.get(area)) {
if (System.currentTimeMillis() - p.getStartTime() < 1800000) {
pubsInArea.add(p);
}
}
}
}
HashtablePublication pub = qosLogic.calculateAverageSensorReadings(area, pubsInArea);
return pub;
}
private void addPublicationInArea(HashtablePublication sensorPublication) {
//if there are already some pubs in the area, add new one; else add new area and sensor pub in the map publicationsInArea
synchronized (mutexPublicationsInArea) {
if (publicationsInArea.containsKey((String) sensorPublication.getProperties().get("Area"))) {
publicationsInArea.get((String) sensorPublication.getProperties().get("Area")).add(sensorPublication);
} else {
Set<HashtablePublication> sensorPubs = new HashSet<HashtablePublication>();
sensorPubs.add(sensorPublication);
publicationsInArea.put((String) sensorPublication.getProperties().get("Area"), sensorPubs);
}
}
}
private void matchWithSensorsInArea(TripletSubscription subscription, String area) {
Set<String> possibleSensors = new HashSet<String>();
Set<String> activeSensors = new HashSet<String>();
Set<String> activateNewSensors = new HashSet<String>();
Set<HashtablePublication> sensorsInAreaToRemove = new HashSet<HashtablePublication>();
Set<String> listOfSensorsInArea = getAllSensorsInArea(area);
log.writeToLog("--------------------------------------", true);
log.writeToLog("New subscription arrived! Search sensors in the area " + area, true);
synchronized (sensorsInArea) {
if (listOfSensorsInArea != null) {
for (String sensor : listOfSensorsInArea) {
//sensor announcement and subscription have to be valid, sub covers sensor announcement
if (subscription.isValid() && announcedSensors.get(sensor).isValid() && subscription.coversPublication(announcedSensors.get(sensor))) {
if (activeSensorsInArea.containsKey(area) && activeSensorsInArea.get(area).contains(sensor)) {
activeSensors.add(sensor);
} else {
possibleSensors.add(sensor);
}
} else {
if (!subscription.isValid() && !announcedSensors.get(sensor).isValid()) {
removeSubscriptionInArea(subscription);
sensorsInAreaToRemove.add(announcedSensors.get(sensor));
} else if (!subscription.isValid() && announcedSensors.get(sensor).isValid()) {
removeSubscriptionInArea(subscription);
} else if (subscription.isValid() && !announcedSensors.get(sensor).isValid()) {
sensorsInAreaToRemove.add(announcedSensors.get(sensor));
}
}
}
log.writeToLog("Already active sensors in the area: " + activeSensors, true);
log.writeToLog("Possible candidates in the area: " + possibleSensors, true);
activateNewSensors = qosLogic.findBestSensors(activeSensors, possibleSensors);
if (activateNewSensors != null && activateNewSensors.size() >= activeSensors.size()) {
for (String s : activateNewSensors) {
//put sub in the list of active subs for every sensor in bestK sensors
activateSensorSub(s, subscription);
//put bestK sensors in the list of active sensors in the area
activateSensorInArea(area, s);
}
for (String s : possibleSensors) {
if (!activateNewSensors.contains(s)) {
addSubscriptionCandidate(s, subscription);
}
}
for (String s : activeSensors) {
if (!activateNewSensors.contains(s)) {
if (checkSensorActiveSubs(s, subscription)) {
activateCandidateIfExists(s, subscription, (String) announcedSensors.get(s).getProperties().get("Area"));
sensorActiveSubs.remove(s);
System.out.println(s);
activeSensorsInArea.get(area).remove(s);
addSubscriptionCandidate(s, subscription);
}
}
}
} else if (activateNewSensors != null && activateNewSensors.size() < activeSensors.size()) {
for (String s : activateNewSensors) {
//put sub in the list of active subs for every sensor in bestK sensors
activateSensorSub(s, subscription);
//put bestK sensors in the list of active sensors in the area
activateSensorInArea(area, s);
}
for (String s : possibleSensors) {
if (!activateNewSensors.contains(s)) {
addSubscriptionCandidate(s, subscription);
}
}
for (String s : activeSensors) {
if (!activateNewSensors.contains(s)) {
sensorActiveSubs.remove(s);
System.out.println(s);
activeSensorsInArea.get(area).remove(s);
addSubscriptionCandidate(s, subscription);
}
}
} else if (activateNewSensors == null) {
//treba ugasit sve senzore
turnOffAllSensors();
}
}
}
//remove expired announcement of a sensor
if (!sensorsInAreaToRemove.isEmpty()) {
for (HashtablePublication pub : sensorsInAreaToRemove) {
removeAnnouncedSensorInArea(pub);
}
}
log.writeToLog("Active sensors by areas: " + activeSensorsInArea, true);
log.writeToLog("Active subscriptions by sensor: " + sensorActiveSubs, true);
log.writeToLog("--------------------------------------", true);
}
private void turnOffAllSensors() {
//makni sve senzore iz aktivnih
//sve aktivne stavi u kandidate
synchronized (mutexSensorActiveSubs) {
for (String sensor : sensorActiveSubs.keySet()) {
for (TripletSubscription sub : sensorActiveSubs.get(sensor)) {
addSubscriptionCandidate(sensor, sub);
}
}
sensorActiveSubs.clear();
}
synchronized (mutexActiveSensorsInArea) {
activeSensorsInArea.clear();
}
}
private void activateCandidateIfExists(String s, TripletSubscription subscription, String area) {
synchronized (mutexSensorActiveSubs) {
synchronized (mutexSubCandidates) {
for (TripletSubscription sub : sensorActiveSubs.get(s)) {
if (!sub.equals(subscription) && subCandidates.get(sub) != null) {
String activateSensor = qosLogic.activateBestCandidate(subCandidates.get(sub));
activateSensorInArea(area, activateSensor);
activateSensorSub(activateSensor, sub);
subCandidates.get(sub).remove(activateSensor);
turnSensorOn(activateSensor);
}
}
}
}
}
private void matchWithSubscriptionsInArea(HashtablePublication pub, String area) {
String sensorID = (String) pub.getProperties().get("SensorID");
ArrayList<TripletSubscription> subsInAreaToRemove = new ArrayList<TripletSubscription>();
Set<String> newSensors = new HashSet<String>();
log.writeToLog("--------------------------------------", true);
log.writeToLog("New sensor publication arrived! Sensor: " + sensorID + " Area: " + area, true);
log.writeToLog("All subscriptions in the area: " + subscriptionsInArea.get(area), true);
if (subscriptionsInArea.containsKey(area)) {
for (TripletSubscription sub : subscriptionsInArea.get(area)) {
Set<String> activeSensors = new HashSet<String>();
if (activeSensorsInArea.containsKey(area) && !activeSensorsInArea.get(area).isEmpty()) {
for (String s : activeSensorsInArea.get(area)) {
if (sensorActiveSubs.containsKey(s) && sensorActiveSubs.get(s).contains(sub) && !sensorActiveSubs.get(s).isEmpty()) {
activeSensors.add(s);
}
}
}
if (sub.isValid() && sub.coversPublication(announcedSensors.get(sensorID)) && announcedSensors.get(sensorID).isValid() && !activeSensors.contains(sensorID)) {
newSensors = qosLogic.newActiveSensors(activeSensors, sensorID);
if (newSensors != null && newSensors.size() >= activeSensors.size()) {
for (String s : newSensors) {
//put sub in the list of active subs for every sensor in bestK sensors
activateSensorSub(s, sub);
//put bestK sensors in the list of active sensors in the area
activateSensorInArea(area, s);
}
if (!newSensors.contains(sensorID)) {
addSubscriptionCandidate(sensorID, sub);
}
for (String s : activeSensors) {
if (!newSensors.contains(s)) {
if (checkSensorActiveSubs(s, sub)) {
activateCandidateIfExists(s, sub, (String) announcedSensors.get(s).getProperties().get("Area"));
sensorActiveSubs.remove(s);
System.out.println(s);
activeSensorsInArea.get(area).remove(s);
addSubscriptionCandidate(s, sub);
}
}
}
} else if (newSensors != null && newSensors.size() < activeSensors.size()) {
for (String s : newSensors) {
//put sub in the list of active subs for every sensor in bestK sensors
activateSensorSub(s, sub);
//put bestK sensors in the list of active sensors in the area
activateSensorInArea(area, s);
}
if (!newSensors.contains(sensorID)) {
addSubscriptionCandidate(sensorID, sub);
}
for (String s : activeSensors) {
if (!newSensors.contains(s)) {
sensorActiveSubs.remove(s);
System.out.println(s);
activeSensorsInArea.get(area).remove(s);
addSubscriptionCandidate(s, sub);
}
}
} else if (newSensors == null) {
//treba ugasit sve senzore
turnOffAllSensors();
}
// if (!qosLogic.deactivateSensor(sub,activeSensors, sensorID)) {
// // add sub in the list of active subs of the sensor
// activateSensorSub(sensorID, sub);
// // put sensor in active sensors in area
// activateSensorInArea(area, sensorID);
// }else
// addSubscriptionCandidate(sensorID, sub);
} else {
if (!sub.isValid() && !announcedSensors.get(sensorID).isValid()) {
//remove both sub and sensor announcement from area because they aren't valid anymore
subsInAreaToRemove.add(sub);
removeAnnouncedSensorInArea(announcedSensors.get(sensorID));
} else if (!sub.isValid() && announcedSensors.get(sensorID).isValid()) {
//remove sub from area because it isn't valid anymore
subsInAreaToRemove.add(sub);
} else if (sub != null && sub.isValid() && announcedSensors.get(sensorID) != null && !announcedSensors.get(sensorID).isValid()) {
//remove sensor announcement from area because it isn't valid anymore
removeAnnouncedSensorInArea(announcedSensors.get(sensorID));
}
}
}
}
//remove expired subs
if (!subsInAreaToRemove.isEmpty()) {
for (TripletSubscription s : subsInAreaToRemove) {
removeSubscriptionInArea(s);
}
}
log.writeToLog("Active sensors by areas: " + activeSensorsInArea, true);
log.writeToLog("All candidates by subscriptions: " + subCandidates, true);
log.writeToLog("Active subscriptions by sensors: " + sensorActiveSubs, true);
log.writeToLog("--------------------------------------", true);
}
private void removeSubscriptionInArea(TripletSubscription subscription) {
log.writeToLog("--------------------------------------", true);
log.writeToLog("Subscription is not valid anymore! " + subscription, true);
Set<Triplet> triplets = subscription.attributePredicates("Area");
for (Triplet t : triplets) {
//remove sub from all areas
removeSubscriptionFromActiveSensorSubs((String) t.getValue(), subscription);
synchronized (mutexSubscriptionsInArea) {
subscriptionsInArea.get((String) t.getValue()).remove(subscription);
//if there is no more subs in area, remove that area
if (subscriptionsInArea.get((String) t.getValue()).isEmpty()) {
subscriptionsInArea.remove((String) t.getValue());
}
}
}
log.writeToLog("--------------------------------------", true);
}
//checks whether sensor has other active subs for which there is no substitute sensor
private boolean checkSensorActiveSubs(String sensorID, TripletSubscription s) {
boolean b = false;
synchronized (mutexSensorActiveSubs) {
if (sensorActiveSubs.get(sensorID).size() == 1) {
b = true;
} else {
for (TripletSubscription sub : sensorActiveSubs.get(sensorID)) {
if (existOtherActiveSensorsForSub(sensorID, sub)) {
b = true;
} else {
b = false;
break;
}
}
}
}
return b;
}
private boolean existOtherActiveSensorsForSub(String sensorID, TripletSubscription sub) {
boolean b = false;
synchronized (mutexSensorActiveSubs) {
for (String sensor : sensorActiveSubs.keySet()) {
for (TripletSubscription s : sensorActiveSubs.get(sensor)) {
if (sensor != sensorID && s.equals(sub)) {
b = true;
}
}
}
}
return b;
}
private void removeSubscriptionFromActiveSensorSubs(String area, TripletSubscription sub) {
ArrayList<String> activeSensorsInAreaToRemove = new ArrayList<String>();
log.writeToLog("--------------------------------------", true);
log.writeToLog("Remove the subscription from active subscriptions of a sensor in this area " + area, true);
//if there are active sensors in the area remove sub
if (activeSensorsInArea.containsKey(area) && !activeSensorsInArea.get(area).isEmpty()) {
for (String sensorID : activeSensorsInArea.get(area)) {
//remove sub from the list of active sensor subs
synchronized (mutexSensorActiveSubs) {
if (sensorActiveSubs.containsKey(sensorID) && !sensorActiveSubs.get(sensorID).isEmpty() && sensorActiveSubs.get(sensorID).contains(sub)) {
sensorActiveSubs.get(sensorID).remove(sub);
}
//if sensor doesn't have any more active subs, remove sensor from active sensors in the area
if (sensorActiveSubs.containsKey(sensorID) && sensorActiveSubs.get(sensorID).isEmpty()) {
activeSensorsInAreaToRemove.add(sensorID);
turnSensorOff(sensorID);
}
}
}
}
synchronized (mutexActiveSensorsInArea) {
if (!activeSensorsInAreaToRemove.isEmpty()) {
activeSensorsInArea.get(area).removeAll(activeSensorsInAreaToRemove);
}
if (activeSensorsInArea.containsKey(area) && activeSensorsInArea.get(area).isEmpty()) {
activeSensorsInArea.remove(area);
}
}
synchronized (mutexSubCandidates) {
if (subCandidates.containsKey(sub) && !subCandidates.get(sub).isEmpty()) {
subCandidates.remove(sub);
}
}
log.writeToLog("Active sensors by areas after removing invalid subscription: " + activeSensorsInArea, true);
log.writeToLog("--------------------------------------", true);
}
private void removeAnnouncedSensorInArea(HashtablePublication announcement) {
log.writeToLog("--------------------------------------", true);
log.writeToLog("Sensor announcement is not valid anymore! ", true);
synchronized (mutexAnnouncedSensors) {
//remove sensor announcement
log.writeToLog("Remove announced sensor from the system: " + announcedSensors.get(announcement.getProperties().get("SensorID")), true);
announcedSensors.remove(announcement.getProperties().get("SensorID"));
}
synchronized (mutexSensorsInArea) {
//remove sensor from area
if (sensorsInArea.get(announcement.getProperties().get("Area")) != null && sensorsInArea.get(announcement.getProperties().get("Area")).contains(announcement.getProperties().get("SensorID"))) {
sensorsInArea.get(announcement.getProperties().get("Area")).remove(announcement.getProperties().get("SensorID"));
log.writeToLog("Remaining sensors in the area: " + sensorsInArea.get(announcement.getProperties().get("Area")), true);
}
//if there is no more sensors in the area, remove that area
if (sensorsInArea.get(announcement.getProperties().get("Area")) == null && sensorsInArea.get(announcement.getProperties().get("Area")).isEmpty()) {
sensorsInArea.remove(announcement.getProperties().get("Area"));
}
}
synchronized (mutexActiveSensorsInArea) {
if (activeSensorsInArea.containsKey(announcement.getProperties().get("Area")) && activeSensorsInArea.get(announcement.getProperties().get("Area")).contains(announcement.getProperties().get("SensorID"))) {
activeSensorsInArea.get(announcement.getProperties().get("Area")).remove(announcement.getProperties().get("SensorID"));
}
}
if (sensorActiveSubs.containsKey(announcement.getProperties().get("SensorID")) && !sensorActiveSubs.get(announcement.getProperties().get("SensorID")).isEmpty()) {
for (TripletSubscription sub : sensorActiveSubs.get(announcement.getProperties().get("SensorID"))) {
if (subCandidates.containsKey(sub) && !subCandidates.get(sub).isEmpty()) {
String activateSensor = qosLogic.activateBestCandidate(subCandidates.get(sub));
activateSensorInArea((String) announcement.getProperties().get("Area"), activateSensor);
activateSensorSub(activateSensor, sub);
//remove new sensor that will be activated from list of candidates
synchronized (mutexSubCandidates) {
subCandidates.get(sub).remove(activateSensor);
}
turnSensorOn(activateSensor);
}
}
}
//remove all sensor's active subs
synchronized (mutexSensorActiveSubs) {
sensorActiveSubs.remove(announcement.getProperties().get("SensorID"));
}
//if sensor was candidate for other subs, remove it from list of candidates
ArrayList<TripletSubscription> list = new ArrayList<TripletSubscription>();
synchronized (mutexSubCandidates) {
for (TripletSubscription s : subCandidates.keySet()) {
if (subCandidates.get(s).contains(announcement.getProperties().get("SensorID"))) {
list.add(s);
}
}
}
synchronized (mutexSubCandidates) {
for (TripletSubscription s : list) {
subCandidates.get(s).remove(announcement.getProperties().get("SensorID"));
}
}
log.writeToLog("--------------------------------------", true);
}
private void removeSensorActiveSubsInPreviousArea(String oldSensorArea, String sensorID) {
log.writeToLog("--------------------------------------", true);
log.writeToLog("Remove sensor active subscriptions from previously announced area", true);
Set<String> set = new HashSet<String>();
synchronized (mutexActiveSensorsInArea) {
log.writeToLog("Active sensors by areas. " + activeSensorsInArea, true);
if (activeSensorsInArea.get(oldSensorArea) != null && activeSensorsInArea.get(oldSensorArea).contains(sensorID)) {
activeSensorsInArea.get(oldSensorArea).remove(sensorID);
}
if (activeSensorsInArea.get(oldSensorArea) == null || activeSensorsInArea.get(oldSensorArea).isEmpty()) {
activeSensorsInArea.remove(oldSensorArea);
}
log.writeToLog("Active sensors by areas after deleting. " + activeSensorsInArea, true);
}
ArrayList<TripletSubscription> tempSensorActiveSubs = new ArrayList<TripletSubscription>();
synchronized (mutexSensorActiveSubs) {
tempSensorActiveSubs = sensorActiveSubs.get(sensorID);
}
synchronized (sensorActiveSubs) {
if (tempSensorActiveSubs != null) {
log.writeToLog("Active subs of a sensor that need to be deleted. " + tempSensorActiveSubs, true);
//for every active sub of a sensor, activate sensor from list of candidates if exist and delete sub from list of sensor active subs
for (TripletSubscription sub : tempSensorActiveSubs) {
if (subCandidates.containsKey(sub) && !subCandidates.get(sub).isEmpty()) {
String activateSensor = qosLogic.activateBestCandidate(subCandidates.get(sub));
activateSensorInArea(oldSensorArea, activateSensor);
activateSensorSub(activateSensor, sub);
set.add(activateSensor);
// putAllSensorInactiveSubsInActive(activateSensor);
// removeSensorFromCandidates(activateSensor);
}
}
}
}
for (String s : set) {
putAllSensorInactiveSubsInActive(s);
removeSensorFromCandidates(s);
}
removeSensorFromCandidates(sensorID);
//remove all sensor's active subs
synchronized (mutexSensorActiveSubs) {
sensorActiveSubs.remove(sensorID);
}
log.writeToLog("--------------------------------------", true);
}
private void putAllSensorInactiveSubsInActive(String sensor) {
//if sensor was candidate for other subs, activate all this subs
synchronized (mutexSubCandidates) {
for (TripletSubscription s : subCandidates.keySet()) {
if (subCandidates.get(s).contains(sensor)) {
activateSensorSub(sensor, s);
}
}
}
}
private void removeSensorFromCandidates(String sensorID) {
//if sensor was candidate for other subs, remove it from list of candidates
ArrayList<TripletSubscription> list = new ArrayList<TripletSubscription>();
synchronized (mutexSubCandidates) {
for (TripletSubscription s : subCandidates.keySet()) {
if (subCandidates.get(s).contains(sensorID)) {
list.add(s);
}
}
}
synchronized (mutexSubCandidates) {
for (TripletSubscription s : list) {
subCandidates.get(s).remove(sensorID);
}
}
}
private void addSensorInArea(String area, String sensorID) {
// if new area is not empty add sensor in area
synchronized (mutexSensorsInArea) {
if (sensorsInArea.containsKey(area)) {
sensorsInArea.get(area).add(sensorID);
} // create new area and add sensor
else {
Set<String> sensors = new HashSet<String>();
sensors.add(sensorID);
sensorsInArea.put(area, sensors);
}
}
}
private void addSubscriptionInArea(String area, TripletSubscription sub) {
synchronized (mutexSubscriptionsInArea) {
if (subscriptionsInArea.containsKey(area) && !subscriptionsInArea.get(area).contains(sub)) {
subscriptionsInArea.get(area).add(sub);
} else if (!subscriptionsInArea.containsKey(area)) {
ArrayList<TripletSubscription> subs = new ArrayList<TripletSubscription>();
subs.add(sub);
subscriptionsInArea.put(area, subs);
}
}
}
private void activateSensorSub(String sensorID, TripletSubscription sub) {
synchronized (mutexSensorActiveSubs) {
if (!sensorActiveSubs.containsKey(sensorID)) {
ArrayList<TripletSubscription> subs = new ArrayList<TripletSubscription>();
subs.add(sub);
sensorActiveSubs.put(sensorID, subs);
} else if (sensorActiveSubs.containsKey(sensorID) && !sensorActiveSubs.get(sensorID).contains(sub)) {
sensorActiveSubs.get(sensorID).add(sub);
}
}
}
private void activateSensorInArea(String area, String sensorID) {
synchronized (mutexActiveSensorsInArea) {
if (activeSensorsInArea.containsKey(area) && !activeSensorsInArea.get(area).contains(sensorID)) {
activeSensorsInArea.get(area).add(sensorID);
} else if (!activeSensorsInArea.containsKey(area)) {
Set<String> sensors = new HashSet<String>();
sensors.add(sensorID);
activeSensorsInArea.put(area, sensors);
}
}
}
private void addSubscriptionCandidate(String sensorID, TripletSubscription sub) {
log.writeToLog("Candidate! Turn sensor off. " + sensorID, true);
boolean alreadyCandidate = false;
synchronized (mutexSubCandidates) {
for (TripletSubscription ts : subCandidates.keySet()) {
if (subCandidates.get(ts).contains(sensorID)) {
alreadyCandidate = true;
}
}
if (!alreadyCandidate) {
turnSensorOff(sensorID);
}
if (subCandidates.containsKey(sub)) {
if (!subCandidates.get(sub).contains(sensorID)) {
subCandidates.get(sub).add(sensorID);
}
} else {
Set<String> list = new HashSet<String>();
list.add(sensorID);
subCandidates.put(sub, list);
}
}
}
private void turnSensorOn(String sensorID) {
//turn on the sensor
HashtablePublication hp = new HashtablePublication(-1, System.currentTimeMillis());
hp.setProperty("Type", "SensorControl");
hp.setProperty("Status", "True");
hp.setProperty("Timestamp", hp.getStartTime());
hp.setProperty("SensorID", sensorID);
qosMB.publish(hp);
}
private void turnSensorOff(String sensorID) {
//turn off the sensor
HashtablePublication hp = new HashtablePublication(-1, System.currentTimeMillis());
hp.setProperty("Type", "SensorControl");
hp.setProperty("Status", "False");
hp.setProperty("Timestamp", hp.getStartTime());
hp.setProperty("SensorID", sensorID);
qosMB.publish(hp);
}
private void subscribeOnIndividualReadingsInArea(String area) {
TripletSubscription sub = new TripletSubscription(-1, System.currentTimeMillis());
sub.addPredicate(new Triplet("Area", area, Operator.EQUAL));
sub.addPredicate(new Triplet("Type", "SensorReading", Operator.EQUAL));
sub.addPredicate(new Triplet("temperature", Float.NEGATIVE_INFINITY, Operator.GREATER_OR_EQUAL));
qosMB.subscribe(sub);
TripletSubscription sub1 = new TripletSubscription(-1, System.currentTimeMillis());
sub1.addPredicate(new Triplet("Area", area, Operator.EQUAL));
sub1.addPredicate(new Triplet("Type", "SensorReading", Operator.EQUAL));
sub1.addPredicate(new Triplet("humidity", Integer.MIN_VALUE, Operator.GREATER_OR_EQUAL));
qosMB.subscribe(sub1);
TripletSubscription sub2 = new TripletSubscription(-1, System.currentTimeMillis());
sub2.addPredicate(new Triplet("Area", area, Operator.EQUAL));
sub2.addPredicate(new Triplet("Type", "SensorReading", Operator.EQUAL));
sub2.addPredicate(new Triplet("pressure", Integer.MIN_VALUE, Operator.GREATER_OR_EQUAL));
qosMB.subscribe(sub2);
TripletSubscription sub3 = new TripletSubscription(-1, System.currentTimeMillis());
sub3.addPredicate(new Triplet("Area", area, Operator.EQUAL));
sub3.addPredicate(new Triplet("Type", "SensorReading", Operator.EQUAL));
sub3.addPredicate(new Triplet("co", Float.NEGATIVE_INFINITY, Operator.GREATER_OR_EQUAL));
qosMB.subscribe(sub3);
TripletSubscription sub4 = new TripletSubscription(-1, System.currentTimeMillis());
sub4.addPredicate(new Triplet("Area", area, Operator.EQUAL));
sub4.addPredicate(new Triplet("Type", "SensorReading", Operator.EQUAL));
sub4.addPredicate(new Triplet("so2", Float.NEGATIVE_INFINITY, Operator.GREATER_OR_EQUAL));
qosMB.subscribe(sub4);
TripletSubscription sub5 = new TripletSubscription(-1, System.currentTimeMillis());
sub5.addPredicate(new Triplet("Area", area, Operator.EQUAL));
sub5.addPredicate(new Triplet("Type", "SensorReading", Operator.EQUAL));
sub5.addPredicate(new Triplet("no2", Float.NEGATIVE_INFINITY, Operator.GREATER_OR_EQUAL));
qosMB.subscribe(sub5);
}
private void cleanExpiredMessages() {
HashMap<String, ArrayList<TripletSubscription>> subsInAreaToRemove = new HashMap<String, ArrayList<TripletSubscription>>();
ArrayList<String> sensorsToRemove = new ArrayList<String>();
log.writeToLog("--------------------------------------", true);
log.writeToLog("Searching for expired subscriptions in the system", true);
//remove expired subscriptions
log.writeToLog("All subscriptions by areas: " + subscriptionsInArea, true);
for (String area : subscriptionsInArea.keySet()) {
for (TripletSubscription sub : subscriptionsInArea.get(area)) {
if (!sub.isValid()) {
//put this sub in the list of subs in this area that will be removed later
if (!subsInAreaToRemove.containsKey(area)) {
ArrayList<TripletSubscription> tempSubs = new ArrayList<TripletSubscription>();
tempSubs.add(sub);
subsInAreaToRemove.put(area, tempSubs);
} else {
subsInAreaToRemove.get(area).add(sub);
}
}
}
}
//remove all expired subs for all areas and all candidates for expired sub
for (String a : subsInAreaToRemove.keySet()) {
for (TripletSubscription sub : subsInAreaToRemove.get(a)) {
removeSubscriptionInArea(sub);
}
}
log.writeToLog("After removing expired subscriptions by areas: " + subscriptionsInArea, true);
log.writeToLog("--------------------------------------", true);
log.writeToLog("Searching for expired sensor announcements in the system", true);
//remove expired sensor announcements
for (String sensorID : announcedSensors.keySet()) {
if (!announcedSensors.get(sensorID).isValid()) {
sensorsToRemove.add(sensorID);
}
}
for (String sensorID : sensorsToRemove) {
removeAnnouncedSensorInArea(announcedSensors.get(sensorID));
}
log.writeToLog("Remaining announced sensors in the system: " + announcedSensors, true);
log.writeToLog("--------------------------------------", true);
}
private void calculateAverageSensorReadings() {
log.writeToLog("--------------------------------------", true);
log.writeToLog("Calculate average sensor readings in last 30 minutes and delete publications that fell out from time window", true);
HashMap<String, ArrayList<HashtablePublication>> pubsInAreaToRemove = new HashMap<String, ArrayList<HashtablePublication>>();
synchronized (mutexPublicationsInArea) {
for (String area : publicationsInArea.keySet()) {
for (HashtablePublication p : publicationsInArea.get(area)) {
//delete all publications older than 30 minutes
if (System.currentTimeMillis() - p.getStartTime() >= 1800000) {
if (!pubsInAreaToRemove.containsKey(area)) {
ArrayList<HashtablePublication> tempPubs = new ArrayList<HashtablePublication>();
tempPubs.add(p);
pubsInAreaToRemove.put(area, tempPubs);
} else {
pubsInAreaToRemove.get(area).add(p);
}
}
}
}
}
synchronized (mutexPublicationsInArea) {
for (String a : pubsInAreaToRemove.keySet()) {
publicationsInArea.get(a).removeAll(pubsInAreaToRemove.get(a));
if (publicationsInArea.get(a).isEmpty()) {
publicationsInArea.remove(a);
}
}
}
synchronized (mutexPublicationsInArea) {
for (String a : publicationsInArea.keySet()) {
log.writeToLog("Average readings for area " + a + ": ", true);
qosMB.publish(qosLogic.calculateAverageSensorReadings(a, publicationsInArea.get(a)));
}
}
log.writeToLog("--------------------------------------", true);
}
private void registerVirtualSensor(String area) throws IOException, InterruptedException {
LatLonPoint llpoint = MGRSPoint.MGRStoLL(new MGRSPoint(area));
double lat = llpoint.getLatitude();
double lng = llpoint.getLongitude();
synchronized (mutexVirtualSensors){
virtualSensors.put(area, wrapperPort);
}
VirtualSensor vs = new VirtualSensor(area, wrapperPort, lat, lng, this.sensorParameters, this.sensorTypes, this.lsmProperty, this.lsmUnit, this.gsnAddress);
vs.createAndRegister();
wrapperPort++;
}
private void sendToXGSN(Integer port, HashtablePublication sensorPublication) {
HashtablePublication toGSN = new HashtablePublication(sensorPublication.getProperties(), sensorPublication.getValidity(), sensorPublication.getStartTime());
Map<String, Object> mapToGSN = toGSN.getProperties();
for (String prop : sensorParameters) {
if (mapToGSN.get(prop) != null && mapToGSN.get(prop) instanceof Number && !(mapToGSN.get(prop) instanceof Double)) {
if (mapToGSN.get(prop) instanceof Integer) {
Double propValue = ((Integer) mapToGSN.get(prop)).doubleValue();
mapToGSN.put(prop, propValue);
} else if (mapToGSN.get(prop) instanceof Short) {
Double propValue = ((Short) mapToGSN.get(prop)).doubleValue();
mapToGSN.put(prop, propValue);
}
}
}
//send publication to x-gsn listening on defined port
try {
String gsnIP = this.gsnAddress.split(":")[0];
DatagramSocket socket = new DatagramSocket();
ByteArrayOutputStream baseOut = new ByteArrayOutputStream(64 * 1000); //64KB, max for IP packet
baseOut.reset();
ObjectOutputStream oos = new ObjectOutputStream(baseOut); //has to write a new header each time
oos.writeObject(mapToGSN);
oos.flush();
DatagramPacket packet = new DatagramPacket(baseOut.toByteArray(), baseOut.size(),InetAddress.getByName(gsnIP), port);
socket.send(packet);
System.out.println("!!!!!!!!!!!");
} catch (Exception e) {
log.writeToLog("Exception occured while sending the UDP package to the GSN: " + e);
}
}
private void startTimer() {
Timer time = new Timer();
CleanExpiredMessagesTask clean = new CleanExpiredMessagesTask();
AverageSensorReadingsTask average = new AverageSensorReadingsTask();
//schedule cleaning of expired messages every 5 minutes, start after 5 minutes
time.scheduleAtFixedRate(clean, 300000, 300000);
//schedule calculating average values every 15 minutes, start immediately
time.scheduleAtFixedRate(average, 0, 900000);
}
private class CleanExpiredMessagesTask extends TimerTask {
public void run() {
cleanExpiredMessages();
}
}
private class AverageSensorReadingsTask extends TimerTask {
public void run() {
calculateAverageSensorReadings();
}
}
}