nRF5 SDK for Mesh v2.0.0
Interactive PyACI

The Interactive Python Application Controller Interface (PyACI) ( can be used to interactively control devices running the mesh stack and the serial interface. The script opens up one or more COM ports and enables an interactive Python command line.

Follow the instructions in this README to get your environment up and running. Afterwards, you can run through the provided examples and tutorials.


The interactive console is written for Python 3. To install the required packages, move to the scripts/interactive_pyaci directory and install the requirements using pip:

nrf5_sdk_for_mesh$ cd scripts/interactive_pyaci
interactive_pyaci$ pip install -r requirements.txt

Using the interface

To start the serial interface, run the following command in the directory of the script:

interactive_pyaci$ python -d <COM>

Where <COM> is the COM port of the device you're connecting to. You may specify to multiple COM ports separated by a space. Note that COM port names are case sensitive.


On Windows, the COM port is on the form COM12. To identify the correct COM port, open up the "Device Manager" (Run -> devmgmt.msc) and connect the device. Your device should appear under "Ports (COM & LPT)".


On Ubuntu/Linux and similar systems, the COM port is usually on the form /dev/tty*, e.g., /dev/ttyACM0. To identify the correct COM port, you can use dmesg. Connect the device and run:

$ dmesg | tail

The output should look like this:

[46406.952479] usb 1-2: new high-speed USB device number 8 using ehci-pci
[46407.258960] usb 1-2: New USB device found, idVendor=1366, idProduct=0105
[46407.258964] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[46407.258966] usb 1-2: Product: J-Link
[46407.258967] usb 1-2: Manufacturer: SEGGER
[46407.258969] usb 1-2: SerialNumber: 000682576262
[46407.273985] cdc_acm 1-2:1.0: ttyACM1: USB ACM device

As you can see from the output, the connected device 682576262 was assigned to /dev/ttyACM1. Alternatively, you could also use this command:

$ dmesg | grep -C 3 SEGGER

Other options

Calling the script with the -h option will give you information about the other options.

$ python -h
usage: [-h] -d DEVICES [DEVICES ...] [-b BAUDRATE]
                            [--no-logfile] [-l LOG_LEVEL]

nRF5 SDK for Mesh Interactive PyACI

optional arguments:
  -h, --help            show this help message and exit
  -d DEVICES [DEVICES ...], --device DEVICES [DEVICES ...]
                        Device Communication port, e.g., COM216 or
                        /dev/ttyACM0. You may connect to multiple devices.
                        Separate devices by spaces, e.g., "-d COM123 COM234"
  -b BAUDRATE, --baudrate BAUDRATE
                        Baud rate. Default: 115200
  --no-logfile          Disables logging to file.
  -l LOG_LEVEL, --log-level LOG_LEVEL
                        Set default logging level: 1=Errors only, 2=Warnings,
                        3=Info, 4=Debug

About the interface

The interface consists of the following files:

├── aci
│   ├──                    # Auto generated command class definitions (serialization)
│   ├──                 # Utility class for parsing firmware configuration file (`nrf_mesh_app_config.h`)
│   ├──                    # Auto generated event class definitions (de-serialization)
│   ├──                   # The UART serial driver
│   └──                  # Utility functions and class definitions
├── database
│   ├── example_database.json         # Example mesh database file
│   └── example_database.json.backup  # Backup of the original database
├── doc                               # Tutorials and documentation
│   ├──
│   ├──
│   └──
├──              # The interactive script itself
├── mesh                              # Mesh helper modules
│   ├──                     # Stripped down access layer
│   ├──                   # Database storage module
│   ├──               # Provisioning interface module
│   └──                      # Mesh type definitions
├── models                            # Mesh models
│   ├──                     # Configuration client
│   └──              # Simple On/Off client
├──                         # The README you're reading now
└── requirements.tx                   # Python pip requirements file

Important: aci/ and aci/ are auto-generated from the C header files of the serial interface with the tools/serial_doc scripts. To re-generate the files, build the serial_pyaci target (requires a CMake based setup).

Commands and Events

Commands available in the interface can be found in aci/ They are imported through the cmd namespace, e.g., cmd.Echo. Similarly, available events are found in aci/ and available in the evt namespace, e.g., evt.MeshMessageReceivedSubscription.

Getting help

To read the documentation for one of the commands, events, functions or anything else, enter a ? before or after the object and press <enter>. E.g., for the BeaconParamsSet command, you would get the following:

In [1]: cmd.BeaconParamsSet?
Init signature: cmd.BeaconParamsSet(beacon_slot, tx_power, channel_map, interval_ms)
Set parameters for application controlled beacon.

    beacon_slot : uint8_t
        Slot number of the beacon to start.
    tx_power : uint8_t
        TX Power value, must be a value from @ref serial_cmd_tx_power_value_t.
    channel_map : uint8_t
        Channel map bitfield for beacon, starting at channel 37.
    interval_ms : uint32_t
        TX interval in milliseconds.
File:           <nrf5_sdk_for_bluetooth_mesh>\scripts\interactive_pyaci\aci\
Type:           type

The help prompt may be used for any python object or function.

The console also provides auto completion, i.e., typing cmd.BeaconParamsS and pressing <tab> will complete the command packet object.

For more details about the commands, see the serial commands documentation.


As with the normal Python shell, you can do more complex scripting, e.g.:

In [1]: import time
In [2]: for i in range(0, 10): send(cmd.Echo("Hello: " + str(i))); time.sleep(1)
2017-08-02 10:21:34,459 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 0')}}
2017-08-02 10:21:35,378 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 1')}}
2017-08-02 10:21:36,394 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 2')}}
2017-08-02 10:21:37,400 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 3')}}
2017-08-02 10:21:38,406 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 4')}}
2017-08-02 10:21:39,440 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 5')}}
2017-08-02 10:21:40,414 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 6')}}
2017-08-02 10:21:41,420 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 7')}}
2017-08-02 10:21:42,427 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 8')}}
2017-08-02 10:21:43,442 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'Hello: 9')}}

Here we use a simple for-loop to send 10 echo commands with a one second delay.

Documentation feedback | Developer Zone | Subscribe | Updated