0

I'd like to add a LDR, Humidity and Temperature sensor, as well as some buttons to the Raspberry Pi 3. I mean, wire them to it (I've done that many times before).

Then the RasPi should be able to advertise itself via its integrated BT to a phone when the phone (an app, as it differs from normal Bluetooth) is scanning for Bluetooth LE devices, and ultimately connect to the phone (btgBluetoothGatt = device.connectGatt(context, false, btGattCallback); on Android), so that the phone can receive those sensor data as if it were a heart rate monitor or a speed and cadence sensor.

Is this possible? Where do I start with it?

I'd also prefer to use Python when possible.

1

I am busy finishing a project that does something similar. My project runs terminal command received by a client, allowing them to access the Pi without the need for 'cluttery' keyboards, mice and screens. The Pi will run the command and send the result back to the client device.

I have the Android, iOS and NodeJS code publicly on my GitHub account. I am not sure how you would do this in Python (perhaps this library) but I am fairly certain it'll end up looking similar. My work is heavily dependant on the NodeJS bleno library.

This code allows the Raspberry Pi 3 to advertise itself as a (BLE) peripheral, which your phone can connect to and read the data. The Android and iOS code is a little bad in the sense that:

  1. They hold on to the connection, preventing other devices to connect. A BLE client should connect, get it's info, and then disconnect
  2. The communication serialisation is wasteful, I use a whole message of a single character to represent the beginning and end. It should indicate how many blocks are being sent at the beginning and send that.
  3. The iOS project is VERY basic, I haven't touched it since deciding what to do with the peripheral.

Anyway, here is the NodeJS code if it helps at all.

var bleno = require('bleno');
var exec = require('child_process').exec;

var CHUNK_SIZE = 20;

var Descriptor = bleno.Descriptor;

var deviceName = 'RaspberrPi3';
var myId = '4afb720a-5214-4337-841b-d5f954214877';
var data = new Buffer('Send me some data to display');
var output = "";
var updateCallback;

var terminalCallback;
var terminalResponse;

var START_CHAR = String.fromCharCode(002); //START OF TEXT CHAR
var END_CHAR = String.fromCharCode(003);   //END OF TEXT CHAR

function sliceUpResponse(callback, responseText) {
    if (!responseText || !responseText.trim()) return;
    callback(new Buffer(START_CHAR));
    while(responseText !== '') {
        callback(new Buffer(responseText.substring(0, CHUNK_SIZE)));
        responseText = responseText.substring(CHUNK_SIZE);
    }
    callback(new Buffer(END_CHAR));
}

var terminal = new bleno.Characteristic({
    uuid : '8bacc104-15eb-4b37-bea6-0df3ac364199',
    properties : ['write','read','notify'],
    onReadRequest : function(offset, callback) {
        console.log("Read request");
        callback(bleno.Characteristic.RESULT_SUCCESS, new Buffer(terminalResponse).slice(offset));
    },
    onWriteRequest : function(newData, offset, withoutResponse, callback) {
        if(offset) {
            callback(bleno.Characteristic.RESULT_ATTR_NOT_LONG);
        } else {
            var data = newData.toString('utf8');
            console.log("Command received: [" + data + "]");
            dir = exec(data, function(err, stdout, stderr) {
                if (err) {
                    var stringError = JSON.stringify(err);
                    console.log(stringError);
                    callback(bleno.Characteristic.RESULT_SUCCESS);
                    terminalResponse = stringError;
                } else {
                    console.log(stdout);
                    callback(bleno.Characteristic.RESULT_SUCCESS);
                    terminalResponse = stdout;
                }
                if (terminalCallback) sliceUpResponse(terminalCallback, terminalResponse);
            });
        }
    },
    onSubscribe: function(maxValueSize, updateValueCallback) {
        console.log("onSubscribe called");
        terminalCallback = updateValueCallback;
    },
    onUnsubscribe: function() {
        terminalCallback = null;
        console.log("onUnsubscribe");
    }
});

bleno.on('stateChange', function(state) {
    console.log('on -> stateChange: ' + state);
    if (state === 'poweredOn') {
        bleno.startAdvertising(deviceName,[myId]);
    } else {
        bleno.stopAdvertising();
    }
});

bleno.on('advertisingStart', function(error) {
    console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));
    if (!error) {
        bleno.setServices([
                new bleno.PrimaryService({
                    uuid : myId,
                    characteristics : [
                            // add characteristics here
                            terminal
                    ]
                })
        ]);
        console.log('service added');
    }
});

bleno.on('accept', function(clientAddress) {
    console.log("Accepted connection from: " + clientAddress);
});

bleno.on('disconnect', function(clientAddress) {
    console.log("Disconnected from: " + clientAddress);
});

Since you haven't posted anything you've tried or researched, I would recommend you give it an attempt first and then post questions based on what you have attempted yourself.

  • Thanks for this. I'm actually very new to BT as I've avoided it over all these years because of the bad experiences I had with devices. These last two days I added BTLE support to an Android app for a Heart Rate sensor I bought, and my yesterday's Google searches always lacked the keyword "peripheral", and thus were pretty useless. – Daniel F Aug 4 '17 at 9:51
  • I just found this, it's a slideshow about Python BLE on the Pi: slideshare.net/LarsAlexanderBlumber/ble-with-raspberry-pi – Quintin Balsdon Aug 8 '17 at 8:12
  • Ok, this works. It does crash but that's ok, at least I was able to use the Android app BLE Scanner to connect and enumerate its services, the console log is verbose so that debugging will be easy. As for the slideshow, thanks because it is basic, essential information (some of which I didn't know), but the referenced Python libs are not for writing devices, but to use existing ones. Haven't found anything for Python yet, but NodeJS is ok as well. – Daniel F Aug 14 '17 at 15:39
  • Yeah it's still in development so you're free to submit a pull request into my repo if you manage to find the bug. – Quintin Balsdon Aug 14 '17 at 15:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.