2 Commits 05a24c937a ... 44ff2b162f

Author SHA1 Message Date
  Andreas T. Meyer-Berg 44ff2b162f Minor Menu Bar Updates 3 years ago
  Andreas T. Meyer-Berg a991c10ad2 Adds Evaluation package and SWC classifier template 3 years ago

+ 429 - 0
src/main/java/de/tu_darmstadt/tk/SmartHomeNetworkSim/evaluation/BasicPacketClassifier.java

@@ -0,0 +1,429 @@
+package de.tu_darmstadt.tk.SmartHomeNetworkSim.evaluation;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map.Entry;
+
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.PacketSniffer;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.protocols.packets.MQTTpublishPacket;
+import weka.core.Attribute;
+import weka.core.DenseInstance;
+import weka.core.Instance;
+import weka.core.Instances;
+
+/**
+ * Unsupervised Classifier Basis, which contains methods for transforming {@link Packet}s into {@link Instance}s.
+ *
+ * @author Andreas T. Meyer-Berg
+ */
+public abstract class BasicPacketClassifier implements PacketSniffer {
+
+	/**
+	 * True, if instances should be used for training
+	 */
+	protected boolean training = true;
+	
+	/**
+	 * Attributes which should be taken into account
+	 */
+	protected ArrayList<Attribute> atts = new ArrayList<Attribute>();
+	
+	/**
+	 * Collected Packets
+	 */
+	protected Instances dataset;
+	
+	/**
+	 * CollectedPackets
+	 */
+	protected HashMap<Link, LinkedList<Packet>> collectedPackets = new HashMap<Link, LinkedList<Packet>>();
+	
+	/**
+	 * HashMap for calculating transmission delay
+	 */
+	protected HashMap<Link, LinkedList<Packet>> lastPackets = new HashMap<Link, LinkedList<Packet>>();
+	
+	/**
+	 * Map for the different Link names
+	 */
+	protected HashSet<String> link_mappings = new HashSet<String>();
+
+	/**
+	 * Map for the difference source device names
+	 */
+	protected HashSet<String> source_mappings = new HashSet<String>();
+	
+	/**
+	 * Map for the different destination device names
+	 */
+	protected HashSet<String> destination_mappings = new HashSet<String>();
+	
+	/**
+	 * Map for the protocol names
+	 */
+	protected HashSet<String> protocol_mappings = new HashSet<String>();
+
+	/**
+	 * Number of packets which are used to calculate the current transmission speed
+	 */
+	protected int NUMBER_OF_PACKETS = 200;
+	
+	/**
+	 * Initializes the different maps
+	 */
+	public BasicPacketClassifier() {
+		// Initialize Attribute list
+		source_mappings.add("unknown");
+		link_mappings.add("unknown");
+		destination_mappings.add("unknown");
+		protocol_mappings.add("unknown");
+	}
+	
+	@Override
+	public void processPackets(HashMap<Link, LinkedList<Packet>> packets) {
+		if(training)
+			try {
+				training(packets);
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		else
+			classify(packets);
+	}
+	
+	/**
+	 * Estimates the current Packets per second (depending on the last 100 packets of the link)
+	 * @param link Link which should be checked
+	 * @param packet Packet which should investigated
+	 * @return estimated number of packets per second
+	 */
+	protected double getEstimatedPacketsPerSecond(Link link, Packet packet) {
+		/**
+		 * Packets used to calculated the packets per second
+		 */
+		LinkedList<Packet> list = lastPackets.get(link);
+		if(list == null) {
+			/**
+			 * Add list if not present
+			 */
+			list = new LinkedList<Packet>();
+			lastPackets.put(link, list);
+		}
+		if(list.isEmpty()) {
+			list.addLast(packet);
+			// Default 1 packet per second
+			return 1.0;
+		}
+		if(list.size() == NUMBER_OF_PACKETS){
+			list.removeFirst();	
+		}
+		list.addLast(packet);
+		/**
+		 * elapsed time in milliseconds since last packet
+		 */
+		long elapsed_time = packet.getTimestamp()-list.getFirst().getTimestamp()/list.size();
+		if(elapsed_time<=0)
+			return Double.POSITIVE_INFINITY;
+		/**
+		 * Return number of packets per second
+		 */
+		return 1000.0/elapsed_time;
+		
+	}
+	
+	/**
+	 * Returns the instance representation of the given packet and link
+	 * @param link link the packet was sent on
+	 * @param packet packet which should be transformed
+	 * @param dataset distribution the packet is part of
+	 * @return instance representation
+	 */
+	protected Instance packet2Instance(Link link, Packet packet, Instances dataset) {
+		/**
+		 * Instance for the given Packet
+		 */
+		DenseInstance instance = new DenseInstance(dataset.numAttributes());
+		instance.setDataset(dataset);
+		
+		// link
+		instance.setValue(0, stringToNominal(link_mappings, link.getName()));
+		
+		// source
+		if(packet.getSource()==null) {
+			instance.setValue(1, "unknown");
+			instance.setValue(2, Double.NEGATIVE_INFINITY);
+		}else if(packet.getSource().getOwner()==null){
+			instance.setValue(1, "unknown");
+			instance.setValue(2, packet.getSource().getPortNumber());
+		}else {
+			instance.setValue(1, stringToNominal(source_mappings, packet.getSource().getOwner().getName()));
+
+			instance.setValue(2, packet.getSource().getPortNumber());
+		}
+		
+		// Destination
+		if(packet.getDestination()==null) {
+			instance.setValue(3, "unknown");
+			instance.setValue(4, Double.NEGATIVE_INFINITY);
+		}else if(packet.getDestination().getOwner()==null){
+			instance.setValue(3, "unknown");
+
+			instance.setValue(4, packet.getDestination().getPortNumber());
+		}else {
+			instance.setValue(3, stringToNominal(destination_mappings, packet.getDestination().getOwner().getName()));
+			instance.setValue(4, packet.getDestination().getPortNumber());
+		}
+		
+		// Protocol name
+		instance.setValue(5, stringToNominal(protocol_mappings, packet.getProtocolName()));
+		
+		// Packets per second
+		instance.setValue(6, getEstimatedPacketsPerSecond(link, packet));
+		// MQTT Value
+		if(packet instanceof MQTTpublishPacket)
+			instance.setValue(7, ((MQTTpublishPacket)packet).getValue());
+		else
+			instance.setValue(7, -1);
+		
+		return instance;
+	}
+	
+	/**
+	 * Inserts the
+	 * @param map
+	 * @param nominal
+	 */
+	protected void insertNominalIntoMap(HashSet<String> map, String nominal) {
+		if(map == null || nominal == null)
+			return;
+		map.add(nominal);
+	}
+	/**
+	 * Transforms the String into an Number
+	 * @param map
+	 * @param s
+	 * @return
+	 */
+	protected String stringToNominal(HashSet<String> map, String s) {
+		return map.contains(s)?s:"unknown";
+	} 
+	
+	/**
+	 * Train the clusterer by collecting the packets
+	 * 
+	 * @param packets packets to be learned
+	 */
+	protected void training(HashMap<Link, LinkedList<Packet>> packets) {
+		for(Entry<Link, LinkedList<Packet>> e:packets.entrySet()) {
+			Link l = e.getKey();
+			// TODO: ERROR ????????
+			LinkedList<Packet> p = collectedPackets.get(l);
+			if(p == null) {
+				collectedPackets.put(l, new LinkedList<Packet>(e.getValue()));
+			} else
+				p.addAll(e.getValue());
+			insertNominalIntoMap(link_mappings, l.getName());
+			for(Packet pac: e.getValue()) {
+				if(pac == null || pac.getSource()==null ||pac.getDestination() == null || pac.getSource().getOwner() == null || pac.getDestination().getOwner() == null)
+					continue;
+				insertNominalIntoMap(destination_mappings, pac.getSource().getOwner().getName());
+				insertNominalIntoMap(destination_mappings, pac.getDestination().getOwner().getName());
+				insertNominalIntoMap(source_mappings, pac.getSource().getOwner().getName());
+				insertNominalIntoMap(source_mappings, pac.getDestination().getOwner().getName());
+				insertNominalIntoMap(protocol_mappings, pac.getProtocolName());
+			}
+			//TODO: Add packet/Link/Names etc. to mappings
+		}
+	}
+	
+	/**
+	 * Finishes the collection and trains the clusterer on the collected packets
+	 * 
+	 * @throws Exception
+	 */
+	protected void finishDataCollection() throws Exception{
+		/**
+		printHashSet("Link-Name", link_mappings);
+		printHashSet("Source-Device", source_mappings);
+		printHashSet("Destination-Port", destination_mappings);
+		printHashSet("Protocol-name", protocol_mappings);
+		*/
+		atts.add(new Attribute("Link-Name", new LinkedList<String>(link_mappings)));//TODO:??
+		atts.add(new Attribute("Source-Device", new LinkedList<String>(source_mappings)));
+		atts.add(new Attribute("Source-Port-number", false));
+		atts.add(new Attribute("Destination-Device", new LinkedList<String>(destination_mappings)));
+		atts.add(new Attribute("Destination-Port-number", false));
+		Attribute pn = new Attribute("Protocol-name", new LinkedList<String>(protocol_mappings));
+		//pn.setWeight(10);
+		atts.add(pn);
+		Attribute pps = new Attribute("Packets-per-second", false);
+		//pps.setWeight(20);
+		atts.add(pps);
+		atts.add(new Attribute("PacketValue", false));
+		//atts.add(new Attribute("Anomaly", false));
+
+		/*
+		atts = new ArrayList<Attribute>();
+		atts.add(new Attribute("LN", new LinkedList<String>(link_mappings)));//TODO:??
+		atts.add(new Attribute("SD", new LinkedList<String>(source_mappings)));
+		atts.add(new Attribute("SPN", false));
+		atts.add(new Attribute("DD", new LinkedList<String>(destination_mappings)));
+		atts.add(new Attribute("DPN", false));
+		atts.add(new Attribute("PN", new LinkedList<String>(protocol_mappings)));
+		atts.add(new Attribute("PPS", false));
+		atts.add(new Attribute("A", false));*/
+		dataset = new Instances("Packets", atts, 100000);
+		//dataset.setClassIndex(7);
+
+		/**
+		 * Add Instances to dataset
+		 */
+		for (Iterator<Entry<Link, LinkedList<Packet>>> it = collectedPackets.entrySet().iterator(); it.hasNext();) {
+			Entry<Link, LinkedList<Packet>> entry = it.next();
+			/**
+			 * Link the packet was captured on
+			 */
+			Link l = entry.getKey();
+			for (Iterator<Packet> itPacket = entry.getValue().iterator(); itPacket.hasNext();) {
+				/**
+				 * Packets to be added to the dataset
+				 */
+				Packet packet = (Packet) itPacket.next();
+				dataset.add(packet2Instance(l, packet, dataset));
+			}
+		}
+		
+		trainModel(dataset);
+	}
+	
+	private void printHashSet(String name, HashSet<String> toPrint) {
+		System.out.println(name+":");
+		for (Iterator<String> iterator = toPrint.iterator(); iterator.hasNext();) {
+			String string = (String) iterator.next();
+			System.out.print(string);
+			if(iterator.hasNext())
+				System.out.print(", ");
+		}
+		System.out.println();
+	}
+	/**
+	 * Try to classify the given packets and detect anomalies
+	 * @param packets packets to be classified
+	 */
+	protected void classify(HashMap<Link, LinkedList<Packet>> packets) {
+		int tp = 0;
+		int fp = 0;
+		int tn = 0;
+		int fn = 0;
+		long start = Long.MAX_VALUE;
+		long end = Long.MIN_VALUE;
+		for (Iterator<Entry<Link, LinkedList<Packet>>> it = packets.entrySet().iterator(); it.hasNext();) {
+			/**
+			 * Link & its packets
+			 */
+			Entry<Link, LinkedList<Packet>> entry = it.next();
+			/**
+			 * Link the packets were captured on
+			 */
+			Link l = entry.getKey();
+			for (Iterator<Packet> itPacket = entry.getValue().iterator(); itPacket.hasNext();) {
+				/**
+				 * Packet which should be checked
+				 */
+				Packet packet = (Packet) itPacket.next();
+
+				start = Math.min(start, packet.getTimestamp());
+				end = Math.max(end, packet.getTimestamp());
+				/**
+				 * Instance Representation
+				 */
+				Instance packet_instance = packet2Instance(l, packet, dataset);
+				
+				if(packet_instance == null)continue;
+				try {
+					double dist = classifyInstance(packet_instance, packet);	
+					if(dist<=1.0) {
+						if(packet.getLabel()==0)
+							tn++;
+						else {
+							fn++;
+
+							System.out.println(packet.getTextualRepresentation());
+						}
+					}else {
+						if(packet.getLabel()==0)
+							fp++;
+						else
+							tp++;
+					}
+				} catch (Exception e) {
+					if(packet.getLabel()==0)
+						fp++;
+					else
+						tp++;
+				}
+			}	
+		}
+		int n = tp+tn+fp+fn;
+		if(n!=0) {
+			System.out.println(getAlgoName()+" Performance: ["+start+"ms, "+end+"ms]");
+			System.out.println("n: "+n);
+			System.out.println("TP: "+tp);
+			System.out.println("FP: "+fp);
+			System.out.println("TN: "+tn);
+			System.out.println("FN: "+fn);
+			System.out.println("TPR: "+(tp/(tp+fn+0.0)));
+			System.out.println("FPR: "+(fp/(fp+tn+0.0)));
+			System.out.println("");
+		}
+	}
+	
+	/**
+	 * Train the model using the given instances
+	 * @param instances training set, which should be learned
+	 */
+	public abstract void trainModel(Instances instances);
+	
+	/**
+	 * classifies the given instance
+	 * @param instance instance which should be classified
+	 * @param origin original packet, which was transformed into the instance
+	 * @return distance to next centroid
+	 * @throws Exception if anomaly was detected
+	 */
+	public abstract double classifyInstance(Instance instance, Packet origin) throws Exception;
+	
+	/**
+	 * Returns the timestep, after which the classifier should start classifying instead of training.
+	 * @return timestep of the testing begin.
+	 */
+	public abstract long getClassificationStart();
+	
+	@Override
+	public void setMode(boolean testing) {
+		training = !testing;
+		if(testing) {
+			try {
+				finishDataCollection();
+			} catch (Exception e) {
+				System.out.println("Clustering failed");
+				e.printStackTrace();
+			}	
+		}
+	}
+	
+	@Override
+	public boolean getMode() {
+		return !training;
+	}
+	
+	/**
+	 * Short String representation of the classifier
+	 * @return
+	 */
+	public abstract String getAlgoName();
+}

+ 122 - 0
src/main/java/de/tu_darmstadt/tk/SmartHomeNetworkSim/evaluation/SWCKMeansClustering.java

@@ -0,0 +1,122 @@
+package de.tu_darmstadt.tk.SmartHomeNetworkSim.evaluation;
+
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet;
+import weka.clusterers.SimpleKMeans;
+import weka.core.Instance;
+import weka.core.Instances;
+import weka.core.SelectedTag;
+
+/**
+ * Unsupervised Example: K Means Clustering
+ *
+ * @author Andreas T. Meyer-Berg
+ */
+public class SWCKMeansClustering extends BasicPacketClassifier {
+
+	/**
+	 * Clusterer
+	 */
+	private SimpleKMeans clusterer;
+
+	/**
+	 * Number of Clusters
+	 */ 
+	//17 works fine
+	//34 found value anomalies
+	protected int NUMBER_OF_CLUSTERS = 8;
+	protected double[] stdv = new double[NUMBER_OF_CLUSTERS];
+	/**
+	 * Initializes the k means clusterer
+	 */
+	public SWCKMeansClustering() {
+		super();
+		clusterer = new SimpleKMeans();
+		clusterer.setSeed(42);
+		//clusterer.setDisplayStdDevs(true);
+		clusterer.setInitializationMethod(new SelectedTag(SimpleKMeans.FARTHEST_FIRST,SimpleKMeans.TAGS_SELECTION));
+		//clusterer.setCanopyPeriodicPruningRate(100);
+		//clusterer.setCanopyT1(0.001);
+		//clusterer.setCanopyT2(0.1);
+		try {
+			clusterer.setNumClusters(this.NUMBER_OF_CLUSTERS);
+		} catch (Exception e) {
+			System.out.println("Error while building cluster");
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void trainModel(Instances instances) {
+		try {
+			clusterer.buildClusterer(instances);
+			double[] sumOfSquares = new double[NUMBER_OF_CLUSTERS];
+			for(Instance i: instances) {
+				/**
+				 * Id of the closest cluster centroid
+				 */
+				int x = clusterer.clusterInstance(i);
+				/**
+				 * centroid instance
+				 */
+				Instance center = clusterer.getClusterCentroids().get(x);
+				/**
+				 * Distance
+				 */
+				double dist = clusterer.getDistanceFunction().distance(center, i);
+				sumOfSquares[x] += dist*dist;
+			}
+			/**
+			 * Calculate Standard Deviations
+			 */
+			for(int i = 0; i<NUMBER_OF_CLUSTERS; i++)
+				this.stdv[i] = Math.sqrt(sumOfSquares[i]);
+		} catch (Exception e) {
+			System.out.println("Failed while training the classifier");
+			e.printStackTrace();
+		}
+	}
+	private boolean test = true;
+	
+	@Override
+	public double classifyInstance(Instance instance, Packet origin) throws Exception {
+		/**
+		 * Id of the closest cluster centroid
+		 */
+		int x = clusterer.clusterInstance(instance);
+		/**
+		 * centroid instance
+		 */
+		Instance center = clusterer.getClusterCentroids().get(x);
+		
+		double dist = clusterer.getDistanceFunction().distance(center, instance);
+		if(test && dist<stdv[x] && origin.getLabel()!=0) {
+			test = false;
+			System.out.println("Analysis of: "+origin.getTextualRepresentation());
+			System.out.println("Classified as: "+x+" Dist: "+dist+" Stdv: "+stdv[x]);
+			for(int i=0; i<NUMBER_OF_CLUSTERS; i++) {
+				Instance centroid = clusterer.getClusterCentroids().get(i);
+				if(centroid == null)continue;
+				double d = clusterer.getDistanceFunction().distance(centroid, instance);
+				
+				System.out.println("Cluster: "+i+" Dist: "+d+" Stdv: "+stdv[i]);
+			}
+			test = false;
+			System.out.println("");
+		}
+		if(dist < stdv[x])
+			return 0;
+		else
+			return Double.MAX_VALUE;
+		
+	}
+
+	@Override
+	public long getClassificationStart() {
+		return 3600000;
+	}
+
+	@Override
+	public String getAlgoName() {
+		return "KNN";
+	}
+}

+ 1 - 0
src/main/java/de/tu_darmstadt/tk/SmartHomeNetworkSim/evaluation/package-info.java

@@ -0,0 +1 @@
+package de.tu_darmstadt.tk.SmartHomeNetworkSim.evaluation;

+ 113 - 33
src/main/java/de/tu_darmstadt/tk/SmartHomeNetworkSim/view/menuBar/MenuBarNetworkExamples.java

@@ -9,6 +9,8 @@ import java.util.Map.Entry;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
 
+import org.apache.commons.math3.distribution.NormalDistribution;
+
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.Controller;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.ExampleAnomalyController;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.ImportController;
@@ -27,6 +29,7 @@ import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Port;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.PrecisionLink;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Protocol;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.RoomStatus;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.SimulationManager;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.SmartDevice;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.BoolCollectorDevice;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.BoolSensorDevice;
@@ -38,10 +41,12 @@ import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.SmartTemperatureProdu
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.SmartTemperatureSensor;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.distributionHandler.NormalDistributionHandler;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.protocols.MQTT_protocol;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.scheduler.AbstractEvent;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.CountingMetric;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.Manipulation_RandomMove;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleLink;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleProtocol;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.evaluation.SWCKMeansClustering;
 
 public class MenuBarNetworkExamples extends JMenu{
 
@@ -827,6 +832,7 @@ public class MenuBarNetworkExamples extends JMenu{
 		pBroker.setResponseTime((short)2);
 		networkController.addDeviceToConnectionAndProtocol(pBroker, mqtt, 0);
 		networkController.addConnection(mqtt);
+		mqtt.setLabel((short) 0);
 		
 		/**
 		 * Room
@@ -841,20 +847,20 @@ public class MenuBarNetworkExamples extends JMenu{
 		/**
 		 * Room Thermostat
 		 */
-		SmartTemperatureSensor floatSensor = new SmartTemperatureSensor(roomName + " Thermostat", room);
-		floatSensor.setFSinfoName("home/" + roomName + "/sensorTemp");
-		networkController.addLinkToDevice(zigbee, floatSensor);
-		networkController.moveSmartDevice(floatSensor, 300, 300, 50);
-		floatSensor.setFSmin(19.0f);
-		floatSensor.setFSmax(21.0f);
-		floatSensor.setFSval(19.0f);
-		networkController.addSmartDevice(floatSensor);
-		Port pFloatSensor = new Port(floatSensor, (short)1883, 15000);
+		SmartTemperatureSensor heatSensor = new SmartTemperatureSensor(roomName + " Thermostat", room);
+		heatSensor.setFSinfoName("home/" + roomName + "/sensorTemp");
+		networkController.addLinkToDevice(zigbee, heatSensor);
+		networkController.moveSmartDevice(heatSensor, 300, 300, 50);
+		heatSensor.setFSmin(19.0f);
+		heatSensor.setFSmax(21.0f);
+		heatSensor.setFSval(19.0f);
+		networkController.addSmartDevice(heatSensor);
+		Port pFloatSensor = new Port(heatSensor, (short)1883, 15000);
 		pFloatSensor.setTriggerHandler(new NormalDistributionHandler(15000, 500));
 		pFloatSensor.setStatus(Port.SENDING);
 		pFloatSensor.setLastTrigger(-357L);
 		networkController.addDeviceToConnectionAndProtocol(pFloatSensor, mqtt,1);
-		
+		heatSensor.setLabel((short) 0);
 		/*
 		 * Add Heater (every second update)
 		 */
@@ -871,7 +877,7 @@ public class MenuBarNetworkExamples extends JMenu{
 		pHeaterDevice.setTriggerHandler(new NormalDistributionHandler(15000, 500));
 		pHeaterDevice.setLastTrigger(-1231L);
 		networkController.addDeviceToConnectionAndProtocol(pHeaterDevice, mqtt,1);
-		
+		heaterDevice.setLabel((short) 0);
 		
 		/*
 		 * Add a light
@@ -886,6 +892,7 @@ public class MenuBarNetworkExamples extends JMenu{
 		pSmartLight.setStatus(Port.SENDING);
 		pSmartLight.setLastTrigger(-1207L);
 		networkController.addDeviceToConnectionAndProtocol(pSmartLight, mqtt,1);
+		smartLight.setLabel((short) 0);
 		
 		/*
 		 * Add light Sensor
@@ -900,7 +907,7 @@ public class MenuBarNetworkExamples extends JMenu{
 		pLightSensor.setStatus(Port.SENDING);
 		pLightSensor.setLastTrigger(-1337L);
 		networkController.addDeviceToConnectionAndProtocol(pLightSensor, mqtt,1);
-		
+		lightSensor.setLabel((short) 0);
 		
 		/* 
 		 * Update visualization 
@@ -916,7 +923,7 @@ public class MenuBarNetworkExamples extends JMenu{
 			/**
 			 * Instances of the packet Sniffers
 			 */
-			PacketSniffer snifferEM = null, snifferKNN = null, snifferHC = null;
+			PacketSniffer snifferKNN = null; //, snifferEM = null, snifferHC = null;
 			/*
 			 * Import Example PacketSniffer algorithms
 			 */
@@ -927,8 +934,7 @@ public class MenuBarNetworkExamples extends JMenu{
 			Class<? extends PacketSniffer> hc = (Class<? extends PacketSniffer>) ImportController.importJavaClass(new File("examples/classifier/HierarchicalClustering.java"));
 			snifferHC = hc.newInstance();*/
 			
-			Class<? extends PacketSniffer> knn = (Class<? extends PacketSniffer>) ImportController.importJavaClass(new File("examples/classifier/KMeansClustering.java"));
-			snifferKNN = knn.newInstance();
+			snifferKNN = new SWCKMeansClustering();
 			
 			System.out.println("Check 2: Imported");//TODO
 			/*
@@ -962,11 +968,55 @@ public class MenuBarNetworkExamples extends JMenu{
 			sim.resetSimulation();
 			sim.setStepDuration(hour);
 			sim.setPrintPackets(false);
-			sim.setEndTime(24*hour);
+			long endTime = 24*hour;
+			sim.setEndTime(endTime);
 
-			heaterDevice.setFSmin(19f);
-			heaterDevice.setFSmax(23f);
-			heaterDevice.setFSval(20f);
+			/**
+			 * Training events
+			 */
+			System.out.println("Create training events");
+			/**
+			 * Light Events (random switch every 30min+-15min
+			 */
+			NormalDistribution lightDist = new NormalDistribution(hour/2, hour/4);
+			long eventTime = 0;
+			while(eventTime < endTime + hour/2) {
+				/**
+				 * At least 1 second between events
+				 */
+				eventTime+=Math.max(1000, Math.round(lightDist.sample()));
+				SimulationManager.scheduleEvent(new AbstractEvent(eventTime) {
+					
+					@Override
+					public void simulateEvent(long time) {
+						smartLight.setBSval(!smartLight.isTrueStatus());
+						smartLight.setTrueStatus(!smartLight.isTrueStatus());
+					}
+				});
+				
+			}
+			/**
+			 * Heater Events (random switch every 2h +- 30min
+			 */
+			NormalDistribution tempDist = new NormalDistribution(2*hour, hour/2);
+			eventTime = 0;
+			while(eventTime < endTime + 1 * hour) {
+				/**
+				 * At least 1 second between events
+				 */
+				eventTime+=Math.max(1000, Math.round(tempDist.sample()));
+				SimulationManager.scheduleEvent(new AbstractEvent(eventTime) {
+					
+					@Override
+					public void simulateEvent(long time) {
+						float newTemp = (float)(heaterDevice.getFSmax() + Math.random() * (heaterDevice.getFSmax()-heaterDevice.getFSmin()));
+						heaterDevice.setFSval(newTemp);
+						heaterDevice.setFSval(newTemp);
+					}
+				});
+				
+			}
+			
 			System.out.println("Training:");//TODO
 			for(int i=0; i<24; i++)
 				sim.getSimulationManager().simulateTimeIntervall(i*hour, hour);
@@ -994,7 +1044,7 @@ public class MenuBarNetworkExamples extends JMenu{
 			 */
 
 			System.out.println("Test w/0 anomalies:");//TODO
-			for(int i=24; i<25; i++)
+			for(int i=24; i<26; i++)
 				sim.getSimulationManager().simulateTimeIntervall(hour*i, hour);
 			
 			new_time = System.currentTimeMillis();
@@ -1003,23 +1053,53 @@ public class MenuBarNetworkExamples extends JMenu{
 			currentTime = new_time;
 			
 			/**
+			 * Light Anomaly 1h
 			 * Light != Sensor
-			 * Value Anomaly 1h
-			 * TODO: Do more complex Anomaly Scenario
 			 */
-			System.out.println("Value Anomalies:");
-			float min = heaterDevice.getFSmin();
-			float max = heaterDevice.getFSmax();
-			float val = heaterDevice.getFSval();
-			heaterDevice.setFSmin(18);
-			heaterDevice.setFSval(18.5f);
-			heaterDevice.setFSmax(24);
+			System.out.println("Light Anomaly:");
+			smartLight.setTrueStatus(smartLight.getBSval());
+			smartLight.setLabel((short)-1);
+			for(int i=26; i<27; i++)
+				sim.getSimulationManager().simulateTimeIntervall(hour*i, hour);
+			smartLight.setLabel((short)0);
+			
+			new_time = System.currentTimeMillis();
+			elapsed_time = new_time-currentTime;
+			System.out.println("Anomaly generation & classification: "+elapsed_time+"ms");
+			currentTime = new_time;
+			
+			/**
+			 * Schedule new light events
+			 */
+			eventTime = 27 * hour;
+			while(eventTime < 29 * hour) {
+				/**
+				 * At least 1 second between events
+				 */
+				SimulationManager.scheduleEvent(new AbstractEvent(eventTime) {
+					
+					@Override
+					public void simulateEvent(long time) {
+						smartLight.setBSval(!smartLight.isTrueStatus());
+						smartLight.setTrueStatus(!smartLight.isTrueStatus());
+					}
+				});
+				
+				eventTime+=Math.max(1000, Math.round(lightDist.sample()));
+				
+			}
+			
+			/**
+			 * Temperature Anomaly 2h
+			 */
+			System.out.println("Temperature Anomaly:");
+			heaterDevice.setFSval(21f);
+			heaterDevice.setTrueTemperature(34f);
 			heaterDevice.setLabel((short)-1);//-1 Value anomaly
-			for(int i=25; i<26; i++)
+			for(int i=27; i<29; i++)
 				sim.getSimulationManager().simulateTimeIntervall(hour*i, hour);
-			heaterDevice.setFSmin(min);
-			heaterDevice.setFSmax(max);
-			heaterDevice.setFSval(val);
+			heaterDevice.setFSval(21f);
+			heaterDevice.setTrueTemperature(21f);
 			heaterDevice.setLabel((short)0);
 			
 			new_time = System.currentTimeMillis();