diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index de8a85e3ba87d0e659d0ecb96e6457e6c48fab46..68348df5fd61850754758dba49f426712bcbc2a6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -600,7 +600,7 @@ sphinx-documentation:
   stage: documentation
   before_script:
     - sudo apt-get update
-    - sudo apt-get install -y git
+    - sudo apt-get install -y git graphviz
   script:
     - cd tangostationcontrol
     - tox -e docs
diff --git a/tangostationcontrol/docs/source/conf.py b/tangostationcontrol/docs/source/conf.py
index 9ab504856ca00dbf2c934478ec60bdece9853ad0..90b156ff1ac73a80f5a2dbc2c12d0931113eb744 100644
--- a/tangostationcontrol/docs/source/conf.py
+++ b/tangostationcontrol/docs/source/conf.py
@@ -28,6 +28,7 @@ author = 'Stichting ASTRON'
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = [
+    "sphinx.ext.graphviz"
 ]
 
 # Add any paths that contain templates here, relative to this directory.
diff --git a/tangostationcontrol/docs/source/devices/using.rst b/tangostationcontrol/docs/source/devices/using.rst
index 825ee74d83b5a7ad8a8e18c8813ee1ace81f5459..6eff9278eb74fc06a66b0d5b90f09d4f58eb0008 100644
--- a/tangostationcontrol/docs/source/devices/using.rst
+++ b/tangostationcontrol/docs/source/devices/using.rst
@@ -25,6 +25,33 @@ The state of a device is then queried with ``device.state()``. Each device can b
 - ``DevState.FAULT``: The device is malfunctioning. Functionality cannot be counted on.
 - The ``device.state()`` function can throw an error, if the device cannot be reached at all. For example, because it's docker container is not running. See the :ref:`docker` device on how to start it.
 
+
+.. graphviz::
+
+    digraph finite_state_machine {
+        fontname="Helvetica,Arial,sans-serif"
+        node [fontname="Helvetica,Arial,sans-serif"]
+        edge [fontname="Helvetica,Arial,sans-serif"]
+        rankdir=LR;
+        node [shape = doublecircle fixedsize=true width=0.7]; off;
+        node [shape = circle fixedsize=true width=0.9];
+        init -> off [label = "user", color="red"];
+        standby -> off [label = "user", color="red"];
+        on -> off [label = "user", color="red"];
+        alarm -> off [label = "user", color="red"];
+        off -> init [label = "device", color="green"];
+        init -> standby [label = "device", color="green"];
+        standby -> on [label = "device", color="green"];
+        on -> alarm [label = "device", color="green"];
+        init -> fault [label = "device", color="green"];
+        standby -> fault [label = "device", color="green"];
+        on -> fault [label = "device", color="green"];
+        alarm -> fault [label = "device", color="green"];
+        fault -> init [label = "user", color="red"];
+        fault -> off [label = "user", color="red"];
+    }
+
+
 Each device provides the following commands to change the state:
 
 :boot(): Turn on the device, and initialise the hardware. Moves from ``OFF`` to ``ON``.
diff --git a/tangostationcontrol/requirements.txt b/tangostationcontrol/requirements.txt
index b65be92168032276a4120804d581d4bc95e6c028..6bb820aeaa883e039ee012e46d6025b98f9cbc5c 100644
--- a/tangostationcontrol/requirements.txt
+++ b/tangostationcontrol/requirements.txt
@@ -13,4 +13,6 @@ docker >= 5.0.3 # Apache 2
 python-logstash-async >= 2.3.0 # MIT
 python-casacore >= 3.3.1 # LGPLv3
 etrs-itrs@git+https://github.com/brentjens/etrs-itrs # license pending
+# numpy must be manually added even though etrs-itrs requires it
+numpy >= 1.21.0 # BSD
 lofarantpos >= 0.5.0 # Apache 2