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:
# 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.
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:
Page last edited November 13, 2014
Text editor powered by tinymce.