Connect to a MI FlowerCare sensor

Posted on
  • Im trying to connect to a MI FlowerCare sensor. Im having a issue thoe.

    function getData() {
       var gatt;
       NRF.connect("C4:7C:8D:61:FB:E0").then(function(g) {
     gatt = g;
     return gatt.getPrimaryService("00001204-0000-1000-8000-00805f9b34fb");
     }).then(function(service) {
     return service.getCharacteristic("00001a01-0000-1000-8000-00805f9b34fb");
     }).then(function(characteristic) {
     return characteristic.readValue();
     }).then(function(value) {
     console.log(value);
     gatt.disconnect();
     console.log("Done!");
     }).catch(function(error){
     console.log("error", error);
     });
    }
    
    setWatch(function() {
     getData();
    }, 
     BTN, { repeat:true, edge:"rising", debounce:50 });
    

    I get error disconnected it seems that the flower sensor gets disconnected (I get error disconnected) :) in order to save battery there is a automatic disconnect after like 2 secs. Is there something I can do? Is my code correct ? I got the values using the gatttool on a raspberry Pi. I also found some clues here: https://github.com/open-homeautomation/miflora/blob/master/miflora/miflora_poller.py, Any sudgestions?

  • I'm going to try the new firmware 1,92
    But the timeout is in the miflora sensor so I'm not sure it will help. Is there a way to influence the timeout from the puck.js?

  • Puck.js should have no timeout itself - the 1v92 firmware might well help though, so give that a try first.

    Perhaps you could also try using the nRF Connect app and making sure that those services and characteristics are correct and that you can read the values. It might be that the characteristic isn't readable but only handles notifications

  • The nRF connect closes the connection after 2-3 seconds that why I suspect the miflora tries to save energy, it seems that you have to write to a characteristic first, then you could get the real values, otherwise it only return zeroes.

    https://wiki.hackerspace.pl/projects:xiaomi-flora

  • That document mentions handles. Ideally you'd have the actual characteristic UUIDs to use - perhaps you could write some code for Puck.js that uses BluetoothRemoteGATTService.getCharacteristics() in order to get a list of the characteristics with their handles?

    Worst case, you could actually create a new http://www.espruino.com/Reference#BluetoothRemoteGATTCharacteristic class with the internal handle variables set to the handles mentioned in that document, and then set them up as it says?

  • @Gordon thanks. I will go through it step and try the things you mentioned. It sounds like it will work. Looks like I have something to tinker with this weekend to :)

  • Finally some success

    var currentSevice = false;
    
    function getData() {
      var gatt;
      NRF.connect("C4:7C:8D:62:0D:5A").then(function(g) {
        gatt = g;
        return gatt.getPrimaryService("00001204-0000-1000-8000-00805f9b34fb");
      })
      .then(function(service) {
        currentService = service;
        return service.getCharacteristic("00001a00-0000-1000-8000-00805f9b34fb");
     })
     .then(function(characteristic) {
         return characteristic.writeValue([0xa0, 0x1f]);
     })
     .then(() => {
         return currentService.getCharacteristic("00001a01-0000-1000-8000-00805f9b34fb");
     })
     .then((characteristic) => {
        return characteristic.readValue();
     })
     .then(function(value) {
       console.log(value);
       gatt.disconnect();
       console.log("Done!");
     })
       .catch(function(error){
         console.log("error", error);
       });
    }
    
    setWatch(function() {
      getData();
    }, BTN, { repeat:true, edge:"rising", debounce:50 });
    

    Output

    DataView {
      "buffer": new ArrayBuffer([207, 0, 0, 209, 12, 0, 0, 24, 124, 1, 2, 60, 0, 251, 52, 155])
       }
    

    Next is to format the values but I save that for this weekend :)

  • Great! Thanks for posting up your working code as well!

  • //In python 
    temperature, sunlight, moisture, fertility = unpack('<hxIBHxxxxxx',data)
    

    Format C Type Python type Standard size
    h short integer 2
    x pad byte no value
    I unsigned int integer 4
    B unsigned char integer 1
    H unsigned short integer 2

    How can I do this with the ArrayBuffer in JavaScript?

    var data = 
    new ArrayBuffer([215, 0, 0, 208, 13, 0, 0, 20, 53, 1, 2, 60, 0, 251, 52, 155]);
    
    // 21.5 C, type h
    var temp = data[0]/10;
    // ~ 3500 lux, data[2],data[3],data[4], 0,208,13, type I
    //var sunlight =  ?
    // 20 %, data[7], type B
    var moister = data[7];
    // 315,  data[8], data[9], type H
    //var fertility = ?
    

    I wonder if there is an easy solution to this?

  • Gordon has recently added the Dataview class which allows you to pack and read from a byte array have a look in the reference...

  • http://www.espruino.com/Reference#l_DataView_DataView

    function DataView.getInt16(byteOffset)

  • @Wilberforce thank you very much for the help. With a little googling and some other tutorials about the sensor in python I finally had success.

    This is the code I used to get the correct values.

    var currentSevice = false;
    
        function getData() {
          var gatt;
          NRF.connect("C4:7C:8D:62:0D:5A").then(function(g) {
            gatt = g;
            return gatt.getPrimaryService("00001204-0000-1000-8000-00805f9b34fb");
          })
          .then(function(service) {
            currentService = service;
            return service.getCharacteristic("00001a00-0000-1000-8000-00805f9b34fb");
         })
         .then(function(characteristic) {
             return characteristic.writeValue([0xa0, 0x1f]);
         })
         .then(() => {
             return currentService.getCharacteristic("00001a01-0000-1000-8000-00805f9b34fb");
         })
         .then((characteristic) => {
            return characteristic.readValue();
         })
         .then(function(value) {
            console.log("temperature: ", value.getInt16(0, true)/10);
       console.log("Sunlight: ",value.getInt32(3,true));
       console.log("Moister: ", value.getUint8(7,true));
    console.log("Fertility: ", value.getUint16(8,true));
            console.log(JSON.stringify(value.buffer));
           gatt.disconnect();
           console.log("Done!");
         })
           .catch(function(error){
             console.log("error", error);
           });
        }
    
        setWatch(function() {
          getData();
        }, BTN, { repeat:true, edge:"rising", debounce:50 });
    
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Connect to a MI FlowerCare sensor

Posted by Avatar for furuskog @furuskog

Actions