Intermittently getting connect error: Function not implemented (38) when connecting with gatttool

4.8k Views Asked by At

I'm working on a project where I need to get data from a BLE environmental sensor onto a raspberry pi and send it to a server at regular intervals. The more often I can send, the better. I found a script online that works with the particular type of sensor that I'm working, but it only reads the data once and doesn't update unless some device connects and disconnects to the sensor.

So, for example, if I ran the script twice in a row it would contain the same data, but if I run the script once, then connected and disconnected from the sensor with my phone, then ran the script again, it would have new, updated data. Now, I'm trying to make this fully automated and don't want to have to keep connecting and disconnecting with my phone every time to get new data, so I've found that running gatttool and connecting has the same effect as if I were to connect and disconnect with my phone. So I've come up with a somewhat clunky solution of automation that all runs through crontab:

  1. Run a script that connects and immediately disconnects from the sensor using gatttool
  2. Run the data-collection script and send the data to the server
  3. Repeat as soon as possible

Step 3 is where the issue lies. I can't run this series as often as I want. The ideal interval is to collect and send data every 30 seconds, but for some reason I intermittently get an error from gatttool:

connect error: Function not implemented (38)

I get this error on every iteration of the cron schedule until I set the interval so that the scripts only run every 2 minutes, and even then I'm intermittently getting the error. I need the data to be consistent and definitely not as sparse as 2 minutes apart. 1 minute would be the absolute max interval I can afford to have the data sent.

How can I get rid of this error?

My script to connect and disconnect from the device:

import pexpect
import time

print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

scan = pexpect.spawn("sudo hcitool lescan")
time.sleep(5)
print(scan.terminate())

child = pexpect.spawn("sudo gatttool -i hci0 -b E2:D8:9D:FF:72:A2 -I -t random")
child.sendline("connect")

child.expect("Connection successful", timeout=7)
print("connected!")


child.sendline("disconnect")
child.sendline("quit")

child.sendline("sudo hciconfig hci0 down")
child.sendline("sudo hciconfig hci0 up")

print("done!")
1

There are 1 best solutions below

0
On

The script that you linked to at the start of your question does not seem to be connecting to the sensor. My understanding of their script is that it is scanning for the advertising data from the sensor which contains the measurement information. This is a common thing to do and there are many different types of beacons you can get.

I speculate that you are seeing more frequent measurements when you connect and disconnect because that is reseting the advertising as the sensor will not be advertising when you are connected.

On the front-page of the repo you linked to, there is some information about about how to change the measurement interval. You said you wanted this to be every 30 seconds, so that would be a value of 1E that you would need to write to that characteristic.

They suggest an app to do this with. I have used that app and there is nothing specific about that app they point you towards. If you wanted alternatives, I find the nRF Connect app very good for these kinds of activities. If you have the Chrome or Chromium browser installed on your PC or Raspberry Pi, then you can do it from there if you enter the URL of:

chrome://bluetooth-internals/#devices

Press Start Scan -> Inspect the sensor device -> click on 0C4C3010-7700-46F4-AA96D5E974E32A54 service -> click on 0C4C3011-7700-46F4-AA96D5E974E32A54 characteristic -> enter the value (1E) -> press Write button.

This should allow you to use their original script with the frequency of measurement you want.