package at.bakery.kippen.server.objects;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;
import at.bakery.kippen.common.AbstractData;
import at.bakery.kippen.common.data.AccelerationData;
import at.bakery.kippen.common.data.BatteryData;
import at.bakery.kippen.common.data.CubeOrientationData;
import at.bakery.kippen.common.data.MoveData;
import at.bakery.kippen.common.data.ShakeData;
import at.bakery.kippen.common.data.WifiLevelsData;
import at.bakery.kippen.server.EventTypes;
import at.bakery.kippen.server.KippenServer;
import at.bakery.kippen.server.command.Command;
public class CubeObject extends AbstractKippenObject {
static Logger log = Logger.getLogger(CubeObject.class.getName());
private int currentSide = -1;
private Queue<WifiLevelsData> avgWifiLevel = new LinkedList<>();
public CubeObject(String id, int timeout) {
super(id, timeout);
log.setLevel(KippenServer.LOG_LEVEL);
}
@Override
public void processData(AbstractData d) {
super.processData(d);
log.log(Level.FINEST, "CUBE processes " + d.getClass().getSimpleName() + " -> " + d.toString());
if (d instanceof WifiLevelsData) {
processWifiData((WifiLevelsData) d);
} else if (d instanceof AccelerationData) {
processAccelerationData((AccelerationData) d);
} else if (d instanceof CubeOrientationData) {
processCubeOrientationData((CubeOrientationData) d);
} else if (d instanceof ShakeData) {
processShakeData((ShakeData) d);
} else if (d instanceof MoveData) {
processMoveData((MoveData) d);
} else if (d instanceof BatteryData) {
processBatteryData((BatteryData) d);
}
}
protected void timeout() {
super.timeout();
}
private long lastShook = System.nanoTime();
private void processShakeData(ShakeData shakeData) {
if (shakeData.isShaking() == false) {
return;
}
long curTime = System.nanoTime();
if (curTime - lastShook < NEW_SHAKE_AFTER) {
// ignore if shake events indifferent
return;
}
lastShook = curTime;
HashMap<String, String> paramMap = new HashMap<String, String>();
List<Command> sideChangeEvents = eventsOfObject.get(EventTypes.SHAKE);
if (sideChangeEvents != null) {
for (Command c : eventsOfObject.get(EventTypes.SHAKE)) {
try {
c.execute(paramMap);
} catch (Exception e) {
log.warning("Failed to execute command " + c.getClass().getSimpleName());
}
}
}
}
private void processCubeOrientationData(CubeOrientationData data) {
CubeOrientationData cd = (CubeOrientationData) data;
if (cd.getOrientation() == CubeOrientationData.Orientation.UNKNOWN) {
return;
}
int sideInt = cd.getOrientation().ordinal();
if (sideInt == currentSide) {
return;
}
String sideString = String.valueOf(sideInt);
log.log(Level.FINE, "Executing side change with side " + sideString);
HashMap<String, String> paramMap = new HashMap<String, String>();
paramMap.put("clipNumber", sideString);
List<Command> sideChangeEvents = eventsOfObject.get(EventTypes.SIDECHANGE);
if (sideChangeEvents != null) {
for (Command c : sideChangeEvents) {
try {
c.execute(paramMap);
} catch (Exception e) {
log.warning("Failed to execute command " + c.getClass().getSimpleName());
}
}
// set the current side
currentSide = sideInt;
}
}
private void processWifiData(WifiLevelsData data) {
WifiLevelsData wd = (WifiLevelsData) data;
// add the current measurement to the list
avgWifiLevel.offer(wd);
// compute average
if (avgWifiLevel.size() > 0) {
double avgLevel = 0;
// for each measurement item ...
for (WifiLevelsData w : avgWifiLevel) {
double innerAvgLevel = 0;
// for each measured wifi in the item ...
for (Entry<String, Object> val : w.getNetworks()) {
innerAvgLevel += (double) val.getValue();
}
// ... compute average
avgLevel += (innerAvgLevel / w.getNetworks().size());
}
avgLevel /= avgWifiLevel.size();
// RSSI to meters conversion
double dist = Math.pow(10, ((27.55 - (67.6 + avgLevel)) / 20.0));
log.log(Level.FINEST, "~ " + dist + "m (level: " + avgLevel + ")");
// remember the last to measurements, remove others
if (avgWifiLevel.size() > 10) {
avgWifiLevel.poll();
}
}
}
private void processAccelerationData(AccelerationData data) {
}
private void processBatteryData(BatteryData data) {
}
private void processMoveData(MoveData data) {
}
}