Puck.js stuck while uploading code with noble.js

Posted on
  • Hi, sometimes when i want to upload buffer code to puck.js, it stuck in middle of uploading.
    I use noble.js, i connect to the puck then convert the code splitted every 19 bytes to write each splitted code to puck.
    Sometimes the uploads stop and i cannot reconnect to the puck , i must force reset it to be able to reconnect..

    sample code :

    0|server   | Sending block "clearInterval();cle", wait 50ms
    0|server   | buffer :  <Buffer 63 6c 65 61 72 49 6e 74 65 72 76 61 6c 28 29 3b 63 6c 65>
    0|server   | Sending block "arWatch();var press", wait 50ms
    0|server   | buffer :  <Buffer 61 72 57 61 74 63 68 28 29 3b 76 61 72 20 70 72 65 73 73>
    0|server   | Sending block "es=0;\nsetWatch(func", wait 50ms
    0|server   | buffer :  <Buffer 65 73 3d 30 3b 0a 73 65 74 57 61 74 63 68 28 66 75 6e 63>
    
    

    i have tested with a delay of 100ms and it change nothing..

    when the upload works :

    0|server   | Sending block "clearInterval();cle", wait 50ms
    0|server   | buffer :  <Buffer 63 6c 65 61 72 49 6e 74 65 72 76 61 6c 28 29 3b 63 6c 65>
    0|server   | Sending block "arWatch();var press", wait 50ms
    0|server   | buffer :  <Buffer 61 72 57 61 74 63 68 28 29 3b 76 61 72 20 70 72 65 73 73>
    0|server   | Sending block "es=0;\nsetWatch(func", wait 50ms
    0|server   | buffer :  <Buffer 65 73 3d 30 3b 0a 73 65 74 57 61 74 63 68 28 66 75 6e 63>
    0|server   | Sending block "tion(){\nif(presses ", wait 50ms
    0|server   | buffer :  <Buffer 74 69 6f 6e 28 29 7b 0a 69 66 28 70 72 65 73 73 65 73 20>
    0|server   | Sending block "> 100){presses=0;}\n", wait 50ms
    0|server   | buffer :  <Buffer 3e 20 31 30 30 29 7b 70 72 65 73 73 65 73 3d 30 3b 7d 0a>
    0|server   | Sending block "presses++;\nLED2.res", wait 50ms
    0|server   | buffer :  <Buffer 70 72 65 73 73 65 73 2b 2b 3b 0a 4c 45 44 32 2e 72 65 73>
    0|server   | Sending block "et();\nLED3.reset();", wait 50ms
    0|server   | buffer :  <Buffer 65 74 28 29 3b 0a 4c 45 44 33 2e 72 65 73 65 74 28 29 3b>
    0|server   | Sending block "\nNRF.setAdvertising", wait 50ms
    0|server   | buffer :  <Buffer 0a 4e 52 46 2e 73 65 74 41 64 76 65 72 74 69 73 69 6e 67>
    0|server   | Sending block "({},{manufacturer:0", wait 50ms
    0|server   | buffer :  <Buffer 28 7b 7d 2c 7b 6d 61 6e 75 66 61 63 74 75 72 65 72 3a 30>
    0|server   | Sending block "x0590,manufacturerD", wait 50ms
    0|server   | buffer :  <Buffer 78 30 35 39 30 2c 6d 61 6e 75 66 61 63 74 75 72 65 72 44>
    0|server   | Sending block "ata:[presses]});\n},", wait 50ms
    0|server   | buffer :  <Buffer 61 74 61 3a 5b 70 72 65 73 73 65 73 5d 7d 29 3b 0a 7d 2c>
    0|server   | Sending block "BTN,{edge:'rising',", wait 50ms
    0|server   | buffer :  <Buffer 42 54 4e 2c 7b 65 64 67 65 3a 27 72 69 73 69 6e 67 27 2c>
    0|server   | Sending block "repeat:1,debounce:5", wait 50ms
    0|server   | buffer :  <Buffer 72 65 70 65 61 74 3a 31 2c 64 65 62 6f 75 6e 63 65 3a 35>
    0|server   | Sending block "0})\nLED1.set()\nsetT", wait 50ms
    0|server   | buffer :  <Buffer 30 7d 29 0a 4c 45 44 31 2e 73 65 74 28 29 0a 73 65 74 54>
    0|server   | Sending block "imeout(function(){L", wait 50ms
    0|server   | buffer :  <Buffer 69 6d 65 6f 75 74 28 66 75 6e 63 74 69 6f 6e 28 29 7b 4c>
    0|server   | Sending block "ED1.reset()},2000)\n", wait 50ms
    0|server   | buffer :  <Buffer 45 44 31 2e 72 65 73 65 74 28 29 7d 2c 32 30 30 30 29 0a>
    0|server   | Sending block "save()", wait 0ms
    0|server   | buffer :  <Buffer 73 61 76 65 28 29>
    

    the full javascript code :

      clearInterval();clearWatch();var presses=0;\nsetWatch(function(){\nif(pre­sses > 100){presses=0;}\npresses++;\nLED2.reset­();\nLED3.reset();\nNRF.setAdvertising({­},{manufacturer:0x0590,manufacturerData:­[presses]});\n},BTN,{edge:'rising',repea­t:1,debounce:50})\nLED1.set()\nsetTimeou­t(function(){LED1.reset()},2000)\nsave()­
    
    

    Thank You!

  • What code are you using on Noble to do the transmit? And what OS are you on?

    I think if Noble isn't transmitting anything it's quite likely it's some issue with your Noble code. There isn't any flow control on Bluetooth LE so Puck.js can't just reject writes. If the write isn't happening it's probably the code that is sending.

    Bluetooth LE OS support can be a bit iffy - I know on Linux it's possible to get it into a state where (for instance) notifications no longer work and you have to restart the Bluetooth stack to get anywhere.

  • I'm on Raspbian Stretch,
    Here the code from my app :

    if (puckJSnoble) {
          puckJSnoble.connect()
          puckJSnoble.once('connect', () => {
            puckJSnoble.discoverAllServicesAndCharac­teristics(function (
              error,
              services,
              characteristics
            ) {
              var txCharacteristic = findByUUID(characteristics, NORDIC_TX)
              var rxCharacteristic = findByUUID(characteristics, NORDIC_RX)
              console.log("passage connected");
              if (txCharacteristic && rxCharacteristic) {
                rxCharacteristic.subscribe(function () {
                  try {
                    var writeData = () => {
                      splitTheScript(scriptInit)
                      setTimeout(() => {
                        txCharacteristic.write(
                          stringToBuffer(splittedScript),
                          false,
                          function (error) {
                            if (error) {
                              console.log(
                                'error writing data in puck - init : ',
                                error
                              )
                            }
                            if (splitFinished == true) {
                              rxCharacteristic.unsubscribe(error => {
                                // console.log('unsubscribe : ', error)
                                puckJSnoble.disconnect(error => {
                                  console.log(error)
                                })
                              })
                              splitFinished = false
                            } else {
                              writeData()
                            }
                          }
                        )
                      }, delayWrite)
                    }
                    if (!reseted) {
                      txCharacteristic.write(
                        stringToBuffer('reset()\nsave()'),
                        false,
                        function (error) {
                          puckJSnoble.disconnect(error => {
                            console.log(error)
                          })
    
                        }
                      )
                    } else {
                      writeData();
                    }
                  } catch (e) {
                    console.log('BT> SEND ERROR ' + e)
                  }
                })
              }
            })
          })
          puckJSnoble.once('disconnect', () => {
            console.log('PASSAGE disconnect')
            if (reseted) {
              noble.startScanning([], true)
            } else {
              reseted = true;
              initPuck();
              cbStopScanning();
            }
          })
        }
    
    // Converts a string to a Buffer
    function stringToBuffer(str) {
      // console.log(str);
      var buf = new Buffer(str.length)
      for (var i = 0; i < buf.length; i++) {
        buf.writeUInt8(str.charCodeAt(i), i)
      }
      console.log('buffer : ', buf)
      return buf
    }
    
    // split the script every 19 byte (device's limit..)  to write data in puck.js
    function splitTheScript(data) {
      var writeData = [{
        data: data,
        blockSize: 19
      }]
    
      var d
      var split = writeData[0].nextSplit || {
        start: 0,
        end: writeData[0].data.length,
        delay: 0
      }
      // Otherwise split based on block size
      if (split.end >= writeData[0].blockSize) {
        split = {
          start: 0,
          end: writeData[0].blockSize,
          delay: 0
        }
      } else {
        splitFinished = true
      }
    
      // Only send some of the data
      if (writeData[0].data.length > split.end) {
        if (split.delay == 0) split.delay = 50
        d = writeData[0].data.substr(0, split.end)
        writeData[0].data = writeData[0].data.substr(split.end)
        if (writeData[0].nextSplit) {
          writeData[0].nextSplit.start -= split.end
          writeData[0].nextSplit.end -= split.end
          if (writeData[0].nextSplit.end <= 0) writeData[0].nextSplit = undefined
        }
      } else {
        d = writeData[0].data
        writeData[0].data = ''
        writeData[0].nextSplit = undefined
      }
      // actually write data
      scriptInit = writeData[0].data
      splittedScript = d
      delayWrite = split.delay
      console.log(
        'Sending block ' + JSON.stringify(d) + ', wait ' + split.delay + 'ms'
      )
    }
    
  • function findByUUID(list, uuid) {
      // console.log(list.length)
      for (var i = 0; i < list.length; i++) {
        // console.log('LIST : ', list[i].uuid)
        if (list[i].uuid == uuid) {
          // console.log(list[i].uuid)
          return list[i]
        }
      }
    }
    
  • Ahh - this could be related to 'echo'.

    So normally, when you write text to Espruino in the REPL it echoes back those characters so you can see what you typed (plus the JS prompt >). Probably if you dump the data you're getting from rxCharacteristic you'll see a bunch of stuff coming back. It might actually help to remove all the lines to do with rxCharacteristic if you don't care about the data coming back - that might improve things.

    The data that can be sent on BLE is about the same as what can be received, so if you keep sending data to Puck.js it'll keep sending those characters back (plus a few) and it ends up spending all its time waiting to send characters. Eventually it runs out of memory and drops some. I'm not sure it explains the connection issues though.

    You can manually turn that off by sending "echo(0);\n" first (and back on with echo(1).

    Or - what the Web IDE does is:

    • Clears the line with Ctrl-C (char code 3)
    • Sends character code 16 at the start of each line to turn echo off just for that line

    So just adding "\x03\x10" to the front of the code you send (and removing any newlines) might well fix it for you?

  • OK thank you i'll try it !

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

Puck.js stuck while uploading code with noble.js

Posted by Avatar for Christof550 @Christof550

Actions