-
Notifications
You must be signed in to change notification settings - Fork 2
ObsSM Listener Developing Guide
First you need to know how ObsSM works!
The interpreter works using a SCXML Framework Apache commons scxml this framework is used to read and parse the SCXML Model and execute the transitions.
We developed a simple JSON parser who translate a log line message like:
2016-05-29T10:57:21.451 CONTROL/Array002 alma.Control.ObservingModes.ArrayMountControllerImpl waitForSubscanStart Not waiting as the subscan started 25.675 seconds ago.
and the parser says if is a legal event for the state machine or not.
The ObsSM read data from ElasticSearch and for each line log search first for a keyName (See more about keyName in Models) with this keyName the ObsSM has a StateMachineManager who has a single state machine for each keyName. The StateMachineManager is waiting on each line for a initial transition to initialize the State Machine.
The StateMachineManager controls the lifecycle of every StateMachine, and on every change over the StateMachine it has a EntryListener who implements a SCXMLListener class:
public interface SCXMLListener {
/**
* Handle the entry into a TransitionTarget.
*
* @param state The TransitionTarget entered
*/
void onEntry(TransitionTarget state);
/**
* Handle the exit out of a TransitionTarget.
*
* @param state The TransitionTarget exited
*/
void onExit(TransitionTarget state);
/**
* Handle the transition.
*
* @param from The source TransitionTarget
* @param to The destination TransitionTarget
* @param transition The Transition taken
*/
void onTransition(TransitionTarget from, TransitionTarget to,
Transition transition);
}
In order to simplify the acquisition of vars relatives to a transitions we made another version:
public abstract class EntryListener implements SCXMLListener {
/**
* Parent state machine execution.
*/
protected StateMachine stateMachine = null;
/**
* Global Manager instance.
*/
protected final Manager manager;
/**
*
* @param manager
*/
public EntryListener(Manager manager) {
this.manager = manager;
}
/**
* This method will be executed after the parent State machine receive a keyName.
*/
public abstract void initialize();
@Override
public void onTransition(TransitionTarget from, TransitionTarget to, Transition transition) {
onTransition(from, to, transition, Parser.savedArray, Parser.savedTimeStamp, Parser.savedLogLine);
}
/**
* this methods allow to execute what you need, on every transition.
*
* @param from
* @param to
* @param transition
* @param array
* @param timeStamp
* @param logLine
*/
public abstract void onTransition(TransitionTarget from, TransitionTarget to, Transition transition, String array, String timeStamp, String logLine);
}
So, we can look an example: This is the default EntryListener.
public class DefaultEntryListener extends EntryListener {
public DefaultEntryListener(Manager manager) {
super(manager);
}
@Override
public void onEntry(TransitionTarget state) {
}
@Override
public void onExit(TransitionTarget state) {
}
@Override
public void onTransition(TransitionTarget from, TransitionTarget to, Transition transition, String array, String timeStamp, String logline) {
System.out.println("ARRAY: "+array+" EVENT: " + transition.getEvent() + " TO: " + to.getId() + " FROM: " + from.getId() + " TS: " + timeStamp);
}
@Override
public void initialize() {
}
}
To create an example we are going to use a similiar code of above.
CustomEntryListener:
import org.alma.obssm.Manager;
import org.alma.obssm.sm.EntryListener;
import org.apache.commons.scxml.model.Transition;
import org.apache.commons.scxml.model.TransitionTarget;
public class CustomEntryListener extends EntryListener {
public CustomEntryListener(Manager manager) {
super(manager);
}
@Override
public void onEntry(TransitionTarget state) {
}
@Override
public void onExit(TransitionTarget state) {
}
@Override
public void onTransition(TransitionTarget from, TransitionTarget to, Transition transition, String array, String timeStamp, String logline) {
System.out.println("ARRAY: "+array+" EVENT: " + transition.getEvent() + " TO: " + to.getId() + " FROM: " + from.getId() + " TS: " + timeStamp);
}
@Override
public void initialize() {
System.out.println("I am the array: " + getParent().getKeyName());
}
}
Now we have to compile it!
We suppose you're in the ObsSM folder. And you've compiled the ObsSM
Compiling process:
javac -classpath .:target/ObsSM-1.0.jar:target/dependency/commons-scxml-0.9.jar CustomEntryListener.java
jar cf CustomEntryListener.jar CustomEntryListener.class
Execution:
./obssm.sh -c --date_from="2016-05-22T21:16:22.037" --date_to="2016-05-23T21:16:22.037" --query="*" --listener="CustomEntryListener.jar:CustomEntryListener"
Now we have a custom listener. Maybe you want to interconnect data between state machines. On every StateMachine a listener is created, so you can use static vars to share data between all the instances.
Like this:
public class GraphViewer extends EntryListener{
public static Viewer view = null;
public GraphViewer(Manager m) {
super(m);
if (view == null) {
view = new Viewer();
}
}