-
- Hear you on that. For awhile I was using a pen insert to push with, or sometimes risking a screwdriver when I didn't want to take a pen apart. Finally took 2 thin coffee stirrer sticks and glued them together forming a skinny but thicker, and stiffer, push stick. Works well.
- .
- Yep. I'm the dude that forked it to make some changes with great results (for me at least). When @Gordon gets back well see if he wants to pull it in. Up to him.
I'm thinking of sacrificing a puck (well, just its mobility really) and making a puck breakout/breadboard just for development/experimentation. USB power, tactile buttons for power cycle, button click, etc. Breakout of all the I/O. Maybe add a small display. Maybe a small buzzer. And importantly, 3v3 TTL serial so I can have a proper connection to the console that doesn't interfere with the BLE. It's just a thought.
- Hear you on that. For awhile I was using a pen insert to push with, or sometimes risking a screwdriver when I didn't want to take a pen apart. Finally took 2 thin coffee stirrer sticks and glued them together forming a skinny but thicker, and stiffer, push stick. Works well.
-
Here's my variation on the Controlling Other Pucks tutorial code. It does some console logging, plus keeps track of attempts, retries, etc. There's a setInterval that simulates a button press every 5 seconds. That can be commented out. What it shows, at least in my case, is that the connection from one puck to another only lasts about 70 seconds, even when being frequently used. Another thing that I did was add some basic retry logic. For each button 'press' the logic will try up to a total of 3 times to connect and toggle the other puck before giving up and calling it a failure. Also attached is a log file that shows my results over a few minutes. Very consistent disconnect, retry pattern.
var busy = false; var connected = false; var txCharacteristic = false; var attempts = 0; var retries = 0; var failures = 0; function writeToggle() { attempts++; return new Promise(function(fulfill, reject) { var emsg = "did not find device"; if(!busy) { if (!connected) { busy = true; // be sure to change the filter to match your puck! NRF.requestDevice({ filters: [{ name: 'Puck.js d958' }] }).then(function(device) { console.log("got device, connecting..."); return device.gatt.connect(); }).then(function(d) { console.log("connected!"); emsg = "did not get service"; connected = d; return d.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); }).then(function(s) { console.log("got service"); emsg = "did not get characteristic"; return s.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); }).then(function(c) { console.log("got characteristic"); emsg = "unable to write value"; txCharacteristic = c; return txCharacteristic.writeValue("toggle()\n"); }).then(function() { console.log("wrote toggle"); emsg = "did not disconnect"; }).then(function() { digitalPulse(LED2, 1, 500); // light green to show it worked busy = false; console.log("success!"); fulfill(); }).catch(function(error) { console.log(emsg + ": " + error); digitalPulse(LED1, 1, 500); // light red if we had a problem if (connected) { connected.disconnect(); connected = false; } busy = false; reject(); }); } else { emsg = "unable to write value"; txCharacteristic.writeValue("toggle()\n").then(function() { digitalPulse(LED2, 1, 500); // light green to show it worked busy = false; fulfill(); }).catch(function(error) { digitalPulse(LED1, 1, 500); // light red if we had a problem console.log(emsg + ": " + error); if (connected) { connected.disconnect(); connected = false; } busy = false; reject(); }); } } }); } function success() { /*console.log("ok");*/ } function retry() { console.log("error, retrying..."); retries++; console.log("attempts: " + attempts + ", retries: " + retries + ", failures: " + failures); return writeToggle(); } function start() { writeToggle() .then(success, retry) .then(success, retry) .catch(function(error) { console.log("oops, failed! " + error !== undefined ? error : ""); failures++; }); } setInterval(function() { start(); }, 5000); setWatch(start, BTN, { edge:"rising", debounce:50, repeat: true });
-
-
-
I experience the same results. I've been tweaking the example code to make it more resilient. The promise paradigm makes that tricky, at least for me. I'll post that code tonight or tomorrow. I find that even when communicating with the remote puck every 5 seconds over an established connection, the connection will just drop after a minute or so.
I've got the EspruinoHub up and running with some changes I made to it. Connecting to a puck seems very fast and reliable. At least with my experience with it. So I wonder if the inconsistency we see is with the puck originating the connection, and not so much with the puck accepting the connection.
-
That's correct, you have to download from the forum. That firmware should have fixed the promise rejection exception. Here's an even newer one: link
When I saw your original post I loaded v90 onto a puck and confirmed the same error, just to see. Then reloaded the 90.12 and it worked fine.
-
That's unfortunate. Is the output the same as your original post above? All I can say is it's working great here. RPi3, fresh install of latest OS, updated and upgraded all packages, followed the instructions for building the hub. Of course it didn't work for me originally but since I modified the hub code it's fine.
-
It's hard to know what's wrong exactly. Clearly the hub is connecting to the puck. You did say sometimes it works. I'm using an RPi3 and the built in bluetooth. This is what I get using the same code for the hub. I can do it 10 times in a row and it's reliable:
Config loaded MQTT Connected <HTTPProxy> Bleno State poweredOn <HTTPProxy> Bleno.startAdvertising Success <HTTPProxy> Bleno.setServices Success Scanning started... MQTT>/ble/write/c7:6e:71:2e:0e:90/nus/nus_tx => "digitalPulse(LED3, 1, 1000);\n" Service 6e400001b5a3f393e0a9e50e24dcca9e Characteristic 6e400002b5a3f393e0a9e50e24dcca9e <Connect> Connected. Getting Services... <Connect> found service: 6e400001b5a3f393e0a9e50e24dcca9e <Connect> found characteristic: 6e400002b5a3f393e0a9e50e24dcca9e <Connect> Writing "digitalPulse(LED3, 1, 1000);\n"... <Connect> wrote data: 20 bytes <Connect> wrote data: 9 bytes <Connect> disconnected! Scanning restarted...
Have you updated the firmware in your puck? What version?
-
@solick I had a very similar problem. I got into the EspruinoHub code and made several changes to the logic and it seems to help a lot. At least for me. Plus I fixed a few other little things. You're welcome to try it out. :post:
https://github.com/dklinkman/EspruinoHub
Also if you want to try a slightly newer firmware look here
-
This is an updated function. Added 2 lines to the 2nd catch. It handles the disconnected case better. You'll still get a red blink because the write fails. But on next press it will try and reconnect and you'll be back in business.
// Function to call 'toggle' on the other Puck function sendToggle() { if (!busy) { busy = true; if (!connected) { NRF.requestDevice({ filters: [{ name: 'Puck.js d958' }] }).then(function(device) { return device.gatt.connect(); }).then(function(d) { connected = d; return d.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); }).then(function(s) { return s.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); }).then(function(c) { txCharacteristic = c; busy = false; // Now actually send the toggle command sendToggle(); }).catch(function() { if (connected) connected.disconnect(); connected=false; digitalPulse(LED1, 1, 500); // light red if we had a problem busy = false; }); } else { txCharacteristic.writeValue("toggle()\n").then(function() { digitalPulse(LED2, 1, 500); // light green to show it worked busy = false; }).catch(function() { if (connected) connected.disconnect(); connected=false; digitalPulse(LED1, 1, 500); // light red if we had a problem busy = false; }); } } }
-
What firmware are you using? Have you updated firmware? There was a bug around promise rejection that was fixed by @Gordon link
The reason for the rejection is the pucks will disconnect from each other after a minute or two. When you press the button the code thinks it's still connected and tried to use the characteristic and fails. Then the bug cause the exception.
-
-
@stevie4711 Are you willing to share the code you are uploading/saving/running when you experience this? I'd love to see if there are similar elements. @Gordon probably has better eyes for it but I'm curious...
-
Well it happened once again but without the BLE message. Maybe a red herring there. Hmmm. New strategy. Don't save while troubleshooting/debugging.
When I need to save options include:
go for it. it may work
pop the battery. services will not start until on-disconnect so should be safe
Use this technique added to on-connect from my PC addr. Connect, disconnect, then reconnect. Slightly less inconvenient than popping the battery. Verified works
-
This may be really obvious to some but I just figured it out.
Using nRF Connect you can monitor your pucks runtime console. In your code write something short to the console every little while. For example:
var clicks = 0; setInterval(function() { console.log("clicks: " + clicks); }, 1000); setWatch(function() { clicks++; }, BTN, { repeat:true, edge:'rising', debounce: 20 });
Disconnect then connect via nRF Connect, expand the UART Service, tap the little bunch of down arrows icon next to TX Characteristic, and watch your button clicks being reported in near real-time;
Yep I realize that connecting nRF to the puck stops the puck from doing certain other bluetoothy things while connected. And I'm not sure about battery friendliness. But it's still cool. Handy for grabbing a quick status update perhaps. Especially when developing/testing. The RX Characteristic lets you send short commands too. But it's not very convenient.
For fast moving values I had good luck outputting short updates every 500ms, and the phone keeping up.
-
Argh! Happened to me again. Apparently reset() doesn't stop the bluetooth services after all.
>reset() =undefined BLE Connected, so queueing service update for later _____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v90.12 Copyright 2016 G.Williams >BLE Connected, so queueing service update for later _____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v90.12 Copyright 2016 G.Williams > =undefined >save() =undefined BLE Connected, so queueing service update for later Erasing Flash... Disconnected
-
I've been able to fairly consistently cause this problem on one of my pucks while I was troubleshooting some code. It occurs when I am uploading the attached file. Generally I would upload some new code, maybe save it, or not, disconnect so I can check the temperature service from my phone, then reconnect. So basically repeating the sequence. It doesn't happen frequently, but on occasion, I get the following on a save:
_____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v90.12 Copyright 2016 G.Williams > =undefined >save() =undefined BLE Connected, so queueing service update for later Erasing Flash... Disconnected
It seems to happen when that BLE message appears during the save. It's not unusual to see that message when the IDE console is connected. But normally it doesn't affect anything.
At this point I have to pull the battery to get reconnected. I can upload code but I can't save it. If I try the puck disconnects. I apply the fix which is this:
var f = require("Flash"); f.erasePage((120 - 3) * 4096); f.erasePage((120 - 2) * 4096); f.erasePage((120 - 1) * 4096);
and then I can reset() and save(), and everything is good again. Upload the code and save(), and back in business. When @Gordon gets back I'm sure he'll take a look at this scenario of the BLE message appearing during the save. If there was a way to disable services I could do that in the NRF.on("connect", ...) function. Maybe I'll try doing a reset 'on connect'. That will stop the services, and then I just need to type load() to get the code back. Services won't be running yet in this case. Or just try to remember to type reset() before uploading new code. Not really a solution though.
-
I was able to figure this out eventually. Can't believe how much google searching and code searching. Bluetooth specs are specific but not much help to the uninformed.
Bottom line is that the value sent to the characteristic needs to be a signed 16 bit integer supplied as a mantissa with an 'implied' decimal exponent of -2. All along I was trying to fit a float16 or a half-precision float or a 4 bit exponent float variant into a sint16 and it just doesn't work. Duh.
This works:
function tempTo2a6e(temp) { var f = parseFloat(temp.toFixed(2)) * 100; if (tempTo2a6e.buf === undefined) tempTo2a6e.buf = new Uint8Array(2); tempTo2a6e.buf[0] = f & 0xff; tempTo2a6e.buf[1] = f >> 8 & 0xff; return tempTo2a6e.buf; } NRF.setServices({ 0x1809 : { 0x2a6e : { readable : true, value : tempTo2a6e(E.getTemperature()) } } });
Be sure to disconnect from the puck and then connect using nRF Connect or whatever and look for the Health Thermometer service. The temperature now reads correctly as 18.75'C. If reading the value using another puck you just need to divide by 100 (or multiply by 10^-2).
Of course this simple example doesn't update the temperature value over time. NRF.updateServices in some sort of a timed loop would do that.
Writing a string to the characteristic does work (doesn't fail) and if you read back the data and interpet it as a string that will work too. But the spec for the characteristic is sint16. Tools like nRF Connect expect to see an sint16 vs an array of chacters which is why it appeared to display an incorrect value.
-
If you mean notifications via MQTT on Android I use MyMQTT. For iOS there's and app called MQTT Tester that I haven't tried. If you mean notification directly from the puck via BLE there's nRF Connect for Android that works. For iOS it's called nRF Toolbox but I haven't tried it. My iPad is too old. For OSX I have no idea.
-
-
-
I have a fork of the EspruinoHub that fixes the problems I have been experiencing. I think this is still related to this thread since mqtt is integral to node-red and being able to initiate and respond to events.
https://github.com/dklinkman/EspruinoHub
I had trouble connecting to the puck reliably, initially, and I was able to figure out over time that this was related to something in noble. But short of it is that I changed the logic in EspruinoHub and it's a lot more reliable now. At least for me.
I also added logic so the mqtt message text sent to the puck was no longer limited to just 20 bytes.
So something like this works now on the RPi:
mosquitto_pub -t /ble/write/c7:6e:71:dd:ee:ff/nus/nus_tx -m $'digitalPulse(LED3, 1, 200);\n'
even while the text is > 20 chars. Note also the RPi /bin/bash $'...' syntax. Required.
Reading a service now works. There was a bug causing a crash. For example the following now reads the puck name:
mosquitto_pub -t /ble/read/c7:6e:71:dd:ee:ff/1800/2A00 -n
and outputs the result when appropriately subscribed to mosquitto_sub -v -t /ble/data/#
/ble/data/c7:6e:71:dd:ee:ff/1800/2a00 Puck.js eeff
I also fixed a problem where the device discovery would stop after an mqtt event resulting in a watchdog timeout and restart but only by the shell script. Now the discovery restart happens more inline.
-
@AntiCat I've got v90.12 also but I'm still having problems. There's something going on inside EspruinoHub with a function within noble called discoverAllServicesAndCharacteristics(). It should return very quickly with arrays of services and characteristics, but most of the time it doesn't and the connect process times out after 4 seconds. At the puck end I see a connection followed by an immediate disconnect. It shouldn't disconnect and that's probably why discoverAllServicesAndCharacteristics() doesn't pass back any data. These are the messages:
<Connect> Timed out getting services. Disconnecting. <Connect> Disconnect error: TypeError: value is out of bounds
The second error is because the timeout is trying to disconnect but the device is already disconnected.
I wrote my own javascript that uses noble and runs at the command line to do similar and I get the same results. Oddly if I do an explicit connect followed only by an explicit disconnect, all of the above works but only one time. It's maddening. In my javascript I changed the logic to do separate discover services and discover characteristics and now that part is working better. I also tweaked the logic to allow writing up to 60 characters vs 20. I might try similar changes to the EspruinoHub logic and see if that helps at all.
-
here's a short bash script that will portion the message into multiple messages. i actually can't test this properly since my hub is messed up but hopefully you get the idea.
#!/bin/bash if [[ -z ${1} ]]; then echo No message! exit -1 fi echo Publishing message: $1 msg=$1 while [[ ! -z ${msg} ]]; do data=${msg:0:20} msg=${msg:20} mosquitto_pub -t /ble/write/c7:6e:71:dd:ee:ff/nus/nus_tx -m "$data" sleep 1 done
for example (assuming the script above is named 'script'):
./script "digitalPulse(LED1, 1, 100);\\n"
Mostly it's long running tests. Connecting several times a minute and logging results to the console will drain the battery in a day or two. But that's expected.