tklab-tud / uscxml

SCXML interpreter and transformer/compiler written in C/C++ with bindings to Java, C#, Python and Lua
Other
106 stars 54 forks source link

How to get data model info from interpreter #189

Closed crichardson332 closed 5 years ago

crichardson332 commented 5 years ago

I'm trying to figure out how to pass data into my state machine from external events, and then extract that data using the uscxml interpreter. My scxml looks something like this:

<scxml name="Scxml" initial="State0" version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
    <transition event="GoState1" target="State1"/>
    <state id="State1">
        <datamodel>
            <data id="Num"/>
        </datamodel>
        <onentry>
            <assign location="Num" expr="_event.data"/>
        </onentry>
    </state>
</scxml>

I'm able to assign data to Num when I push the event into the interpreter externally, but now I can't figure out how to see that data from the interpreter after performing a macrostep. Does the interpreter class have this, or am I approaching this wrong? I'm also still learning the scxml standard so I might not be setting up my scxml file correctly.

alexzhornyak commented 5 years ago

Your example contains the next errors: 1) NULL datamodel does not support location and value expressions 2) \<transition> element can not be child of \<scxml> element

Actually, your question was not fully clear, so, I made one simple example. May be it will help you.

github_issue_189_1

<scxml datamodel="lua" name="Scxml" version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
    <state id="State1">
        <datamodel>
            <data expr="5" id="Num"/>
        </datamodel>
        <transition target="FinalShape1"/>
    </state>
    <final id="FinalShape1">
        <onentry>
            <assign expr="Num + 5" location="Num"/>
        </onentry>
    </final>
</scxml>
Interpreter interpreter = Interpreter::fromURL("github_issue_189_1.scxml");

InterpreterState state = InterpreterState::USCXML_UNDEF;
while (state != InterpreterState::USCXML_FINISHED) {
    state = interpreter.step();
}

auto numData = interpreter.getImpl()->getAsData("Num"); // Not Evaluated
// auto numData = interpreter.getImpl()->evalAsData("Num"); // Evaluated
std::cout << std::stol(numData);

Output: 10

crichardson332 commented 5 years ago

Thanks! I've got something working now.

I ran into another issue though when trying to run my application inside a docker container. On my host, all my tests run fine; but inside docker my code crashes with output that isn't useful. So I ran uscxml-browser -c on my scxml file and got the following output:

[Debug] Issue (FATAL) at /scxml[1]: SCXML document requires unknown datamodel 'ecmascript'

The same thing happens with lua as well:

[Debug] Issue (FATAL) at /scxml[1]: SCXML document requires unknown datamodel 'lua'

This docker container definitely doesn't have all the packages that a normal ubuntu desktop would have. What packages do I need to install for this to work?

Also, I noticed in your NullDataModel implementation that it uses the Data class's fromJSON() function to get data. All I really need from the data model is to store dictionaries in something like a JSON format...can I just use the null datamodel? The scxml documentation makes it sound like the null is meant for a non-existent data model, but if I can at least do JSON dictionaries then that works for me.

crichardson332 commented 5 years ago

Never mind, I figured it out. Turns out, the docker container did not have the scripting languages installed, but I specified the language in my scxml file so it was crashing.

For ecmascript, you need to install a javascript engine, like so

sudo apt install libjavascriptcoregtk-4.0-dev

And similar packages if you're using lua, or any of the other scripting languages. But for ecmascript you only need the javascript one.