/** * */ package at.bakery.kippen.server.objects; import java.util.HashMap; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; import at.bakery.kippen.common.AbstractData; import at.bakery.kippen.common.data.MoveData; import at.bakery.kippen.server.EventTypes; import at.bakery.kippen.server.command.Command; /** * @author thomasw * */ public abstract class AbstractKippenObject { static Logger log = Logger.getLogger(AbstractKippenObject.class.getName()); protected String id; protected HashMap<String, List<Command>> eventsOfObject = new HashMap<String, List<Command>>(); private static long IDLE_AFTER_SECONDS = 340; private long lastActivityTime = System.nanoTime(); protected double MOVE_DATA_THRESHHOLD = 0.2; protected static final long NEW_SHAKE_AFTER = (long) 2e9; /** * @param id * usually mac address */ public AbstractKippenObject(String id, int timeout) { this.id = id; IDLE_AFTER_SECONDS = timeout * 60; // periodically checks whether the object is idle or not (defined by the // constant) ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { if (System.nanoTime() - lastActivityTime > IDLE_AFTER_SECONDS * 1e9) { timeout(); } } }, IDLE_AFTER_SECONDS, 10, TimeUnit.SECONDS); } public void setCommandsForEvents(String eventID, List<Command> commandList) { this.eventsOfObject.put(eventID, commandList); } protected void timeout() { System.out.println("Calling TIMOUT on object " + id); HashMap<String, String> paramMap = new HashMap<String, String>(); List<Command> list = eventsOfObject.get(EventTypes.TIMEOUT); if (list != null) { for (Command c : eventsOfObject.get(EventTypes.TIMEOUT)) { try { c.execute(paramMap); } catch (Exception e) { log.warning("Failed to execute command " + c.getClass().getSimpleName()); } } } } /** * Default implementation for data processing. Does nothing except storing * received data and updating activity timer. Due to the latter this super * method needs to be called by overriding clients. * * @param data * The received data object. */ public void processData(AbstractData data) { // only count as activity when the object did a significant action if (data instanceof MoveData) { MoveData move = (MoveData) data; double moveAmpl = Math.sqrt(move.getX() * move.getX() + move.getY() * move.getY() + move.getZ() * move.getZ()); if (moveAmpl > MOVE_DATA_THRESHHOLD) { lastActivityTime = System.nanoTime(); } } } /** * Looks for the commands of this object that are registed for this specific * event type. */ protected void executeCommands(HashMap<String, String> paramMap, String eventType) { List<Command> commands = eventsOfObject.get(eventType); if (commands != null) { for (Command c : commands) { try { c.execute(paramMap); } catch (Exception e) { e.printStackTrace(); log.warning("Failed to execute command " + c.getClass().getSimpleName()); } finally { } } } } public String getId() { return id; } }