GATT service on RuuviTag

Posted on
  • Hello,
    I'm trying to set up a GATT service on the Ruuvitag. I used the Espruino's documentation to find that code :

    var Ruuvitag = require("Ruuvitag");
    
    Ruuvitag.setEnvOn(true);
    
    NRF.setServices({
      0x1800: {
        0x2A6E: {
          notify: true,
          value : Ruuvitag.getEnvData().temp,
        }
      }
    }, { advertise: [0x1801] });
    
    setInterval(function () {
      NRF.updateServices({
        0x1800: {
          0x2A6E: {
            value: Ruuvitag.getEnvData().temp,
            notify: true
          }
        }
      });
    }, 1000);
    

    But when I run it on the Ruuvitag, I got the following error from the javascript console :

    Uncaught Error: Unable to find service with UUID 0x2a6e
     at line 8 col 4
      });
       ^
    in function called from system
    

    I don't know what i'm doing wrong. Thanks for helping me.

  • It probably also says something like BLE Connected, queueing BLE restart for later before that?

    The issue is that you're still connected to the RuuviTag over BLE, and the Nordic chips can't change their services on the fly (they can't remove/re-order them). So... Espruino has to wait until you disconnect, then it can restart the Bluetooth LE stack and add the services and everything will work.

    I think if you just upload and disconnect you'll find everything is actually working as you expect.

  • Yes i get this message. Thank you very much. I will try to use BLE with the IDE disconnected.

  • When I'm connecting to RuuvTag with nRFC app on android I can see service but I can't see the characteristic.

  • Try using value : [Math.round(Ruuvitag.getEnvData().temp)]­, instead of value: Ruuvitag.getEnvData().temp,- as you were specifying a floating point value for the characteristic it's possible that caused you some problems.

    The change will just make it clear to Espruino that you want the temperature in a single byte value.

  • I tried several times but nothing changed. Here is my new code :

    var Ruuvitag = require("Ruuvitag");
    
    Ruuvitag.setEnvOn(true);
    
    NRF.setServices({
      0x1800: { // heart_rate
        0x2A6E: { // heart_rate_measurement
          notify: true,
          value : [Math.round(Ruuvitag.getEnvData().temp)]­,
        }
      }
    }, { advertise: [0x1801] });
    
    setInterval(function () {
      NRF.updateServices({
        0x1800: {
          0x2A6E: {
            value : [Math.round(Ruuvitag.getEnvData().temp)]­,
            notify: true
          }
        }
      });
    }, 1000);
    

    Here is what I get with my phone :

    It's says no service. And in the section "TX characteristic" I can see an error from the javascript interpreter but I'm not able to read it because it goes too fast.
    I don't understand why there is an error even with the IDE disconnected. The code looks very simple.

  • Actually I just tried this on a Pixl.js - what happens is when you disconnect it does the Bluetooth restart and tries to add the service. However the Bluetooth stack itself throws an error, because 1800 isn't something you're supposed to add your own characteristics too as far as I can see: https://www.bluetooth.com/specifications­/gatt/viewer?attributeXmlFile=org.blueto­oth.service.generic_access.xml

    That error would get reported to the console, but obviously it can't because you're disconnected!

    I think you meant to use 0x180D not 0x1800? https://www.bluetooth.com/specifications­/gatt/viewer?attributeXmlFile=org.blueto­oth.service.heart_rate.xml

    If you use that it'll be fine.

  • Ok, I understand I can't put the characteristic I want in a random service.
    I tried to follow the requirement for the heart rate service but I still have the same problem. It's says Unable to find the service with UUID 0x2A37.

    var Ruuvitag = require("Ruuvitag");
    
    Ruuvitag.setEnvOn(true);
    
    NRF.setServices({
      0x180D: {
        0x2902:{
          value: 0,
          read: true,
          write: true,
        },
        0x2A37: {
          notify: true,
          value : [Math.round(Ruuvitag.getEnvData().temp)]­,
        }
      }
    }, { advertise: [0x180D] });
    
    setInterval(function () {
      NRF.updateServices({
        0x180D: {
          0x2A37: {
            value : [Math.round(Ruuvitag.getEnvData().temp)]­,
            notify: true
          }
        }
      });
    }, 1000);
    
  • When i delete the NRF.updateServices function I get no error. But I still can't see the service.

  • Well, I just tried your previous example here with 0x180D (and on-board temperature so it works on other devices) and it works fine:

    NRF.setServices({
      0x180D: { // heart_rate
        0x2A6E: { // heart_rate_measurement
          notify: true,
          value : [Math.round(E.getTemperature())],
        }
      }
    }, { advertise: [0x180D] });
    setInterval(function () {
      NRF.updateServices({
        0x180D: {
          0x2A6E: {
            value : [Math.round(E.getTemperature())],
            notify: true
          }
        }
      });
    }, 1000);
    

    You can't 'read' the service because you didn't specify readable : true but you can get notified about changes. "NRF Connect" complains that the data isn't in the right format, but it does receive it.

  • Just to add, the docs for setServices are here: http://www.espruino.com/Reference#l_NRF_­setServices

    Neither read nor write in your example above are valid, so that probably explains why at least 0x2902 isn't readable.

  • Ok thank you so much it works ! Just a last question : if I want to use another service than that of heart rate should I use heart service and just change the name or there is a specific service ?

  • You're not really supposed to re-use UUIDs for different things, so the Bluetooth SIG suggests you should use a totally random 128 bit UUID (the chances of duplicates and then basically nothing).

    So, go to a site like this and get a random UUID - for instance:

    123fd926-40c3-4cf3-9797-9a8703e32795
    

    Then just change the second group of 4 for all your services and characteristics, eg:

    123f0001-40c3-4cf3-9797-9a8703e32795
    123f0002-40c3-4cf3-9797-9a8703e32795
    123f0003-40c3-4cf3-9797-9a8703e32795
    123f0004-40c3-4cf3-9797-9a8703e32795
    

    So then you have:

    NRF.setServices({
      "123f0001-40c3-4cf3-9797-9a8703e32795": {
        "123f0002-40c3-4cf3-9797-9a8703e32795": {
          notify: true,
          value : [Math.round(E.getTemperature())],
        }
      }
    });
    setInterval(function () {
      NRF.updateServices({
        "123f0001-40c3-4cf3-9797-9a8703e32795": {
          "123f0002-40c3-4cf3-9797-9a8703e32795": {
            value : [Math.round(E.getTemperature())],
            notify: true
          }
        }
      });
    }, 1000);
    

    And you're sorted.

    The only gotcha is advertising 128bit UUIDs is hard since they use up a lot of your available space for advertising - so honestly I'd avoid that and would instead try to find your device based on its name (which you can easily change).

  • Thank you for your grateful help !

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

GATT service on RuuviTag

Posted by Avatar for louisld @louisld

Actions