Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Random service updates #1361

Merged
merged 1 commit into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/org/myrobotlab/service/JMonkeyEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -2157,7 +2157,7 @@ public void simpleInitApp() {
new File(getDataDir()).mkdirs();
new File(getResourceDir()).mkdirs();

// assetManager.registerLocator("./", FileLocator.class);
assetManager.registerLocator("./", FileLocator.class);
assetManager.registerLocator(getDataDir(), FileLocator.class);
assetManager.registerLocator(assetsDir, FileLocator.class);
assetManager.registerLocator(modelsDir, FileLocator.class);
Expand Down
262 changes: 147 additions & 115 deletions src/main/java/org/myrobotlab/service/Random.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,26 @@ public class Random extends Service<RandomConfig> {

public final static Logger log = LoggerFactory.getLogger(Random.class);

transient private RandomProcessor processor = null;

transient private final Object lock = new Object();

/**
*
* RandomMessage is used to contain the ranges of values and intervals for
* which random messages will be sent
*
*/
static public class RandomMessage {
public String taskName;
public String name;
public String method;
public Range[] data;
public boolean enabled = true;
public long minIntervalMs;
public long maxIntervalMs;
public long interval;
public boolean oneShot = false;
public transient long nextProcessTimeTs = 0;

public RandomMessage() {
}
Expand Down Expand Up @@ -103,6 +108,23 @@ public double getRandom(double min, double max) {
return min + (Math.random() * (max - min));
}

public void addRandom(String taskName, long minIntervalMs, long maxIntervalMs, String name, String method, Integer... values) {
addRandom(taskName, minIntervalMs, maxIntervalMs, name, method, toRanges((Object[]) values));
}

public void addRandom(String taskName, long minIntervalMs, long maxIntervalMs, String name, String method, Double... values) {
addRandom(taskName, minIntervalMs, maxIntervalMs, name, method, toRanges((Object[]) values));
}

// FIXME - test this
public void addRandom(String taskName, long minIntervalMs, long maxIntervalMs, String name, String method) {
addRandom(taskName, minIntervalMs, maxIntervalMs, name, method, toRanges((Object[]) null));
}

public void addRandom(String taskName, long minIntervalMs, long maxIntervalMs, String name, String method, String... params) {
addRandom(taskName, minIntervalMs, maxIntervalMs, name, method, setRange((Object[]) params));
}

public void addRandom(long minIntervalMs, long maxIntervalMs, String name, String method, Integer... values) {
addRandom(minIntervalMs, maxIntervalMs, name, method, toRanges((Object[]) values));
}
Expand Down Expand Up @@ -170,74 +192,105 @@ public void removeAll() {
}

public void addRandom(long minIntervalMs, long maxIntervalMs, String name, String method, Range... ranges) {
String taskName = String.format("%s.%s", name, method);
addRandom(taskName, minIntervalMs, maxIntervalMs, name, method, ranges);
}

RandomMessage msg = new RandomMessage();
msg.name = name;
msg.method = method;
msg.minIntervalMs = minIntervalMs;
msg.maxIntervalMs = maxIntervalMs;
msg.data = ranges;

String key = String.format("%s.%s", name, method);
randomData.put(key, msg);

msg.interval = getRandom(minIntervalMs, maxIntervalMs);
log.info("add random message {} in {} ms", key, msg.interval);
if (enabled) {
// only if global enabled is enabled do we start the task
addTask(key, 0, msg.interval, "process", key);
}
public void addRandom(String taskName, long minIntervalMs, long maxIntervalMs, String name, String method, Range... ranges) {

RandomMessage data = new RandomMessage();
data.name = name;
data.method = method;
data.minIntervalMs = minIntervalMs;
data.maxIntervalMs = maxIntervalMs;
data.data = ranges;
data.enabled = true;

randomData.put(taskName, data);

log.info("add random message {} in {} to {} ms", taskName, data.minIntervalMs, data.maxIntervalMs);
broadcastState();
}

public void process(String key) {
// if (!enabled) {
// return;
// }
private class RandomProcessor extends Thread {

RandomMessage msg = randomData.get(key);
if (msg == null || !msg.enabled) {
return;
public RandomProcessor(String name) {
super(name);
}

Message m = Message.createMessage(getName(), msg.name, msg.method, null);
if (msg.data != null) {
List<Object> data = new ArrayList<>();

for (int i = 0; i < msg.data.length; ++i) {
Object o = msg.data[i];
if (o instanceof Range) {
Range range = (Range) o;
Object param = null;

if (range.set != null) {
int rand = getRandom(0, range.set.size() - 1);
param = range.set.get(rand);
} else if (range.min instanceof Double) {
param = getRandom((Double) range.min, (Double) range.max);
} else if (range.min instanceof Long) {
param = getRandom((Long) range.min, (Long) range.max);
} else if (range.min instanceof Integer) {
param = getRandom((Integer) range.min, (Integer) range.max);
public void run() {
while (enabled) {
try {
// minimal interval time for processor to check
// and see if any random event needs processing

sleep(200);
for (String key : randomData.keySet()) {

long now = System.currentTimeMillis();

RandomMessage randomEntry = randomData.get(key);
if (!randomEntry.enabled) {
continue;
}

// first time set
if (randomEntry.nextProcessTimeTs == 0) {
randomEntry.nextProcessTimeTs = now + getRandom((Long) randomEntry.minIntervalMs, (Long) randomEntry.maxIntervalMs);
}

if (now < randomEntry.nextProcessTimeTs) {
// this entry isn't ready
continue;
}

Message m = Message.createMessage(getName(), randomEntry.name, randomEntry.method, null);
if (randomEntry.data != null) {
List<Object> data = new ArrayList<>();

for (int i = 0; i < randomEntry.data.length; ++i) {
Object o = randomEntry.data[i];
if (o instanceof Range) {
Range range = (Range) o;
Object param = null;

if (range.set != null) {
int rand = getRandom(0, range.set.size() - 1);
param = range.set.get(rand);
} else if (range.min instanceof Double) {
param = getRandom((Double) range.min, (Double) range.max);
} else if (range.min instanceof Long) {
param = getRandom((Long) range.min, (Long) range.max);
} else if (range.min instanceof Integer) {
param = getRandom((Integer) range.min, (Integer) range.max);
}

data.add(param);
}
}
m.data = data.toArray();
}
m.sendingMethod = "process";
log.debug("random msg @ {} ms {}", now - randomEntry.nextProcessTimeTs, m);
out(m);

// auto-disable oneshot
if (randomEntry.oneShot) {
randomEntry.enabled = false;
}

// reset next processing time
randomEntry.nextProcessTimeTs = now + getRandom((Long) randomEntry.minIntervalMs, (Long) randomEntry.maxIntervalMs);

}

data.add(param);
} catch (Exception e) {
error(e);
}
}
m.data = data.toArray();
}
m.sendingMethod = "process";
log.info("random msg @ {} ms {}", msg.interval, m);
out(m);

purgeTask(key);
if (!msg.oneShot) {
msg.interval = getRandom(msg.minIntervalMs, msg.maxIntervalMs);
// must re-schedule unless one shot
if (enabled) {
// only if global enabled is enabled do we start the task
addTask(key, 0, msg.interval, "process", key);
}

} // while (enabled) {

log.info("Random {}-processor terminating", getName());
}
}

Expand Down Expand Up @@ -280,12 +333,12 @@ public RandomConfig apply(RandomConfig c) {
return c;
}

@Deprecated /* use remove(String key) */
public RandomMessage remove(String name, String method) {
return remove(String.format("%s.%s", name, method));
}

public RandomMessage remove(String key) {
purgeTask(key);
return randomData.remove(key);
}

Expand All @@ -294,79 +347,49 @@ public Set<String> getKeySet() {
}

public void disable(String key) {
// exact match
if (key.contains(".")) {
RandomMessage msg = randomData.get(key);
if (msg == null) {
log.warn("cannot disable random event with key {}", key);
return;
}
randomData.get(key).enabled = false;
purgeTask(key);

if (!randomData.containsKey(key)) {
error("disable cannot find key %s", key);
return;
}
// must be name - disable "all" for this service
for (RandomMessage msg : randomData.values()) {
if (msg.name.equals(key)) {
msg.enabled = false;
purgeTask(String.format("%s.%s", msg.name, msg.method));
}
}

randomData.get(key).enabled = false;
}

public void enable(String key) {
// exact match
if (key.contains(".")) {
RandomMessage msg = randomData.get(key);
if (msg == null) {
log.warn("cannot enable random event with key {}", key);
return;
}
randomData.get(key).enabled = true;
if (enabled) {
// only if global enabled is enabled do we start the task
addTask(key, 0, msg.interval, "process", key);
}
if (!randomData.containsKey(key)) {
error("disable cannot find key %s", key);
return;
}
// must be name - disable "all" for this service
String name = key;
for (RandomMessage msg : randomData.values()) {
if (msg.name.equals(name)) {
msg.enabled = true;
String fullKey = String.format("%s.%s", msg.name, msg.method);
if (enabled) {
// only if global enabled is enabled do we start the task
addTask(fullKey, 0, msg.interval, "process", fullKey);
}
}
}
randomData.get(key).enabled = true;
}

public void disable() {
// remove all timed attempts of processing random
// events
purgeTasks();
enabled = false;
broadcastState();
synchronized (lock) {
enabled = false;
processor = null;
broadcastState();
}
}

public void enable() {
for (RandomMessage msg : randomData.values()) {
// re-enable tasks which were previously enabled
if (msg.enabled == true) {
String fullKey = String.format("%s.%s", msg.name, msg.method);
addTask(fullKey, 0, msg.interval, "process", fullKey);
synchronized (lock) {
enabled = true;
if (processor == null) {
processor = new RandomProcessor(String.format("%s-processor", getName()));
processor.start();
// wait until thread starts
sleep(200);
} else {
info("%s already enabled");
}
broadcastState();
}

enabled = true;
broadcastState();
}

public void purge() {
randomData.clear();
purgeTasks();
broadcastState();
}

public Set<String> getMethodsFromName(String serviceName) {
Expand Down Expand Up @@ -395,13 +418,22 @@ public List<MethodEntry> methodQuery(String serviceName, String methodName) {
}
return MethodCache.getInstance().query(si.getClass().getCanonicalName(), methodName);
}

public Map<String, RandomMessage> getRandomEvents(){
return randomData;
}

public RandomMessage getRandomEvent(String key) {
return randomData.get(key);
}

public static void main(String[] args) {
try {

LoggingFactory.init(Level.INFO);

Runtime.setConfig("dev");
Runtime.start("c1", "Clock");
Runtime.start("python", "Python");

Random random = (Random) Runtime.start("random", "Random");

Expand Down
5 changes: 1 addition & 4 deletions src/main/java/org/myrobotlab/service/meta/RandomMeta.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@ public RandomMeta() {
// add a cool description
addDescription("provides a service for random message generation");

// false will prevent it being seen in the ui
setAvailable(true);

// add dependencies if necessary
// addDependency("com.twelvemonkeys.common", "common-lang", "3.1.1");

setAvailable(false);
setAvailable(true);

// add it to one or many categories
addCategory("general");
Expand Down
Loading