Avatar for Thinkscape


Member since May 2017 • Last active Jul 2017
  • 4 conversations

Most recent activity

  • in Puck.js
    Avatar for Thinkscape

    Hey again! :-)

    This time, it's about Puck.getBatteryPercentage().

    I've got two pucks, purchased together. One is showing a steady 100% battery at all measurements (calls to getBatteryPercentage()), the other one is fluctuating up to 15%. Measurements are made every 30s, the code is the same, no connections, only BLE advertisements.

    Here's how it looks like on a 12h graph:

  • in Puck.js
    Avatar for Thinkscape

    I'm testing something now... I've put the over-high puck into freezer for a minute (went down to ~15 deg). I've then put them together on a table and let them "settle".

    The second puck has also been triggering button presses when I picked it up, or when gently tapping it (without the click, just vibrations).

    I've since reset it again, uploaded my code again and let it settle with temp. I now have around 3 deg difference between them, which is not bad. I'm calibrating them now with a primitive thermometer.

    I'll try to get a more accurate one and calibrate them both again, and see if I get this weird behaviour again.

    I'll report back. Thanks!

  • in Puck.js
    Avatar for Thinkscape

    Hey guys, I need some advice.

    I've purchased two Puck-s (to start with), and I'm running exactly the same code on both, which reports temperature via BLE advertising (example from docs).

    I'm seeing wildly different readings between both -- look at the screenshot below.
    One would report 19, while the other: 27 degrees.

    Is it something I should consider normal?

  • in Puck.js
    Avatar for Thinkscape

    Thanks mate! Works like a charm.
    I'll update the docs, maybe it'll be useful for others as well.

  • in Puck.js
    Avatar for Thinkscape

    I'm not 100% sure the docs you found are for the UUID 0x1809 that's being used though

    GATT docs list that as:

    Health Thermometer  org.bluetooth.service.health_thermometer­    0x1809

    It matches your example in docs. From what I can tell 0x2A1C is a code for "temperature measurement", while 0x1809 is the code for the "health thermometer" service as a whole. Not sure if the NRF library we're using even has a notion of those formats, or is it up for us to provide an implementation.

    The issue is with the EspruinoHub's decoding. It's doing something pretty simple right now - 8 bit is interpreted as-is, and 16 bit is the temperature x100

    Hmm... it seems that you're bitshifting the second value ((((a[1]<<8)+a[0])/100)), which makes it hard for me to reverse it.

    How would you encode a 16 bit float to this that would work on puck (i'm assuming its BE)?

    function encodeFloat(num) {
      const dec = Math.round(n);
      const fractional = Math.round(n % 1 * 100);
      return [ dec, fractional >> 8 ]; // ???
  • in Puck.js
    Avatar for Thinkscape

    Hey there!
    I'm using NRF.setAdvertising() to advertise temperature readings from Puck.js.
    The examples in docs sadly only mention byte arrays, integers and string fragments as supported data:

    // straight from official docs
    setInterval(function() {
        0x1809 : [Math.round(E.getTemperature())]
    }, 30000);

    What I'm trying to do is advertise the floating point temperature without rounding. Puck currently reports temperature with 0.25 accuracy, but I'm struggling with how to encode it in a way, that would make EspruinoHub understand it.

    The official BLE GATT spec for thermometer actually supports extra flags in the first byte and temp. reading (default is Celsius) as a Float32.

    The node on puck doesn't sadly provide Buffer so I tried encoding with TypedArrays like so:

    setInterval(function() {
        0x1809 : temperatureAsArray()
    }, 30000);
    function temperatureAsArray() {
      const a = new Float32Array(1);
      a[0] = E.getTemperature();
      const b = new Uint8Array(a.buffer);
      const c = new Uint8Array(5);
      c[0] = 0;    // the first byte set to 0 means a single celsius measurement without timestamp
     // I've also tried without this byte, didn't change anything
      c.set(b, 1);
      const result = [];
      for (let x = 0; x < c.length; x ++) {
        result[x] = c[x];
      return result;

    The resulting array is something like: [0, 0, 0, 236, 65] for temperature of around 21 deg, or [0, 0, 236, 65] if you don't include the "flags" byte and just have BE 32-bit float.

    However, when I receive it in EspruinoHUB, the debug shows me:

    d1:bf:fb:93:39:bf - Puck.js (RSSI -57)
      1809 => {"temp":0}

    It seems to struggle to decode those Float32 byte arrays.
    When I sent something like [236, 65] (without the GATT flags and trimmed to just 2 bytes) then it shows me:

    d1:bf:fb:93:39:bf - Puck.js (RSSI -57)
      1809 => {"temp":168.76}

    I have no idea how it got 168.75 from those bytes.

    Any idea what EspruinoHub/Noble/bleno expect as a format for floats?

    Have anyone succeeded in encoding floats for BLE Adv. ?

  • in Puck.js
    Avatar for Thinkscape

    Maybe not as sexy as some other projects, but here it goes

    I'm working on a better way to heat my apartment using electric oil heaters, pucks and Wemo plugs.

    1. I'm using Puck.js as temperature sensors, attached to ceiling or walls to measure and average temperature across rooms.
    2. Pucks advertise the temperature via BLE (low-energy, super-long adv. period, very rare temperature reads every few minutes to maximise battery life).
    3. A running instance of EspruinoHUB serves as BLE -> MQTT bridge.
    4. Node-red instance reacts to MQTT messages.
    5. I'm implementing logic which will guarantee temperatures in a set range, in specific rooms, at different days of the week.
    6. Node-red talks via uPnP to Belkin Wemo Insight power switches, turning oil heaters on and off to maintain the temperature.