/** * Copyright (c) 2011-2014, OpenIoT * * This file is part of OpenIoT. * * OpenIoT is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, version 3 of the License. * * OpenIoT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with OpenIoT. If not, see <http://www.gnu.org/licenses/>. * * Contact: OpenIoT mailto: info@openiot.eu * @author Sofiane Sarni */ package org.openiot.gsn.wrappers.tinyos; import org.apache.log4j.Logger; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedQueue; public class SensorScope2Listener implements Runnable { private static final int MAX_BUFFER_SIZE = 128; private boolean initialized = false; private boolean running = false; private static SensorScope2Listener instance = null; private transient Logger logger = Logger.getLogger(this.getClass()); private int server_port; long counter = 0; private ServerSocket serverSocket = null; private Socket client = null; private Thread thread; private static final long PACKET_AGE_LIMIT = 600000; // packet stay for a maximum of PACKET_AGE_LIMIT (ms) before being recycled public ConcurrentLinkedQueue<SensorScope2Packet> queue = new ConcurrentLinkedQueue<SensorScope2Packet>(); //public SensorScope2Packet public SensorScope2Packet getNextPacketAfter(SensorScope2Packet latestPacket) { RecyclePackets(); long timestamp = 0; if (latestPacket != null) timestamp = latestPacket.timestamp; Iterator iter = queue.iterator(); boolean found = false; SensorScope2Packet packet = null; while (iter.hasNext() && !found) { packet = (SensorScope2Packet) iter.next(); if (packet.timestamp >= timestamp) { // duplicate timestamps are possible because of multiple station ids if (packet != latestPacket) // skip same packet already processed if (queue.contains(latestPacket)) { if (indexOf(packet) > indexOf(latestPacket)) found = true; } else { found = true; } } } if (found) return packet; else return null; } private int indexOf(SensorScope2Packet packet) { Iterator iter = queue.iterator(); int index = -1; boolean found = false; while (iter.hasNext() && !found) { index++; if (packet == iter.next()) found = true; } if (found) return index; else return -1; } /* * Delete elements older than age limit * */ public void RecyclePackets() { Iterator iter = queue.iterator(); long currentTimeMillis = System.currentTimeMillis(); int n_packets_deleted = 0; SensorScope2Packet packet = null; while (iter.hasNext()) { packet = (SensorScope2Packet) iter.next(); if (currentTimeMillis - packet.timestamp > PACKET_AGE_LIMIT) { queue.remove(packet); n_packets_deleted++; } } if (n_packets_deleted != 0) logger.warn("Deleted " + n_packets_deleted + " packet(s). New size => " + queue.size()); } public void start() { if (!running && initialized) { this.thread.start(); running = true; } else { logger.warn("Listener thread already running or not initialized."); } } public void setPort(int server_port) { if (initialized) { logger.warn("Port already initialized. (Singleton can be initialized only once)"); return; // initialize only once } this.server_port = server_port; this.initialized = true; // Create a server socket logger.warn("Trying to open a server socket on port " + server_port); try { serverSocket = new ServerSocket(server_port); } catch (IOException e) { logger.error("Cannot open a server socket on port " + server_port + "."); this.initialized = false; } } public static SensorScope2Listener getInstance() { if (instance != null) { return instance; } else { instance = new SensorScope2Listener(); return instance; } } private SensorScope2Listener() { this.thread = new Thread(this); } public void run() { if (!initialized) return; logger.warn("Started SensorScope listener on port " + server_port + "."); while (running) { byte[] packet = null; try { // Wait for a request client = serverSocket.accept(); // Get the streams packet = new byte[MAX_BUFFER_SIZE]; int n_read = client.getInputStream().read(packet); byte[] real_packet = new byte[n_read]; System.arraycopy(packet, 0, real_packet, 0, n_read); SensorScope2Packet _packet = new SensorScope2Packet(System.currentTimeMillis(), real_packet); queue.add(_packet); String order = "[" + String.format("%8d", counter) + "]"; logger.warn(order + " " + _packet.toString()); counter++; //RecyclePackets(); // recycle old packets. Calling } catch (IOException e) { logger.error("Error in Server: " + e.getMessage(), e); } finally { try { //inbound.close(); //outbound.close(); client.close(); //serverSocket.close(); } catch (IOException e) { logger.warn("Cannot close stream " + e.getMessage(), e); } } } } public void stopAcquisition() { running = false; } }