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

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:
Run a script that connects and immediately disconnects from the sensor using gatttool
Run the data-collection script and send the data to the server
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!")

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.

Related

Raspberry Pi 3 Model B (Android things OS) Error: Failed to open /dev/ttyAMA0: No such file or directory

I am a beginner in Android and testing Android code in which I am receiving and sending data through UART communication.
Hardware for communication- MAX232 device which is connected to Raspberry Pi3 Model B and the other part of MAX232 is connected to Vending Machine Port(Rx,Tx,Gnd to communicate my android app with the Vending Machine). My communication breaks SPORADICALLY and then starts communicating.
I do not know what the reason is
If anyone can help me in this, please suggest. Or any other information will be needed,I will share
private static final String UART_DEVICE_NAME = "UART0"; // define in my code.
**
I have to use ttyAMA0(PL011 UART) port because baudrate does not
change with the core frequency like with ttyS0(MIniUART)
**
For example: If I send 100 commands one by one, I get 2-5 times this
error.
**
> ERROR: Failed to open /dev/ttyAMA0: No such file or directory
**
Same thing happens to me reading data. I do not talk to the device (particle photon) connected to it, just listen. Since i'm expecting a response frequently, anything more than a couple seconds means things have gone south on one side or the other. It didn't seem likely though that my photon code was bad, as I had done many day-long tests with other things reading the data (arduino IDE, whatever).
Anyway, I created a runnable that fires every few seconds and checks when the last received response was. If it exceeds 60 seconds (things are most certainly wrecked and not going to get any better), I'll attempt to start up the connection again (Periperhal manager's openUartDevice). The main code waits another 60 seconds before trying again if it still has not received a response.
I also added code in 'onUartDeviceError' to trigger a callback the second that goes bad (not really sure if that's ever been the culprit in this), which will attempt the same restart logic but with a much smaller wait (like 5 seconds).
Lastly I made the Pi reboot itself (and thus the attached photon) so everything starts fresh, every morning at 6am. This has solved the issue for my purposes and its been in service for somewhere in the neighborhood of two years. Due to this reliability issue I don't do anything important with the pi, it simply exists to aggregate data from a few places and provide JSON. The photon is much more reliable even if the pi stops listening to it, so it controls the important/dangerous stuff (heaters, lithium batteries). Hopes this helps a little, but maybe some reconnect logic would solve the problem.

Understanding & testing Android M+ Doze Mode

I am working on making my Android app a good citizen of the post Android M world which imposes severe constraints on what an app can/cannot do when the device goes into doze. My understanding of the issues involved is still rather fragmentary so I am hoping that someone here can fill the gaps.
The duration of doze
My own empirical findings here
Doze first starts within about half an hour of stationary, screen-off, inactivity
The first maintenance window happens within 30 minutes
The next one happens in about an hour
The ones after than in ca 2, 4 and 6 h. I have not tested beyond that
Are these the official Android doze periods or is it just one empirical observation.
All of the above on an Android N device.
Testing Apps in Doze Mode
Connect the device to a computer with ADB
Bring the app to the foreground
Turn off the device screen
From the command line issue adb shell dumpsys battery unplug
Now cycle through the commands `adb shell dumpsys deviceidle step light OR deep
finally issue adb shell dumpsys battery reset
Entering/Exiting Doze
Happens when the screen is off and the device is not being subjected to movement
Presumably this uses the motion sensor in the phone so a phone sitting quietly on a remarkably smoothly moving train will still enter doze?
If I pick up a dozing phone and start walking around with it without otherwise interacting with it will it automatically exit doze?
Suppose my app is not in the foreground when its host device enters doze. Then I start using the device again but without visiting that app. Will it automatically start "working" again, i.e.
Its broadcast receivers will become functional?
Its handlers will start working?
Its scheduled jobs with setRequiresDeviceIdle(true) will stop being called?
The various modes of Doze & Job Scheduling
From what I have understood there are two doze modes LIGHT & DEEP. They both have sub-modes
LIGHT:Active, Idle, Idle_Maintenance,Override. I do not understand what the various modes do. From ADB I have issued step light with the screen on and seen the return value ACTIVE. With the screen off step light returns IDLE.
DEEP: Active,IDLE_PENDING,SENSING,LOCATING,IDLE,IDLE_MAINTENANCE with the screen on too returns ACTIVE but with the screen off it returns IDLE_PENDING. So when exactly do the other sub modes, IDLE, SENSING... happen?
I assume that IDLE_MAINTENANCE happens when the device enters a maintenance window from DOZE and attempts to run pending Job requests from various apps.
But if that is the case why is it that PowerManager.isDeviceIdleMode() and PowerManger.isPowerSaveMode() ALWAYS return false when I check them when a schedule job in my app runs?
JobInfo.Builder very kindly allows you to set criteria such as setMinimumLatency and setOverrideDeadline but as far as I can tell the OS hen goes and blithely ignores them - at times I have had jobs running withtin seconds of each other and at other times as far as two hours apart.
Why is there no API function to test for Doze and its sub modes? I would expect to find it in PowerManager but all I find there are isDeviceIdleMode and isPowerSaveMode which consistently return false whenever tested
The App in Doze Mode
Will have all its background services destroyed?
Will not get normal priority push messages?
Will not respond to alarms - but is that with the exception of setAndAllowWhenIdle?
Will get no comms from any of its broadcast receivers?
Will not be able to connect to the outside world on sockets - so push messaging, pub/sub etc will not work?
Will immediately destroy any broadcast receivers declared in the Android manifest. This has been my own finding - receivers that I create from Java code stay put, though they do not work during doze.
My own app watches for geo location changes by setting up a broadcast receiver and calling .FusedLocationApi.requestLocationUpdates. This receiver survives the doze/wakeup cycle. However, is there a guarantee my LocationUpdates request still being honored after wake up?
I have run into a rather peculiar bug. I found that my scheduled jobs in doze ran too close to one another on occassion even though I have given them a latency of 900,000 ms (15 minutes) and a deadline of 1,000,000 ms. I thought I would get round this by testing for the last time the job was run by keeping track of the last run time which I did thus
private static Boolean shortInstantGap()
{
Long instantNow = Instant.now().getEpochSecond();
if (300 > (instantNow - this.lastInstant)) return true;
//ignore the job opportunity if the last one was
//less than 300s (5 minutes) ago
this.lastInstant = instantNow;
return false;
}
and then aborting the job slot
private static Runnable timeRunner = new Runnable()
{
#Override
public void run()
{
if (shortInstantGap()) return;
callMyHandlerCode();
}
};
However, I found that this code causes the OS to abruptly terminate my app if it is on screen when I go through a screen-off screen-on cycle. Why was that happening?
Finally, is there not an API call I can use to test that the device has just returned from doze so I get an opportunity to do some post doze housekeeping?
I think good post and questions on this thread, thanks.
Really hope Android OS will improve push notification delays. Sometimes it doesnt get notification for an hour if you dont touch the screen. It may be good for some users due to battery saving but optimising push notification along with battery optimisation can be win win for everyone.
Anyway, here my 2 cents, are a few little tips my for those who want to analyse dozing stuff and those not aware of these already:
Wireless debugging feature can be used to connect device with computer/adb tools. So no need a usb cable and charging the phone while connected doing tests. I think since Android 11 most devices has wireless debugging option under developer options, this works natively without a usb cable setup. If no wifi debugging available(Android versions before 11) then usb cable can be used to setup it.
"adb shell dumpsys deviceidle" this command summarize some info like status of doze and sub states, can be used to check current status during doze/app testings.
You can check other adb doze commands and their effects like forcing doze, enable/disable it etc. online.

Can I send data over my Arduino ethernet without "blocking" my sketch?

Sorry for my bad english first.
I'm currently working on an Arduino project which is really simple.
I'm working on an attendance logger for my school to know how much time students are spending studying.
The RFID Reader part is working fine. When a tag is detected, I'm storing the value and the time in a SD Card.
Every hour, my system have to send the logs to a web server to store it in a database and here come my problem. I'm struggling with the ethernet part.
Indeed, when I'm performing a HTTP Request, my sketch is "blocked" and students can't use the system anymore.
It's a real big problem, because if there are like 200 lines in my logs, sending those throught a request, one by one, will take really long.
I'm already aware of using millis() to use "multi-tasking".
I have absolutly no idea about how to send requests without "blocking" my sketch.. I'm not looking for someone to write my sketch. I just want to know if there is a way to avoid the "blocking" effect of the ethernet shield when I'm performing a request.
Thanks for your help.
Even if you send one by one, you dont have control over the server side. you have no gurantee that the server will Always response within a certain timeframe.
if your system is very busy, then this may not be your perfect solution.
on other hand, just a thought though, (I dont have personal experience with ethernet shield.)
you could send data serially from first arduino to second ardiuno, individually, every time RFID is detected. This should not take much time compare to the time to send 100 lines of logs. Now, one by one, second ardiuno can save these data in its memory until it is finally sent to server.
now when second arduino is busy sending data to server, we can collect some those RFID reading in first arduino's memory, and pass to, when the things with server is done.
to check if second arduino is bg, we could set a pin high in second arduino until the server part is done.
but still, I dont see why do you have to send it every one hour. I am asuming you have your reason.
If you still want to save some time, the make a parallel data transfer between two arduino, instead of serially.

Gatttool "Characteristic Write Request failed:" How to reduce fail timeout for read/write?

I'm reading and writing the characteristics from my board using bluez-4.101. using gatttool.
sometimes i get Characteristic Write Request failed: or read failed.
Frequency of these errors is like 2/10, is there something that i can do to make full proof, if it is usual, I'd like to reduce the timeout i get before failing.
If you say the frequency is not 100% then this is probably not a software issue. Rather, you might have to bring that your devices are brought closer together so that there is less chance of interference, or that your advertising device has a higher tx power.
Unfortunately there is no option through the BlueZ commands to reduce the timeout. I'm guessing you are using the gatttool command to interrogate the gatt table on the other end. Use #gatttool --help-all for a full list of the options and you will see that the timeout is not one of them.

How to synchronize hour between two Win7 machines to have the same timestamp

I developed a MFC application in C++ which I use to capture data from some USB sensors in order to save the information in a TXT file. For each data, I also save the timestamp with boost function.
I need to use my application also with another pc since I have to acquire data twice and I'd like to know what's the best method to synchronize the data between these two pcs.
I'm using the first pc to create a Wifi network and I'm able to connect the second pc to the first one and then I'm trying to use "net time" to set the NTP service without success.
Is there any tutorial or someone which can explain me how to synchronize date time between two Win7 pcs, please?
Perhaps this command? Run from the cmd prompt.
net time \\MasterPC /set /yes
where MasterPC is the network name of the computer you want to take the time from.

Resources