Command Examples

The following code snippets can be used when operating in Command Mode to perform specific tasks.

Heart Rate Monitor Service

The command list below will add a Heart Rate service to the BLEFriend's attribute table, with two characteristics:

Download: file
# Perform a factory reset to make sure we get a clean start
AT+FACTORYRESET
OK
  
# Add the Heart Rate service entry
AT+GATTADDSERVICE=UUID=0x180D
1
OK

# Add the Heart Rate Measurement characteristic
AT+GATTADDCHAR=UUID=0x2A37, PROPERTIES=0x10, MIN_LEN=2, MAX_LEN=3, VALUE=00-40
1
OK

# Add the Body Sensor Location characteristic
AT+GATTADDCHAR=UUID=0x2A38, PROPERTIES=0x02, MIN_LEN=1, VALUE=3
2
OK

# Create a custom advertising packet that includes the Heart Rate service UUID
AT+GAPSETADVDATA=02-01-06-05-02-0d-18-0a-18
OK

# Reset the device to start advertising with the custom payload
ATZ
OK

# Update the value of the heart rate measurement (set it to 0x004A)
AT+GATTCHAR=1,00-4A
OK

Python Script

The following code performs the same function, but has been placed inside a Python wrapper using PySerial to show how you can script actions for the AT parser.

Download: file
import io
import sys
import serial
import random
from time import sleep

filename = "hrm.py"
ser = None
serio = None
verbose = True  # Set this to True to see all of the incoming serial data


def usage():
    """Displays information on the command-line parameters for this script"""
    print "Usage: " + filename + " <serialPort>\n"
    print "For example:\n"
    print "  Windows : " + filename + " COM14"
    print "  OS X    : " + filename + " /dev/tty.usbserial-DN009WNO"
    print "  Linux   : " + filename + " /dev/ttyACM0"
    return


def checkargs():
    """Validates the command-line arguments for this script"""
    if len(sys.argv) < 2:
        print "ERROR: Missing serialPort"
        usage()
        sys.exit(-1)
    if len(sys.argv) > 2:
        print "ERROR: Too many arguments (expected 1)."
        usage()
        sys.exit(-2)


def errorhandler(err, exitonerror=True):
    """Display an error message and exit gracefully on "ERROR\r\n" responses"""
    print "ERROR: " + err.message
    if exitonerror:
        ser.close()
        sys.exit(-3)


def atcommand(command, delayms=0):
    """Executes the supplied AT command and waits for a valid response"""
    serio.write(unicode(command + "\n"))
    if delayms:
        sleep(delayms/1000)
    rx = None
    while rx != "OK\r\n" and rx != "ERROR\r\n":
        rx = serio.readline(2000)
        if verbose:
            print unicode(rx.rstrip("\r\n"))
    # Check the return value
    if rx == "ERROR\r\n":
        raise ValueError("AT Parser reported an error on '" + command.rstrip() + "'")


if __name__ == '__main__':
    # Make sure we received a single argument (comPort)
    checkargs()

    # This will automatically open the serial port (no need for ser.open)
    ser = serial.Serial(port=sys.argv[1], baudrate=9600, rtscts=True)
    serio = io.TextIOWrapper(io.BufferedRWPair(ser, ser, 1),
                             newline='\r\n',
                             line_buffering=True)

    # Add the HRM service and characteristic definitions
    try:
        atcommand("AT+FACTORYRESET", 1000)  # Wait 1s for this to complete
        atcommand("AT+GATTCLEAR")
        atcommand("AT+GATTADDSERVICE=UUID=0x180D")
        atcommand("AT+GATTADDCHAR=UUID=0x2A37, PROPERTIES=0x10, MIN_LEN=2, MAX_LEN=3, VALUE=00-40")
        atcommand("AT+GATTADDCHAR=UUID=0x2A38, PROPERTIES=0x02, MIN_LEN=1, VALUE=3")
        atcommand("AT+GAPSETADVDATA=02-01-06-05-02-0d-18-0a-18")
        # Perform a system reset and wait 1s to come back online
        atcommand("ATZ", 1000)
        # Update the value every second
        while True:
            atcommand("AT+GATTCHAR=1,00-%02X" % random.randint(50, 100), 1000)
    except ValueError as err:
        # One of the commands above returned "ERROR\n"
        errorhandler(err)
    except KeyboardInterrupt:
        # Close gracefully on CTRL+C
        ser.close()
        sys.exit()

The results of this script can be seen below in the 'HRM' app of Nordic's nRF Toolbox application:

Please note that nRF Toolbox will only display HRM data if the value changes, so you will need to update the Heart Rate Measurement characteristic at least once after opening the HRM app and connecting to the BLEFriend
This guide was first published on Jan 13, 2016. It was last updated on Jan 13, 2016. This page (Command Examples) was last updated on Jul 16, 2019.