Reading Characteristics / Enabling notifications using the SmartRF06 EVB (TI)

Ask, and ye shall receive.
actony2015
Posts: 1
Joined: 11:00, 06 Oct 2015

Reading Characteristics / Enabling notifications using the SmartRF06 EVB (TI)

Postby actony2015 » 11:46, 06 Oct 2015

Hi. I am fairly new to EvoThings development and have questions regarding uing the TI SmartRF06 development board with EVO Things. I found this example to be a good starting point for understanding the Bluetooth development using the CC2650 IC from TI. I am using the EvoThings Workbench V1.2 which has the hooks in it for this processor.

To give you some background I am using the sample application from Texas Instruments Developer Studio 6 called "SimpleBlePeripheral" as well as the "SimpleBlePeripheral Bluetooth stack." and modifying it per this example:

http://processors.wiki.ti.com/index.php ... e_CC2650DK


Basically There is a single service and a characteristic that reads the value that gets modified using the keypad and a second characteristic that merely copies the first characteristic and provides notification.
I have modified the evothings example project: ti-sensortag-cc2650-demo to work with my Texas Instruments Bluetooth board. So far , I can connect to the device and connect to the service listed above, but I cannot seem to enable notifications or read either characteristic. The modified code is shown below:
The app initially has only two buttons - connect / disconnect. I added an additional button to test reading characteristic 1. If I run the example code I get the following error messages using the console. The error messages occur when pressing the "data" (app.onReadButton) button. Notice the service 2902e00e... - this contains the two characteristics mentioned above. It also does not display the actual value of Characteristic 1 which should be zero to start. Thanks for any information and help you can provide.

LOG: writeType: WRITE_TYPE_DEFAULT
LOG: c15: 00002a29-0000-1000-8000-00805f9b34fb. 0 desc.
LOG: properties: PROPERTY_READ
LOG: writeType: WRITE_TYPE_DEFAULT
LOG: c16: 00002a2a-0000-1000-8000-00805f9b34fb. 0 desc.
LOG: properties: PROPERTY_READ
LOG: writeType: WRITE_TYPE_DEFAULT
LOG: c17: 00002a50-0000-1000-8000-00805f9b34fb. 0 desc.
LOG: properties: PROPERTY_READ
LOG: writeType: WRITE_TYPE_DEFAULT
LOG: s4: 0 2902e00e-7001-4618-da10-29027831d113. 2 chars.
LOG: c18: f000ee01-0451-4000-b000-000000000000. 1 desc.
LOG: properties: PROPERTY_READ PROPERTY_WRITE
LOG: writeType: WRITE_TYPE_DEFAULT
LOG: d21: 00002901-0000-1000-8000-00805f9b34fb
LOG: rd 21
LOG: c19: f000ee02-0451-4000-b000-000000000000. 2 desc.
LOG: properties: PROPERTY_NOTIFY
LOG: writeType: WRITE_TYPE_DEFAULT
LOG: d22: 00002902-0000-1000-8000-00805f9b34fb
LOG: d23: 00002901-0000-1000-8000-00805f9b34fb
LOG: rd 23
LOG: rdw 21: Sunlight Value
LOG: rdw 23: Sunlight Value Notification
LOG: connect 2 state 0
LOG: [ERR] Uncaught TypeError: Object #<Device> has no method 'readServices' [myapp.js: 460]
LOG: [ERR] Uncaught TypeError: Object #<Device> has no method 'readServices' [myapp.js: 460]



// JavaScript code for the TI SensorTag Demo app.

/**
* Object that holds application data and functions.
*/
var app = {};

/**
* Data that is plotted on the canvas.
*/
app.dataPoints = [];

/**
* Timeout (ms) after which a message is shown if the SensorTag wasn't found.
*/
app.CONNECT_TIMEOUT = 3000;

/**
* Object that holds SensorTag UUIDs.
*/
app.sensortag = {};

//Object that holds the sunlight UUIDS
app.mysensor = {};


//app.mysensor.SUNLIGHT_SERV_UUID = 'f000ee00-0451-4000-b000-000000000000';
app.mysensor.SUNLIGHT_SERV_UUID = '2902e00e-7001-4618-da10-29027831d113'; //UUID as read from the device using the discovery app.
app.mysensor.SUNLIGHT_CHAR1_UUID = 'f000ee01-0451-4000-b000-000000000000';
app.mysensor.SUNLIGHT_CHAR2_UUID = 'f000ee02-0451-4000-b000-000000000000';

app.mysensor.CHAR2_DESCRIPTOR_UUID = '00002902-0000-1000-8000-00805f9b34fb'; //Notification ID
app.mysensor.CHAR2_DESCRIPTOR_UUID2 = '00002901-0000-1000-8000-00805f9b34fb'; //Second ID. (Description)
////////////////////////////////////////////////////////////////

// UUIDs for movement services and characteristics.
/*app.sensortag.MOVEMENT_SERVICE = 'f000aa80-0451-4000-b000-000000000000';
app.sensortag.MOVEMENT_DATA = 'f000aa81-0451-4000-b000-000000000000';
app.sensortag.MOVEMENT_CONFIG = 'f000aa82-0451-4000-b000-000000000000';
app.sensortag.MOVEMENT_PERIOD = 'f000aa83-0451-4000-b000-000000000000';
app.sensortag.MOVEMENT_NOTIFICATION = '00002902-0000-1000-8000-00805f9b34fb';*/

/**
* Initialise the application.
*/
app.initialize = function()
{
document.addEventListener(
'deviceready',
function() { evothings.scriptsLoaded(app.onDeviceReady) },
false);

// Called when HTML page has been loaded.
$(document).ready( function()
{
// Adjust canvas size when browser resizes
$(window).resize(app.respondCanvas);

// Adjust the canvas size when the document has loaded.
app.respondCanvas();
});
};

/**
* Adjust the canvas dimensions based on its container's dimensions.
*/
app.respondCanvas = function()
{
var canvas = $('#canvas')
var container = $(canvas).parent()
canvas.attr('width', $(container).width() ) // Max width
// Not used: canvas.attr('height', $(container).height() ) // Max height
};

app.onDeviceReady = function()
{
app.showInfo('Activate the SensorTag and tap Start.');
};

app.showInfo = function(info)
{
document.getElementById('info').innerHTML = info;
};

app.onStartButton = function()
{
app.onStopButton();
app.startScan();
app.showInfo('Status: Scanning...');
app.startConnectTimer();
};

app.onStopButton = function()
{
// Stop any ongoing scan and close devices.
app.stopConnectTimer();
evothings.easyble.stopScan();
evothings.easyble.closeConnectedDevices();
app.showInfo('Status: Stopped.');
};

app.startConnectTimer = function()
{
// If connection is not made within the timeout
// period, an error message is shown.
app.connectTimer = setTimeout(
function()
{
app.showInfo('Status: Scanning... ' +
'Please press the activate button on the tag.');
},
app.CONNECT_TIMEOUT)
}

app.stopConnectTimer = function()
{
clearTimeout(app.connectTimer);
}

app.startScan = function()
{
evothings.easyble.startScan(
function(device)
{
// Connect if we have found a sensor tag.
if (app.deviceIsSensorTag(device))
{
app.showInfo('Status: Device found: ' + device.name + '.');
evothings.easyble.stopScan();
app.connectToDevice(device);
app.stopConnectTimer();
}
},
function(errorCode)
{
app.showInfo('Error: startScan: ' + errorCode + '.');
});
};

app.deviceIsSensorTag = function(device)
{
console.log('device name: ' + device.name);
return (device != null) &&
(device.name != null) &&
//(device.name.indexOf('Sensor Tag') > -1 ||
// device.name.indexOf('SensorTag') > -1);
(device.name.indexOf('Sunlight Sensor') > -1 ||
device.name.indexOf('SunlightSensor') > -1);
};

/**
* Read services for a device.
*/
app.connectToDevice = function(device)
{
app.showInfo('Connecting...');
device.connect(
function(device)
{
app.showInfo('Status: Connected - reading SensorTag services...');
app.readServices(device);
},
function(errorCode)
{
app.showInfo('Error: Connection failed: ' + errorCode + '.');
evothings.ble.reset();
// This can cause an infinite loop...
//app.connectToDevice(device);
});
};

app.readServices = function(device)
{
device.readServices( //null,
[
/*app.sensortag.MOVEMENT_SERVICE // Movement service UUID.*/
app.mysensor.SUNLIGHT_SERV_UUID,

],
function(device)
{
app.showInfo('BLE Services available.');
//app.logAllServices(app.device); //new from MBED example.

app.startSunlightNotification(device);
// TODO: Read/write/enable notifications here.
},
// Function that monitors accelerometer data.
//app.startAccelerometerNotification,
app.startSunlightNotification,
function(errorCode)
{
console.log('Error: Failed to read services: ' + errorCode + '.');
});
app.showInfo('DONE Reading services');
};


/**
Read characteristic data for the sunlight sensor
**/

app.startSunlightNotification = function(device)
{
app.showInfo('Status: Starting Sunlight notification...');

/*device.writeCharacteristic(
app.sensortag.MOVEMENT_CONFIG,

new Uint8Array([56,0]),
function()
{
console.log('Status: writeCharacteristic ok.');
},
function(errorCode)
{
console.log('Error: writeCharacteristic: ' + errorCode + '.');
});*/

// Set accelerometer period to 100 ms.
/*device.writeCharacteristic(
app.sensortag.MOVEMENT_PERIOD,
new Uint8Array([10]),
function()
{
console.log('Status: writeCharacteristic ok.');
},
function(errorCode)
{
console.log('Error: writeCharacteristic: ' + errorCode + '.');
});*/

// Turn on Sunlight Sensor characteristic
device.writeDescriptor(
/*app.sensortag.MOVEMENT_DATA,*/ app.mysensor.SUNLIGHT_CHAR2_UUID,
/*app.sensortag.MOVEMENT_NOTIFICATION,*/ // Notification descriptor.
app.mysensor.CHAR2_DESCRIPTOR_UUID,
new Uint8Array([1,0]),//Uint8Array([1,0]),
function()
{
console.log('Status: writeDescriptor ok.');
//app.showInfo('Status: writeDescriptor OK.');
},
function(errorCode)
{
// This error will happen on iOS, since this descriptor is not
// listed when requesting descriptors. On iOS you are not allowed
// to use the configuration descriptor explicitly. It should be
// safe to ignore this error.
//app.showInfo('Error: writeDescriptor: ' + errorCode + '.');
console.log('Error: writeDescriptor: ' + errorCode + '.');
});

//Removed temporarily AJC - 10/4/15
// Start accelerometer notification.
device.enableNotification(
//app.sensortag.MOVEMENT_DATA,
app.mysensor.SUNLIGHT_CHAR2_UUID,
function(data)
{
//Try this
//app.showInfo('BLE characteristic data: ' + evothings.ble.fromUtf8(data));
console.log('BLE characteristic data: ' + evothings.ble.fromUtf8(data));

//app.showInfo('Status: Data stream active.');
//var dataArray = new Uint8Array(data);
//var values = dataArray;//app.getAccelerometerValues(dataArray);
//app.drawDiagram(values);
},
function(errorCode)
{
//app.showInfo('Error: enableNotification: ' + errorCode + '.');
console.log('Error: enableNotification: ' + errorCode + '.')
});

device.readCharacteristic(
app.mysensor.SUNLIGHT_CHAR1_UUID,
function(data)
{
//app.showInfo('BLE characteristic data: ' + evothings.ble.fromUtf8(data));
console.log('BLE characteristic data: ' + evothings.ble.fromUtf8(data));
},
function(errorCode)
{
//app.showInfo('BLE readCharacteristic error: ' + errorCode);
console.log('BLE readCharacteristic error: ' + errorCode);
});


};




/**
* Read accelerometer data.
*/


/* app.startAccelerometerNotification = function(device)
{
app.showInfo('Hello World');
}*/


/*app.startAccelerometerNotification = function(device)
{
app.showInfo('Status: Starting accelerometer notification...');

// Set accelerometer configuration to ON.
// magnetometer on: 64 (1000000) (seems to not work in ST2 FW 0.89)
// 3-axis acc. on: 56 (0111000)
// 3-axis gyro on: 7 (0000111)
// 3-axis acc. + 3-axis gyro on: 63 (0111111)
// 3-axis acc. + 3-axis gyro + magnetometer on: 127 (1111111)
device.writeCharacteristic(
app.sensortag.MOVEMENT_CONFIG,
new Uint8Array([56,0]),
function()
{
console.log('Status: writeCharacteristic ok.');
},
function(errorCode)
{
console.log('Error: writeCharacteristic: ' + errorCode + '.');
});

// Set accelerometer period to 100 ms.
device.writeCharacteristic(
app.sensortag.MOVEMENT_PERIOD,
new Uint8Array([10]),
function()
{
console.log('Status: writeCharacteristic ok.');
},
function(errorCode)
{
console.log('Error: writeCharacteristic: ' + errorCode + '.');
});

// Set accelerometer notification to ON.
device.writeDescriptor(
app.sensortag.MOVEMENT_DATA,
app.sensortag.MOVEMENT_NOTIFICATION, // Notification descriptor.
new Uint8Array([1,0]),
function()
{
console.log('Status: writeDescriptor ok.');
},
function(errorCode)
{
// This error will happen on iOS, since this descriptor is not
// listed when requesting descriptors. On iOS you are not allowed
// to use the configuration descriptor explicitly. It should be
// safe to ignore this error.
console.log('Error: writeDescriptor: ' + errorCode + '.');
});

// Start accelerometer notification.
device.enableNotification(
app.sensortag.MOVEMENT_DATA,
function(data)
{
app.showInfo('Status: Data stream active - accelerometer');
var dataArray = new Uint8Array(data);
var values = app.getAccelerometerValues(dataArray);
app.drawDiagram(values);
},
function(errorCode)
{
console.log('Error: enableNotification: ' + errorCode + '.');
});
};*/

/**
* Calculate accelerometer values from raw data for SensorTag 2.
* @param data - an Uint8Array.
* @return Object with fields: x, y, z.
*/

//Remove in case causing a problem AJC 10/4/15
/*app.getAccelerometerValues = function(data)
{
//var divisors = { x: -16384.0, y: 16384.0, z: -16384.0 };
var divisors = { x: 1.0, y: 1.0, z: 1.0 };

// Calculate accelerometer values.
var ax = evothings.util.littleEndianToInt16(data, 6)/ divisors.x;
var ay = evothings.util.littleEndianToInt16(data, 8)/ divisors.y;
var az = evothings.util.littleEndianToInt16(data, 10) / divisors.z;

// Return result.
return { x: ax, y: ay, z: az };
};*/

/**
* Plot diagram of sensor values.
* Values plotted are expected to be between -1 and 1
* and in the form of objects with fields x, y, z.
*/
app.drawDiagram = function(values)
{
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

// Add recent values.
app.dataPoints.push(values);

// Remove data points that do not fit the canvas.
if (app.dataPoints.length > canvas.width)
{
app.dataPoints.splice(0, (app.dataPoints.length - canvas.width));
}

// Value is an accelerometer reading between -1 and 1.
function calcDiagramY(value)
{
// Return Y coordinate for this value.
var diagramY =
((value * canvas.height) / 2)
+ (canvas.height / 2);
return diagramY;
}

function drawLine(axis, color)
{
context.strokeStyle = color;
context.beginPath();
var lastDiagramY = calcDiagramY(
app.dataPoints[app.dataPoints.length-1][axis]);
context.moveTo(0, lastDiagramY);
var x = 1;
for (var i = app.dataPoints.length - 2; i >= 0; i--)
{
var y = calcDiagramY(app.dataPoints[i][axis]);
context.lineTo(x, y);
x++;
}
context.stroke();
}

// Clear background.
context.clearRect(0, 0, canvas.width, canvas.height);

// Draw lines.
drawLine('x', '#f00');
drawLine('y', '#0f0');
drawLine('z', '#00f');
};

//From MBED code example
app.onReadButton = function()
{
app.getdata(device);
};

//Added as a test
app.getdata = function(device)
{
device.readServices( //null,
[
/*app.sensortag.MOVEMENT_SERVICE // Movement service UUID.*/
//app.mysensor.SUNLIGHT_CHAR1_UUID
app.mysensor.SUNLIGHT_SERV_UUID,

],
function(device)
{
app.showInfo('BLE Services available.');
//app.logAllServices(app.device); //new from MBED example.


// TODO: Read/write/enable notifications here.
},
// Function that monitors accelerometer data.
//app.startAccelerometerNotification,
//app.startSunlightNotification,
function(errorCode)
{
console.log('Error: Failed to read services: ' + errorCode + '.');
});
app.showInfo('DONE Reading services');

device.readCharacteristic(
app.mysensor.SUNLIGHT_CHAR1_UUID,
function(data)
{
var view = new Uint8Array(data);
//app.showInfo('Data READ:.. ' + evothings.ble.fromUtf8(data));
console.log('Data READ:.. ' + evothings.ble.fromUtf8(data));

},
function(error)
{
//app.showInfo('Could not get data... ' + error);
console.log('Could not get data... ' + error);
});
};

//NEW SAMPLE CODE FROM MBED EXAMPLE - 10/4/15
app.logAllServices = function(device)
{
// Here we simply print found services, characteristics,
// and descriptors to the debug console in Evothings Workbench.

// Notice that the fields prefixed with "__" are arrays that
// contain services, characteristics and notifications found
// in the call to device.readServices().

// Print all services.
console.log('Found services:');
for (var serviceUUID in device.__services)
{
var service = device.__services[serviceUUID];
console.log(' service: ' + service.uuid);

// Print all characteristics for service.
for (var characteristicUUID in service.__characteristics)
{
var characteristic = service.__characteristics[characteristicUUID];
console.log(' characteristic: ' + characteristic.uuid);

// Print all descriptors for characteristic.
for (var descriptorUUID in characteristic.__descriptors)
{
var descriptor = characteristic.__descriptors[descriptorUUID];
console.log(' descriptor: ' + descriptor.uuid);
}
}
}
};

// Initialize the app.
app.initialize();

User avatar
micke
Posts: 256
Joined: 20:49, 18 Nov 2013

Re: Reading Characteristics / Enabling notifications using the SmartRF06 EVB (TI)

Postby micke » 22:15, 29 Dec 2015

Hi, this is an old question, hope you are still with us!

Looks like the problem is that the variable "device" on line 460 is null/undefined. This is beacause app.getdata is called with an undefined variable in this function:

Code: Select all

app.onReadButton = function()
{
    app.getdata(device);
};


When the device is found, in startScan, e.g. on line 128, set a field on the app object to hold the device. This gives you a "global" variable for the device object. Like this:

Code: Select all

app.device = device;


Then use the "global" reference as follows:

Code: Select all

app.onReadButton = function()
{
    app.getdata(app.device);
};


This should work!

Best regards, Mikael


Return to “Questions and answers”

Who is online

Users browsing this forum: No registered users and 2 guests