2008-02-20

"The Big Loop"

Atlantis (STS-122) is landing today. During the mission ground teams have used the term "big loop" many times. So what is this big loop? NASA has the answer:

"...Both the orbiter and ISS have two channels that can be used to communicate between the vehicle and the ground. For the orbiter, these are called Air-To-Ground 1 and Air-To-Ground 2. For ISS, these are called Space-To-Ground 1 and Space-To-Ground 2. During docked missions, we configure these channels so that Air-To-Ground 1 and Space-To-Ground 1 are connected. This means that when people talk to either vehicle on this "Big Loop," both vehicles hear the calls. The Air or Space-To-Ground 2 loops are used for the ISS team to talk just to the ISS or for the shuttle team to talk just to the shuttle.

The crew and ground usually call out which loop they are calling on so that the other side knows which channel to reply on."

2008-02-09

TODO: REST Describe & Compile Javascript code generation

The REST Describe & Compile generates code for PHP, Ruby, Python and Java. I'm working on a Javascript generator for REST Compile and decided to first write a working piece of code that I could use as a reference while implementing the actual code generator. This is the code so far (note: the term "class" used in comments is misleading because we're not really dealing with classes here):

// class auto-generated by REST Compile
function RestRequest() {
  // provide user and password for HTTP AUTH
  this.user = null;
  this.password = null;
  this.epoch = new Date(0);  // for If-Modified-Since brutality
}

// XXX: check this works with non-ascii characters etc.
RestRequest.prototype.urlencode = function(str) {
  return escape(str).replace('+', '%2B').replace('%20', '+').replace('*', '%2A').replace('/', '%2F').replace('@', '%40');
}

// the GET function
RestRequest.prototype.doGetCall = function(uri, callback) {

  // XXX: seems to works on major browsers, check harder
  var request = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();

  var async = (callback === undefined) ? false : true;

  // XXX: username, password not tested
  // XXX: isn't the user logged in already?
  if(this.user && this.password)
    request.open('GET', uri, async, this.user, this.password);
  else if(this.user)
    request.open('GET', uri, async, this.user);
  else
    request.open('GET', uri, async);

  // skip cache
  request.setRequestHeader('If-Modified-Since', this.epoch);

  if(async) {
    request.onreadystatechange = function() {
      window.status = request.readyState;
      if(request.readyState == 4) {
        callback((request.status == 200) ? request.responseText : null);
      }
      return;
    }
    request.send();
  }
  else {
    request.send();
    return (request.status == 200) ? request.responseText : null;
  }
}

// the POST function
RestRequest.prototype.doPostCall = function(uri, XXXDATA) {
    // XXX content-type
    // ...etc...
}

// class auto-generated by REST Compile
function Sleep(t) {
  this.params = {};

  // XXX: this should handle required params
  this.params['t'] = t;
}

Sleep.prototype = new RestRequest;

Sleep.prototype.prepareParams = function() {
  pStr = '';
  for(var i in this.params) {
    pStr += '&' + this.urlencode(i) + '=' + this.urlencode(this.params[i]);
  }

  // strip off the first '&'
  return pStr.length > 0 ? pStr.substring(1) : pStr;
}

// the optional Javascript callback function is given at this stage
// so that the constructor can be fed with just request parameters.
Sleep.prototype.submit = function(callback) {
  var requestUri = "sleep.php";

  if(undefined === callback)
    return this.doGetCall(requestUri + '?' + this.prepareParams());
  else
    this.doGetCall(requestUri + '?' + this.prepareParams(), callback);

  return;
}

The usage would be like (using jQuery to manipulate elements):

function synccall() {
  s = new Sleep(1);
  $('#sync').append('<p>' + s.submit() + '</p>');
}

function asynccall() {
  var s = new Sleep(2);
  s.submit(asynccallback);
}

function asynccallback(response) {
  $('#async').append('<p>' + response + '</p>');
}

Several questions came to mind while writing. Should there be some kind of error handling mechanism (definetely!)? An (optional) errback() function that would be fed with HTTP status and headers in case something went wrong, maybe? Because at this point the user would only get null back as a response and that is not too informative (and raising exceptions in a callback doesn't sound too clever either).