/** * * @author greg (at) myrobotlab.org * * This file is part of MyRobotLab (http://myrobotlab.org). * * MyRobotLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version (subject to the "Classpath" exception * as provided in the LICENSE.txt file that accompanied this code). * * MyRobotLab is distributed in the hope that it will be useful or fun, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * All libraries in thirdParty bundle are subject to their own license * requirements - please refer to http://myrobotlab.org/libraries for * details. * * Enjoy ! * * */ package org.myrobotlab.service; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import org.myrobotlab.codec.CodecUtils; import org.myrobotlab.framework.Message; import org.myrobotlab.framework.Service; import org.myrobotlab.framework.ServiceType; import org.myrobotlab.logging.Level; import org.myrobotlab.logging.LoggerFactory; import org.myrobotlab.logging.Logging; import org.myrobotlab.logging.LoggingFactory; import org.myrobotlab.service.data.ClockEvent; import org.slf4j.Logger; /** * Clock - This is a simple clock service that can be started and stopped. It * generates a pulse with a timestamp on a regular interval defined by the * setInterval(Integer) method. Interval is in milliseconds. */ public class Clock extends Service { public class ClockThread implements Runnable { public Thread thread = null; ClockThread() { thread = new Thread(this, getName() + "_ticking_thread"); thread.start(); } @Override public void run() { try { while (isClockRunning == true) { Date now = new Date(); Iterator<ClockEvent> i = events.iterator(); while (i.hasNext()) { ClockEvent event = i.next(); if (now.after(event.time)) { // TODO repeat - don't delete set time forward // interval send(event.name, event.method, event.data); i.remove(); } } invoke("pulse", new Date()); Thread.sleep(interval); } } catch (InterruptedException e) { log.info("ClockThread interrupt"); isClockRunning = false; } } } private static final long serialVersionUID = 1L; public final static Logger log = LoggerFactory.getLogger(Clock.class.getCanonicalName()); public boolean isClockRunning; public int interval = 1000; public transient ClockThread myClock = null; // FIXME ArrayList<ClockEvent> events = new ArrayList<ClockEvent>(); public Clock(String n) { super(n); } public void addClockEvent(Date time, String name, String method, Object... data) { ClockEvent event = new ClockEvent(time, name, method, data); events.add(event); } // clock started event public void clockStarted() { } public void clockStopped() { } public Date pulse(Date time) { return time; } public void setInterval(Integer milliseconds) { interval = milliseconds; broadcastState(); } public void startClock() { if (myClock == null) { info("starting clock"); isClockRunning = true; myClock = new ClockThread(); invoke("clockStarted"); } else { log.warn("clock already started"); } broadcastState(); } public void stopClock() { if (myClock != null) { info("stopping clock"); log.info("stopping " + getName() + " myClock"); isClockRunning = false; myClock.thread.interrupt(); myClock.thread = null; myClock = null; // have requestors broadcast state ! // broadcastState(); invoke("clockStopped"); } else { log.warn("clock already stopped"); } isClockRunning = false; broadcastState(); } @Override public void stopService() { stopClock(); super.stopService(); } public static void main(String[] args) throws Exception { LoggingFactory.init(Level.INFO); String test = "tcp"; if ("tcp".equals(test)) { // TCP CONNECT WORKS BEGIN --------------------------------- try { int i = 6; // for (int i = 1; i < 4; ++i) { Runtime.main(new String[] { "-runtimeName", String.format("runtime.%d", i) }); // auto-grab the next port if can not listen??? RemoteAdapter remote = (RemoteAdapter) Runtime.start(String.format("remote%d", i), "RemoteAdapter"); // remote.setUDPPort(6868); // remote.setTCPPort(6868); // remote.scan(); // remote.setDefaultPrefix("raspi"); Runtime.start(String.format("clock%d", i), "Clock"); Runtime.start(String.format("gui", i), "GUIService"); // Runtime.start(String.format("python", i), "Python"); remote.connect("tcp://127.0.0.1:6767"); // Runtime.start(String.format("p%d", i), "Python"); // remote.scan(); // remote.startListening(); // remote.connect("tcp://127.0.0.1:6767"); // FIXME - sholdn't this be sendRemote ??? or at least // in an interface // remote.sendRemote(uri, msg); // xmpp1.sendMessage("xmpp 2", "robot02 02"); // } } catch (Exception e) { Logging.logError(e); } // TCP CONNECT WORKS END --------------------------------- } else if ("xmpp".equals(test)) { // XMPP CONNECT WORKS BEGIN --------------------------------- int i = 2; Runtime.main(new String[] { "-runtimeName", String.format("r%d", i) }); Security security = (Security) Runtime.createAndStart("security", "Security"); security.addUser("incubator incubator"); security.setGroup("incubator incubator", "authenticated"); security.allowExportByType("XMPP", false); security.allowExportByType("Security", false); security.allowExportByType("Runtime", false); Xmpp xmpp1 = (Xmpp) Runtime.createAndStart(String.format("xmpp%d", i), "XMPP"); Clock clock = (Clock) Runtime.createAndStart(String.format("clock%d", i), "Clock"); Runtime.createAndStart(String.format("gui%d", i), "GUIService"); xmpp1.connect("talk.google.com", 5222, "robot02@myrobotlab.org", "mrlRocks!"); Message msg = null; msg = xmpp1.createMessage(null, "register", clock); String base64 = CodecUtils.msgToBase64(msg); xmpp1.sendMessage(base64, "incubator incubator"); // XMPP CONNECT WORKS END --------------------------------- } } /** * This static method returns all the details of the class without it having * to be constructed. It has description, categories, dependencies, and peer * definitions. * * @return ServiceType - returns all the data * */ static public ServiceType getMetaData() { ServiceType meta = new ServiceType(Clock.class.getCanonicalName()); meta.addDescription("used to generate pulses and recurring messages"); meta.addCategory("scheduling"); return meta; } }