-
I am so glad you got back to this! I looked into your bangle app as an example to work from and get started. I am trying to take my puck which I use as a simple on/off/volume up/volume down button in Home Assistant based on button presses. I use the SwButton module to do the button click heavy lifting.
1 short press is toggle on and off via generic boolean (0x0F)
1 long press is vol up count (0x09) goes from 0 to 1 vol goes up
2 short presses is vol down count (0x09)goes from 0 to 2 vol goes down
These numbers come in as count in bthome and get used in an automation.I have it working w EspruinoHub and MQTT fine - but want to "upgrade" BTHome so I can use the PiZero with the EspruinoHub on it for something else, and I have a lot to BluetoothProxies around the house anyway.
I wrote the following which seems to work fine except one issue -- the advertised count reverting to 0 after the button is pressed doesn't seem fast enough. Is that in my idletimeout?
Anyway - any comments or ways to make this cleaner/faster appreciated
//https://raw.githubusercontent.com/muet/EspruinoDocs/master/modules/SWButton.js var SWBtn = require("SWButton"); var buttonState = 0; var btnData = {}; var idleTimeout; if (!Puck.bleAdvert) Puck.bleAdvert = {}; // these get created with a puck button press var mySWBtn = new SWBtn(function(k){ if (k === "S" ) { // single button press buttonState = !buttonState; btnData.state = buttonState; btnData.press = + 0; } else if (k === "L" ) { // long button press btnData.press = 1; } else if (k === "SS") { // double short press btnData.press = 2; } updateBTHome(btnData); }); function initBTHome() { tempF = [(E.getTemperature()*9/5)+32]; Puck.bleAdvert[0xFCD2] = [ 0x40, /* BTHome Device Information bit 0: "Encryption flag" bit 1-4: "Reserved for future use" bit 5-7: "BTHome Version" */ 0x01, // Battery, 8 bit E.getBattery(), 0x02, // Temperature, 16 bit tempF&255,tempF>>8, ]; NRF.setAdvertising(Puck.bleAdvert); } setInterval(function() { initBTHome(); }, 1*60*1000); // 1 min function updateBTHome(btnData) { Puck.bleAdvert[0xFCD2] = [ 0x40, /* BTHome Device Information bit 0: "Encryption flag" bit 1-4: "Reserved for future use" bit 5-7: "BTHome Version" */ 0x09, // count button press, 1 bit btnData.press, 0x0F, // binary button state, uint8 (1 byte) btnData.state, ]; NRF.setAdvertising(Puck.bleAdvert); if (idleTimeout) clearTimeout(idleTimeout); idleTimeout = setTimeout(function() { idleTimeout = undefined; Puck.bleAdvert[0xFCD2][2] = 0; NRF.setAdvertising(Puck.bleAdvert); },2000); }
Thanks for getting to this despite it being "another standard"
-
-
-
Coming back to this out of interest due to the new bluetooth proxy that home assistant has. Has anyone looked into BTHome https://bthome.io/ for home Assistant. I think if this was used the whole hub and mqtt could be skipped?
-
ok. Cleared out all my files, went back to basics.
added an image and an info file to storage. then added a ibeacon.boot.js file to storage withvar myiBeacon = require("ble_ibeacon").get({ uuid : [0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx], [#myuuid](http://forum.espruino.com/search/?q=%23myuuid) rssi : -74 }); var _setAdvertising = NRF.setAdvertising; NRF.setAdvertising = function(a,b) { if (Array.isArray(typeof a)) a = [a,myiBeacon]; _setAdvertising(a,b); }; function advertiseBeacon() { NRF.setAdvertising(Bangle.bleAdvert); } if (!Bangle.bleAdvert) Bangle.bleAdvert = {}; setInterval(advertiseBeacon, 60 * 1000); advertiseBeacon();
did a load() and it disconnected from bangle2 with prompt not detected, upload failed, trying to recover. And it reconnected. At that point I checked the file was saved - it was and I did load() and then disconnected - and all seems to work. It is picked up by Home Assistant Espresense as an ibeacon.
I guess I should now try t add widget bootgattbat and see if they all work together. First... a backup
-
Nope. With code below I only get to the bangle logo with a line
-> bluetooththen it sticks
var myiBeacon = require("ble_ibeacon").get({ uuid : [0xbd, 0x84, 0xb1, 0xb2, 0x1c, 0x2c, 0x00, 0xbe, 0x0c, 0xe9, 0x26, 0x70, 0x0f, 0xfe, 0x0c, 0xa0], rssi : -74 }); NRF.setAdvertising = function(a,b) { if (Array.isArray(typeof a)) a = [a,myiBeacon]; _setAdvertising(a,b); }; var _setAdvertising = NRF.setAdvertising; function advertiseBeacon() { NRF.setAdvertising(Bangle.bleAdvert); } if (!Bangle.bleAdvert) Bangle.bleAdvert = {}; setInterval(advertiseBeacon, 60 * 1000); advertiseBeacon();
-
-
Thanks for info on error.
Also - thanks for overwrite of setAdvertising. Tried it and get an error on left side of ide at line 7: invalid typeof value "array"
I g-searched but could not come up with a fix. I assume you are checking to see if incoming a is an array? Sorry - just a hair above my javascript knowledge. -
How would I use this example as a way use my bangle2 to advertising it as a beacon?
I have tried(() => { function advertiseBeacon() { NRF.setAdvertising([ require("ble_ibeacon").get({ uuid : [0xb1, 0xae, 0x51, 0x2b, 0x97, 0x03, 0x4a, 0xe2, 0xb9, 0xc3, 0x9e, 0x26, 0x0c, 0xa7, 0xb3, 0x99], rssi : -60 }) ]); } setInterval(advertiseBeacon, 60 * 1000); advertiseBeacon(); })();
but get a "Uncaught Storage Updated" when I try to save it to a file in storage on the watch.
I want to figure out how to use it in this format
Bangle.bleAdvert[0x180F] = [E.getBattery()];
so they all play together
Thanks
Katherine -
-
nope, not connected to gadgetbridge.
I use espruino hub now for mqtt and bluetooth "translation" to get my puck ble advertising into home assistant for controlling automations with button presses.what I was thinking
I currently have presence detection via bluetooth/home assistant. When presence is detected coming in the front door, check to see if any data avail (via bangle bluetooth ad?) , if so automatically download it to NAS (or somewhere)like I said, clueless so not even sure of the questions to ask.
-
I wonder if you could point me in the direction to get started.
I would like to be able to automatically (?) download my recorder gpx tracks(s) locally either via an automation (eg every day at xx:ii), or eg whenever I am within ble of my espruino hub.Like when I walk in my front door and pass my rasppi, or every night.
I currently have a py automation file that can go get my garmin gpx tracks and store them on my DB, and I'd like to do something similar with my bangle2 recorder gpx files.
Not quite sure where to start.
ThanksThanks
-
Trying not to have my phone by my side constantly, but wanting access simple to Sonos player controls, I started looking for a hardware button that I could use to play/pause my Sonos, and turn the volume up/down. Just something to sit on my desk, nothing fancy, something simple and functional. A one (maybe two) trick pony.
I found Home assistant and Puck.JS and EspruinoHub. Combined, it did the trick. I can sit at my desk, push the puck button one to play/pause, long press to raise the volume, and two short presses to lower the volume.
Note - I am a novice at this so any comments/suggestions welcome.
Read my posting on the Home Assistant website
https://community.home-assistant.io/t/control-sonos-player-with-puck-js-hardware-button/391110
And thanks Gordon for your patience with me on this journey.
-Katherine -
-
I am working on my next project. I'd like to change volume via BLE by using the Puck lying flat on a table and rotating it left or right to send a BLE advertisement volume up (right) or volume down (left). So, rotate puck right - send signal "volumeup". rotate Puck left send signal "volume down".
I don't want (I think) to use the hid keyboard/mouse etc options because I want just a passive signal being sent out to Espruino Hub and "translate" the advertisement via MQTT. I don't want the Puck to have to be connected.
I have tried the various postings for compasses, mag/accel/ averaging but really had no luck. Must admit the maths go a bit over my head. I think what I should be watching is x? going positive or negative but haven't found that to be true in my tests.
The I found the puckrotate posted code on the apploader(?) which works, if the button is vertical. I have tried to figure out how to change it such that it works with the button flat - with no luck.
Thanks
-
-
Thanks @PuckU for this pointer. Was also having a heck of a time getting this installed, with lots of versioning errors. Legacy Raspbian seemed to work, at least with a lot fewer errors.
-
@Gordon In http://forum.espruino.com/comments/13410449/ you stated...
"Advertising is just something that's broadcast - you're not guaranteed to receive it on the phone - so I'd suggest using a 'buttonPresses' variable that just increments. On the phone, if that's different from the last time you got an advertising packet you know that the button has been pressed between times.
It beats using something that's set to 1 and then returns to 0, since you could potentially miss all the advertising packets sent while it was 1."Do you have an example of this? I have my buttonPresses counted and sent via MQTT, but how would my app use it.?
Something like (psuedo) if lastbuttoncount != this buttonCount-1 then... ?
-
-
Yes that was what I meant. Sorry should have been clearer. But I need it at two different speeds, if that makes sense. When the button gets pressed, I need the BLE advertising data to get sent ASAP, while I don't need temp/battery as often, or as quickly. So one setAdvertising when the button gets pressed (used to turn a media player on/off via MQTT) and another more casual setAdvertising which poodles along every 5 minutes or so to let me know Temp and Battery. I think I am probably making this more difficult than it needs to be (smile)
-
-
I am still a bit confused about the differences between setadvertising interval vs setinterval vs timeout.
Is my understanding of each of these examples correct?A: This will send out a single, one shot blast of BLE advertisement of the battery, lasting only of 375 ms
NRF.setAdvertising({ 0x180F : E.getBattery() },{interval: 375 });
B: This will continuously send out a BLE advertisement of the battery once a minute, forever or until the Interval is cleared
setInterval(function () { NRF.setAdvertising({ 0x180F : E.getBattery() }) }, 1 * 60 * 1000);
C. This, with the press of BTN1, this will send out 5 sets of BLE battery advertising once a minute. Each of those five sets of BLE advertising blasts will last 375 ms. In this case I am not sure if I need XX and YY (see code). This is where I get confused.
setWatch(function() { updateBLE(); }, BTN1, { repeat:true, edge:"rising", debounce: 25 }); function updateBLE(presses) { let x = 0; const intervalID = setInterval(() => { if (++x === 5) { global.clearInterval(intervalID); } NRF.setAdvertising({ 0x180F : E.getBattery() },{interval: 375 }); //XX }, 1 * 60 * 1000); //YY }
Thanks
-
Got this to work per your first suggestion. THANK YOU!
Any way to speed the sending of the buttonpress ?
Left in the console logging/press count for debugging to see if it really is working.var buttonState = false; var whichLED; var presses = 0; setInterval(function () { console.log("starting set interval"); updateBLE(presses); }, 10000); function updateBLE(presses) { console.log("update ble advert " + buttonState); NRF.setAdvertising({ 0x1809 : E.getTemperature(), 0x180F : E.getBattery(), 0xFFFF : [buttonState], 0x2A3D : [presses] },{interval: 375}); } setWatch(function() { buttonState = !buttonState; whichLED = buttonState != 1 ? LED3 : LED2; digitalPulse(whichLED, 1, 500); console.log("pressed"); presses++; updateBLE(presses); }, BTN1, { repeat:true, edge:"rising", debounce: 25 });
-Katherine
-
Thanks for the tips - as always very helpful - and again thanks for the bthome example.