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();
Reading Characteristics / Enabling notifications using the SmartRF06 EVB (TI)
-
- Posts: 1
- Joined: 11:00, 06 Oct 2015
Re: Reading Characteristics / Enabling notifications using the SmartRF06 EVB (TI)
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:
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:
Then use the "global" reference as follows:
This should work!
Best regards, Mikael
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 59 guests