B1: autoreset after a few minutes, how to debug

Posted on
  • Hi,

    I wrote an app which communicates with an Android app and transfers data continuously. Everything works fine until the watch seems to (soft) reset for seamingly no reason. What I did so far:

    • use 2v16 release build
    • Android app drives communication (no Bluetooth.write unless requested)
    • continuously log memory consumption using Terminal.println and buzz when exceeding ~2/3
    • disabled home button (set option btnLoadTimeout to 0) and implemented a 3s count down with buzz when holding a button to reenable the home button

    Because it takes a couple of minutes to appear and the timespan varies a lot (observed 7m and 12m from sent data), I didn't "see" what happens on screen so far.

    I would appreciate any information on what I should "log", on JS or C level, to get a grip on this.

    Thanks in advance!

  • Hi, I'm not really sure to be honest. Having the code would really help.

    But maybe you could try disabling the 'btnLoadTimeout' code you added? It seems like it could be related, since the Bangle wouldn't normally do it and that code is pretty much completely related to resetting.

  • edit: OMG, there is actually a critical bug in the code (buf[bufi] = 0; when bufi == buf.length). If this turns out to be the source, please apologize the distraction!

    Unfortunately I can't reliably reproduce the issue. It happened thrice in a row (2 outdoors, 1 indoors), then once at BT disconnect (Android blessed.BluetoothPeripheral.closeConnect­ion; saw the bootloader screen) followed by 2 times without issues. My guess now is that the BT device in my phone is buggy and somehow triggers an extra hard reset on connection loss/disconnect.

    I will therefore rewrite the app to recover in case of a hard reset and look for any pattern in the data.

    Code:

    var ACC = 1;
    var MAG = 2;
    var GPS = 3;
    var TIM = 4;
    
    var bufs = [];
    var buf = new ArrayBuffer(1000);
    var bufi = 0;
    
    function get_dv(len) {
      if (buf.length < (bufi + len)) {
        buf[bufi] = 0;
        bufs.push(buf);
        buf = new ArrayBuffer(1000);
        bufi = 0;
      }
      var dv = new DataView(buf, bufi);
      bufi += len;
      return dv;
    }
    
    function send_buf() {
      if (bufs.length) {
        Bluetooth.write(btoa(bufs[0]));
      }
      Bluetooth.write('\n');
    }
    
    function remove_buf() {
      bufs.shift();
    }
    
    function on_accel(a) {
      var v = get_dv(7);
      v.setUint8(0, ACC);
      v.setInt16(1, a.x * 8192);
      v.setInt16(3, a.y * 8192);
      v.setInt16(5, a.z * 8192);
    }
    
    function on_mag(m) {
      var v = get_dv(7);
      v.setUint8(0, MAG);
      v.setInt16(1, m.x);
      v.setInt16(3, m.y);
      v.setInt16(5, m.z);
    }
    
    function on_gps(g) {
      if (g.fix == 0) return;
      var v = get_dv(26);
      v.setUint8(0, GPS);
      v.setInt32(1, g.lat * 11930464);
      v.setInt32(5, g.lon * 11930464);
      v.setUint16(9, clamp(g.alt * 16, 0, 65535));
      v.setFloat64(11, g.time.getTime());
      v.setUint8(19, g.fix);
      v.setUint8(20, clamp(g.hdop * 12, 0, 255));
      v.setUint8(21, g.satellites);
      v.setUint16(22, g.course * 182);
      v.setUint16(24, clamp(g.speed * 327, 0, 65535));
    }
    
    var clamp = (a, mi, ma) => a < mi ? mi : (ma < a ? ma : a);
    
    function log(s) {
      Terminal.println(s);
    }
    
    g.clear();
    Bangle.loadWidgets();
    Bangle.drawWidgets();
    
    log('# Cyclometer');
    log('press top button to start');
    Bangle.setGPSPower(true, 'cyc');
    
    var satc = 0;
    function ready(g) {
      if (g.fix) {
        Bangle.removeListener('GPS', ready);
        Bangle.buzz(500);
        log('GPS ready');
      } else if (g.satellites != satc) {
        satc = g.satellites;
        log('GPS satellites: ' + satc);
      }
    }
    Bangle.on('GPS', ready);
    
    setWatch(() => {
      log('starting ...');
      Bangle.setLCDTimeout(0);
      Bangle.setOptions({btnLoadTimeout: 0});
      Bangle.setCompassPower(true, 'cyc');
      Bangle.on('accel', on_accel);
      Bangle.on('mag', on_mag);
      Bangle.on('GPS', on_gps);
    
      var tim_id = setInterval(() => {
        var v = get_dv(9);
        v.setUint8(0, TIM);
        v.setFloat64(1, getTime());
      }, 60 * 1000);
    
      var log_id = setInterval(() => {
        var m = process.memory();
        var p = Math.floor((m.usage / m.total) * 100);
        log('queue: ' + bufs.length + ' memory: ' + p + '%');
        if (67 <= p) {
          Bangle.buzz(500);
          setTimeout(() => Bangle.buzz(500), 1000);
        }
      }, 5 * 1000);
    
      log('started');
      log('hold top button for 3 seconds to stop');
    
      var cnt;
      var cnt_id;
      var btn_id = setWatch((e) => {
        if (e.state) {
          log('stop in 3');
          cnt = 3;
          cnt_id = setTimeout(stop, 1000);
          Bangle.buzz(300);
        } else if (cnt_id) {
          clearTimeout(cnt_id);
          cnt_id = undefined;
        }
      }, BTN1, {repeat: true, edge: 'both'});
    
      function stop() {
        cnt--;
        if (cnt == 0) {
          log('stopping ...');
          Bangle.setLCDTimeout(10);
          Bangle.setOptions({btnLoadTimeout: 1500});
          Bangle.setGPSPower(false, 'cyc');
          Bangle.setCompassPower(false, 'cyc');
          var _ = Bangle.removeListener.bind(Bangle);
          _('accel', on_accel);
          _('mag', on_mag);
          _('GPS', on_gps);
          clearInterval(tim_id);
          clearInterval(log_id);
          clearWatch(btn_id);
          log('stopped');
        } else {
          log('stop in ' + cnt);
          cnt_id = setTimeout(stop, 1000);
          Bangle.buzz(300);
        }
      }
    }, BTN1);
    

  • The bug fix actually solved the reset situation. Who would have thought writing 0 out of bounds is bad xD

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

B1: autoreset after a few minutes, how to debug

Posted by Avatar for !evil @!evil

Actions