Skip to content

Commit

Permalink
Merge branch 'random-service-update' of github.com-myrobotlab:MyRobot…
Browse files Browse the repository at this point in the history
…Lab/myrobotlab into inmoov-and-statemachine-1
  • Loading branch information
supertick committed Nov 11, 2023
2 parents 52381d3 + b521675 commit 37624b4
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 144 deletions.
11 changes: 7 additions & 4 deletions src/main/java/org/myrobotlab/service/InMoov2.java
Original file line number Diff line number Diff line change
Expand Up @@ -1290,10 +1290,13 @@ public void onPirOn() {
led.timeOff = 10;
// FIXME flash on config.flashOnBoot
invoke("publishFlash");
String botState = chatBot.getPredicate("botState");
if ("sleeping".equals(botState)) {
invoke("publishEvent", "WAKE");
}
ProgramAB chatBot = (ProgramAB)getPeer("chatBot");
if (chatBot != null) {
String botState = chatBot.getPredicate("botState");
if ("sleeping".equals(botState)) {
invoke("publishEvent", "WAKE");
}
}
}

/**
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

0 comments on commit 37624b4

Please sign in to comment.