docs: function handle(js,line){
      // handle message from board.
      //stream.log("handle",stream.token,line);
  
      var hasToken = stream.token;
      if(js.type == "token") {
  
        // send in event stream.
        stream.queue(js); 
        stream.token = js.token;
  
        if(!hasToken) {
          readycb(false,stream);
          clearTimeout(readyTimeout); 
        }
        return;
      }
  
      if(!stream.token) return stream.log('data from socket before auth/id token.',js);
  
      if(js.type == 'reply'){
  
        o = stream.callbacks[js.id]||{};
  
        if(o.id === undefined) return stream.log('got reply with no id mapping! ',js);
  
  
        var output = js.output||js.reply||"";
        var ret = js.return;// not set yet.
  
        if(!o.output) o.output = "";
        // handle chunked responses. they come in order.
        o.output += output;
  
        // soon the firmware will support returning the return int value of the scout script function/expression. it willbe the property return.
        if(ret) {
          o.return = ret;
        }
  
        js._cid = js.id;
        js.id = o.id;
  
        if(js.err || js.end) {
  
          delete stream.callbacks[js._cid];
          js.reply = js.output = o.output;
          js.return = o.return;
          o.cb(js.err,js)
        }
  
      } else if(js.type == "report" && line == stream._lastreport){
        // duplicate reports are not really useful to propagate as events because nothing changed.
        return;// stream.log('duplicate report ',line);
      } else if (js.type == "report") {
        stream._lastreport = line;
        stream.queue(js);// send report in stream.
      } else {
        stream.log('unknown message type',js);
      }
    }