aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/design.md86
-rw-r--r--docs/fig.drawio2
-rw-r--r--docs/img/blender_node_editor.pngbin0 -> 69812 bytes
-rw-r--r--docs/img/fig-architecture-lv1.svg3
-rw-r--r--docs/img/fig-architecture-lv2.svg3
-rw-r--r--docs/img/fig-architecture.svg3
-rw-r--r--docs/img/figma_ui_automations.pngbin0 -> 322285 bytes
-rw-r--r--docs/img/figma_ui_menu_bar.pngbin0 -> 396145 bytes
-rw-r--r--docs/img/figma_ui_node_overview.pngbin0 -> 280762 bytes
-rw-r--r--docs/img/qt_ui_automations.pngbin0 -> 33434 bytes
-rw-r--r--docs/img/qt_ui_menu_bar.pngbin0 -> 18108 bytes
-rw-r--r--docs/img/qt_ui_node_overview.pngbin0 -> 16125 bytes
12 files changed, 82 insertions, 15 deletions
diff --git a/docs/design.md b/docs/design.md
index e1ef1cc..eea59c3 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -1,6 +1,6 @@
# General system architecture
-![System architecture](img/fig-architecture.svg)
+![System architecture (level 1)](img/fig-architecture-lv1.svg)
Above is a diagram that shows the component layout of the end product. Notable
details are:
@@ -10,19 +10,18 @@ details are:
Bluetooth mesh was chosen because it provides an abstraction layer between
the node behaviour and low-level bluetooth protocol routines.
-- The use of a J-Link debugger for connecting the border router node to a
- desktop computer running the configuration utility.
-
- The use of the J-Link debugger was chosen because it requires no additional
- USB controller setup on the node side to communicate.
-
- Because the network should continue functioning even without the
+- Because the network should continue functioning even without the
configuration utility connected to the border router, all network
configuration (which buttons control which lights) is stored on the border
router. The configuration utility is only a 'viewer' for the network with
features to edit the configuration and node state, but all action handling is
happening on the nodes.
+## Detailed system architecture
+
+Below is a slightly more detailed version of the system architecture:
+
+![System architecture (level 2)](img/fig-architecture-lv2.svg)
# Framework
@@ -116,15 +115,80 @@ A complete list of commands and the additional data they send is located in the
The protocol implementation is written in portable C, and is used by both the
client and server side to send and receive data.
-# Asynchronous QT Serial port
+# QT GUI
+
+## UI/UX layout
+
+The current layout implemented in the QT GUI was chosen based on the following
+criteria during a brainstorming session:
+
+- The complete network state should be visible at a glance
+- Less information based on a specific context is good
+- More abstraction from the actual network functionality is good
+
+The ideas that were considered during the brainstorming sessions were:
+
+1. A two column layout, with each list containing nodes. The right list is
+ contextual, and shows the light(s) that the node selected in the left column
+ is currently controlling.
+
+ This idea was scrapped because it scales poorly in networks with a high
+ number of nodes, and because it hides a lot of information due to a context
+ specific list.
+2. A node editor layout, like the shader editor found in blender (see figure
+ below). Node buttons/lights can be connected with wires or lines, and nodes
+ can be grouped visually into clusters.
+
+ ![Node editor in Blender](img/blender_node_editor.png)
+
+ This idea was scrapped due to significant implementation complexity.
+3. A layout with two tabs, (1) for managing node state directly and
+ provisioning, and (2) for managing button and light publish/subscribe
+ addresses for linking nodes together.
+
+ While this design would not show the complete network state at a glance, it
+ would be easier to implement than option 2, and scale better than option 1.
+
+After continuing the brainstorming session, focusing on the third design idea,
+we came up with the following list of design specifications:
+
+- A global tabbed layout with tabs for (A) managing *individual* nodes, and (B)
+ managing actions *between* nodes.
+- Actions between nodes are abstracted to the user as "automations", which
+ simplifies the process of asigning publish/subscribe addresses down to
+ "button of device A does X to light on device B".
+- Nodes are displayed in the node list, even if they are not provisioned into
+ the network, mirroring the way a bluetooth pairing menu might look.
+- The act of provisioning a node into or out of the network is abstracted as
+ "pairing" and "unpairing", mirroring the way regular bluetooth devices work.
+- Only relevant controls for nodes are shown (e.g. light toggle is hidden when
+ node is not provisioned, because controlling the light would be impossible).
+
+A prototype version of this layout was then made using Figma:
+
+![QT UI prototype in Figma (node tab)](img/figma_ui_node_overview.png)
+![QT UI prototype in Figma (automations tab)](img/figma_ui_automations.png)
+![QT UI prototype in Figma (menu bar)](img/figma_ui_menu_bar.png)
+
+The end result is the current UI, shown in the following figure. The only
+feature from the Figma prototype that was not implemented in the QT version, is
+the toggle switch UI element as the only toggling UI element available in the
+default QT widget selection is a checkbox, which serves the same purpose in
+this case.
+
+![QT UI (node tab)](img/qt_ui_node_overview.png)
+![QT UI (automations tab)](img/qt_ui_automations.png)
+![QT UI (menu bar)](img/qt_ui_menu_bar.png)
+
+## Asynchronous serial port
The serial data communication is done in an asynchronous manner, which allows the program to efficiently handle data that is arriving on a serial port.
-## Benefits
+### Benefits
Using an asynchronous approach allows the program to efficiently handle incoming data from the serial port, while still allowing the UI to remain responsive. This also prevents the program from having to continuously poll the serial port to check for new data. Without an asynchronous approach, this could freeze the UI and consume a lot of CPU resources. By using an asynchronous approach, the application can handle incoming data as soon as it arrives, without blocking the UI or consuming excessive CPU resources.
-## Data processing
+### Data processing
When new data arrives at the serial port, it sends out a "ready read" signal. This signal tells the Qt event loop to call the asynchronous serial data read function, which processes the data at the next available opportunity. This ensures that the data is handled efficiently and asynchronously, without blocking the UI or consuming excessive CPU resources.
diff --git a/docs/fig.drawio b/docs/fig.drawio
index 19a86e6..1d53c35 100644
--- a/docs/fig.drawio
+++ b/docs/fig.drawio
@@ -1 +1 @@
-<mxfile host="Electron" modified="2023-01-17T19:38:40.650Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.7.4 Chrome/106.0.5249.199 Electron/21.3.3 Safari/537.36" etag="vHeCIsdALQldInCo5Wv6" version="20.7.4" type="device" pages="3"><diagram id="TQBjHMX74tOWVntnVVwY" name="architecture">5VnRcps4FP0az7QPyYAA4zzGjpNtJztN683s9lGAjFUL5BUitvv1K4EAgzAhMWnq2Twk0pUQ0rnn3ntERtYs2t0xuFn9SQNERsAIdiPrZgSA49ritzTsc4PtuLkhZDjITWZlWOCfSBkNZU1xgJLaRE4p4XhTN/o0jpHPazbIGN3Wpy0pqb91A0OkGRY+JLr1bxzwVW6dOEZl/wPhcFW82TTUSASLycqQrGBAtwcmaz6yZoxSnrei3QwRiV2BS/7c7ZHRcmMMxbzPA5sr98f3zfzT3Hc8tv3yiL7N+YU5yZd5giRVJ/ZES0Asdi8OgRL5J0Z8S9lanYPvC3AYTeMAyfXNkTXdrjBHiw305ehWsEHYVjwiahgSHMaiTdBS7HdKoIfIA00wx1SafXEMxMTAE2IcCwfcNyZ4lHMaHUy4VgtyKt+0xITMKKFiiZuYxmIP04QzukaFcQQsI/sRI1TsEnNJSVd2IfMV84Atu15CScrRdWmW+w9gsirPKjsPkIsdx5kFGNKqu0R5SW4Z7Q5MykV3iEaIs72YUowqtuzr3W3FPTBWttUB78TZFOcV38Ny5YoSoqFY8QKGWK7GkOlfJTUahECBCB7VpYyvaEhjSOaVdVpRJvNDOeeeSi9m2P5AnO8V8DDltE4jFAfXMq4rNwvLLZaHypZExMsGC5Y0Pdft+qMeTGjKfNSB01glJ8hCxDvmKTglUp18YIhAjp/qaWhw744158Yig3cEutEj0PtE0wChAhqhMtFjxTRbYsV5q1AxdTR/61DpiouWMBosVNyeoWL2DBXFhwvj0gYT5YPe4aOWe6BYHKNcy3YaabjBmXzv6qGKNgJuuD+YtpETkuOvceuvcY0GB/P1Gs8Wi9PlMkF81GRtCczriayn/PPNCsZ7ZwVga2jOaLzEYcpgJm2AkXJMZOyBMZHSyGOiFcrWh2xYCOC1FDlS5UYbARr7eJoUe732KkQcy4E7osUavm6W3HeUV2DSgx5WCz1KzgxfNY4Em8YF8WZgeJQFwlUiwdH/LxFatH52kin012EGQDEaoCVMMyAHII/p1MkDeqYWrXoMxx3nXXTFDvN/5OOXjup9L8S3aN/sDjv7ovOMFhlMXNg9xQXoKS5eJiReKgDKe1vxeaRDAQxV3fV6RDKunkd5b1yQW0S/3RKCb3c91sD0UpEi4/NA0xz/XmgCvRZ+u3XAZLc7TzwtHc+rX4mnqdNTLxhaZj4Aro7yqxL/s/VosNRvDZz6D7zmdNwYTrxqmpPxJajfA8cNPuQn126bejWxx5fjwx+rtmxTwg50iS1TRGsNe+H0k0veBJnh02IWfTUmrvk1/PenPbtqKXmPi6mkFGIYknfRUM/ooROiwNHDoBWUwRXQaYXU0XxUeMfYCIDz22+UxuKWkV+bz6EglOm+CMGWD/pv9jmi1ev6ddNvfI24e/x0puC6PcEdot62gmudbSrpyhC//i51khN0Efn54h7H65H8kualYSi/n5wjv1vU5FD0Ft3qP9F51a3+nW/N/wM=</diagram><diagram id="rUv2yiT5bNfH3vxD9CJS" name="demo">3VdNb9swDP01Pm7wB+Jm1yZZd8iAARnQ7ajarK1VMT1Fju3++tERHUc10DVLh6Q9WXymaOrxiZK9aLZubrQo86+YgvJCP228aO6FYRCFMT06pLXI1Gcg0zJlpwFYyUdg0Ge0kilsHEeDqIwsXTDBooDEOJjQGmvX7R6V+9VSZDACVolQY/RWpiZnNIg/DS++gMxy/vQ0vLIv1qJ35pVscpFifQBFCy+aaURjR+tmBqojr+clb33h423xezkN7rKrx/q7ePhgg30+Zsp+CRoK87qhpzb0VqiK+eK1mrYnEFLik03UJscMC6EWA3qtsSpS6D7jkzX4LBFLAgMCf4ExLYtDVAYJys1a8Vtalm5/dPM/TnrzJ4fbGfPGsVq2bK5dgk9q/Rei2G+DlU7gGT8mwwidwXPxor0aaBsBroGSpHkalDBy6yYnWM/Z3m8/9RtKSjv0ee9NWHe88YKp70awafGkofA0OMhigHZyOEZ1wXml4Ahh0MWFSyE+UQpOFY8tWTjazXPYEvAgSSGxoryv7zSNsm40U7KjZoSvammSfFx7pahldzWuc2lgVYodXzWdGm4Fxaa0ffxeNp0SuDRb0AaafyjOmMz6oI/7vCnygxa+B1+d4OgYglegadFjfLnL9IL55YZDh7+Ncz6+g4s6joIz96DJW+hBvWjOVLLAu6hj46UlO/UGcVLJJuOuhkVGhXlHZwZHCWP3UnUBPS5+Mftv9kB5Sv7/IJvM4VfM3oGHH9po8Qc=</diagram><diagram id="zfEZus7OmDisMN2gApZM" name="protocol">5ZjRbtowFIafJtJ2UWQnBMIlsHabtknVqmmXk0tOE68mjhzTwp5+J9ghCYZRWIG14wLZv+1j55yP34AXjKfz94rl6RcZg/B8Es+94J3n+91+hO+lsDBCEFEjJIrHRmoIN/wXWJFYdcZjKFoTtZRC87wtTmSWwUS3NKaUfGxPu5OivWvOEnCEmwkTrvqdxzo1ahSSWv8APEmrnSmxI1NWTbZCkbJYPjak4NILxkpKbVrT+RhEmbsqL2bd1ZbR1cEUZPopC35ItUjVR7j61LuIZPiteODhhY3ywMTMPvBY8DKgObJeVHnA0+dlczYVn/kdCJ5hb5SD4lPQoHBEWPm61kZYFc1QK8fpsi8Eywt+uwxLUFEwmamCP8BXKEzxl6qcZTHEtrfK3LKjlbxf1aIMatf55ah9HFAa5lvzRFfZR2pB4mHVAqc81vXt2ZqljdIGVWWZRSpZLa2zjg2b+D2K4DtFuAGFz/A/FqFa0LfJPltRAqcoXjjqeSG2iIIil1kB2HyTAX5YyE/JM8/HnYi8f+vUrUwFR08ZCp5kKN1KreUUMwVZPCxNCjWZAw6NYlaky5xTM2wdMdpdAbMrxI6freUcTyZnagK7gdRMJaB3uYdbQwWCaaSpbcYbCmSXXmPydF37MDQr7I3hB7QzaL7a8cwhbYim/a1Fxbj7hDU5csJitdiiMS0vJxTbn4V2SXvXfsuksWEi1pyu8ng4ut1N6PoG3SauB1B6K+Tk/qQsVpf+Lhb9U7AYkQ5pvCg9DTT+CaAJN0HTLaEZ+96Q5DxLXggxZ3avQWeA3w/7tGveu22C6PqFtYUZ17+CQWdHqC1WuDd+vTZ+p7Cs3ib6iHvbGgxfyz17Zm/7M6n+E/F6AqlOqCMZ5eAEpPY3kUoNqcnycs3wN/ALscp/G0D6bFbphHouq1wDsOoflcBoE4Gh65VNGl+LY573bj/8Dj7W14S9gQ3XgP27yx279R9YZnr9L2Bw+Rs=</diagram></mxfile> \ No newline at end of file
+<mxfile host="Electron" modified="2023-01-23T15:54:32.926Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.7.4 Chrome/106.0.5249.199 Electron/21.3.3 Safari/537.36" etag="lVwbV1NkXNzKCbfOQqtS" version="20.7.4" type="device" pages="4"><diagram name="architecture-lv1" id="dWg040635boJ6XjAoByq">3VhLc9owEP41zLSHdvzi0WMgpD0kGabp45gR9mKryF5GlgPk13dly3ZsE0IeJG04gPRptdLufrte3HMn8earZKvoAgMQPccKNj33tOc4I2tE3xrYFoD3pV8AoeRBAdk1cMVvwYCWQTMeQNoQVIhC8VUT9DFJwFcNjEmJ66bYAkXz1BULoQNc+Ux00d88UJExq2/V+DfgYVSebFtmJWalsAHSiAW4vgO50547kYiqGMWbCQjtu9IvZ7fJhbJOf1zPfn0X15e3l8up/alQdvaYLZUJEhL1sqqdQvUNE5nx15xGFCCynVwAqf5JQK1RLo0X1LZ0rcQsCUCrt3vueB1xBVcr5uvVNXGJsEjFwiwzwcOExgIWZMNYsDmIGaZccdSwLEIwvgGpOEXvvLUe8yDQ51YCJ0bfHJXCmBYWXIgJCpQEJpho2VRJXEIJ9hzXyj+0gnRPrjSlh3rKpG+Y63h6Ok9RZApOKlhbELA0qqzVkxlTCmSSI46lUeNNuiJsWvR7IHZ2RShKRMAYlNzSvlKLoeC2OV3XhLZdg0V3yOyUXGYmicJKc00UGhiuPII3boc34x8VYVo0gYAS0kxRqghDTJiY1ui4JlIem0rmHHFl/P0HlNqaYLBMYZNckAQnulbUoSfkjGubcpUg5vliSZ52NPfTobBIm/GEmJIrMJM+7JHzTFlkMoR9+ga7OSJBMMVvmpd78Yh7nYgn9KjYUxOsA2rCIWl3rJxyWjk17CbVaEdOucdKqf7/lVL78mdHur1ySg0OTKnRM1PKbJ0hp2tX1PL6rXLd4kxxLbOppg35m23viK20QHr/MYMmg0et5/9jpGlQnN7aW14FF4sUVK/N8cplT6f94L3XFeuN68qw4+AJJgseZpLlvZVjZYoLnb3OQOgWbC5pFOrRh3yZ2veloqqhe/R4RX6UH58Xnnbv55O7QR7S/JVNZGdH2Q3Wkm9KgRYHnAP7Ne9YHBjdk2SdgNPJjjVHGZB3qQzie4r2jj8I+d3GzF+GuUnlagALluWueaUisYsg9msSxO62dz+vxjrqIDk9wP/BBuTYLcTwTVsI1+t/tpxRf2h7xfew+VSxW0wozOm0FB29Tr/JvLJVeeHWxLGbLZC3p9t4uJOgaf2apRCv31W5078=</diagram><diagram id="TQBjHMX74tOWVntnVVwY" name="architecture-lv2">5Vlbc9o4FP41zGwfmvEd8hgISTvTnU1LM90+ClvYaoTFynKA/voe2fJVhjiJs5QpD4l0JOvyne/c7JE9W+9uOdpEf7MA05FlBLuRfT2yLG9sw18p2OcCx1SCkJMgF5mVYEF+YiU0lDQlAU4aEwVjVJBNU+izOMa+aMgQ52zbnLZitLnrBoVYEyx8RHXpNxKIKJdOXKOSf8AkjIqdTUONrFExWQmSCAVsWxPZ85E944yJvLXezTCV2BW45M/dHBgtD8ZxLPo8sLkc//i+mX+c++6Sb/+5x1/m4r05yZd5RDRVN15CCyCG08MlcCL/xVhsGX9Q9xD7AhzO0jjAcn1zZE+3ERF4sUG+HN0CG0AWiTVVw4iSMIY2xSs475SiJaZ3LCGCMCn24RqYw8Aj5oKAAj61JiyZEGxdm3ClFhRM7rQilM4YZbDEdcxiOMM0EZw94EI4smwj+8EIg1MSISk5ll3EfcU8y5HdZcJoKvBVKZbnD1ASlXeVnTsk4MRxJrEMKdVVorQkj4x3NZFS0S1mayz4HqYUo4ot+2Z3W3HP8pQsqvEO7qY4r/gelitXlICGYsUzGGKPNYZMv5bUaBECB2A8qsu4iFjIYkTnlXRaUSbTQznnE5NazLD9gYXYK+BRKliTRjgOrqRdV2oGyQ2Rl8qWxHSZDRYsaWvuuOoPajBhKffxEZw85ZwQD7E4Mk/BKZE6ygeOKRLksemGBteupyk3Bg9+xNCNHobex5oGMBWrZSoT3VZMs8NW3LcyFVNH87c2lWN20WFGg5nKuKepmD1NRfHhvXHhWBOlg97mo5a7YwSuUa7luC033OJMfnb1UEUbgBvta9M2ckJyeJtxc5ux0eJgvl7r2WJxtlolWIzarC2BeTmRdZd/vl7BOLVXgOu20ZyxeEXClKMstbGMVBAqbc/yqEyNlhxaoWz9lQ1DAvwgkxyZ5a43ABp/97pU7OW5V5HE8Ry4A7lYS9ftkHvC9Mqa9KCH3UGPkjPDR40DxqZxAXa2jCXjAagKHBz7c4nQketnN5ki/yHMAChGA7xCaQbkAOQx3SZ5rJ6uRYsew3HHPUlesSPiX/n4hat634vkG9rXu3pnX3SeyEUGSy6cnsmF1TO5eF4i8dwEoKzbitcjRzKAoaK7Ho9oxtXzCO+tArkj6Xc6TPDtymMNzGUKLjI+DzRN7/dC09Jj4Zcb15rsdueJp63jefl/4mnq9NQDhuaZa8A1UX6R438yHg3m+u2BXX9Na+6RiuGVpaY58S6sZh3otfiQ31yrNvVo4ngXXv1nN5Ztp7ADFbGli+iMYc+c/uqQN8Fm+LiYrT8bk7H5OfzvpzO77Ah594uppBTmBNGT5FBP5EOvsAL3pBmQpm+79S7FeRsWatu4g9LqKNQ1XhWMMjZAirxiX6cxVEZ5qX8OQawMUYXb6PgI8WavUDrNVy+R/dYblNv7j2cK7rgnuC/IEaBbfV7MOV99o7XnvwA=</diagram><diagram id="rUv2yiT5bNfH3vxD9CJS" name="demo">3VdNc5swEP01HNtBEBN6je2kB3emM3Qm7VGBDSiRWSoLA/n1FWYxqMx47KlbOz2hfVp97NunlXD8+bp+ULzIvmAC0vHcpHb8heN57IbdmE+LNB0SBrcdkCqRkNMAROINCHQJLUUCG8tRI0otChuMMc8h1hbGlcLKdntGaa9a8BQmQBRzOUUfRaIzQlnwaej4DCLNaOnQo/jWvHemSDYZT7AaQf7S8ecKUXetdT0H2ZLX85I1LnfxMf+5CtlTevtWfeOvH7rJ7k8Zsg9BQa7PO3XYTb3lsiS+KFbd9ARCYvgkE5XOMMWcy+WA3iks8wTaZVxjDT4rxMKAzIAvoHVD4uClRgNlei2p14Slmu/t+I+z3vxB0+2MRW1ZDVlH8kL8bbBUMRzwo9g1Vykcms/v/FpiRhoj1h8A12A2aRwUSK7F1hYiJz2ne7/90K8oTByeS2dvRrqjg8dC156h2ycNGhJvGqNdDNBODqeojl1WCpYQBl1clxSCc0vByuKpKfMmp3kBWwO8CqOQQJpA7p6UaaVtay5Fy9UEjyqh42yaeylNyW5zXGVCQ1TwHYGVuTXsDPJN0dXxZ1G3SjgxNVtQGuqDZFajOu7SochGJXwPnp1g/xSCI1AmmCm+2u30ivmlguMxCvdyfLOruo7Yv61Bs3dZg3rRXChlzLnktXFsys7+gvijlM2mVQ3z1CTmP7ozqNcL7EfVFdS44Gj23+2F8jv5f4NsYw6/Yt0bePih9Ze/AA==</diagram><diagram id="zfEZus7OmDisMN2gApZM" name="protocol">5Zhdb9owFIZ/TaTtoshOCB+XwNpu2iZVq6ZdToacJl5NHDnma79+J9ghCYZRukKpxkVkv7ZPnHMeXkO8YDRd3iqWJV9lBMLzSbT0gg+e73e6AV4LYWWENrVCrHhkJFoJ9/w3WJFYdcYjyBsTtZRC86wpTmSawkQ3NKaUXDSnPUjRvGvGYnCE+wkTrvqDRzoxai8klf4ReJyUd6bEjkxZOdkKecIiuahJwbUXjJSU2rSmyxGIIndlXsy6mz2jm40pSPVTFvyUapWoT3DzuXPVk+H3fM7DKxtlzsTMPvBI8CKg2bJelXnA3WdFczYVX/gDCJ5ib5iB4lPQoHBEWPmu0oZYFc1QK8bpui8Ey3I+XoclqCiYzFTO5/ANclP8tSpnaQSR7W0yt+5oJR83tSiC2nV+MeompXxCUBqWNckm6RYkblatcMqiqm/H1iyplTYoK8ssUvFmaZV1bNjEH1EE3ynCPSjc8P9YhHK0a5P9akUJnKJ44bDjhdgiCvJMpjlg810K+GUhvyRPPR/vROTje6duxXNz9JSB4HGK0lhqLaeYKUijQWFSqMkMcGgYsTxZ55yaYeuIvcMV2Jv1XM7UBA7zp5mKQR82C4galunWUIFgGmlqmvGOAtmld5g8XdU+DM0Ke2L4AW31659mPLNrG6Juf1tRMe4xYU3SnLBYLbaqTcuKCfn+Z6Ft0rxrt2HS2DARK043eXw+uu1d6PoG3Tquz6B0LOTk8ZQslmf8IRb9V2GxR1qk9qH0PND4Z4Am3AVNu4Bm5HsDkvE0vkxiLs29+q0+/j7s0ra5tpsE0e0Daw8zrn8F/daBUHus8Gj8Ok38zmFZnV30Efe0NRi+0XP20rzt76T6T8TrCaQ6oU5klP0zkNrdRSo1pMbrwzXF/8CXaZVvDED6YlbphHopq9wCsOyflMDeLgJD1yvrNL5Rx7yws/35Z/CpfiYcDWy4Bey/He7YrV5gmenVW8Dg+g8=</diagram></mxfile> \ No newline at end of file
diff --git a/docs/img/blender_node_editor.png b/docs/img/blender_node_editor.png
new file mode 100644
index 0000000..33dc529
--- /dev/null
+++ b/docs/img/blender_node_editor.png
Binary files differ
diff --git a/docs/img/fig-architecture-lv1.svg b/docs/img/fig-architecture-lv1.svg
new file mode 100644
index 0000000..a1994a0
--- /dev/null
+++ b/docs/img/fig-architecture-lv1.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="341px" height="201px" viewBox="-0.5 -0.5 341 201" style="background-color: rgb(255, 255, 255);"><defs/><g><rect x="0" y="0" width="130" height="200" rx="12" ry="12" fill="none" stroke="#000000" stroke-opacity="0.7" stroke-dasharray="1 1" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-start; width: 132px; height: 1px; padding-top: 197px; margin-left: 132px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bluetooth mesh network</div></div></div></foreignObject><text x="132" y="197" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">bluetooth mesh network</text></switch></g><path d="M 50 160 L 50 120" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 140px; margin-left: 50px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BT mesh</div></div></div></foreignObject><text x="50" y="143" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BT mesh</text></switch></g><rect x="10" y="160" width="80" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 175px; margin-left: 11px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">node</div></div></div></foreignObject><text x="50" y="179" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">node</text></switch></g><path d="M 50 90 L 50 70.03 L 50 50" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 70px; margin-left: 50px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BT mesh</div></div></div></foreignObject><text x="50" y="73" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BT mesh</text></switch></g><rect x="10" y="90" width="80" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 105px; margin-left: 11px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">node</div></div></div></foreignObject><text x="50" y="109" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">node</text></switch></g><rect x="210" y="10" width="130" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 30px; margin-left: 211px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Configuration utility<br />(on desktop computer)</div></div></div></foreignObject><text x="275" y="34" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Configuration utility...</text></switch></g><rect x="10" y="10" width="110" height="40" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 30px; margin-left: 11px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: normal; overflow-wrap: normal;">node<br />(as border router)</div></div></div></foreignObject><text x="65" y="34" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">node...</text></switch></g><path d="M 210 30.03 L 205.03 30.03 L 120 30.03" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 30px; margin-left: 165px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">USB serial</div></div></div></foreignObject><text x="165" y="33" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">USB serial</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file
diff --git a/docs/img/fig-architecture-lv2.svg b/docs/img/fig-architecture-lv2.svg
new file mode 100644
index 0000000..4603a16
--- /dev/null
+++ b/docs/img/fig-architecture-lv2.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="401px" height="252px" viewBox="-0.5 -0.5 401 252" style="background-color: rgb(255, 255, 255);"><defs/><g><rect x="0" y="0" width="260" height="230" rx="12" ry="12" fill="none" stroke="#000000" stroke-opacity="0.7" stroke-dasharray="1 1" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-start; width: 258px; height: 1px; padding-top: 237px; margin-left: 2px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bluetooth mesh network</div></div></div></foreignObject><text x="2" y="249" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">bluetooth mesh network</text></switch></g><path d="M 65 170 L 65 150 L 65 160 L 65 140" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 155px; margin-left: 65px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BT mesh</div></div></div></foreignObject><text x="65" y="158" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BT mesh</text></switch></g><rect x="10" y="170" width="110" height="50" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 195px; margin-left: 11px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">node</div></div></div></foreignObject><text x="65" y="199" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">node</text></switch></g><path d="M 65 90 L 65 60 L 140 60" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 60px; margin-left: 65px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BT mesh</div></div></div></foreignObject><text x="65" y="63" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BT mesh</text></switch></g><rect x="10" y="90" width="110" height="50" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 115px; margin-left: 11px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">node</div></div></div></foreignObject><text x="65" y="119" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">node</text></switch></g><rect x="270" y="90" width="130" height="110" rx="12" ry="12" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-dasharray="1 1" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-end; width: 128px; height: 1px; padding-top: 207px; margin-left: 270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Configuration utility<br />(on desktop computer)</div></div></div></foreignObject><text x="398" y="219" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">Configuration utility...</text></switch></g><rect x="140" y="10" width="110" height="100" rx="12" ry="12" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-dasharray="1 1" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-end; width: 108px; height: 1px; padding-top: 117px; margin-left: 140px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: normal; overflow-wrap: normal;">node<br />(as border router)</div></div></div></foreignObject><text x="248" y="129" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">node...</text></switch></g><path d="M 220 70 L 220 50" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><rect x="200" y="70" width="40" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 85px; margin-left: 201px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">light</div></div></div></foreignObject><text x="220" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">light</text></switch></g><rect x="150" y="70" width="40" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 85px; margin-left: 151px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">button</div></div></div></foreignObject><text x="170" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">button</text></switch></g><rect x="150" y="20" width="90" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 35px; margin-left: 151px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">nRF528xx</div></div></div></foreignObject><text x="195" y="39" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">nRF528xx</text></switch></g><path d="M 170 70 L 170 50" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 335 100 L 335 35 L 240 35" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 35px; margin-left: 320px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">USB serial</div></div></div></foreignObject><text x="320" y="38" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">USB serial</text></switch></g><rect x="280" y="100" width="110" height="50" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 125px; margin-left: 281px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">serial port communication</div></div></div></foreignObject><text x="335" y="129" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">serial port commun...</text></switch></g><rect x="280" y="160" width="110" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 175px; margin-left: 281px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">configuration GUI</div></div></div></foreignObject><text x="335" y="179" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">configuration GUI</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file
diff --git a/docs/img/fig-architecture.svg b/docs/img/fig-architecture.svg
deleted file mode 100644
index 8b65f9f..0000000
--- a/docs/img/fig-architecture.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1251px" height="803px" viewBox="-0.5 -0.5 1251 803" style="background-color: rgb(255, 255, 255);"><defs/><g><rect x="24" y="24" width="780" height="690" rx="36" ry="36" fill="none" stroke="#000000" stroke-opacity="0.7" stroke-width="3" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-start; width: 258px; height: 1px; padding-top: 245px; margin-left: 10px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bluetooth mesh network</div></div></div></foreignObject><text x="10" y="257" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">bluetooth mesh network</text></switch></g><path d="M 219 534 L 219 474 L 219 504 L 219 444" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 163px; margin-left: 73px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BT mesh</div></div></div></foreignObject><text x="73" y="166" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BT mesh</text></switch></g><rect x="54" y="534" width="330" height="150" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 203px; margin-left: 19px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">node</div></div></div></foreignObject><text x="73" y="207" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">node</text></switch></g><path d="M 219 294 L 219 204 L 444 204" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 68px; margin-left: 73px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BT mesh</div></div></div></foreignObject><text x="73" y="71" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BT mesh</text></switch></g><rect x="54" y="294" width="330" height="150" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 123px; margin-left: 19px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">node</div></div></div></foreignObject><text x="73" y="127" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">node</text></switch></g><rect x="834" y="294" width="390" height="330" rx="36" ry="36" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-width="3" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-end; width: 128px; height: 1px; padding-top: 215px; margin-left: 278px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Configuration utility<br />(on desktop computer)</div></div></div></foreignObject><text x="406" y="227" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">Configuration utility...</text></switch></g><rect x="444" y="54" width="330" height="300" rx="36" ry="36" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-width="3" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-end; width: 108px; height: 1px; padding-top: 125px; margin-left: 148px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: normal; overflow-wrap: normal;">node<br />(as border router)</div></div></div></foreignObject><text x="256" y="137" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">node...</text></switch></g><path d="M 684 234 L 684 174" fill="none" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><rect x="624" y="234" width="120" height="90" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 93px; margin-left: 209px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">light</div></div></div></foreignObject><text x="228" y="97" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">light</text></switch></g><rect x="474" y="234" width="120" height="90" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 93px; margin-left: 159px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">button</div></div></div></foreignObject><text x="178" y="97" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">button</text></switch></g><rect x="474" y="84" width="270" height="90" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 43px; margin-left: 159px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">nRF528xx</div></div></div></foreignObject><text x="203" y="47" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">nRF528xx</text></switch></g><path d="M 534 234 L 534 174" fill="none" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 1029 324 L 1029 174" fill="none" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 83px; margin-left: 343px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">USB serial</div></div></div></foreignObject><text x="343" y="86" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">USB serial</text></switch></g><rect x="864" y="324" width="330" height="150" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 133px; margin-left: 289px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">serial port communication</div></div></div></foreignObject><text x="343" y="137" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">serial port commun...</text></switch></g><rect x="864" y="504" width="330" height="90" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 183px; margin-left: 289px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">configuration GUI</div></div></div></foreignObject><text x="343" y="187" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">configuration GUI</text></switch></g><path d="M 864 129 L 744 129" fill="none" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><rect x="864" y="84" width="330" height="90" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="3" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(3)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 43px; margin-left: 289px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">J-Link debugger</div></div></div></foreignObject><text x="343" y="47" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">J-Link debugger</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file
diff --git a/docs/img/figma_ui_automations.png b/docs/img/figma_ui_automations.png
new file mode 100644
index 0000000..8edd35d
--- /dev/null
+++ b/docs/img/figma_ui_automations.png
Binary files differ
diff --git a/docs/img/figma_ui_menu_bar.png b/docs/img/figma_ui_menu_bar.png
new file mode 100644
index 0000000..f1cfc39
--- /dev/null
+++ b/docs/img/figma_ui_menu_bar.png
Binary files differ
diff --git a/docs/img/figma_ui_node_overview.png b/docs/img/figma_ui_node_overview.png
new file mode 100644
index 0000000..43620f0
--- /dev/null
+++ b/docs/img/figma_ui_node_overview.png
Binary files differ
diff --git a/docs/img/qt_ui_automations.png b/docs/img/qt_ui_automations.png
new file mode 100644
index 0000000..0bb00b9
--- /dev/null
+++ b/docs/img/qt_ui_automations.png
Binary files differ
diff --git a/docs/img/qt_ui_menu_bar.png b/docs/img/qt_ui_menu_bar.png
new file mode 100644
index 0000000..1f01f29
--- /dev/null
+++ b/docs/img/qt_ui_menu_bar.png
Binary files differ
diff --git a/docs/img/qt_ui_node_overview.png b/docs/img/qt_ui_node_overview.png
new file mode 100644
index 0000000..7cd75a1
--- /dev/null
+++ b/docs/img/qt_ui_node_overview.png
Binary files differ