No connection timeout using javascript sdk
I have switched to the node.js bindings to connect and stream data from MetaMotionR (before I was using python but had a lot of problems). Now performance is better (lower cpu usage, more stable data rates and usually faster connection).
The connection is basically like this:
function connect() {
console.log(format('Discovering {}', sensor_state.address));
MetaWear.discoverByAddress(sensor_state.address.toLowerCase(), function(device) {
console.log(format('Connecting to {}', sensor_state.address));
// you can be notified of disconnects
device.on('disconnect', function () {
console.log(format('Disconnected from {}', sensor_state.address));
process.exit(0);
});
// you'll need to call connect and set up
device.connectAndSetUp(function (error) {
console.log(format('Connected to {} ({})', sensor_state.address, error));
// do stuff
}
}
}
Sometimes, the process is stuck at the "discovering" part, some others at "connecting" part, and I have to kill the process and restart. Isn't there a timeout?
This discussion has been closed.
Comments
discoverByAddress
doesn't complete within X seconds, throw an error, same withconnectAndSetUp
.Also, sometimes the sensor becomes undiscoverable (don't know if frozen or what). So I have to hard reset it, which is difficult because I have to take it out from a custom case we have.
I would like to know if, inside the nodejs app I can reconnect in some way. That is, when I call discoverByAddress, after a timeout I was doing a process.exit(-1), but now I would like that the same process cancels in some way the discoverByAddress call and calls it again (same as if I was pressing ctrl-c and reruning).
Is it possible?
Use
discoverAll
andstopDiscoverAll
https://github.com/noble/noble-device#discovery-api
In fact, the device is discovered, but it is the connectAndSetUp function that "hangs" without any disconnect, error, timeout.
The problem is not only with discover, but with connect. Sometimes the device disconnects after trying to connect using connectAndSetup, but when I try to run the connectAndSetup again, it does not connect (ends up in an endless try-to-connect/timeout/retry loop).
Basically, I need a nodejs process that is able to connect to multiple devices and can reconnect to them if they are: not discovered after X seconds/not connecting after X seconds/suddenly disconnecting.
Before, I solved it by having a process monitor and killing the nodejs process, but with Noble, I cannot connect to multiple devices using multiple processes that share the same hci interface.
The disconnect issue was patched in a C++ SDK update; the JavaScript SDK must still be referencing an earlier release.
You can work around this for now by initializing a new
MblMwMetaWearBoard
objectIf I try to update the javascript sdk using npm, it still uses (I think) the 0.11.4 version.
If I try to install Javascript SDK from git+https, I get an error when it tries to download the submodule.
I downloaded from git the latest JavaScript SDK, compiled it (npm install, locally in that folder) and then copied the MetaWear-Cpp folder and the lib folder to my project node_modules/metawear folder.
Still, I see that the SDK is still compiling libmetawear.0.12.8 instead of 0.12.10.
After the dodgy update I managed to do, still getting the disconnected with error code = 19.
I don't understand what you mean by initializing a MblMwMetaWearBoard object.
I will ask the question in a simpler way:
"How can I implement reconnection using the JavaScript SDK?"
I modified the led.js example code to make a simple reconnect:
And while I get 2 or 3 connect-disconnect-reconnect loops, it gets stuck after a few successful tries. See the console output:
Your code repeatedly adds disconnect handlers, to the point where node will throw warnings about EventEmitter memory leaks. Modify your code such that the disconnect handler is only added once.
A non-zero disconnect status is expected when using
mbl_mw_debug_disconnect
.Now it seems to work better. However, sometimes I encounter this error:
The "Disconnected (error code = xx)" and "Connection error: XXX" lines receive the error code from MetaWear callbacks, executed by the disconnect handler and the connectAndSetUp handler.
Maybe you will reference this message regarding my previous post. I manually updated the node_modules/metawear folder with the C++ SDK. I can see that inside it has the libmetawear.so.0.12.8 and that it is referenced in the nodejs code, so it should be updated even though "npm install metawear" command did not install the newest version.
How can it be initialized? I see in the source code in metawear.js that it is done in the MetaWear library constructor.
Sorry, this was the output of my other code (not the test code I posted). It happens because I have a setTimeout that tries to execute again the connectAndSetup function, so it throws the "Peripheral already conected" error.
In the test code that I put before, the output is:
Which means that the last "connecting..." doesn't finish: either connecting or giving an error. Resetting the board or rebooting is not an option, as in the production system (a raspberry pi) there can be potentially lots of sensors connected (and working).
Having a process manager that monitors (and kills) this process is also not a good option, given that there should be one process per HCI interface, so it can also be the case that there are 3-4 sensors connected and one is frozen connecting, so killing the process would disconnect those 3-4 sensors.
BTW, is this way of handling Ctrl-C correct? Particularly asking about usage of mbl_mw_debug_disconnect
If you've manually updated the underlying C++ SDK to the latest release, then this is a moot point.
The error message states that a connection is already established to the peripheral so disconnect from the remote device before retrying
connectAndSetUp
.There's no way to guarantee the disconnect command was sent before the app closes. The BLE link should be severed anyways when the app terminates so there isn't really a need for a SIGINT handler.
Looks like it is very important to wait for the disconnect before finishing the process. So I have added code to capture the stdin and using it to issue a mbl_mw_debug_disconnect command.
Then in the disconnect handler, I trigger the process.exit(0). In this way, the connection is cleanly finished.
However, the disconnect part is still not working well. If the sensor is in a "good state", it will connect/reconnect each 5 seconds, as shown in the code. This is the normal output:
That 'q' is done by me in order to trigger the "clean disconnect" parsing stdin as I said above. But when the sensor is not in a "good state", as for example if the nodejs code unexpectedly quits (e.g. due to some bug), the output is:
Notice that the "disconnect" is emitted during the "connecting" process (connectAndSetUp call), and then the 'disconnect' handler tries to connect again, but in this case, the subsequent connectAndSetUp calls never go through, stay there in an endless loop.
I have tried to reset the bluetooth service/devices using the following script, even rebooting the machine, with no luck (sometimes it works for killing some connections and making some device discoverable again):
Using Android MetaWear app, I can connect to the sensor, but disconnecting from Android and trying again in linux also does not change anything.
Here's the weird thing: if in Android MetaWear app I go to Sensor Fusion (in the other code that I use the sensors I am using SF) and start streaming, after 3-5 seconds the MetaWear app blocks and I have to restart it. The second time that I connect (Android) to the sensor and go to Sensor Fusion, streaming works well. Then I disconnect and now I am able to use the sensor again in linux.
@Eric any update in this topic?
Sometimes, in normal app functioning, I am getting a sudden disconnect with error code 8, then it tries to reconnect, gets an error code 19 and from then it cannot reconnect anymore.
In this case, if I close the nodejs (multi-)sensor manager, and open again, it can connect to that sensor.
Is there any way of knowing what the error codes are?
connectAndSetUp
able to connect to the board or is it unable to even do that?The following code adds the sensor fusion configuration to my previously sent code. If you ctrl-c right after the "Configuring sensor fusion" message, it should enter in this "limbo state", that is, if you then re-run the code, it should not connect, giving you the error 19.
The connectAndSetUp does not connect after the board is in this limbo state.
I found a list of HCI error codes in https://mynewt.apache.org/network/ble/ble_hs/ble_hs_return_codes/#return-codes-hci
According to this, errors that I am getting so far are:
19 - Remote User Terminated Connection --> after a normal disconnect (triggered by me) and also when the device is in "limbo state" and does not connect
8 - Connection Timeout --> this happens as i said two posts ago, a "sudden disconnect that happens sometimes"
Ok, I'll see what I can do with that script.
On a side note, if the NodeJS app needs to crash / unexpectedly exit in order for this board to be put in the aforementioned limbo state, perhaps your main focus should be on addressing these crashes.
Thank you
Yes, and right now it does not (usually) crash, as now my nodejs program only deals with connection and sending data out. However, bad things happen, like the "sudden disconnect that happens sometimes" or that the user shuts down the raspberry, or it freezes, etc... and the system should be able to recover from that.
After trying out your reproduction steps, it appears that the issue is that the board is still streaming data at a high frequency (100Hz) when the script terminates. This results in the BLE link being immediately flooded with sensor data as soon as connection is restored and the setup part does not complete. You can replicate this behavior by removing the sensor fusion stop code then terminate the script with your
q
input.You have two options here:
connectAndSetup
, then pass the cached state into subsequent calls toconnectAndSetup
I think the best is to serialize the board right after a successful connection, but before setting any sensorfusion or whatever handler. Am I right?
How can i use the mbl_mw_metawearboard_serialize call?
I tried with the following code, but I get an error:
I get the same error by passing "b" instead of "b.ref()".
Call it wherever it is convenient in your code after connection.
Check the bindings file to see what types are expected for the ffi interface. That function requires a reference to a
MetaWearBoard
object and a reference to aref.uint32
object.