The terminal can be used to communicate with nodes either by connecting to them using a debugger connection and Segger RTT or by using UART. The terminal is optional and the user can decide whether to compile it into the firmware or not by specifying this in the featureset. The terminal can be either used in prompt mode or json mode which can also be specified in the featureset using the terminalMode setting in the config. Prompt mode is mostly for testing and debugging, while json mode can be used to build a MeshGateway that processes received messages and sends commands into the mesh.

Setting Terminal Mode (Local Command)

When working with UART (Terminal and UART must be enabled), FruityMesh supports a convenient blocking terminal mode with echo back functionality. For communication with another device such as a MeshGateway, an interrupt based input method and JSON output is used. To toggle between these two modes, there are two commands:


Using startterm invokes a blocking mode where all functionality is halted and user input is received in a busy loop until a line feed '\r' is received. The command is then processed and other functionality is resumed. The input is echoed back on the terminal. Backspace is supported as well for most terminal programs. If the command isn’t recognized, a warning is echoed.


The stopterm command switches the node into an interrupt based input mode where terminal input does not affect the functionality until a line feed '\r' is received. All output messages are in JSON format.

CRC checking on terminal commands and output

FruityMesh supports CRC checks for terminal commands and JSON messages. There are two possibilities to enable CRC checks:

  • Call GS→terminal.EnableCrcChecks() (done by prod_sink_nrf52 on boot)

  • Send some terminal command that contains a CRC at the end

For both, terminal commands and JSONs, the CRC is appended to the string. The CRC has the exact regex form " CRC: \d+$" (without ""). When the CRC checks are enabled, debugging can be quite difficult. To solve this issue, you can replace the calculated CRC number to the exact string "skip", so when appending " CRC: skip" to a message, CRC calculation is disabled for this single terminal command. Note however that CRC checks are still enabled after this terminal command.

When printing out a json with logjson the CRC is automatically appended. In cases where the printing of a json is split between multiple lines, the macro logjson_partial can be used for every json part, except the last one which has to be a logjson.

Rebooting (Local Command)


To reset the node via the terminal, enter this command and a software reboot is performed.

Enabling CRC checks on Terminal Communication

It is possible to add a CRCs check to all communications that go through the terminal. This might be necessary if the communication channel is unreliable. To do this, execute the following command:


After this command is sent, the firmware only accepts terminal commands that have a correct CRC32 appended at the end. For example, a terminal command may look like this:

action this status get_status CRC: 3968018817

In addition, all JSON messages from the firmware have a CRC32 appended:

{"nodeId":1,"type":"status","module":3,"batteryInfo":0,"clusterSize":2,"connectionLossCounter":0,"freeIn":2,"freeOut":2,"inConnectionPartner":0,"inConnectionRSSI":0, "initialized":0} CRC: 3703755059

USB CDC ACM - nRF52840

The nRF52840 SoC includes a USB peripheral and the Nordic SDK includes code to provide the communications device class (CDC) abstract control model (ACM). This is a standardized way of providing a serial terminal via USB.

Our implemention can e.g. be used with USB Dongles based on the nRF52840 SoC or with the nRF52840-DK which has a second Micro-USB port attached to the SoC which is used together with the USB peripheral.

The FruityMesh binding is implemented in C in src/c/drivers/nrf/virtual_com_port.[ch] and used by the terminal implementation in Terminal.cpp for input and output.