package cgl.iotcloud.core; import cgl.iotcloud.core.transport.Channel; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public abstract class AbstractSensor implements ISensor { private Map<String, QueueProducer> producers = new HashMap<String, QueueProducer>(); private Map<String, QueueListener> listeners = new HashMap<String, QueueListener>(); public void startSend(Channel channel, MessageSender sender, int interval) { QueueProducer producer = new QueueProducer(sender, interval, channel); producers.put(channel.getName(), producer); Thread t = new Thread(producer); t.start(); } public void startSend(Channel channel, BlockingQueue messages) { QueueProducer producer = new QueueProducer(messages, channel); producers.put(channel.getName(), producer); Thread t = new Thread(producer); t.start(); } public void startListen(Channel channel, MessageReceiver receiver) { QueueListener listener = new QueueListener(channel.getOutQueue(), receiver); listeners.put(channel.getName(), listener); Thread t = new Thread(listener); t.start(); } public void stopChannel(String name) { if (producers.containsKey(name)) { producers.get(name).stop(); } if (listeners.containsKey(name)) { listeners.get(name).stop(); } } protected class QueueProducer implements Runnable { private BlockingQueue<byte[]> queue = new ArrayBlockingQueue<byte[]>(1024); private MessageSender messageSender; private boolean run = true; private int interval; private boolean pause = false; private BlockingQueue<byte []> messages; private Channel channel; private QueueProducer(MessageSender handler, int interval, Channel channel) { this.messageSender = handler; this.interval = interval; this.channel = channel; } public QueueProducer(BlockingQueue<byte []> messages, Channel channel) { this.messages = messages; this.channel = channel; } @Override public void run() { if (messages == null) { runFixedInterval(); } else { runFromQueue(); } } private void runFixedInterval() { while (run) { synchronized (this){ while (pause) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } messageSender.loop(queue); while (!queue.isEmpty()) { try { byte[] data = queue.take(); channel.publish(data); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(interval); } catch (InterruptedException e) { throw new RuntimeException(e); } } } private void runFromQueue() { while (run) { synchronized (this){ while (pause) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } try { byte[] message = messages.take(); channel.publish(message); } catch (InterruptedException e) { throw new RuntimeException(e); } try { Thread.sleep(interval); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public void stop() { run = false; notifyAll(); } public void deactivate() { pause = true; } public synchronized void activate() { pause = false; notifyAll(); } } protected class QueueListener implements Runnable { private BlockingQueue queue; private MessageReceiver messageReceiver; private boolean run = true; private boolean pause = false; private QueueListener(BlockingQueue queue, MessageReceiver handler) { this.queue = queue; this.messageReceiver = handler; } @Override public void run() { while (run) { synchronized (this) { while (pause) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } try { Object o = queue.take(); messageReceiver.onMessage(o); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public void stop() { run = false; notifyAll(); } public void deactivate() { pause = true; } public synchronized void activate() { pause = false; notifyAll(); } } @Override public void close() { // do nothing } @Override public void activate() { for (QueueProducer p : producers.values()) { p.activate(); } for (QueueListener p : listeners.values()) { p.activate(); } } @Override public void deactivate() { for (QueueProducer p : producers.values()) { p.deactivate(); } for (QueueListener p : listeners.values()) { p.deactivate(); } } }