Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subscribing to characteristics #29

Open
FizixRichard opened this issue Sep 20, 2017 · 52 comments
Open

Subscribing to characteristics #29

FizixRichard opened this issue Sep 20, 2017 · 52 comments

Comments

@FizixRichard
Copy link

FizixRichard commented Sep 20, 2017

Hi,

I'm having trouble subscribing to characteristics and the documentation doesn't explain how. Following the XCode Core Bluetooth documentation isn't helping.

I am trying to subscribe to a couple of services on a BT device, battery and immediate alert.

I'm successfully scanning for devices, finding the device, getting its data, listing services and getting the characteristics.

What I need to do from here is to subscribe to the characteristics I need and receive callbacks whenever the battery level changes or the alert level changes on the BT device. I've tried a number of approaches but none seem to be working.

Code up to subscription below:

// -----------------------------------------------------------------------------
// Peripheral Connect Callback
// -----------------------------------------------------------------------------
centralManager.addEventListener('didConnectPeripheral', function(e) 
{
    Ti.API.info('Connected to Periperal...');
    
    connectedPeripheral = e.peripheral;
    
    
    connectedPeripheral.addEventListener('didUpdateValueForCharacteristic', function(e) {
        Ti.API.info('didUpdateValueForCharacteristic');
        Ti.API.info(e);
	});


    connectedPeripheral.addEventListener('didDiscoverServices', function(e) 
    {
    	Ti.API.info('Service Discovery...');
    	
    	p = e.peripheral;

		Ti.API.info('peripheral has', p.services.length, 'service(s)');	
		
		p.services.forEach(function(service) 
		{
			Ti.API.info('service: ', service.uuid);	
			
			
			// Assign battery service
			if(service.uuid == gattBattery)
			{
				Ti.API.info("BatteryService Found");
				serviceBattery = service;
			
				p.addEventListener('didDiscoverCharacteristicsForService', function(e) 
				{
					var characteristics = e.service.characteristics;
					
					characteristics.forEach(function(characteristic) 
					{
						Ti.API.info('Characteristic ID:', characteristic.uuid);
						
						// Want to subscribe to this characteristic and receive value changes from peripheral
						if(characteristic.uuid == '2A19')
						{										
						
						}
					});
				});	
				
				p.discoverCharacteristicsForService({
					characteristics : [],
					service : service
				});
			}
		});
    });
    
    
    // Discover services
    connectedPeripheral.discoverServices();
});
@FizixRichard
Copy link
Author

Btw, I think the documentation and example lacks basic info like this. So if anyone can help with this problem then I'll submit working code to the project so that the example/docs are more complete.

@lazzaratom
Copy link

Hi how can read data from HM-10 BLE device?
This is my log:
[INFO] : testBluetooth/1.0 (6.2.1.301ffa4)
[INFO] : didUpdateState
[INFO] : Powered On
[INFO] : didDiscoverPeripheral
[INFO] : HMSoft
[INFO] : connecting
[INFO] :
[INFO] : didConnectPeripheral
[INFO] : connected to HMSoft
[INFO] :
[INFO] : didDiscoverServices
[INFO] : peripheral has 1 service(s)
[INFO] : service: FFE0
[INFO] : calling discoverCharacteristicsForService
[INFO] :
[INFO] : didDiscoverCharacteristicsForService
[INFO] : service: FFE0
[INFO] : characteristic: FFE1

@FizixRichard
Copy link
Author

Is anyone monitoring this forum?

@hansemannn
Copy link
Owner

As I am not making example-codes for all kind of possible BLE-use-cases, either something or my or your end is incorrect. Please feel free to submit a fix if something does not work for you.

@FizixRichard
Copy link
Author

OK, I followed the core bluetooth examples and when I try to subscribe to either the battery or immediate alert service by setting notify value to true, I am not getting state change callbacks.

here is my code for attempting to get the value and state changes for the battery service:

centralManager.addEventListener('didDiscoverPeripheral', function(e) 
{
	if(e.peripheral.name == peripheralName)
	{		
		Ti.API.info('Peripheral ' + e.peripheral.name + ' Found...');
		centralManager.stopScan();
		peripheralRSSI = e.rssi;
		
		var options = { notifyOnConnection : true, notifyOnDisconnection : true, notifyOnNotification : true };			
			
		centralManager.connectPeripheral(e.peripheral, options);   
	}
});




// -----------------------------------------------------------------------------
// Peripheral Connect Callback
// -----------------------------------------------------------------------------
centralManager.addEventListener('didConnectPeripheral', function(e) 
{
    Ti.API.info('Connected to Periperal...');
    
    connectedPeripheral = e.peripheral;
    
    
    

    connectedPeripheral.addEventListener('didDiscoverServices', function(e) 
    {
    	Ti.API.info('Service Discovery...');
    	
    	p = e.peripheral;

		p.addEventListener('didUpdateValueForCharacteristic', function(e) 
		{
       	 	Ti.API.info('didUpdateValueForCharacteristic');
        	Ti.API.info(e);
		});


		Ti.API.info('peripheral has', p.services.length, 'service(s)');	
		
		p.services.forEach(function(service) 
		{			
			// Assign battery service
			if(service.uuid == gattBattery)
			{
				Ti.API.info("BatteryService Found: " + service.uuid);
				serviceBattery = service;
			
				p.addEventListener('didDiscoverCharacteristicsForService', function(e) 
				{
					var characteristics = e.service.characteristics;
					
					characteristics.forEach(function(characteristic) 
					{
						Ti.API.info('Characteristic ID:', characteristic.uuid);
						
						// Want to subscribe to this characteristic and receive value changes from peripheral
						if(characteristic.uuid == '2A19')
						{			
							
													
							p.setNotifyValueForCharacteristic(true, characteristic);
							
							p.readValueForCharacteristic(characteristic);												
							Ti.API.info('Characteristic Value:', characteristic.value);
							
						}
					});
				});	
				
				p.discoverCharacteristicsForService({
					characteristics : [],
					service : service
				});
			}
			
			
			// Assign immediate alert service
			/*
			if(service.uuid == gattImmediateAlert)
			{
				Ti.API.info("Immediate Alert Found: " + service.uuid);
				serviceImmediateAlert = service;
			
				p.addEventListener('didDiscoverCharacteristicsForService', function(e) 
				{
					var characteristics = e.service.characteristics;
					
					characteristics.forEach(function(characteristic) 
					{
						Ti.API.info('Characteristic ID:', characteristic.uuid);
						
						// Subscribe to this characteristic and receive value changes from peripheral
						if(characteristic.uuid == '2A06')
						{										
							p.setNotifyValueForCharacteristic(true, characteristic);
							
							p.readValueForCharacteristic(characteristic);
							
							Ti.API.info('Characteristic Value:', characteristic.value);
							
						}
						
					});
				});	
				
				p.discoverCharacteristicsForService({
					characteristics : [],
					service : service
				});
			}
			*/
		});
    });
    
    
    // Discover services
    connectedPeripheral.discoverServices();
});


// -----------------------------------------------------------------------------
// Central Manager Updated State
// -----------------------------------------------------------------------------
centralManager.addEventListener('didUpdateState', function(e) 
{
    Ti.API.info('Central Manager State Updated:');
    
    switch (e.state) {
        case BLE.MANAGER_STATE_RESETTING: 
            Ti.API.info('Resetting');
        break;

        case BLE.MANAGER_STATE_UNSUPPORTED: 
            Ti.API.info('Unsupported');
        break;

        case BLE.MANAGER_STATE_UNAUTHORIZED: 
            Ti.API.info('Unauthorized');
        break;
        
        case BLE.MANAGER_STATE_POWERED_OFF: 
            Ti.API.info('Powered Off');
        break;
        
        case BLE.MANAGER_STATE_POWERED_ON: 
            Ti.API.info('Powered On');
        break;
        
        case BLE.MANAGER_STATE_UNKNOWN: 
        default: 
            Ti.API.info('Unknown');
        break;
    }
});

and output:

[INFO] :   Central Manager State Updated:
[INFO] :   Powered On
[INFO] :   Peripheral "Security Tag" Found...
[INFO] :   Connected to Periperal...
[INFO] :   Service Discovery...
[INFO] :   peripheral has 6 service(s)
[INFO] :   BatteryService Found: 180F
[INFO] :   Characteristic ID: 2A19
[INFO] :   Characteristic Value: I

I'm not sure why the characteristic value is showing as I, and the immediate alert service:

// Assign immediate alert service
			
			if(service.uuid == gattImmediateAlert)
			{
				Ti.API.info("Immediate Alert Found: " + service.uuid);
				serviceImmediateAlert = service;
			
				p.addEventListener('didDiscoverCharacteristicsForService', function(e) 
				{
					var characteristics = e.service.characteristics;
					
					characteristics.forEach(function(characteristic) 
					{
						Ti.API.info('Characteristic ID:', characteristic.uuid);
						
						// Subscribe to this characteristic and receive value changes from peripheral
						if(characteristic.uuid == '2A06')
						{										
							p.setNotifyValueForCharacteristic(true, characteristic);							
							p.readValueForCharacteristic(characteristic);
							
							Ti.API.info('Characteristic Value:', characteristic.value);
							
						}
						
					});
				});	
				
				p.discoverCharacteristicsForService({
					characteristics : [],
					service : service
				});
			}

output:

Connected to Periperal...
[INFO] :   Service Discovery...
[INFO] :   peripheral has 6 service(s)
[INFO] :   Immediate Alert Found: 1802
[INFO] :   Characteristic ID: 2A06
[INFO] :   Characteristic Value: [object TiBlob]

When i press the button on the peripheral that changes the Immediate Alert State I am not getting a value change callback response. So it appears that its not subscribing to the characteristic, or the callback isnt working.

@hansemannn
Copy link
Owner

There are a couple of issues in your code, one sinificant is:

p.setNotifyValueForCharacteristic(true, characteristic);							
p.readValueForCharacteristic(characteristic);
Ti.API.info('Characteristic Value:', characteristic.value);

You cannot set, get and display a value synchronously.

Writing will fire didUpdateNotificationStateForCharacteristic (just exposed as a new event), writing will fire didUpdateValueForCharacteristic. BLE is highly asynchronous and event-driven, please check the exposed events to receive the correct values and become familiar with the general event-driven programming.

@lazzaratom
Copy link

Hi FizixRichard have you solved?

@FizixRichard
Copy link
Author

FizixRichard commented Sep 25, 2017

No I haven't, I'm looking through the BTLE core docs and examples as per hansemannn's suggestion. However it doesn't seem to mesh with this API. In the examples it appears as though they are subscribing to the service characteristic and then listening for state changes from the device. Similarly with that expensive titanium BT plugin, the heart rate sensor just subscribes to the characteristic and then listens for value change notifications. It feels like there is something "missing" that's going on behind this that I'm not seeing.

@lazzaratom
Copy link

Hi hansemannn what is the right code for read Characteristic notifications from BLE device?
I have 1 service (FFE0) with 1 Characteristic (FFE1).
Can you write sample code?
Thanks in advance.

@FizixRichard
Copy link
Author

If I can figure it out I'll post code and an example to the project. Still, any help would be greatly appreciated.

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

p.addEventListener('didUpdateValueForCharacteristic', _didUpdateValueForCharacteristic);
p.setNotifyValueForCharacteristic(true, characteristic);

function _didUpdateValueForCharacteristic(e) {
  Ti.API.info('didUpdateValueForCharacteristic');
  Ti.API.info(e);
 }

every time the peripheral updates value, _didUpdateValueForCharacteristic will be called

@lazzaratom
Copy link

Hi wilson,
this is my code (from app.js example):

var BLE = require('ti.bluetooth');
var peripheralManager;

var win = Ti.UI.createWindow({
backgroundColor : '#fff'
});

var btn1 = Ti.UI.createButton({
title : 'Start scan',
top : 40
});

var centralManager = BLE.createCentralManager();
var peripheralManager = BLE.createPeripheralManager();

btn1.addEventListener('click', function() {
if (centralManager.isScanning()) {
alert('Already scanning, please stop scan first!');
return;
} else if (centralManager.getState() != BLE.MANAGER_STATE_POWERED_ON) {
alert('The BLE manager needs to be powered on before. Call initialize().');
return;
}

centralManager.startScan();
Ti.API.info('Scanning....');
// Optional: Search for specified services
// centralManager.startScanWithServices(['384DF4C0-8BAE-419D-9A65-2D67942C2DB7']);

});

var btn2 = Ti.UI.createButton({
title : 'Stop scan',
top : 100
});

btn2.addEventListener('click', function() {
if (!centralManager.isScanning()) {
alert('Not scanning!');
return;
}
Ti.API.info('Stop scan...');
centralManager.stopScan();
});

/**

  • Central Manager Events
    */

centralManager.addEventListener('didDiscoverPeripheral', function(e) {
console.log('didDiscoverPeripheral');
console.log(e.peripheral.name);

if ((e.peripheral.name != null) && e.peripheral.name.indexOf('HMS') == 0) {
	Ti.API.info('Stop scan...');
	centralManager.stopScan();
	console.log('connecting');
	var options = {
		notifyOnConnection : true,
		notifyOnDisconnection : true,
		notifyOnNotification : true
	};
	centralManager.connectPeripheral(e.peripheral);
}

});

centralManager.addEventListener('didUpdateState', function(e) {
Ti.API.info('didUpdateState');

switch (e.state) {
case BLE.MANAGER_STATE_RESETTING:
	Ti.API.info('Resetting');
	break;

case BLE.MANAGER_STATE_UNSUPPORTED:
	Ti.API.info('Unsupported');
	break;

case BLE.MANAGER_STATE_UNAUTHORIZED:
	Ti.API.info('Unauthorized');
	break;

case BLE.MANAGER_STATE_POWERED_OFF:
	Ti.API.info('Powered Off');
	break;

case BLE.MANAGER_STATE_POWERED_ON:
	Ti.API.info('Powered On');
	break;

case BLE.MANAGER_STATE_UNKNOWN:
default:
	Ti.API.info('Unknown');
	break;
}

});

centralManager.addEventListener('didConnectPeripheral', function(e) {
Ti.API.info('Connected to Periperal...');

connectedPeripheral = e.peripheral;

connectedPeripheral.addEventListener('didDiscoverServices', function(e) {
	Ti.API.info('Service Discovery...');

	p = e.peripheral;

	Ti.API.info('peripheral has', p.services.length, 'service(s)');

	p.services.forEach(function(service) {
		// Assign service
		if (service.uuid == 'FFE0') {
			Ti.API.info("service Found: " + service.uuid);

			p.addEventListener('didDiscoverCharacteristicsForService', function(e) {
				var characteristics = e.service.characteristics;
				characteristics.forEach(function(characteristic) {
					Ti.API.info('Characteristic ID:', characteristic.uuid);
					// Want to subscribe to this characteristic and receive value changes from peripheral
					if (characteristic.uuid == 'FFE1') {
						p.setNotifyValueForCharacteristic(true, characteristic);
					}
				});
			});

			p.discoverCharacteristicsForService({
				characteristics : [],
				service : service
			});
		}

	});
});

// Discover services
connectedPeripheral.discoverServices();

});

centralManager.addEventListener('willRestoreState', function(e) {
Ti.API.info('willRestoreState');
Ti.API.info(e);
});

centralManager.addEventListener('didFailToConnectPeripheral', function(e) {
Ti.API.info('didFailToConnectPeripheral');
Ti.API.info(e);
});

/**

  • Peripheral Manager Events
    */

peripheralManager.addEventListener('didUpdateState', function(e) {
Ti.API.info('didUpdateState');
Ti.API.info(e);
});

peripheralManager.addEventListener('willRestoreState', function(e) {
Ti.API.info('willRestoreState');
Ti.API.info(e);
});

peripheralManager.addEventListener('didStartAdvertising', function(e) {
Ti.API.info('didStartAdvertising');
Ti.API.info(e);
});

peripheralManager.addEventListener('didAddService', function(e) {
Ti.API.info('didAddService');
Ti.API.info(e);
});

peripheralManager.addEventListener('didSubscribeToCharacteristic', function(e) {
Ti.API.info('didSubscribeToCharacteristic');
Ti.API.info(e);
});

peripheralManager.addEventListener('didUnsubscribeFromCharacteristic', function(e) {
Ti.API.info('didUnsubscribeFromCharacteristic');
Ti.API.info(e);
});

peripheralManager.addEventListener('didReceiveReadRequest', function(e) {
Ti.API.info('didReceiveReadRequest');
Ti.API.info(e);
});

peripheralManager.addEventListener('didReceiveWriteRequests', function(e) {
Ti.API.info('didReceiveWriteRequests');
Ti.API.info(e);
});

peripheralManager.addEventListener('readyToUpdateSubscribers', function(e) {
Ti.API.info('readyToUpdateSubscribers');
Ti.API.info(e);
});
peripheralManager.addEventListener('didUpdateValueForCharacteristic', _didUpdateValueForCharacteristic);

function _didUpdateValueForCharacteristic(e) {
Ti.API.info('didUpdateValueForCharacteristic');
Ti.API.info(e);
}

win.add(btn1);
win.add(btn2);
win.open();

@lazzaratom
Copy link

and this is my output:
-- Start application log -----------------------------------------------------
[INFO] : testBluetooth/1.0 (6.2.1.301ffa4)
[INFO] : didUpdateState
[INFO] : Powered On
[INFO] : Scanning....
[INFO] : didDiscoverPeripheral
[INFO] : HMSoft
[INFO] : Stop scan...
[INFO] : connecting
[INFO] : Connected to Periperal...
[INFO] : Service Discovery...
[INFO] : peripheral has 1 service(s)
[INFO] : service Found: FFE0
[INFO] : Characteristic ID: FFE1

@lazzaratom
Copy link

what is wrong?

@lazzaratom
Copy link

....this is that my module send:

1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:48+10:00
1999-12-01T10:52:49+10:00
1999-12-01T10:52:49+10:00
1999-12-01T10:52:49+10:00

simple timestamp....

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

woah, this is a lot, haha, maybe you tell me what are you trying to do and what doesn't work, so that i can pin point the problem and save some time

@lazzaratom
Copy link

i have a simple project where my device (HM-10) send data to mobile (similar serial communication).
I need to subscribe service and characteristic (FFE0-->FFE1) and print data.
If i use app LightBlue i can read HMSoft is my peripheral FFE0 is service FFE1 is characteristic.
When i put Listen for notifications i receive data from device
it is possible to do this?
Thanks

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

yes you can, so I assume you can get the characteristic now? i think the problem of your code is the way you listen to _didUpdateValueForCharacteristic.
try listen it here:

p.addEventListener('didDiscoverCharacteristicsForService', function(e) {
	var characteristics = e.service.characteristics;
	characteristics.forEach(function(characteristic) {
		Ti.API.info('Characteristic ID:', characteristic.uuid);
		// Want to subscribe to this characteristic and receive value changes from peripheral
		if (characteristic.uuid == 'FFE1') {
			p.addEventListener('didUpdateValueForCharacteristic', _didUpdateValueForCharacteristic);
			p.setNotifyValueForCharacteristic(true, characteristic);
		}
	});
});

@lazzaratom
Copy link

This is the code:
centralManager.addEventListener('didConnectPeripheral', function(e) {
Ti.API.info('Connected to Periperal...');
connectedPeripheral = e.peripheral;
connectedPeripheral.addEventListener('didDiscoverServices', function(e) {
Ti.API.info('Service Discovery...');
peripheralManager = e.peripheral;
Ti.API.info('peripheral has', peripheralManager.services.length, 'service(s)');
peripheralManager.services.forEach(function(service) {
// Assign service
if (service.uuid == 'FFE0') {
Ti.API.info("service Found: " + service.uuid);
peripheralManager.addEventListener('didDiscoverCharacteristicsForService', function(e) {
var characteristics = e.service.characteristics;
characteristics.forEach(function(characteristic) {
Ti.API.info('Characteristic ID:', characteristic.uuid);
// Want to subscribe to this characteristic and receive value changes from peripheral
if (characteristic.uuid == 'FFE1') {
peripheralManager.addEventListener('didUpdateValueForCharacteristic', _didUpdateValueForCharacteristic);
peripheralManager.setNotifyValueForCharacteristic(true, characteristic);
}
});
});

			peripheralManager.discoverCharacteristicsForService({
				characteristics : [],
				service : service
			});
		}

	});
});

// Discover services
connectedPeripheral.discoverServices();

});

@lazzaratom
Copy link

the result is the same

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

you should be more specific, or I can't help you

@FizixRichard
Copy link
Author

This isn't working for me.

p.addEventListener('didDiscoverCharacteristicsForService', function(e) 
		{
			var characteristics = e.service.characteristics;
					
			characteristics.forEach(function(characteristic) 
			{
				Ti.API.info('Characteristic ID:', characteristic.uuid);
				
				if(characteristic.uuid == IA_STATE_UUID)
				{
					Ti.API.info('Alert Level Characteristic Found');
					Ti.API.info(characteristic.value);
					
					//p.setNotifyValueForCharacteristic(true, characteristic);
					
					function _didUpdateValueForCharacteristic(e) {
  						Ti.API.info('didUpdateValueForCharacteristic');
  						Ti.API.info(e);
 					}
 					
					p.addEventListener('didUpdateValueForCharacteristic', _didUpdateValueForCharacteristic);
					p.setNotifyValueForCharacteristic(true, characteristic);

					
				}						
			});
		});	

output:

Connected to Periperal...
[INFO] :   Service Discovery...
[INFO] :   peripheral has 6 service(s)
[INFO] :   Immediate Alert Service Found
[INFO] :   Characteristic ID: 2A06
[INFO] :   Alert Level Characteristic Found
[INFO] :   [object TiBlob]

I have a keyfob type peripheral device with a button on it, pressing the button sets the alert level between off, low and high alerts. My app needs to know the current alert level. According to the documentation for the device I can write the alert level or be notified of the alert level. Unfortunately the docs dont explain how.

Using the example you've provided, pressing the button returns no response.

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

@FizixRichard
my fault, try this:

p.addEventListener('didDiscoverCharacteristicsForService', function(e) {
	var peripheral = e.peripheral;
	var characteristics = e.service.characteristics;

	characteristics.forEach(function(characteristic) {
		Ti.API.info('Characteristic ID:', characteristic.uuid);

		if (characteristic.uuid == IA_STATE_UUID) {
			Ti.API.info('Alert Level Characteristic Found');
			Ti.API.info(characteristic.value);

			//p.setNotifyValueForCharacteristic(true, characteristic);

			function _didUpdateValueForCharacteristic(e) {
				Ti.API.info('didUpdateValueForCharacteristic');
				Ti.API.info(e);
			}

			peripheral.addEventListener('didUpdateValueForCharacteristic', _didUpdateValueForCharacteristic);
			peripheral.setNotifyValueForCharacteristic(true, characteristic);
		}
	});
});

@FizixRichard
Copy link
Author

No change, its not notifying me ><

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

Did it go into 'Alert Level Characteristic Found' here?

@FizixRichard
Copy link
Author

Here is the code:

p.addEventListener('didDiscoverCharacteristicsForService', function(e) {
			var peripheral = e.peripheral;
			var characteristics = e.service.characteristics;
		
			characteristics.forEach(function(characteristic) {
				Ti.API.info('Characteristic ID:', characteristic.uuid);
		
				if (characteristic.uuid == IA_STATE_UUID) {
					Ti.API.info('Alert Level Characteristic Found');
					Ti.API.info(characteristic.value);
		
					//p.setNotifyValueForCharacteristic(true, characteristic);
		
					function _didUpdateValueForCharacteristic(e) {
						Ti.API.info('didUpdateValueForCharacteristic');
						Ti.API.info(e);
					}
		
					peripheral.addEventListener('didUpdateValueForCharacteristic', _didUpdateValueForCharacteristic);
					peripheral.setNotifyValueForCharacteristic(true, characteristic);
				}
			});
		});
			
			
		p.services.forEach(function(service) 
		{			
			Ti.API.info("Service Found: " + service.uuid);
			
			
			if (service.uuid == IA_SERVICE_UUID) 
			{
				Ti.API.info('Immediate Alert Service Found');				
				p.discoverCharacteristicsForService({characteristics : [], service: service});					
			}
			
						
			
		});

@FizixRichard
Copy link
Author

Yep, same as before.

One interesting thing. It kinda works if I change the service/characteristic to the GAP Profile on service: 00001C00-D102-11E1-9B23-000EFB0000A7, characteristics 00001C0F-D102-11E1-9B23-000EFB0000A7 and 00001C01-D102-11E1-9B23-000EFB0000A7

If I attempt to listen to these then I get a response when I press the button:

didUpdateValueForCharacteristic
[INFO] :   {
[INFO] :       bubbles = 1;
[INFO] :       cancelBubble = 0;
[INFO] :       characteristic = "[object TiBluetoothCharacteristic]";
[INFO] :       error = "<null>";
[INFO] :       peripheral = "[object TiBluetoothPeripheral]";
[INFO] :       source = "[object TiBluetoothPeripheral]";
[INFO] :       type = didUpdateValueForCharacteristic;
[INFO] :   }
[INFO] :   didUpdateValueForCharacteristic
[INFO] :   {
[INFO] :       bubbles = 1;
[INFO] :       cancelBubble = 0;
[INFO] :       characteristic = "[object TiBluetoothCharacteristic]";
[INFO] :       error = "<null>";
[INFO] :       peripheral = "[object TiBluetoothPeripheral]";
[INFO] :       source = "[object TiBluetoothPeripheral]";
[INFO] :       type = didUpdateValueForCharacteristic;
[INFO] :   }

I assume one callback for each of the two characteristics. This service is labelled as the Find Me Profile but is undocumented in their docs and I assume bespoke. The reason it only kind of works is because I don't know whether this is off, low or high alert and it only fires once, if I press the button again it does not trigger.

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

are you using the latest version? 1.3.0

@FizixRichard
Copy link
Author

1.2.2, I didn't notice a 1.3.0 update, I'll just update and see what happens

@FizixRichard
Copy link
Author

1.3.0 accepts multiple button presses on the proprietary service. Immediate Alert doesn't activate callbacks though.

But, I'm getting callbacks so thank you!

Two questions though:

  1. How would I get the new value in the callback?
  2. How do this for multile services though, if I try to do two services then it only fetches characteristics for the last service in the list?

@lazzaratom
Copy link

hi with 1.3.0 version i have this error:
var peripheralManager = BLE.createPeripheralManager();

message = "undefined is not an object (evaluating 'peripheralManager.addEventListener')";

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

@FizixRichard

  1. var value = e.characteristic.value.toString();
  2. not sure about that, haven't try it

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

@lazzaratom shouldn't be, are you sure your peripheralManager is in the same namespace?

@FizixRichard
Copy link
Author

Thanks. I'm going to do some expansion on it and I'll put them into some examples and submit them so you can include them in this project if you want.

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

@FizixRichard you're welcome :)

@lazzaratom
Copy link

YESSSSSS!!!!!!
Now finally it' work!!!!!
THANKS A LOT!!!!

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

@lazzaratom congrats, and small tips for you guys, you must do the event listener house keeping, or it will cause memory leaks

@lazzaratom
Copy link

just a last question (i hope).
This is the result from my serial monitor:
1999-12-01T15:26:19+10:00
1999-12-01T15:26:19+10:00

and this is the result from BLE:
[INFO] : didUpdateValueForCharacteristic1999-12-01T15:26:19+
[INFO] : didUpdateValueForCharacteristic10:00

Is there a limit on characteristic length?

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

@lazzaratom yes there's a limit but shouldn't be that short

@lazzaratom
Copy link

I have read the limit is 20 bytes it's possible?

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

maybe, and I think you can do some research on how to increase the MTU, never try this before

@FizixRichard
Copy link
Author

one last thing. On getting the value

var value = e.characteristic.value.toString();						
Ti.API.info('VAL: ' + value);

returns:

didUpdateValueForCharacteristic
[INFO] :   {
[INFO] :       bubbles = 1;
[INFO] :       cancelBubble = 0;
[INFO] :       characteristic = "[object TiBluetoothCharacteristic]";
[INFO] :       error = "<null>";
[INFO] :       peripheral = "[object TiBluetoothPeripheral]";
[INFO] :       source = "[object TiBluetoothPeripheral]";
[INFO] :       type = didUpdateValueForCharacteristic;
[INFO] :   }
[INFO] :   VAL: [object TiBlob]

I'm getting a TiBlob object, how do I get the actual value from that? I'm not at all familiar with blobs.

@FizixRichard
Copy link
Author

Yes I will clean up event listeners :)

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

@FizixRichard toString() will convert blob into string, not sure why it doesn't work for you

@FizixRichard
Copy link
Author

I assumed as much, how strange. It's definitely reporting a TiBlob though.

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

sorry mate, can't help you with this, do you know what type it should be? or try toString again?

@focussing
Copy link

focussing commented Sep 25, 2017 via email

@FizixRichard
Copy link
Author

It's ok, I'll figure it out. It should be a string (battery level) or int (alert level)

@focussing
Copy link

Yep, that's why a buffer is required, so you are independent of the type (int or string).
Commercially available Bluetooth modules from Logicallabs (see marketplace) use this also.

@wsliaw
Copy link
Contributor

wsliaw commented Sep 25, 2017

@focussing correct, e.characteristic.value is a buffer (TiBlob), use toString on it should be able to convert it to string

@FizixRichard
Copy link
Author

hmm, battery level comes back as a random character like ">" or ";" whether I output it raw or use ToString(). Could it be getting garboled somewhere?

@FizixRichard
Copy link
Author

FizixRichard commented Oct 26, 2017

Thanks for all the help. How do I submit example code to you for documentation? I've got working code to fetch devices, find characteristics, subscribe and listen for state changes on those characteristics. I need to tidy it up first though.

I have a new question though, this doesn't work for the Android module. I made a copy for Android and make changes as per the example, and stripped it down.

It appears that on Android the process is quite different. It finds devices, appears to auto connect and list services.

However:

  1. The find Devices with Services function doesn't work, it throws an error saying that startScanWithServices() is not a function.

  2. While the service list appears the UDID's look different?

  3. The find services event doesn't fire

  4. How do you listen for state changes in the same way on Android?

I have a sneaking suspicion it doesn't work because there don't appear to be any exposed methods for subscribing and listening for characteristic events, and the documentation looks like the android module is incomplete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants