Drawing State Charts and Code Generation
1. Getting Started
2. Drawing
3. Generating Code

1. Getting Started

Before you can start drawing, there are two preliminary steps required:

1.1 Install UMLet

Download and install version 14.3 of the stand-alone version of UMLet from https://www.umlet.com and note the directory you install it to as you'll need that in the next step.

1.2 Copy the Custom UML Template for OOSMOS

Copy the OOSMOS symbol palette from oosmos\UMLetPalette\OOSMOS.uxf to the palettes directory under your UMLet installation directory. Once you've done this, you can open UMLet and select OOSMOS in the palette pane in the UMLet application window.
The OOSMOS symbol palette looks like this, and you'll be dragging these symbols into your state chart drawing.
OOSMOS Template

2. Drawing

2.1 Draw the State Chart using UMLet

In UMLet, you drag symbols from a symbol palette onto the drawing area and then supplement the symbol with ASCII properties in the Properties pane of the same window.
For example, referring to the state chart below, note the LED state. The corresponding properties for that state are in the snippet that follows the state chart, which holds the attributes for that state including the name of the state and the code to execute when certain OOSMOS events occur.
UMLet will automatically place the default name state into the Properties pane. Change this default name to one appropriate for your state. Click any symbol on the drawing area to highlight it and then edit its attributes inside the Properties pane.
You'll also notice the valign=top line. This is required by UMLet in order to properly format the state.
Typical State Chart - oosmos\Examples\Ortho\Windows\OrthoThreads.uxf
1
2
3
4
5
6
7
8
 
// REQ: (SR28)
LED
--
POLL:
BlinkingThread(pOrtho, pState);
valign=top
 
Properties for the LED State

2.2 State Chart Symbols

2.2.1 States

State Symbol
At a minimum, the properties of a state UML element must have the state name followed by a line that starts with two dashes (--) followed by a line that directs UMLet to vertically align the text at the top of the state box (valign=top).
Optionally, the properties of the state can include code to execute when events occur. Each event name (e.g. ENTER, EXIT, etc.), must start in column one and its associated code must be indented by at least one space. These events must begin right after the dashed line (--).
The properties may also include a leading // REQ: (Requirement designators) that is generated as a comment in the code for requirements traceability purposes. Place this line before all other lines in the properties window for the state.
1
2
3
4
5
6
7
8
9
10
 
// REQ: (REQ10, REQ11)
StateName
--
ENTER:
printf("ENTER\n");
EXIT:
printf("EXIT\n");
valign=top
 
State Properties

2.2.2 Transitions

Transition Symbol
State transitions use the association line/arrow symbol in UMLet. UMLet represents this arrow symbol within the Properties pane as lt=->. You'll add your [event][guard][/action] on the line above it, like this:
1
2
3
4
 
TIMEOUT(5 sec)
lt=->
 
Transition Properties
Where event, guard and /action are all optional. If none of them are supplied, then the transition occurs when the state is complete.

2.2.3 Orthogonals

Orthogonal Symbol
The dashed orthogonal separator is accomplished by dragging the dashed line from the OOSMOS symbol palette into your statechart and positioning it between the sides of a state.
Only horizontal orthogonal separators are supported by the code generator. UMLet represents this horizontal orthogonal symbol within the Properties pane as lt=..
Example State with Orthogonal
1
2
3
 
lt=.
 
Orthogonal Separator Properties

2.2.4 Default Transitions

Default Transition Symbol
Whenever there is more than one state in a state chart or composite state, you must specify the default state with a default transition. Drag the default transition symbol from the OOSMOS symbol palette onto your state chart. No properties are required beyond the default property supplied by UMLet.

2.2.5 Choice States

Choice Symbol
A choice state has one transition in and at least two transitions out. Each "out" transition must have a [guard] and optional /action. There must be exactly one special guard [else].

2.2.6 Final States

Final State Symbol
Final states are dragged from the OOSMOS palette to the drawing area. No properties are required beyond the default property supplied by UMLet.

2.2.7 History Pseudo States

History Pseudo State Symbols
History pseudo states are dragged from the OOSMOS palette to the drawing area. No properties are required beyond the default property supplied by UMLet.

3. Generating Code

Use the OOSMOS code generator to generate C code for OOSMOS objects from UMLet state charts.
The generator is included in the OOSMOS download and comes in two forms:
  • A node.js application, located at Gen\gen.min.js, that can run on any system that has node.js installed (version 7.10.0 or better).
  • A standalone Windows executable, located at oosmos\Gen\gen.exe, that does not require node.js.
These are the steps required to augment a C file from an UMLet state chart. Details are described in the corresponding sections that follow.
  1. Create a .json configuration file.
  2. Mark your .c file with the four OOSMOS code insertion markers EVENTS, DECL, CODE, and INIT.
  3. Run the generator.
  4. Compile the resulting .c file.

3.1 Create the JSON configuration file

The code generator is driven by a JSON formatted configuration file with the following TypeScript interface schema:
1
2
3
4
5
6
7
8
9
10
11
interface iConfig
{
enabled?: boolean;
uxf_filename: string;
filename: string;
type: string;
object_ptr: string;
thread_events?: string[];
queue_size?: number;
debug?: boolean;
}
Schema for Code Generator Configuration File (TypeScript format)
Example:
1
2
3
4
5
6
7
8
9
10
11
[
{
"enabled": true,
"uxf_filename": "Control.uxf",
"filename": "control.c",
"type": "control",
"object_ptr": "pControl",
"queue_size": 3,
"debug": true
}
]
classes.json
  • enabled - (optional) If specified, must be either true or false. true is the normal case where this file will be processed. Use false to disable code generation for this file.
    Optional -- defaults to false.
  • uxf_filename - The UMLet filename that holds the State Machine.
  • filename - The relative path of the filename into which code will be inserted.
  • type - The type of this file's object.
  • object_ptr - The name of the variable to be used to hold a pointer to an object's instance.
  • thread_events - (Optional) Events are generated automatically from the events found in your state chart. However, some events don't appear in your state chart -- only within State Thread functions, so there is no reliable way for the generator to "see" these event names, so you must supply events such as these in this entry. If thread_events is not specified, then no additional events will be generated.

    Optional -- defaults to [].
  • queue_size - (optional) Specifies the size of the object's event queue. A size of 0 will create a state machine with no queue. If queue_size is not specified, then no queue will be generated.

    If you specify a non-zero queue_size, you must create a local typedef called uEvents that is a union of all the event structures that can be delivered to this object. If only simple types are delivered, include oosmos_sEvent as the sole member of the typedef.

    uEvents Example:
    1
    2
    3
    4
    typedef union {
    oosmos_sEvent Event;
    // Add other event types delivered from this or other objects.
    } uEvents;
    uEvents Type Example
  • debug - (Optional) Tells OOSMOS to display state entry, exit and event occurrences to stdout for this object. Defaults to false if not supplied.

3.2 Add insertion markers to your .c file.

During code generation, all the code in your .c file remains untouched other than code between the OOSMOS generator’s four special markers where the appropriate code will be inserted from the State Chart drawing. Those special markers are EVENTS, DECL, CODE, and INIT prefixed by the characters //>>> to begin the group and ///<<< to end it. Correct placement of the markers is vital. See below.

Note that the code generator has an option, --init, that creates an empty OOSMOS class template for both .h and .c to use as a starting point that has the insertion markers in the appropriate locations in the .c file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "oosmos.h"
#include "control.h"
 
//>>>EVENTS
The event enumeration will be generated here.
//<<<EVENTS
 
struct controlTag
{
// Members...
int m_Member;
 
//>>>DECL
State machine declarations will be generated here.
//<<<DECL
};
 
static void LocalFunction(control * pControl)
{
pControl->m_Member += 1;
}
 
//>>>CODE
State machine event handling functions will be generated here.
//<<<CODE
 
extern control * controlNew(void)
{
oosmos_Allocate(pControl, control, 1, NULL);
 
pControl->m_Member = 0;
 
//>>>INIT
State machine initialization code will be generated here.
//<<<INIT
 
return pControl;
}
 
Marker Substitutions in a .c File

3.3 Run the Generator

On Windows, you can elect to use the Windows executable, oosmos\Gen\gen.exe, if you would rather not install node.js.
1
2
3
 
oosmos\Gen\gen.exe classes.json
 
Running the generator on Windows
If you have node.js installed (on any platform), you can run the generator with this command:
1
2
3
 
node oosmos\Gen classes.json
 
Running the generator using node.js

3.4 Compile

Once the code has been generated, your program is ready to be compiled for your target platform.
Copyright © 2014-2024  OOSMOS, LLC