Communicating via BLE

You can connect to a TruConnect module via BLE, and place it in remote command mode. This allows the full range of control and monitoring available via a TruConnect terminal connection.

You can also place the TruConnect module in stream mode, and send and receive streams of data to and from the device.

Introduction to BLE

This section introduces a few terms necessary for later discussion. These terms have a specific meaning in the BLE context.

BLE devices operate in two broad classifications: central and peripheral.

Peripherals offer services, which consist of characteristics. Services and characteristics are distinguished by universally unique identifiers, or UUIDs.

Peripherals advertise, by broadcasting some services and characteristics. This allows them to be discovered by centrals.

After discovering a peripheral of interest, a central requests a connection to the peripheral. After connecting, the central can discover its services, and within those services its characteristics. The central can read the value of characteristics, subscribe to the value of characteristics, and in some cases write the value of the characteristic back to the peripheral.

To subscribe to a characteristic, the BLE mechanism is to register for notification when that characteristic is changed, and provide a callback to be called on each notification. Typically the callback reads the characteristic value and takes any action required.


Connecting to a Peripheral

The general procedure for using a central to interact with a peripheral is as follows:

The implementation of these procedural steps depends on the platform. Code examples are provided below in Objective C, used in Apple iOS BLE development.


TruConnect Services and Characteristics

ACKme TruConnect devices advertise the TruConnect service on start up according to the advertising variables bl v h d, bl v h i, bl v l d & bl v l i. An ACKme TruConnect device can be identified by its SERVICE_TRUCONNECT_UUID. To interact with a TruConnect device as a peripheral, use the TruConnect serial interface service.

The Rx (receive) and Tx (transmit) characteristics are from the point of view of the TruConnect device.

To send a string to be received by the peripheral serial interface, write to the Rx characteristic.

To read a string transmitted from the peripheral serial interface, read from the Tx characteristic.

For an ACKme TruConnect device, the serial interface service and characteristics are as follows:

Service or characteristicAbbrUUIDValues
SERVICE_TRUCONNECT_UUID175f8f23-a570-49bd-9627-815a6a27de2a-
CHARACTERISTIC_TRUCONNECT_PERIPHERAL_RX_UUIDRx1cce1ea8-bd34-4813-a00a-c76e028fadcbStrings sent to TruConnect serial interface
CHARACTERISTIC_TRUCONNECT_PERIPHERAL_TX_UUIDTxcacc07ff-ffff-4c48-8fae-a9ef71b75e26Strings received from TruConnect serial interface
CHARACTERISTIC_TRUCONNECT_MODE_UUIDMode20b9794f-da1a-4d14-8014-a0fb9cefb2f71 (STREAM_MODE) /
2 (LOCAL_COMMAND_MODE) /
3 (REMOTE_COMMAND_MODE)

The Abbr column in the table defines abbreviations used in this note only.


Interacting with a TruConnect Device

The TruConnect device acts as a peripheral, and the BLE mobile device acts as a central.

In the Objective C code examples below, the following definitions and declarations are assumed:

//TruConnect
#define SERVICE_TRUCONNECT_UUID                        @"175f8f23-a570-49bd-9627-815a6a27de2a"
#define CHARACTERISTIC_TRUCONNECT_PERIPHERAL_RX_UUID   @"1cce1ea8-bd34-4813-a00a-c76e028fadcb"
#define CHARACTERISTIC_TRUCONNECT_PERIPHERAL_TX_UUID   @"cacc07ff-ffff-4c48-8fae-a9ef71b75e26"
#define CHARACTERISTIC_TRUCONNECT_MODE_UUID            @"20b9794f-da1a-4d14-8014-a0fb9cefb2f7"
#define STREAM_MODE          1
#define LOCAL_COMMAND_MODE   2
#define REMOTE_COMMAND_MODE  3

CBCentralManager *manager ;
CBPeripheral *peripheral ;

CBCharacteristic *rxChar;   // corresponds to Rx characteristic
CBCharacteristic *txChar;   // corresponds to Tx characteristic
CBCharacteristic *modeChar; // corresponds to Mode characteristic

Scanning for a TruConnect Device

Example of scanning for a TruConnect device:

[manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:SERVICE_TRUCONNECT_UUID]] options:nil ];

Requesting a Connection to a Peripheral

To connect to a peripheral that has been discovered:

- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:
(CBPeripheral *)aPeripheral advertisementData:(NSDictionary
*)advertisementData RSSI:(NSNumber *)RSSI {
    [central stopScan] ;
    peripheral = aPeripheral ;
    [central connectPeripheral:peripheral options:nil] ;
}

Subscribing to Characteristics of the TruConnect Service

The code below assumes a peripheral object has been obtained by scanning. It loops through the peripheral services, and on discovering the TruConnect service, it sets local variables to point to the corresponding characteristics and subscribes to the appropriate characteristics by registering for notification when their values change. The callback function for all changed value notifications is didUpdateValueForCharacteristic.


for (CBService *service in peripheral.services) 
{
    if([service.UUID isEqual:[CBUUID UUIDWithString:SERVICE_TRUCONNECT_UUID]])
    {
        for (CBCharacteristic *characteristic in service.characteristics) 
        {
            if ([characteristic.UUID 
                isEqual:[CBUUID UUIDWithString:CHARACTERISTIC_TRUCONNECT_PERIPHERAL_RX_UUID]])
            {
               rxChar = characteristic;
            }
            else if ([characteristic.UUID 
                isEqual:[CBUUID UUIDWithString:CHARACTERISTIC_TRUCONNECT_PERIPHERAL_TX_UUID]])
            {
               txChar = characteristic;
               [peripheral setNotifyValue:YES forCharacteristic:characteristic]; // subscribe
            }
            else if ([characteristic.UUID 
                isEqual:[CBUUID UUIDWithString:CHARACTERISTIC_TRUCONNECT_MODE_UUID]])
            {
               modeChar = characteristic;
               [peripheral setNotifyValue:YES forCharacteristic:characteristic]; // subscribe
            }
        }
    }
}

Creating a Callback Function to Respond to Notifications

The callback function for all changed value notifications is didUpdateValueForCharacteristic.

The callback function below checks for the characteristic UUID, and processes the characteristic value accordingly.

- (void)peripheral:(CBPeripheral *)aPeripheral \ 
  didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error

{
    if ([characteristic.UUID 
        isEqual:[CBUUID UUIDWithString:CHARACTERISTIC_TRUCONNECT_PERIPHERAL_TX_UUID]])
    {
        [self readTxCharacteristic:characteristic];    
    }
    else if ([characteristic.UUID 
        isEqual:[CBUUID UUIDWithString:CHARACTERISTIC_TRUCONNECT_MODE_UUID]])
    {
        [self readModeCharacteristic:characteristic];    
    }
}

Reading from a TruConnect Device Serial Interface

On notification that Tx data is available, you can read the data value from the Tx characteristic.

Up to 20 bytes can be read from Tx in a single read. Repeated reads are required for longer strings.

To ensure that the Tx data is read only when it is available, subscribe to the Tx characteristic as described above in Subscribing to Characteristics of the TruConnect Service. In the didUpdateValueForCharacteristic callback, process the response.

In the callback example, we call readTxCharacteristic to process the response. The simplest implementation of readTxCharacteristic is to read the charactistic value into a string as shown in the example below.

The example also demonstrates how to remove the "\r" (CR) characters.

- (void)readTxCharacteristic:(CBCharacteristic *)characteristic {

    NSString *deviceTxText = [[NSString alloc] initWithBytes:[characteristic.value bytes] 
       length:characteristic.value.length encoding:NSUTF8StringEncoding];

    deviceTxText = [deviceTxText stringByReplacingOccurrencesOfString:@"\r" withString:@""];

    if(deviceTxText)
    {
        // process the response here 
    }

}

In the example, the string deviceTxText contains the TruConnect response. Further processing is required to parse the response, depending on the application.

To assist in processing the response, machine friendly command mode is recommended. Set this with the command set sy c m machine. See Machine Friendly Command Mode. In this mode the response header is turned on, and command echo and system messages are turned off.

If the value is longer than 20 bytes in length, the response is chunked. To determine the length of the response, parse the length from the response header. See Serial Interface, Response Format.

Writing to a TruConnect Device Serial Interface

To write to the device serial interface, write to the Rx characteristic:

[peripheral writeValue:[stringToWriteToDevice dataUsingEncoding:NSUTF8StringEncoding]
                            forCharacteristic:rxChar
                            type:CBCharacteristicWriteWithResponse];

Switching to Remote Command Mode or Stream Mode

Only the following command mode transitions are permitted via BLE:

Note: The TruConnect device must be in STREAM_MODE before another BLE device can switch it into REMOTE_COMMAND_MODE.

See Serial Interface for details of serial interface mode operation.

Switch the mode via BLE by writing to the Mode characteristic.

The following code demonstrates switching to REMOTE_COMMAND_MODE.

new_mode = REMOTE_COMMAND_MODE;
[peripheral writeValue:[NSData dataWithBytes:&new_mode length:1]  
     forCharacteristic:modeChar type:CBCharacteristicWriteWithResponse];

The following code demonstrates switching to STREAM_MODE.

new_mode = STREAM_MODE;
[peripheral writeValue:[NSData dataWithBytes:&new_mode length:1]  
     forCharacteristic:modeChar type:CBCharacteristicWriteWithResponse];

Check that the mode was changed successfully by reading back the modeChar characteristic's value:

{
    NSString *modeRead = [[NSString alloc] initWithBytes:[modeChar.value bytes] 
       length:modeChar.value.length encoding:NSUTF8StringEncoding];
    if *modeRead != new_mode 
    { 
        //...error handling...
    }
}

Sending a TruConnect Command

First switch to REMOTE_COMMAND_MODE as described above.

Then, write the command to the TruConnect Rx characteristic. See Writing to a TruConnect Device Serial Interface above.

Up to 20 bytes can be written to Rx in a single write. Repeated writes are required for longer strings.

Read the response back as described in Reading from a TruConnect Device Serial Interface.

All commands must be terminated by CR-LF (\r\n), adding two bytes to the length.

It may be more convenient to read responses to TruConnect commands if echo is turned off and response headers are turned on.

The code below shows how to create the command string to turn echo off:

NSString *commandEchoOff = @"set sy c e 0\r\n";

The code below shows how to create the command string to turn headers on:

NSString *commandResponseHeadersOn = @"set sy c h 1\r\n";

See Serial Interface for details of response format.

Sending and Receiving Data in Stream Mode

First switch to STREAM_MODE as described above in Switching to Remote Command Mode or Stream Mode.

To stream data to the TruConnect device, write the data to the TruConnect Rx characteristic. See Writing to a TruConnect Device Serial Interface above.

You can verify that the data is received by connecting a TruConnect terminal to the device. See Getting Started. The data appears on the terminal display.

To stream data from the TruConnect device, read the data from the TruConnect Tx characteristic. See Reading from a TruConnect Device Serial Interface above.

You can verify that the data is received by connecting a TruConnect terminal to the device. Data sent from the central appears directly on the terminal display.

You can send data by connecting a TruConnect terminal to the device. Type data into the terminal. The data is sent directly to the central.

ModifiedChangesTruConnect Version
Required
2015-03-18Created1.0+