Version 3 of Object Oriented Moore Type State Models

Updated 2014-01-02 20:23:22 by RLE
What: oomoore package
Description: The oomoore package defines a TclOO meta-class which can be used to create a state model class with specified state model behavior.

This package is a rework of the moore package to use new Tcl 8.6 object oriented capabilites.

Here's an example of a simple two state pump from a question that came up on C.L.T.

package require Tcl 8.6
# See
# to obtain the "oomoore" package.
package require oomoore

# This class embodies all the state behavior.

oomoore model create ::pump_operation {
    initialState PumpOff

    state PumpOff {} {
        chan puts "[self] is now off"
    transition PumpOff - BelowLower -> PumpOn
    transition PumpOff - WithinLimits -> IG
    transition PumpOff - AboveUpper -> IG

    state PumpOn {} {
        chan puts "[self] is now on"
    transition PumpOn - BelowLower -> IG
    transition PumpOn - WithinLimits -> IG
    transition PumpOn - AboveUpper -> PumpOff

# This class adds some variables and compares the new value of limits
# in order to signal the right event.
oo::class create ::reactorPump {
    superclass ::pump_operation

    constructor {{lower 10} {upper 100}} {
        my variable lLimit
        set lLimit $lower
        my variable uLimit
        set uLimit $upper

    method evalConcentration {conc} {
        my variable uLimit
        my variable lLimit
        if {$conc < $lLimit} {
            my signal BelowLower
        } elseif {$conc > $uLimit} {
            my signal AboveUpper
        } else {
            my signal WithinLimits

# Create an object
reactorPump create pump1
# We want to see the trace
pump1 loglevel info
puts "Initial state: [pump1 currentstate]"

# This sequence just increments a variable to show
# how an asychronous measurement would be reported into
# the "::pump1" object. Here, every second a new concentration is
# fed in.
set conc 0
proc raiseConcentration {who value} {
    global conc
    $who evalConcentration $conc
    incr conc $value
    if {$conc > 100} {
        set value -20
    } elseif {$conc <= 0} {
        set ::done 1
    after 1000 [list raiseConcentration $who $value]
# Kick things off
raiseConcentration ::pump1 20

set ::done 0
vwait ::done