[Announcement] node-red-contrib-xstate-machine - Flexible state-machines for node-red

logo_279

I'd like to announce a new package for node-red that I just published.

Did you ever want to have flexible state-machines in node-red and be able to track their state and data visually?

Then you came to the right place. Check out my blog post or go directly to the package's site.

I'm happy to get your input and suggestions!

7 Likes

Looks great, thanks. Do you have plans to output the state machine on the dashboard ? Might be great use case for process monitoring.

... especially if they were svg... (@BartButenaers)

1 Like

Thank you for your feedback. Indeed, an option to output the graphics (which are rendered as svg) to the dashboard plugin sounds useful. I’ll put it on the release plan for the next versions.

Marcus (@sonntam ),
Nice work!

@dceejay,
Although the node seems to be able to export to SVG underneath, currently the SVG ui node does not allow the full svg string to be loaded from an input message. Although might be possible e.g. via innerHtml perhaps. Not sure... Most probably @Steve-Mcl has a way to workaround it :wink:
Anyway it won't be an interactive state machine editor, but only a viewer...
But would be nice if the current state would be highlighted, e.g. using another color...

1 Like

On my admittedly old Pi2 - the cat example does this

[smxstate:sm-cat ] Rendering of state machine failed: Render process timed out.
smcat renderer process exited with error code null.

@dceejay Thanks for bringing that to my attention. I incorporated a timeout in the render process because I feared the system could get unresponsive if something goes wrong. That and also, because viz.js seems to have some memory-leaks, is why I run the rendering in a separate process in the first place. This timeout is currently hard-coded to 10 seconds.

It seems that the 10 second timeout is too short for your setup.

You could try increasing the timeout and give me feedback what works for you if you don't mind.
Open the file <node-red settings dir>/node_modules/node-red-contrib-xstate-machine/dist/smxstate-node.js and on line 513 change

}, 10000, true);

to a higher timeout, e.g. 20 seconds, so:

}, 20000, true);

then save the file, restart your node-red service and try again. If it works for you I can incorporate your findings and provide an update.

I might also consider changing the rendering process such that I try to observe the process itself in order to detect hanging to get rid of the hard-coded timeout.

Hi,

ok I had to "tune" it up to 40000 (40s) for it to render reliably... looks very nice - but that is not sustainable in real life :frowning: . Presumably it will take even longer if the state machine gets more complex... so yes some other method of detecting completion (or not) would really be needed.

Also - if I create another node - by dragging from the palette - the debug windows shows


Ie - both with some words at the start (SM-Cat Example) that appears nowhere in the node config - as far as I can tell... where is that coming from. (Ah just worked it out - it's the tab name... maybe a bit nicer spacing or start with the node name would make it more obvious (to me at least) ? (and drop the nodeid ?)

And- if I just drag out a new node - while it may be useful to have some of the info in there - if i deploy it it starts creating loads of warnings in the console log - and on this old slow Pi - does then get very unresponsive and hard to break into !

Not sure I quite understand the two outputs of the node either. While I understand it's all about he state machine - from the outside world the important piece is the data that is sent out - so that should really be the primary output (IMHO) . The secondary output should be for interesting meta-data like the internal state and variables. Or am i misunderstanding how this is intended to be used ?

Also if I have a really simple machine with no context - why do I get context messages on every transition when there is none ?

@dceejay Thanks again for your excellent feedback. It is very important to me because it's my first time creating something for node-red and it probably isn't very polished yet (also because there was no one other than me testing it).

Oops, that is taking much longer than I anticipated! Unfortunately the viz.js package that is used in the background for rendering has quite a bit of overhead because it's a 1:1 asm.js port from the original C code using emscripten...

In the long run this will get replaced by something much more performant and modern, maybe dracula.js or d3.js but it will take some time.

That is a good hint. The UI definately has to be improved - I too was thinking that I may drop the node ID in the labels due to the verbosity. The issue with that is that you cannot discern nodes when they are in subflows which have multiple instances.

A possible approach in my mind would be to only have the verbose labels when there are ambiguities. Do you think that would improve the display? About the spacing in the node paths: As you suggested I could put the node name in front, that would also be fine by me. The node path could then be displayed after it in parentheses or smth. similar.

The first output is indeed the most important one. In my opinion messages on state changes and on data changes are both equally important as it allows you to trigger things within the remainder of your node-red flow. They can be easily separated using a switch node on the .topic property.

The second output outputs all the messages that are arguments to the node.send() method from inside the smxstate node.

That may be a bug I'll have to take a look at.

You're right - the default node contains an example that demonstrates the node.warn() functionality. I probably should comment that out at least.

It would probably be fairly easy using uibuilder :wink:

Well maybe one message in the log is ok - but only if it is a real warning... maybe just a log rather than warn message if you like. If I see lots of things in the log I think something is wrong !

Still not quite getting the point of the outputs - OK - I get the state one - but why output the internal context ? If the node wants to send something out surely it should send it (as per the second output). Or if the context is important - then why do i need to ever use node.send - I can just set an internal context variable and it would be sent anyway. By all means surface the internal context via the side bar (as that is the debug to see what is going on inside - but I don't get why it should appear on the output - especially when it can be quite "noisy" (with counters and everything) - which I then have to handle and discard to get to see the state... I think it is overkill. (or indeed I'm just not getting it)

looks pretty fine to me :slight_smile:

Marcus @sonntam good work
In process control & industrial automation FSM are called "State Transition Diagrams" or more formally "Sequential Function Charts" in IEC61131-3

And are implemented in PLCs/Automation controllers.
As means of programming with real time feedback.

The diagrams are a lot simpler (needed for Engineers)
This might help in coming up with as first cut for visualization.

Unfortunately the viz.js package that is used in the background for rendering has quite a bit of overhead because it's a 1:1 asm.js port from the original C code using emscripten...

In the long run this will get replaced by something much more performant and modern, maybe dracula.js or d3.js but it will take some time.

Did you consider mermaid.js ?

2 Likes

Excellent idea @bakman2 . Would certainly trim the fat off.

I've Used Mermaid on an in house wiki. Its so simple to generate from text. Perhaps this node could output compatible Mermaid code for external rendering? Would be easy to consume in UI builder or a dashboard node.

@iiLaw Good point. I always thought they are more about processing in the likes of

read input ➡ do processing ➡ write output

in a cyclic rather than event-based manner.

This is actually the first time I heard about it. Somehow in my research about state chart rendering and layouting libraries for node.js I missed it. It looks nice and promising - will definately check it out!

Also the author of state-machine-cat messaged me and said: Hey, why not use the native graphviz program for rendering instead of the node.js port - it's a lot faster. Smcat can produce graphviz compatible dot output. I might take a look at that as well to get a quick fix for the performance issue.

Using graphviz and server-side SVG rendering compared to d3.js etc. has the advantage that the memory footprint and performance requirements within the browser are super low.

However, mermaid.js uses d3 wich node-red uses anyway. I see a way to use this with only a small additional footprint as well. @bakman2, Steve-Mcl Thanks for pointing it out.

1 Like

Also:


https://bramp.github.io/js-sequence-diagrams/

I adressed this issue in Release 0.2.0. In a couple of hours it should be available in the palette manager.

1 Like