User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Reading response from BLE device on rpi3

Thu Jun 21, 2018 11:44 pm

I have a bluetooth relay board that when sent the character over serial "[", responds with this array of relay states:

{1: 1, 2: 1, 3: 1, 4: 1, 5: 0, 6: 0, 7: 1}

Now Im connecting with it via BLE and I can send it commands just fine and it responds fine. But when I send it the "[" character the python script just hangs without a response until I break Ctrl+C with a keyboard interrupt. This is the python code Im using:

Code: Select all

#!/usr/bin/env python
import bluepy.btle as btle

#Delegate methods
class ReadDelegate(btle.DefaultDelegate):
    def handleNotification(self, cHandle, data):
        print("Here is the data...")
        print(data)

#Create peripheral, connect, services and write...
p = btle.Peripheral("00:0E:0B:00:75:12", "random")
p.withDelegate(ReadDelegate())

services=p.getServices()
for service in services:
   print service

s = p.getServiceByUUID("0000ffe0-0000-1000-8000-00805f9b34fb")
c = s.getCharacteristics()[0]
c.write("[")

#pass while no notifications
while True:
    while p.waitForNotifications(1):
        pass
What am I missing?

User avatar
topguy
Posts: 4915
Joined: Tue Oct 09, 2012 11:46 am
Location: Trondheim, Norway

Re: Reading response from BLE device on rpi3

Fri Jun 22, 2018 9:15 am

A Bluetooth LE "characteristic" represents a short data item which can be read or written. These can be fixed (e.g. a string representing the manufacturer name) or change dynamically (such as the current temperature or state of a button). Most interaction with Bluetooth LE peripherals is done by reading or writing characteristics.
You dont send commands with the write function, you already have direct access to the value. My guess is that you should print the "c"-object first. My guess is that its 1 or 0 based on the state of the first relay. You should then try to write 0 or 1 to change the state of the relay.

BLE already have built in protocol for accessing data on the device, you dont need to send special commands : https://www.bluetooth.com/specification ... s-overview

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Fri Jun 22, 2018 10:51 pm

So you're saying I should print the c object as in:

Code: Select all

s = p.getServiceByUUID("0000ffe0-0000-1000-8000-00805f9b34fb")
c = s.getCharacteristics()[0]
print(c)
like that?

User avatar
topguy
Posts: 4915
Joined: Tue Oct 09, 2012 11:46 am
Location: Trondheim, Norway

Re: Reading response from BLE device on rpi3

Fri Jun 22, 2018 11:18 pm

You should probably read the bluepy documentation so you understand what kind of object is stored in "c" and thus learn how to use the "write()" method of that class.

Printing the object might just dump some information about the "characteristic" so you can learn more about it.
I dont really think it will actually do something, it was bad wording on my part.

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Sun Jun 24, 2018 2:35 am

I just tried printing the c object, its just the characteristic:

Code: Select all

Service <uuid=Generic Attribute handleStart=12 handleEnd=15>
Service <uuid=Generic Access handleStart=1 handleEnd=11>
commonName= 0000ffe0-0000-1000-8000-00805f9b34fb
commonName= ffe0
Service <uuid=ffe0 handleStart=16 handleEnd=65535>
65535
commonName= 0000ffe1-0000-1000-8000-00805f9b34fb
commonName= ffe1
Characteristic <ffe1>
with this code:

Code: Select all

p = btle.Peripheral("00:0E:0B:00:75:12", "random")
p.withDelegate(ReadDelegate())

services=p.getServices()
for service in services:
   print service

s = p.getServiceByUUID("0000ffe0-0000-1000-8000-00805f9b34fb")
c = s.getCharacteristics()[0]
print(c)
In my previous setup (with serial gpio connection hm10 on the rpi2) I would have to send "[" and read the response.

User avatar
topguy
Posts: 4915
Joined: Tue Oct 09, 2012 11:46 am
Location: Trondheim, Norway

Re: Reading response from BLE device on rpi3

Sun Jun 24, 2018 2:45 pm

https://ianharvey.github.io/bluepy-doc/ ... istic.html

Do a "print(c.read())" and see what you get then.. if this is one of the relays you should (in theory) get either the character "1" or "0" or the byte 1 or 0.

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Mon Jun 25, 2018 1:40 am

I get nothing...just a blank line

User avatar
topguy
Posts: 4915
Joined: Tue Oct 09, 2012 11:46 am
Location: Trondheim, Norway

Re: Reading response from BLE device on rpi3

Mon Jun 25, 2018 9:40 am

This is what I would maybe do..
- Look for some documentation for BLE for you device.
- Since you only look at the first charateristic ( c = s.getCharacteristics()[0] ) maybe loop trough all of them.
- Or : Install a BLE tool on my smart-phone so I could easily look at and explore all the characteristics.
( https://play.google.com/store/apps/deta ... nner&hl=en )

User avatar
Douglas6
Posts: 4452
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: Reading response from BLE device on rpi3

Mon Jun 25, 2018 4:13 pm

I am not familiar with the BLE device in question, so please take my comments as, well, comments.

Some BLE devices (in particular HM-10 style serial devices) communicate not by responding to characteristic read requests, but by sending notifications (if you are unfamiliar with these BLE concepts, please do some research on BLE programming.) Perhaps by writing a bracket to the characteristic, the device responds by sending a notification. This theory is supported by the fact that reading the characteristic returns nothing.

I've already given marciokoko example code for reading notifications, and I feel that I have have made these points before. There isn't much more I can do without having the device in hand.

As topguy suggests, exploring the device with a good Android BLE app is an excellent way to learn about the device.

And as I have also pointed out, given marciokoko's unfamiliarity with BLE, I suggest he give up on it. His device seems to have a classic Bluetooth interface as well, which can be used with rfcomm to give a more familiar serial device protocol.

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Mon Jun 25, 2018 5:20 pm

Here is the link to the board:
https://www.tinyosshop.com/index.php?ro ... uct_id=684

Here is the screenshot of when I read the value:
ble2.jpg
ble2.jpg (32.03 KiB) Viewed 760 times

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Mon Jun 25, 2018 5:23 pm

@Douglas6

Hadnt seen your post. Yes I did try using notiications and writing the bracket...Thats the OP of this thread. My code is included and the python script just hangs when I run it.

User avatar
topguy
Posts: 4915
Joined: Tue Oct 09, 2012 11:46 am
Location: Trondheim, Norway

Re: Reading response from BLE device on rpi3

Tue Jun 26, 2018 9:17 am

Why exactly do you want to use BLE instead of the serial (rfcomm) profile of standard BT, since you got it working.
The documentation and example apps seems to always uses serial BT. ( cant really be sure about the iphone/android apps )

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Tue Jun 26, 2018 3:22 pm

Im not for any particular way. Im coming from an rpi2 with gpio connected hm10 module which used serial. When I migrated to rpi3, I asked for help and was suggested to use BLE instead, so I did for writing. Now that I have to read I was suggested to use the delegate to listen for notifications.

So how do you suggest I read from the ble device?

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Tue Jul 24, 2018 12:59 am

So can anyone point me in the right direction for reading data from the BLE device using BLE?


User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Fri Jul 27, 2018 10:43 pm

Thanks phatfil. I started reading and noticed that it uses bleno and noble which are js modules. Well I'll venture into the js world but I was looking for a python way for reading BLE characteristics. Would you happen to know of any?

Also, although I don't see why not, will it work for rpi3? Because I noticed the post talks about hci tool for BLE dangles whereas the rpi3 has built in BLE.

PhatFil
Posts: 508
Joined: Thu Apr 13, 2017 3:55 pm

Re: Reading response from BLE device on rpi3

Sat Jul 28, 2018 12:14 am

marciokoko wrote:
Fri Jul 27, 2018 10:43 pm
Thanks phatfil. I started reading and noticed that it uses bleno and noble which are js modules. Well I'll venture into the js world but I was looking for a python way for reading BLE characteristics. Would you happen to know of any?

Also, although I don't see why not, will it work for rpi3? Because I noticed the post talks about hci tool for BLE dangles whereas the rpi3 has built in BLE.
dont dismiss hcitool ;)

sudo hcitool lescan

should list all ble devices within range

here is a python project querying a ble device with a number of sensors..
https://github.com/ThomDietrich/miflora-mqtt-daemon

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Sat Jul 28, 2018 6:02 am

The node one seems much simpler. It seems to be basically:

Code: Select all

noble.on('discover', function(peripheral) {
  peripheral.connect(function(error) {
    console.log('connected to peripheral: ' + peripheral.uuid);
    peripheral.discoverServices(['180a'], function(error, services) {
      var deviceInformationService = services[0];
      console.log('discovered device information service');

      deviceInformationService.discoverCharacteristics(['2a29'], function(error, characteristics) {
        var manufacturerNameCharacteristic = characteristics[0];
        console.log('discovered manufacturer name characteristic');

        manufacturerNameCharacteristic.read(function(error, data) {
          // data is a buffer
          console.log('manufacture name is: ' + data.toString('utf8'));
        });
      });
    });
  });
});
How do I get the peripheral uuid, service and characteristic id's? Using the hci tool?

PhatFil
Posts: 508
Joined: Thu Apr 13, 2017 3:55 pm

Re: Reading response from BLE device on rpi3

Sat Jul 28, 2018 5:44 pm

Since im using the same sensors as Thom, i simply lifted his project added my sensor macs, and scheduled the deamon to start up with the pi-0 its running on.

This project provides the b/tooth interface to the device https://github.com/open-homeautomation/miflora

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Sat Jul 28, 2018 9:32 pm

I'm using this code from https://github.com/tigoe/BluetoothLE-Ex ... explore.js

But they mention:

var peripheralName = "LED"; // the local name of the peripheral you want
var targetService = '19b10000e8f2537e4f6cd104768a1214'; // the service you want
var targetCharacteristic = '19b10001e8f2537e4f6cd104768a1214'; // the characteristic you want

I know the name of my device but what about the service and characteristic? Using the info command from bluetoothctl I got this:
59E1A7F7-9E3B-4302-9D28-F399966B0483.jpeg
59E1A7F7-9E3B-4302-9D28-F399966B0483.jpeg (227.52 KiB) Viewed 532 times
So Im guessing the service data key is the service but I didn't see the characteristic.

PhatFil
Posts: 508
Joined: Thu Apr 13, 2017 3:55 pm

Re: Reading response from BLE device on rpi3

Sat Jul 28, 2018 11:27 pm

page4 of the article i linked to lists lightblue as an example app to use to query ble devices within range for services and characteristics..

User avatar
Douglas6
Posts: 4452
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: Reading response from BLE device on rpi3

Sat Jul 28, 2018 11:33 pm

Bluetoothctl can also be used to list services from a remote BLE device. They are listed (with UUIDs) when a device is connected, and can also be queried with the 'primary' command, I believe.

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Sun Jul 29, 2018 1:28 am

I ran this:

Code: Select all

npm install noble
but it hangs here:

Code: Select all

fetchMetadata: sill resolveWithNewModule [email protected] checking installable status
By hang I mean it took more than 5 minutes so I Ctrl-C out...
Last edited by marciokoko on Sun Jul 29, 2018 3:54 am, edited 1 time in total.

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Sun Jul 29, 2018 3:45 am

ok i found this and i was able to install everything fine:

Code: Select all

npm config set registry http://registry.npmjs.org/
I'm running my js file now. But it hangs here:

Code: Select all

[email protected]:~/bleproject $ sudo node readtsrb.js
Started scanning
My final code is:

Code: Select all

var noble = require('noble');   //noble library
var peripheralName = "BT Bee-BLE";     // the local name of the peripheral you want
var targetService = '0000ffe000001000800000805f9b34fb';         // the service you want
var targetCharacteristic = '0000ffe100001000800000805f9b34fb';  // the characteristic you want

// The scanning function
function scan(state){
  if (state === 'poweredOn') {    // if the radio's on, scan for this service
    noble.startScanning([targetService], false);
    console.log("Started scanning");
  } else {                        // if the radio's off, let the user know:
    noble.stopScanning();
    console.log("Is Bluetooth on?");
  }
}

// the main discovery function
function findMe (peripheral) {
  console.log('discovered ' + peripheral.advertisement.localName);
  peripheral.connect();     // start connection attempts

  // called only when the peripheral has the service you're looking for:
  peripheral.on('connect', connectMe);

  // the connect function. This is local to the discovery function
  // because it needs the peripheral to discover services:
  function connectMe() {
    noble.stopScanning();
    console.log('Checking for services on ' + peripheral.advertisement.localName);
    // start discovering services:
    // you could also use peripheral.discoverSomeServicesAndCharacteristics here,
    // and filter by the target service and characteristic:
    peripheral.discoverAllServicesAndCharacteristics(exploreMe);
  }

  // when a peripheral disconnects, run disconnectMe:
  peripheral.on('disconnect', disconnectMe);
}
// the service/characteristic exploration function:
function exploreMe(error, services, characteristics) {
  console.log('services: ' + services);
  console.log('characteristics: ' + characteristics);

  for (c in characteristics) {
    // since there's only one characteristic, start it blinking:
    startBlink(characteristics[c]);
  }
}

function startBlink(characteristic) {
  // this function reads the characteristic:
  function blink() {
    characteristic.read(changeState);
  }

  // this function changes the characteristic once it's read:
  function changeState(error, data) {
    if (error) throw error;
    var ledState = data[0];
    // if the current state is 1, make it 0, and vice versa:
    data[0] = !ledState;
    // write it back out to the peripheral:
    characteristic.write(data, false, callback);
  }
  // this function calls the blink function again
  // once the characteristic has been successfully read:
  function callback(data, error) {
    if (error) throw error;
    // wait 50ms, then call blink() again:
    interval = setTimeout(blink, 50);
  }

  // this makes the first call to start the blink loop
  blink();
}


function disconnectMe() {
  console.log('peripheral disconnected');
  // exit the script:
  process.exit(0);
}

/* ----------------------------------------------------
The actual commands that start the program are below:
*/
noble.on('stateChange', scan);  // when the BT radio turns on, start scanning
noble.on('discover', findMe);   // when you discover a peripheral, run findMe()

User avatar
marciokoko
Posts: 276
Joined: Sat Aug 27, 2016 4:33 pm

Re: Reading response from BLE device on rpi3

Sun Jul 29, 2018 7:48 pm

ok from what ive been reading, i think noble is for reading and writing ble chars from a rpi (or computer) with a dongle ble. I dont think it works for rpi3 with onboard ble. Whenever I run simply:

Code: Select all

var noble = require('noble');
noble.startScanning();

var serviceUUIDs = ["0000ffe000001000800000805f9b34fb"]; // default: [] => all
var allowDuplicates = false; // default: false

noble.on('stateChange', function(state) {
  if (state === 'poweredOn')
    noble.startScanning();
  else
    noble.stopScanning();
});
it hangs at scanning. And if I run:

Code: Select all

var noble = require('noble');
noble.startScanning();

var serviceUUIDs = ["0000ffe000001000800000805f9b34fb"]; // default: [] => all
var allowDuplicates = false; // default: false

noble.startScanning();
I get this error:
Error: Could not start scanning, state is unknown (not poweredOn)
Why wouldnt the onboard ble NOT be powered!?

Return to “Beginners”