graphviz state machine with self loops

512 Views Asked by At

I am trying to create a state machine diagram using graphviz and I am having trouble making it display nicely.

This is the diagram described in dot language:

digraph finite_state_machine {
    node [shape = point];
    PWRON

    node [shape=circle];
    PWROFF [fontsize=10]

    PWRON  -> BOOT     [label="start_boot_timer"]

    BOOT   -> HOME   [label="boot_timer_expires"]
    HOME   -> HOME   [label="home to home 1"]
    HOME   -> HOME   [label="home to home 2"]
    HOME   -> HOME   [label="home to home 3"]

    HOME   -> BLEADV [label="short_button_press"]
    BLEADV -> BLECON [label="ble_conn_event"]
    BLECON -> HOME   [label="ble_conn_close"]

    HOME   -> PWROFF [label="power off"]
}

The drawn diagram looks like:

The drawn diagram looks like this

I am a complete newbie in dot/graphviz, can you help me present it better?

The main problems currently are:
* the self loops from home to home all overlapping
* the placement of BLEADV and BLECON is not very good (lesser priority)

2

There are 2 best solutions below

0
On

To improve the loops on HOME, you may use compass points:

HOME:s   -> HOME:n   [label="home to home 1"]
HOME:s   -> HOME:n   [label="home to home 2"]
HOME:s   -> HOME:n   [label="home to home 3"]

Not sure what you'd like to improve about the placement of the nodes, but if you'd like to have a straight vertical edge between HOME and PWROFF, just assign them to the same group (before defining edges involving them):

HOME[group=a]
PWROFF[group=a]

All together:

digraph finite_state_machine {
    node [shape = point];
    PWRON

    node [shape=circle];
    PWROFF [fontsize=10]

    PWRON  -> BOOT     [label="start_boot_timer"]

    HOME[group=a]
    PWROFF[group=a]

    BOOT   -> HOME   [label="boot_timer_expires"]
    HOME:s   -> HOME:n   [label="home to home 1"]
    HOME:s   -> HOME:n   [label="home to home 2"]
    HOME:s   -> HOME:n   [label="home to home 3"]

    HOME   -> BLEADV [label="short_button_press"]
    BLEADV -> BLECON [label="ble_conn_event"]
    BLECON -> HOME:w   [label="ble_conn_close"]


    HOME   -> PWROFF [label="power off"]
}

improved layout

0
On

This uses a different set of attributes:

digraph finite_state_machine {
    //splines=false // probably not

  subgraph cluster1 { 
    peripheries=0

    PWRON  [shape = point ];
    node [shape=circle];
    //node [shape=rect];  // see if you like a different shape
    PWROFF [fontsize=10]

    PWRON    -> BOOT      [label="start_boot_timer"]

    // changes: ports, headlabels, tail labels, spaces, and newlines
    //          cluster was added to (partially) straighten the column
    BOOT     -> HOME      [label="boot_timer_expires"]
    HOME:w   -> HOME:sw   [headlabel="home to home 1      " ]
    HOME:n   -> HOME:nw   [taillabel="home to home 2     \n\n" ]
    HOME:n   -> HOME:e    [label="home to home 3"]

    HOME:s   -> BLEADV    [label="short_button_press"]
    BLEADV   -> BLECON    [label="ble_conn_event"]
    BLECON   -> HOME:se   [label="ble_conn_close"]

  }
  PWROFF
  HOME:s   -> PWROFF    [label="\npower off  " ]
}

Producing this: enter image description here