Any way to implement BLE notifications in Android-L preview - bluetooth-lowenergy

This question is not about Android notificatinos, but BLE notifications (as the title may hint)
I have got basic BLE peripheral mode working on Android-L
Is there any way to implement BLE notifications in Android-L preview. I could do some thing like the following to make a charecteritic be able to notify, but trying to listen for
BluetoothGattCharacteristic firstServiceChar = new BluetoothGattCharacteristic(
UUID.fromString(serviceOneCharUuid),
BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ );
But in LightBlue app on iOS I cannot subscribe to this characteristic. Apprently there is no API that could be use to respond to the calls when a char is subscribed (like there are in iOS)
Kindly share your code if you have successfully enabled BLE notifications on Android-L

On top of what OP has done:
BluetoothGattCharacteristic firstServiceChar = new BluetoothGattCharacteristic(UUID.fromString(serviceOneCharUuid), BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ )
The next thing is to add a Client Characteristic Configuration descriptor (UUID is the 128 bit version of the 16 bit 0x2902 using the Bluetooth base UUID), so that the connected device can tell yours that it wants notifications (or indications), and then add that descriptor to your characteristic:
BluetoothGattDescriptor gD = new BluetoothGattDescriptor(UUID.fromString("00002902-0000-1000-8000-00805F9B34FB"), BluetoothGattDescriptor.PERMISSION_WRITE | BluetoothGattDescriptor.PERMISSION_READ);
firstServiceChar.addDescriptor(gD);
That UUID is from the Bluetooth spec. Apparently a device subscribes to notifications by updating this descriptor, so you've got to handle this in your BluetoothGattServerCallback by overriding onDescriptorWriteRequest:
#Override
public void onDescriptorWriteRequest (BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
btClient = device; // perhaps add to some kind of collection of devices to update?
// now tell the connected device that this was all successfull
btGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
}
Now update your value and notify the connectee:
firstServiceChar.setValue("HI");
btGattServer.notifyCharacteristicChanged(btClient, firstServiceChar, false);
Hopefully this quick and dirty code will help, because it was OP's code that I used in the first place to even get basic peripheral mode working :)

Related

BLE UART - Sending data from the peripheral to the central?

I am trying to implement a BLE UART service where the central can send down a request, the peripheral takes that request and forwards it to a peripheral application to do processing, and then returns a response back to the central. The design is similar to Figure 2 found in https://punchthrough.com/serial-over-ble/
I am having trouble with the last part to return data back to the central.
Below are the tx/rx characteristics I came across to implement the UART
class TxCharacteristic(Characteristic):
def __init__(self, bus, index, service):
Characteristic.__init__(self, bus, index, UART_TX_CHARACTERISTIC_UUID,
['notify'], service)
self.notifying = False
GLib.io_add_watch(sys.stdin, GLib.IO_IN, self.on_console_input)
def on_console_input(self, fd, condition):
s = fd.readline()
if s.isspace():
pass
else:
self.send_tx(s)
return True
def send_tx(self, s):
if not self.notifying:
return
value = []
for c in s:
value.append(dbus.Byte(c.encode()))
self.PropertiesChanged(GATT_CHRC_IFACE, {'Value': value}, [])
def StartNotify(self):
if self.notifying:
return
self.notifying = True
def StopNotify(self):
if not self.notifying:
return
self.notifying = False
class RxCharacteristic(Characteristic):
def __init__(self, bus, index, service):
Characteristic.__init__(self, bus, index, UART_RX_CHARACTERISTIC_UUID,
['write'], service)
def WriteValue(self, value, options):
data = bytearray(value).decode('utf-8')
print(f'Incoming UART data: {data}')
handle_request(data)
With a BLE scanner phone app, I can write data to the RxCharacteristic OK and when RxCharacteristic receives it, I call handle_request(data) for processing.
This is where I'm stuck. How do I get a handle or reference the TxCharacteristic so that I can call send_tx()? Is the 'notify' characteristic flag what I want or do I want a 'write' flag?
Typically with UART over BLE people use the Notify flag. The central device (phone app) will need to enable notifications so that it gets notified when values change.
Using the Nordic UART Service (NUS) is normally a good example to follow. If you do implement NUS then there are several apps that work with it.
Looking at your code, it looks like the plumbing is there to connect your console to the send_tx method. I suspect that your app isn't doing a StartNotify
It is the icon I've circled in Lime Green in the image below. This is from nRF Connect which is a generic Bluetooth Low Energy scanning and exploration tool.
Apps like Serial Bluetooth Terminal will do StartNotify automatically for NUS

Establishing serial port communication between Arduino and Godot?

I’m wondering how do I go about establishing a serial port communication between Arduino Uno (as my input) and Godot game engine (as my output)? Context is, I'm trying to use sensors on Arduino to move/place objects on Godot, thus I need the serial port code or guidance on how to go about achieving that connection.
Any help is appreciated, thank you everyone!
You can try plugin GDSerCommPlugin. But it is work in progress and i didnt test it so i dont know if it is usable.
Since it's a long time this question was asked, I think that an update is welcome.
Since Godot 3.0, C# is fully supported, I'm using Godot 3.3.2 and my conclusion about dealing with serial communication in Godot is : use C#
You'll keep all the multi platform development advantage of Godot without writing a single (low level) line of code, here is a snipped:
using System.IO.Ports; // for .NET SerialPort
Then in your class if you want to open the port (assuming "SerialPort port" is defined):
port = new SerialPort(portName, (Int32)baudRate, Parity.None, 8, StopBits.One);
Then use the _Process to read the data:
public override void _Process(float delta)
{
if (port != null)
{
if (port.BytesToRead > 0)
{
string serData = port.ReadExisting();
string[] str = serData.Split('\n'); // Just an example
parseLines(str); // Your implementation
}
}
}
Note1: "DataReceived" event from SerialPort doesn't work (I don't know why but I think this is due to the different context) but with Godot this function is useless since you can check and parse directly the data in the _Process function.
Note2: For efficiency it's better to use the ReadExisting() function (and parse lines yourself) than the Readline() function in a loop in the _Process function.
Note3: Sending to serial port is immediate eg:
port.Write("Hello\r");

Trying to identify and range (with BLE) an iPhone transmitting as a peripheral *in the background8.

When an app running on iOS8 is backgrounded, all uniquely identifiable information appears to be scrubbed from the Bluetooth advertising package. peripheral.name, peripheral.identifier, etc. It all goes away as soon as the app is backgrounded.
The only workaround I have discovered - to identify and range multiple bluetooth-emitting apps - is to scan and connect with a set of known devices (iPhones).
My app transmits as a peripheral, with a service that has a characteristic whose value is a unique identifier. This works.
Where I fall down is once I have read the characteristic (and identified the device) I need to range it. In the delegate call for did get RSSI, I get a peripheral object, but due to the asynchronous nature of the delegate pattern I don't know which of the discovered peripherals I am getting the RSSI signal for. Peripheral appears to remain anonymous, even after connected!
-(void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
if (error == nil) {
NSString *valueString=[[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(#"The new value=%#",valueString);
peripheral.delegate = self;
[peripheral readRSSI];
}
}
-(void) peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error {
NSLog(#"Got RSSI update in didReadRSSI : %4.1f", [RSSI doubleValue]);
// but which peripheral (and associated id) did we get back??
}
This is either a limitation of Apple's spec, or something wrong with my expectations. One central to many peripherals, unlike the original Bluetooth architecture of one-to-one.
Any ideas how I can identify and range an app broadcasting as a peripheral while backgrounded? Huge thanks if so!
The CBPeripheral object itself should be unique. You can keep a dictionary of your discovered / connected peripherals along with the custom identifier from your characteristic. When the didReadRSSI delegate is called, you can check against your 'known' collection of devices to identify a specific device.

Decreased BLE startScan detected devices on Android 5.0 Lollipop

Short version:
In my tests with Android 5.0 Lollipop I have noticed android.bluetooth.le.BluetoothLeScanner detects BLE devices less frequently than Android 4.4 KitKat. Why is this and is there an alternative?
Long version:
I am developing an Android application, specifically for the Nexus 7 tablet, that focuses on detecting Bluetooth Low Energy (BLE) devices. The app is mainly interested in the RSSI value of the beacons, to determine their proximity to the tablet. This means I won't need to connect to the BLE device, since the RSSI value is passed to the scan callback when the device is detected.
In Android 4.4 KitKat, when I call BluetoothAdapter.startLeScan(LeScanCallback), my callback gets called only ONCE for every detected BLE device. (I have seen some discussions claim that this behaviour can differ per device) However, I am interested in the constantly changing RSSI value, so the currently recommended way is to continuously do startLeScan and stopLeScan with a set interval (250ms in my case):
public class TheOldWay {
private static final int SCAN_INTERVAL_MS = 250;
private Handler scanHandler = new Handler();
private boolean isScanning = false;
public void beginScanning() {
scanHandler.post(scanRunnable);
}
private Runnable scanRunnable = new Runnable() {
#Override
public void run() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (isScanning) {
adapter.stopLeScan(leScanCallback);
} else if (!adapter.startLeScan(leScanCallback)) {
// an error occurred during startLeScan
}
isScanning = !isScanning;
scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
}
};
private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
// use the RSSI value
}
};
}
Essentially this gives me the required results, but this process is very resource intensive and eventually leads to an unresponsive bluetooth adapter.
For these reasons I upgraded my Nexus 7 to Android 5.0 Lollipop, to see whether my BLE issues would be fixed. In Lollipop BluetoothAdapter.startLeScan(LeScanCallback) is deprecated and replaced with a new API that allows for some more control over the scanning process. From my first tests, it appears startScan does not continuously call my callback (on my Nexus 7) when the RSSI values change, so I still need to use the startScan / stopScan implementation:
#TargetApi(21)
public class TheNewWay {
private static final int SCAN_INTERVAL_MS = 250;
private Handler scanHandler = new Handler();
private List<ScanFilter> scanFilters = new ArrayList<ScanFilter>();
private ScanSettings scanSettings;
private boolean isScanning = false;
public void beginScanning() {
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
scanSettings = scanSettingsBuilder.build();
scanHandler.post(scanRunnable);
}
private Runnable scanRunnable = new Runnable() {
#Override
public void run() {
BluetoothLeScanner scanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
if (isScanning) {
scanner.stopScan(scanCallback);
} else {
scanner.startScan(scanFilters, scanSettings, scanCallback);
}
isScanning = !isScanning;
scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
}
};
private ScanCallback scanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
int rssi = result.getRssi();
// do something with RSSI value
}
#Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
// a scan error occurred
}
};
}
As you can see, I have configured the scanner using the ScanSettings class, which allows you to set the scanMode. I use ScanSettings.SCAN_MODE_LOW_LATENCY, which has the following documentation: "Scan using highest duty cycle. It's recommended to only use this mode when the application is running in the foreground." Sounds exactly like what I want, but unfortunately I only get a beacon detect every 15 - 30 seconds, where the KitKat version shows me the same beacon every 1 - 2 seconds on this scan interval.
Do you have any idea what could be the reason for this difference? Am I missing something, maybe some new settings? Are there alternative ways of doing the above?
Thanks a lot in advance!
Abel
PS: I wanted to include more links to resources I've used, but I don't have the rep points for it yet.
I have gotten very different results with a Nexus 5 running the new Android 5.0 scanning APIs. Detections of BLE packets came in at near real time when using SCAN_MODE_LOW_LATENCY, at every 100ms for BLE beacons transmitting at 10Hz.
You can read the full results here:
http://developer.radiusnetworks.com/2014/10/28/android-5.0-scanning.html
These tests are based off of running the open source Android Beacon Library 2.0's experimental android-l-apis branch here.
It is not obvious what the difference is in your test results, but it is possible that starting and stopping scanning is changing the results.
EDIT: it is possible the hardware is the difference. See a report of similar timings on the Nexus 4: https://github.com/AltBeacon/android-beacon-library/issues/59#issuecomment-64281446
I don't have 50 reputation for a comment yet, so bear with me, this comment will be in the form of an answer. In your code, shouldn't this part:
if (isScanning) {
scanner.startScan(...)
be this instead:
if (!isScanning) {
scanner.startScan(...)
Because following your code, you're calling stopScan() before starting a scan. It may not have a direct effect on the result if the stopScan() method is idempotent/safe. But you know, for the sake of code intelligibility you should edit the question. And do the same to your code, sometimes byzantine things are at play ;)
Have you tried larger values for SCAN_INTERVAL_MS? If yes, how large?
I have experienced very similar results with my Nexus 4, in both KitKat and Lollipop.
With KitKat the bluetooth adapter also eventually went unresponsive; at first I though that it could be related to a short scan interval (200ms) but increasing that number to even a second didn't help, in that matter I found that, when unresponsive disabling and enabling the adapter programmatically, sometimes solves the problem. Unfortunately I can't say that it works all the time.
Now with Lollipop, in which I had high hopes to solve this issues, I experienced the same behaviour that you describe. I also had to use the startScan / stopScan implementation, getting similar results regarding the detection times. Sadly, I haven't found a work around to get results more quickly.
Based on what you describe I suppose it could be a hardware issue, even though the Nexus 7 and Nexus 4 are from different manufacturers (Asus and LG).
I know I'm not providing much help here besides trying to answer your question about you missing something; I don't think so, I think the problem is something like the hardware or the bluetooth API that still doesn't behave the way it should across different devices.
Beyond API 21 android uses SCAN_MODE_LOW_POWER by default.
SCAN_MODE_LOW_POWER
Try SCAN_MODE_BALANCED and see if it gets better.
SCAN_MODE_BALANCED
if you search for BW13_DayOne_Session1 Bluetooth Advanced on google, you will find a pdf document that gives you the latencies for devices based on the settings for discovery (see page 8). I'm guessing your problem has to do with these timings. You can verify by figuring out the advertising configuration for the device you are testing (Adv Int, Duty Cycle) then figure out what the API settings are doing for configuring the scan interval, etc. Once you have these, you can then use that table to interpolate to see if your getting the results you expect.
I know this is a software site, but often when interfacing with hardware you need to know the protocol otherwise your shooting in the dark.

Broadcast TCP-Server with libevent

I am looking for some sample code of a dead simple libevent-based TCP-Server which broadcasts incoming Messages to all connected clients. On the Web I only found TCP-Servers which echoes back messages.
One echo example if found is on the bottom of this page http://www.wangafu.net/~nickm/libevent-book/Ref8_listener.html
I am sure that its not so difficult to change the code provided on this Site, so that messages are brodcast to all connected clients, but I don't know how.
Could someone advise me?
EDIT: Yes, some kind of a chat server. It seams i need to do sth like this:
void server_read_cb(struct bufferevent *bev, void *data)
{
struct evbuffer *input = bufferevent_get_input(bev);
struct evbuffer *output = bufferevent_get_output(bev);
char *mem = malloc(len); /* XXX: check for malloc failure */
evbuffer_remove(input, mem, len);
"for every connection conn" {
/* XXX you'll need to implement a real connection list;
the above isn't real C. */
evbuffer_add(bufferevent_get_output(conn), mem, len);
}
free(mem);
}
But i can't put this to work.
Seems you want something similar to a chat server. One example is here. Basically, when you receive data from one connection, you just go through the list of connections and send that same data to each one (including/excluding the original).

Resources