-
(editing as my Internet connection dropped while I was replying)
Not sure I understand here... By application you mean Espruino? So you do get the correct number of callbacks, just not with the right data in them?
Yes, the Espruino JavaScript application. I get 59 callbacks, but not the right data, e.g. original packet 2 is missing but I get packet 3 twice.
Is it just packets 2/3/4 that appear to be wrong, or are all the rest of them wrong?
I have the structure of the data I should be receiving. Some fields are fixed while some are dynamically filled with data. The first couple of packets allow me to interpret the rest of the data. Packet 2 received by the application appears correct but it should have been received as packet 3 - the original packet 2 is missing. And packet 3 received by the application should not be a repeat of the previous packet. I haven't checked the following packets.
Do you know exactly what data you should be receiving or if there are certain bytes that definitely don't change in each packet? It might be we can see if the packets are getting combined somehow.
See above. I don't see any indication that packets are being combined. Packet 2 appears to be fully correct, it's just that it should have been received as packet 3.
If you have an NRF DK then you should be able to put it into a wireshark mode where you can see what data is being sent over the air.
I'm afraid I don't (yet).
Do you have any thoughts about how I might be able to reproduce it here?
Seems like the only way would be to send you one of these sensors, but I need to check with the vendor first.
Thanks
-
Hi Gordon,
E.getErrorFlags()
returns an empty array, both at the point when I have received the 2nd packet with the wrong data as well as at the end of the application after all packets have been received.I tried
{minInterval:50, maxInterval:500}
and{minInterval:10, maxInterval:100}
ingatt.connect()
but that also didn't change the behavior.What makes me suspicious is that the application does receive all 59 packet notifications -- so none are lost -- it's just that the DataView passed into the callback consistently contains the wrong data starting with the 2nd packet (EDIT). That seems to indicate a corner case in the native code that passes an object with the wrong buffer reference into the JS callback.
Thanks
-
Yes, I considered that too - that the log statement might interfere with the timing/buffering (although the system should be able to handle that and not just silently mess up the data). For testing, I just changed the code to not print anything but just check the first byte of the 2nd packet. No luck, still 0x00 instead of 0x41.
-
-
Using nRF Connect to read data from my Bluetooth sensor, I write 'g' to the RX characteristic and then read 1099 packets of data via notifications (23 Byte MTU size, including 3 bytes header). See screenshot:
- packet: 04-e1-4B-...: 2 bytes ID and then 4 bytes each for number of packets (55) and number of data bytes (1099)
- packet: 41-A5-43-...: Sensor ID
- packet: 00-00-D6-...: Sensor configuration
- following packets
Using the standard MDBT42Q 2V04 firmware and the application below, however, the packets are not correct. I get the first packet, but the 2nd packet seems to be missing, and the 3 and 4th packet appear to contain identical data (which they don't).
It seems like the event data passed into the characteristicsvaluechanged() callback is not updated properly on each callback, or is my application code incorrect?
Thanks,
-- Terrencevar gatt; var service; var cntdata; var cntpackets; function getData() { console.log("getData()"); console.log("searching for devices ..."); NRF.requestDevice({ timeout: 20000, filters: [{ name: 'device name'}], active:true }) .then(function(device){ console.log("found - connecting ..."); return device.gatt.connect(); }) .then(function(gattp){ console.log("get primary service"); gatt = gattp; return gatt.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); }) .then(function(servicep){ console.log("get TX characteristic"); service = servicep; return service.getCharacteristic("6e400003-b5a3-f393-e0a9-e50e24dcca9e"); }) .then(function(characteristicp){ cntdata = 0; cntpackets = -1; console.log("start notfifications"); characteristicp.on('characteristicvaluechanged', function(event) { var dataview = event.target.value; cntpackets++; if (cntpackets == 0) { console.log("total data: " + dataview.getInt32(2, true) + ", total packets: " + dataview.getInt32(6, true)); } else { cntdata += dataview.byteLength; } console.log("packet: " + cntpackets + ", data: " + cntdata); if (cntpackets < 4) { console.log(dataview); } }); return characteristicp.startNotifications(); }) .then(function(){ console.log("get RX characteristic"); return service.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); }) .then(function(characteristicp){ console.log("send 'g' command"); characteristicp.writeValue('g'); }) .then(function() { return new Promise(function(resolve) { setTimeout(resolve, 10000); }); }) .then(function() { console.log("end delay - disconnecting ..."); gatt.disconnect(); console.log("getData(): done"); }) .catch(function(err) { console.log("ERROR", err); }); } getData();
- packet: 04-e1-4B-...: 2 bytes ID and then 4 bytes each for number of packets (55) and number of data bytes (1099)
-
Hi,
This firmware installed ok, but I cannot connect to MDBT42 via Web Bluetooth or nRF Connect. I can scan for the device, but when I try to connect to it the IDE just says "CONNECTING ..." for a long time and nRF Connect briefly says "Connecting..." but then goes back to DISCONNECTED.
I tried a hard reset, no change. When I re-flash the 2V04 release it works fine.
-
Hi Gordon,
I tried to DFU http://www.espruino.com/binaries/travis/396d5b50fb378206a14de067222a88487ac063bc/espruino_2v04.105_mdbt42q.zip but nRF Connect shows "Starting DFU..." quickly followed by "Disconnecting...".
I am able to DFU the official 2v04 release so maybe the file you created is invalid?
Thanks,
-- Terrence -
-
Fanoush,
Thanks for this, I found a thread on the Nordic forums related to long characteristics (Read long characteristic as ble central). It seems like in my case though the developers first need to fix their hard-coded MTU size ... I can't imagine long reads work if the peers use mismatched MTU sizes. But I will ask them.
Best,
-- Terrence -
-
Yes, sorry, I updated my question after posting ;-)
I think Bluetooth 4.2 is fine in general as it supports the vast majority of use cases.
Regarding the MTU: Is an increased MTU size possible without Data Length extension?
Also, what does the current Espruino stack do with an incoming gatt MTU request? Does it ignore the request or does it respond with an error? My gut feeling is the sensor should not use an MTU of 40 bytes unless the Central device has acknowledged it.
Thanks,
-- Terrence -
Posting this here because I can't seem to find a reference to the supported Bluetooth version in the documentation. E.g. the nRF52832 can support Bluetooth 5.0, but which version does the Espruino Bluetooth stack support?
Specifically, it looks like my BLE sensor requests the MTU size at 40 bytes during connection setup (using the Bluetooth 4.2 packet extension?) and proceeds to send 37 bytes in each packet. When I try to read from the sensor with the MDBT42Q I only get 20 bytes per packet and the rest of the data appears to be missing.
Thanks,
-- Terrence -
Hi Gordon,
Thanks for the reply. Some answers to your questions:
Is it a completely different number, or just the difference between public/random?
This is what I get when I print(device) right after NRF.requestDevice():
BluetoothDevice: { "id": "d1:1a:a8:29:8c:0d random", "rssi": -62, "data": new Uint8Array([2, 1, 6, 9, 9, 78, 88, 84, 71, 78, 32, 35, 50]).buffer, "name": "devicename" }
I get the same for active:true and active:false (except for RSSI, of course)
The usual fix for this would be a long timeout, but it seems you're already doing that. My guess would be that the device is advertising its name in a scan response packet (only available with active:true rather than in the main packet).
According to the sensor documentation the local device name is included in the regular advertising packet, but the manufacturer-specific data is included in the scan response (active scan).
The device is designed to live for many months on battery, so I suspect it sleeps a lot and minimizes transmissions. nRF Connect says the advertising time is 7ms, but I can see 5 to 10s between packets from the device. So I am not surprised that Espruino misses the device occasionally ... it's not a problem, I can just re-scan.
I guess what might be happening is: the BLE device you connect to advertises very rarely (1 sec or less) and only speeds up when it gets asked to provide a scan response in an active scan.
Sounds plausible.
That's really strange. The 2v04 firmware is really very reliable with Bluetooth and I can't remember the last time I crashed it while connecting to anything. You mentioned a Serial connection earlier - if this happens again please can you try while connected on Serial and see if any errors get reported.
Could the cause of the closed connection also be on the Mac OS side (e.g. the Mac Espruino IDE or the Mac OS Bluetooth support)? I will try and capture a reproducible situation for this disconnect and let you know.
Am I right in thinking you're in Germany? If this continues to be an issue is it possible that you could lend me one of those devices to try out?
Yes. I only have one loaner device from the company, but it may be possible to get another one for testing.
I have now fixed it, so if you try with a 'cutting edge' firmware from http://www.espruino.com/binaries/travis/master/ you may have more success.
Great, thanks. I will try that out tomorrow, I hope.
It still doesn't explain the crashes you were seeing though as mine just failed with ERROR Connection Timeout each time.
I tried many different permutations over the last few days so I am not sure about the exact circumstances under which this happened. Will try and reproduce.
Thanks again,
-- Terrence -
Hi Robin,
Confirming this is the MDBT42Q breakout board with 2V04.
I poked around various BLE documentation some more and -- running out of other options -- set the scan to 'active' in NRF.requestDevice({active:true, ...)}. That made a big improvement in the connect() success rate!
The sensor I'm using supports active scanning ... in my BLE understanding this should be compatible with passive scanning (it just allows the peripheral to send additional advertising data in a second packet) but apparently the MDBT42Q stack doesn't handle this transparently.
I found a hint here: Passive scan returns different address type than active scan for BLE devices -- this appears to be related to the nRF BLE stack, but this post is for a Linux Python driver.
The point is that for (some?) devices a passive scan appears to return a different MAC address of the peripheral than an active scan. So when NRF.requestDevice() does a passive scan (which is the default) and finds a device with a specific MAC, but then you pass that MAC into connect() then it doesn't match the active scan MAC of the device and the connection times out. This is very reproducible in my setup if I flip between {active:true} and {active:false}.
The reason this worked in the nRF app may be because the nRF app handles passive vs. active scans transparently ... there appears to be no way in the app to select passive vs. active scanning and maybe the underlying stack deals with the change in MAC automatically.
In any case, using NRF.requestDevice({active:true, ...)} raised the rate of connect() success significantly ... I still get occasional errors that the device is not found or the connect attempt times out (BLE isn't 100% reliable, so that's OK), but now the code succeeds in pulling off the data from the sensor in >80% of runs so that's a huge improvement.
Best,
-- Terrence -
Hi Robin,
I experimented with this some more now. I simplified the setup and removed the TX/RX Serial1 lines, so only using Web Bluetooth to connect the MDBT42Q to the IDE.
I am connecting to this sensor:
https://www.aspion.de/en/transport-data-logger-aspion-g-log-2/
I have the protocol specs but cannot provide them as they are not public. The sensor behaves like a Nordic UART. I am pretty sure the sensor is the not culprit as I am seeing the same MDBT42Q behavior using the nRF app as a peripheral.Thanks for the hint with the power supply. I just switched to a fresh 4 x AA (6V) battery power supply, so power should not be an issue ... and it doesn't appear to be (no change in behavior).
Right now, the MDBT42Q is just very unreliable. I can connect to the sensor and get data with the Android nRF app reliably 100% of the time, but executing the below MDBT42Q code gives me the following results:
- About 30% of the time: "ERROR No device found matching filters"
- About 30% of the time: "ERROR Connection Timeout"
- About 30% of the time: IDE disconnects from MDBT42Q during execution of the program (usually around connect()), so I loose the console and don't know what's happening
- About 10% of the time: Connection succeeds, sensor data is displayed, then connection is successfully closed
I see the same behavior regardless of whether I freshly power-cycle the MDBT42Q or run the program several times in a row using the IDE upload button. I also checked the Bluetooth traffic in my vicinity but the nRF app actually only sees about 10 devices advertising, so traffic density is not a problem (my 2.4 Ghz WiFi environment is also not crowded) ... and again, the Android nRF app works fine so the wireless environment is likely not the issue.
At this point the evidence points to a bug in the Espruino stack making the MDBT42Q too unreliable to be useful.
Thanks,
-- Terrencevar gatt; var service; console.log("start: searching for devices ..."); NRF.requestDevice({ timeout: 20000, filters: [{ name: 'devicename'}] }) .then(function(device){ console.log("found - connecting ..."); return device.gatt.connect(); }) .then(function(gattp){ console.log("get primary service"); gatt = gattp; return gatt.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); }) .then(function(servicep){ console.log("get TX characteristic"); service = servicep; return service.getCharacteristic("6e400003-b5a3-f393-e0a9-e50e24dcca9e"); }) .then(function(characteristicp){ console.log("start notfifications"); characteristicp.on('characteristicvaluechanged', function(event) { console.log("RX: "+JSON.stringify(event.target.value.buffer)); }); return characteristicp.startNotifications(); }) .then(function(){ console.log("get RX characteristic"); return service.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); }) .then(function(characteristicp){ console.log("send command"); characteristicp.writeValue('g'); }) .then(function() { return new Promise(function(resolve) { setTimeout(resolve, 10000); console.log("delayed for 10s"); }); }) .then(function() { console.log("end delay - disconnecting ..."); gatt.disconnect(); console.log("Done!"); }) .catch(function(err) { console.log("ERROR", err); });
- About 30% of the time: "ERROR No device found matching filters"
-
Hi again,
so this is really weird ... for reasons I don't understand it just started working. I can connect to the sensor now (well, most of the time, see below) and I also just added some code to read a service and characteristic and that works as expected. But the connect part of the code is still the same as before, so it's a bit of a mystery.
What I did change was the console settings. I switched from serial back to Web Bluetooth and that seems to have changed the MDBT42Q Central behavior. Although this is still not 100% reliable ... sometimes Web Bluetooth fails to connect to the MDBT42Q and sometimes Web Bluetooth unexpectedly disconnects and I have to power-cycle the MDBT42Q to get it to connect to the IDE again.
It feels like there is some combination of serial, Bluetooth, the console setting, and some other factor that messes up the MDBT42Q Bluetooth stack to a point where it wouldn't connect to anything as a Central. I also still get occasionally "Uncaught InternalError" from the MDBT42Q.
I will keep on eye on this and try to create reproducible behavior. Thanks for helping so far!
Best,
-- Terrence -
Ok, some more info:
I tried connecting to the BLE sensor from iOS and that worked as well, so I am pretty sure the sensor accepts incoming connections just fine and the issue is with the way the MDBT42Q tries to connect to the sensor.
I noticed https://www.espruino.com/Reference#l_NRF_setSecurity, which indicates that "bond" is true by default. The BLE sensor does not do bonding, so trying to bond will fail ... however, I believe since the connection attempt comes before bonding it should still succeed.
Just to be sure, I tried
NRF.setSecurity({bond:false});
but that fails with "Uncaught Error: BLE error 0x7 (INVALID_PARAM)"
Other security parameters can be set just fine, so something is wrong with the "bond" parameter or the documentation.In any case, I am still stuck.
Thanks,
-- Terrence -
Hi Robin,
Thanks for the pointers, I've looked at these two before.
The "GATT connection timeout" doesn't apply because as far as I can tell in that thread the connect() call initially succeeds but then quickly disconnects due to bonding issues. In my case I can't even get the initial connect() call to succeed.
I've also reviewed "BLE Communications" and tried various versions of BLE example code, including using the "ble_uart" module to see if my BLE sensor responds to the Nordic UART service (even-though the nRF app doesn't seem to need it), but no success.
At this point, connect() continues to fail most of the time with a timeout, and when it succeeds (rarely) it is not reproducible.
Best,
-- Terrence -
-
I am using the MDBT42Q with software version 2v04 and the console on Serial1.
The problem I have is that gatt.connect() only rarely succeeds connecting to either of 2 BLE peripheral devices, in more than 9 out of 10 times it throws "ERROR Connection Timeout". I am using very basic code:
NRF.requestDevice({ filters: [{ name: 'devicename'}] }) .then(function(device){ console.log("found - trying to connect"); return device.gatt.connect(); }) .then(function() { console.log("Done!"); }) .catch(function(err) { console.log("ERROR", err); });
I am trying this with 2 BLE devices: A BLE sensor and the nRF app on Android set as an advertiser (discoverable, connectable).
I am using a 2nd Android phone with the nRF app as BLE Central to scan and connect (and then disconnect) to either of these 2 BLE devices, which works reliably. As far as I know no other BLE central device is trying to connect to the devices.
Given that it works from the nRF app and there are very few parameters to tweak the connection establishment in the MDBT42Q I am not sure what to try next. Any help is appreciated.
Thanks
Gordon,
The sensor vendor will supply me with another testing unit that I can forward to you. I will contact you separately to arrange delivery.