Puck.js send via BLE button press toggle status

Posted on
  • My first Espruino project.

    I just got a Puck.JS. I have been reading for the past few days on BLE, NRF.SetAdvertising, setWatch, tutorials, videos etc. Some excellent stuff out there, but very scattered and some old and some new, so I am a bit confused.

    What I want to do is pretty straight forward - I thought.

    I want to press the button on the Puck.js and turn my stereo on/off through Home Assistant.

    To do this (I think) I want to press the Puck.js button and send a BLE advertisement to a BLE-MQTT Gateway (ESPHome) which turns it into MQTT pub which I can subscribe to in Home Assistant and use to run an automation which will turn a media_player on and off.

    So press- stereo on
    Another press - stereo off.
    Just a plain ol' toggle.

    But I also want the other BLE advertising to go ahead, not just at the button press.

    So... right now I can get E.GetTemperature and E.Battery using NRF.SetAdvertising and can read it via the Gateway/MQTT fine into Home assistant just fine.

    And I can also toggle the state of the button on and off.
    But...
    What I can't do is all of that together. It is an either/ or. Here is my code

    var buttonState = 0;
    NRF.setAdvertising({
      0x1809 : E.getTemperature(),
      0x180F : E.getBattery(),
    }, {interval: 500});
    
    setWatch(function() {
        buttonState = !buttonState;
        digitalWrite(LED2, buttonState);
        NRF.setAdvertising({
            0xFFFF : [buttonState]
        });
    }, BTN1, { repeat:1, edge:"rising", debounce: 20 });
    

    With this code in Puck, (and viewing ble output in nrfconnect) I first see temp and batt, but as soon as I press the button, 0xFFFF gets set with buttonState but Temp and Batt are no longer visible.

    How do I get button state to be passed as and when it is toggled, AND keep temperature and battery going at some set interval as well?

    Thanks

  • Hi, I think all you need is to make sure you keep setting everything you want advertised in setAdvertising. So for example:

    var buttonState = 0;
    
    function updateBLE() {
      NRF.setAdvertising({
        0x1809 : E.getTemperature(),
        0x180F : E.getBattery(),
        0xFFFF : [buttonState]
     }, {interval: 500});
    }
    
    updateBLE();
    setWatch(function() {
        buttonState = !buttonState;
        digitalWrite(LED2, buttonState);
        updateBLE();
    }, BTN1, { repeat:1, edge:"rising", debounce: 20 });
    

    Worth adding that when you call setAdvertising, the values of battery/temp are set at the point that setAdvertising was called, so if you want them to update, you'll need to call it again every few minutes with setInterval

  • Thanks, appreciate the pointers - will give it a go.

  • OK, that works - but I don't want battery and temp updated with button press, I want them only updated at the default advertising time and the button press only updated with the button being pressed. I was thinking I can just pop the buttonState on and off the setAdvertising array?

  • Yes - you can just keep the object you pass to setAdvertising in a global array and just modify the bits you want when you want to

  • 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

  • Any way to speed the sending of the buttonpress ?

    Not sure what you mean here? You mean to make it send faster? You could change interval: 375 to interval: 100 or something like that?

  • 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)

  • OK - finally getting it. Thanks - you have been very patient. Now onto the Home Assistant automation.

  • @Gordon In http://forum.espruino.com/comments/13410­449/ 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... ?

  • Have installed espruino hub and WOW major improvement over esphome hub. fast, toggles, discovered. Other than the requirement to use a legacy version of raspian works great. Love the hub. Now if I could put the hub on my esp32 - that would be great :). thanks

  • Great - glad it's working well for you! Hopefully the changes for non-legacy raspbian shouldn't be huge.

    But yeah, I'd been wondering about having ESP32 'receivers' that could forward what they receive to a Pi/similar but I'm a bit too low on time at the moment

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Puck.js send via BLE button press toggle status

Posted by Avatar for kab @kab

Actions