예제 #1
0
// 'end' this connection
void clientRequestEnd(JsNetwork *net, JsVar *httpClientReqVar) {
    SocketType socketType = socketGetType(httpClientReqVar);
    if (socketType == ST_HTTP) {
        // on HTTP, this actually means we connect
        clientRequestConnect(net, httpClientReqVar);
    } else {
        // on normal sockets, we actually request close after all data sent
        jsvUnLock(jsvObjectSetChild(httpClientReqVar, HTTP_NAME_CLOSE, jsvNewFromBool(true)));
    }
}
예제 #2
0
/*JSON{
  "type"     : "staticmethod",
  "class"    : "ESP8266WiFi",
  "name"     : "getConnectStatus",
  "generate" : "jswrap_ESP8266WiFi_getConnectStatus",
  "return"   : ["JsVar","A connection status"]
}

Retrieve the connection status.  The return is an object that contains:

* status - The status code from ESP8266
* statusMsg - The description of the code

*/
JsVar *jswrap_ESP8266WiFi_getConnectStatus() {
  // Ask ESP8266 for the connection status
  uint8 status = wifi_station_get_connect_status();

  // Create a JS variable to return
  JsVar *var = jsvNewWithFlags(JSV_OBJECT);

  // Populate the return JS variable with a property called "status"
  JsVar *jsStatus = jsvNewFromInteger(status);
  //jsvUnLock(jsStatus);
  jsvUnLock(jsvObjectSetChild(var, "status", jsStatus));

  // Populate the return JS variable with a property called "statusMsg"
  char *statusMsg;
  switch(status) {
  case STATION_IDLE:
    statusMsg = "STATION_IDLE";
    break;
  case STATION_CONNECTING:
    statusMsg = "STATION_CONNECTING";
    break;
  case STATION_WRONG_PASSWORD:
    statusMsg = "STATION_WRONG_PASSWORD";
    break;
  case STATION_NO_AP_FOUND:
    statusMsg = "STATION_NO_AP_FOUND";
    break;
  case STATION_CONNECT_FAIL:
    statusMsg = "STATION_CONNECT_FAIL";
    break;
  case STATION_GOT_IP:
    statusMsg = "STATION_GOT_IP";
    break;
  default:
    statusMsg = "*** Unknown ***";
  }
  JsVar *jsStatusMsg = jsvNewFromString(statusMsg);
  //jsvUnLock(jsStatusMsg);
  jsvUnLock(jsvObjectSetChild(var, "statusMsg", jsStatusMsg));
  //jsvUnLock(var);
  return var;
}
예제 #3
0
void socketClientPushReceiveData(JsVar *connection, JsVar *socket, JsVar **receiveData) {
    if (*receiveData) {
        if (jsvIsEmptyString(*receiveData) ||
                jswrap_stream_pushData(socket, *receiveData, false)) {
            // clear - because we have issued a callback
            jsvObjectSetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
            jsvUnLock(*receiveData);
            *receiveData = 0;
        }
    }
}
예제 #4
0
/*JSON{ "type":"staticproperty",
         "class" : "process", "name" : "env",
         "description" : "Returns an Object containing various pre-defined variables. standard ones are BOARD, VERSION",
         "generate" : "jswrap_process_env",
         "return" : ["JsVar", "An object"]
}*/
JsVar *jswrap_process_env() {
    JsVar *obj = jsvNewWithFlags(JSV_OBJECT);
    jsvUnLock(jsvObjectSetChild(obj, "VERSION", jsvNewFromString(JS_VERSION)));
    jsvUnLock(jsvObjectSetChild(obj, "BUILD_DATE", jsvNewFromString(__DATE__)));
    jsvUnLock(jsvObjectSetChild(obj, "BUILD_TIME", jsvNewFromString(__TIME__)));
    jsvUnLock(jsvObjectSetChild(obj, "BOARD", jsvNewFromString(PC_BOARD_ID)));
    jsvUnLock(jsvObjectSetChild(obj, "CHIP", jsvNewFromString(PC_BOARD_CHIP)));
    jsvUnLock(jsvObjectSetChild(obj, "CHIP_FAMILY", jsvNewFromString(PC_BOARD_CHIP_FAMILY)));
    jsvUnLock(jsvObjectSetChild(obj, "FLASH", jsvNewFromInteger(FLASH_TOTAL)));
    jsvUnLock(jsvObjectSetChild(obj, "RAM", jsvNewFromInteger(RAM_TOTAL)));

    return obj;
}
예제 #5
0
void _jswrap_promise_add(JsVar *parent, JsVar *callback, const char *name) {
  if (!jsvIsFunction(callback)) {
    jsExceptionHere(JSET_TYPEERROR, "Callback must be a function, got %t", callback);
    return;
  }
  JsVar *c = jsvObjectGetChild(parent, name, 0);
  if (!c) {
    jsvObjectSetChild(parent, name, callback);
  } else {
    if (jsvIsArray(c)) {
      jsvArrayPush(c, callback);
    } else {
      JsVar *fns[2] = {c,callback};
      JsVar *arr = jsvNewArray(fns, 2);
      jsvObjectSetChild(parent, name, arr);
      jsvUnLock(arr);
    }
    jsvUnLock(c);
  }
}
예제 #6
0
/*JSON{ "type":"constructor", "class": "Waveform",  "name": "Waveform", "ifndef" : "SAVE_ON_FLASH",
         "description" : [ "Create a waveform class. This allows high speed input and output of waveforms. It has an internal variable called `buffer` (as well as `buffer2` when double-buffered - see `options` below) which contains the data to input/output.",
                           "When double-buffered, a 'buffer' event will be emitted each time a buffer is finished with (the argument is that buffer). When the recording stops, a 'finish' event will be emitted (with the first argument as the buffer)." ],
         "generate" : "jswrap_waveform_constructor",
         "params" : [ [ "samples", "int32", "The number of samples" ],
                      [ "options", "JsVar", "Optional options struct `{doubleBuffer:bool, bits : 8/16}` where: `doubleBuffer` is whether to allocate two buffers or not (default false), and bits is the amount of bits to use (default 8)." ] ],
         "return" : [ "JsVar", "An Waveform object" ]

}*/
JsVar *jswrap_waveform_constructor(int samples, JsVar *options) {
  if (samples<=0) {
    jsExceptionHere(JSET_ERROR, "Samples must be greater than 0");
    return 0;
  }

  bool doubleBuffer = false;
  bool use16bit = false;
  if (jsvIsObject(options)) {
    doubleBuffer = jsvGetBoolAndUnLock(jsvObjectGetChild(options, "doubleBuffer", 0));

    int bits = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "bits", 0));
    if (bits!=0 && bits!=8 && bits!=16) {
      jsExceptionHere(JSET_ERROR, "Invalid number of bits");
      return 0;
    } else if (bits==16) use16bit = true;

  } else if (!jsvIsUndefined(options)) {
    jsExceptionHere(JSET_ERROR, "Expecting options to be undefined or an Object, not %t", options);
  }

  JsVar *arrayLength = jsvNewFromInteger(samples);
  JsVarDataArrayBufferViewType bufferType = use16bit ? ARRAYBUFFERVIEW_UINT16 : ARRAYBUFFERVIEW_UINT8;
  JsVar *arrayBuffer = jswrap_typedarray_constructor(bufferType, arrayLength, 0, 0);
  JsVar *arrayBuffer2 = 0;
  if (doubleBuffer) arrayBuffer2 = jswrap_typedarray_constructor(bufferType, arrayLength, 0, 0);
  jsvUnLock(arrayLength);
  JsVar *waveform = jspNewObject(0, "Waveform");


  if (!waveform || !arrayBuffer || (doubleBuffer && !arrayBuffer2)) {
    jsvUnLock(waveform);
    jsvUnLock(arrayBuffer); // out of memory
    jsvUnLock(arrayBuffer2);
    return 0;
  }
  jsvUnLock(jsvObjectSetChild(waveform, "buffer", arrayBuffer));
  if (arrayBuffer2) jsvUnLock(jsvObjectSetChild(waveform, "buffer2", arrayBuffer2));

  return waveform;
}
예제 #7
0
/*JSON{ "type":"function", "name" : "setTimeout",
         "description" : ["Call the function specified ONCE after the timeout in milliseconds.",
                          "The function that is being called may also take an argument, which is an object containing a field called 'time' (the time in seconds at which the timer happened)",
                          "for example: ```setTimeout(function (e) { print(e.time); }, 1000);```",
                          "This can also be removed using clearTimeout",
                          "**Note:** If `setDeepSleep(true)` has been called and the interval is greater than 5 seconds, Espruino may execute the interval up to 1 second late. This is because Espruino can only wake from deep sleep every second - and waking early would cause Espruino to waste power while it waited for the correct time." ],
         "generate" : "jswrap_interface_setTimeout",
         "params" : [ [ "function", "JsVar", "A Function or String to be executed"],
                      [ "timeout", "float", "The time until the function will be executed" ] ],
         "return" : ["JsVar", "An ID that can be passed to clearTimeout"]
}*/
JsVar *_jswrap_interface_setTimeoutOrInterval(JsVar *func, JsVarFloat interval, bool isTimeout) {
  // NOTE: The 5 sec delay mentioned in the description is handled by jshSleep
  JsVar *itemIndex = 0;
  if (!jsvIsFunction(func) && !jsvIsString(func)) {
    jsError("Function or String not supplied!");
  } else {
    // Create a new timer
    JsVar *timerPtr = jsvNewWithFlags(JSV_OBJECT);
    if (interval<TIMER_MIN_INTERVAL) interval=TIMER_MIN_INTERVAL;
    JsVarInt intervalInt = jshGetTimeFromMilliseconds(interval);
    jsvUnLock(jsvObjectSetChild(timerPtr, "time", jsvNewFromInteger(jshGetSystemTime() + intervalInt)));
    jsvUnLock(jsvObjectSetChild(timerPtr, "interval", jsvNewFromInteger(intervalInt)));
    if (!isTimeout) jsvUnLock(jsvObjectSetChild(timerPtr, "recur", jsvNewFromBool(true)));
    jsvObjectSetChild(timerPtr, "callback", func); // intentionally no unlock

    // Add to array
    itemIndex = jsvNewFromInteger(jsiTimerAdd(timerPtr));
    jsvUnLock(timerPtr);
  }
  return itemIndex;
}
예제 #8
0
/*JSON{ "type":"idle", "generate" : "jswrap_waveform_idle", "ifndef" : "SAVE_ON_FLASH" }*/
bool jswrap_waveform_idle() {
  JsVar *waveforms = jsvObjectGetChild(execInfo.hiddenRoot, JSI_WAVEFORM_NAME, 0);
  if (waveforms) {
    JsvArrayIterator it;
    jsvArrayIteratorNew(&it, waveforms);
    while (jsvArrayIteratorHasElement(&it)) {
      JsVar *waveform = jsvArrayIteratorGetElement(&it);

      bool running = jsvGetBoolAndUnLock(jsvObjectGetChild(waveform, "running", 0));
      if (running) {
        JsVar *buffer = jswrap_waveform_getBuffer(waveform,0,0);
        UtilTimerTask task;
        // Search for a timer task
        if (!jstGetLastBufferTimerTask(buffer, &task)) {
          // if the timer task is now gone...
          JsVar *arrayBuffer = jsvObjectGetChild(waveform, "buffer", 0);
          jsiQueueObjectCallbacks(waveform, "#onfinish", &arrayBuffer, 1);
          jsvUnLock(arrayBuffer);
          running = false;
          jsvUnLock(jsvObjectSetChild(waveform, "running", jsvNewFromBool(running)));
        } else {
          // If the timer task is still there...
          if (task.data.buffer.nextBuffer &&
              task.data.buffer.nextBuffer != task.data.buffer.currentBuffer) {
            // if it is a double-buffered task
            int currentBuffer = (jsvGetRef(buffer)==task.data.buffer.currentBuffer) ? 0 : 1;
            JsVar *oldBuffer = jsvObjectGetChild(waveform, "currentBuffer", JSV_INTEGER);
            if (jsvGetInteger(oldBuffer) !=currentBuffer) {
              // buffers have changed - fire off a 'buffer' event with the buffer that needs to be filled
              jsvSetInteger(oldBuffer, currentBuffer);
              JsVar *arrayBuffer = jsvObjectGetChild(waveform, (currentBuffer==0) ? "buffer" : "buffer2", 0);
              jsiQueueObjectCallbacks(waveform, "#onbuffer", &arrayBuffer, 1);
              jsvUnLock(arrayBuffer);
            }
            jsvUnLock(oldBuffer);
          }
        }
        jsvUnLock(buffer);
      }
      jsvUnLock(waveform);
      // if not running, remove waveform from this list
      if (!running)
        jsvArrayIteratorRemoveAndGotoNext(&it, waveforms);
      else
        jsvArrayIteratorNext(&it);
    }
    jsvArrayIteratorFree(&it);
    jsvUnLock(waveforms);
  }
  return false; // no need to stay awake - an IRQ will wake us
}
예제 #9
0
/*JSON{
  "type"     : "staticmethod",
  "class"    : "ESP8266WiFi",
  "name"     : "getRstInfo",
  "generate" : "jswrap_ESP8266WiFi_getRstInfo",
  "return"   : ["JsVar","A Restart Object"],
  "return_object" : "Restart"
}*/
JsVar *jswrap_ESP8266WiFi_getRstInfo() {
  struct rst_info* info = system_get_rst_info();
  JsVar *restartInfo = jspNewObject(NULL, "Restart");
  jsvUnLock(jsvObjectSetChild(restartInfo, "reason",   jsvNewFromInteger(info->reason)));
  jsvUnLock(jsvObjectSetChild(restartInfo, "exccause", jsvNewFromInteger(info->exccause)));
  jsvUnLock(jsvObjectSetChild(restartInfo, "epc1",     jsvNewFromInteger(info->epc1)));
  jsvUnLock(jsvObjectSetChild(restartInfo, "epc2",     jsvNewFromInteger(info->epc2)));
  jsvUnLock(jsvObjectSetChild(restartInfo, "epc3",     jsvNewFromInteger(info->epc3)));
  jsvUnLock(jsvObjectSetChild(restartInfo, "excvaddr", jsvNewFromInteger(info->excvaddr)));
  jsvUnLock(jsvObjectSetChild(restartInfo, "depc",     jsvNewFromInteger(info->depc)));
  return restartInfo;
}
예제 #10
0
/*JSON{
  "type" : "staticmethod",
  "class" : "Object",
  "name" : "create",
  "generate" : "jswrap_object_create",
  "params" : [
    ["proto","JsVar","A prototype object"],
    ["propertiesObject","JsVar","An object containing properties. NOT IMPLEMENTED"]
  ],
  "return" : ["JsVar","A new object"]
}
Creates a new object with the specified prototype object and properties. properties are currently unsupported.
 */
JsVar *jswrap_object_create(JsVar *proto, JsVar *propertiesObject) {
  if (!jsvIsObject(proto) && !jsvIsNull(proto)) {
    jsWarn("Object prototype may only be an Object or null: %t", proto);
    return 0;
  }
  if (jsvIsObject(propertiesObject)) {
    jsWarn("propertiesObject is not supported yet");
  }
  JsVar *obj = jsvNewObject();
  if (!obj) return 0;
  if (jsvIsObject(proto))
    jsvObjectSetChild(obj, JSPARSE_INHERITS_VAR, proto);
  return obj;
}
예제 #11
0
/*JSON{
  "type" : "function",
  "name" : "setTimeout",
  "generate" : "jswrap_interface_setTimeout",
  "params" : [
    ["function","JsVar","A Function or String to be executed"],
    ["timeout","float","The time until the function will be executed"]
  ],
  "return" : ["JsVar","An ID that can be passed to clearTimeout"]
}
Call the function specified ONCE after the timeout in milliseconds.

The function that is being called may also take an argument, which is an object containing a field called 'time' (the time in seconds at which the timer happened)

for example: ```setTimeout(function (e) { print(e.time); }, 1000);```

This can also be removed using clearTimeout

**Note:** If `setDeepSleep(true)` has been called and the interval is greater than 5 seconds, Espruino may execute the interval up to 1 second late. This is because Espruino can only wake from deep sleep every second - and waking early would cause Espruino to waste power while it waited for the correct time.
*/
JsVar *_jswrap_interface_setTimeoutOrInterval(JsVar *func, JsVarFloat interval, bool isTimeout) {
  // NOTE: The 5 sec delay mentioned in the description is handled by jshSleep
  JsVar *itemIndex = 0;
  if (!jsvIsFunction(func) && !jsvIsString(func)) {
    jsExceptionHere(JSET_ERROR, "Function or String not supplied!");
  } else {
    // Create a new timer
    JsVar *timerPtr = jsvNewWithFlags(JSV_OBJECT);
    if (interval<TIMER_MIN_INTERVAL) interval=TIMER_MIN_INTERVAL;
    JsSysTime intervalInt = jshGetTimeFromMilliseconds(interval);
    //jsiConsolePrintf("interval = %f,intervalInt = %d,now = %d,timeInt = %d\n",interval,intervalInt,jshGetSystemTime(),(jshGetSystemTime() - jsiLastIdleTime) + intervalInt);
    jsvUnLock(jsvObjectSetChild(timerPtr, "time", jsvNewFromLongInteger((jshGetSystemTime() - jsiLastIdleTime) + intervalInt)));
    if (!isTimeout) {
      jsvUnLock(jsvObjectSetChild(timerPtr, "interval", jsvNewFromLongInteger(intervalInt)));
    }
    jsvObjectSetChild(timerPtr, "callback", func); // intentionally no unlock

    // Add to array
    itemIndex = jsvNewFromInteger(jsiTimerAdd(timerPtr));
    jsvUnLock(timerPtr);
  }
  return itemIndex;
}
예제 #12
0
/*JSON{
  "type" : "method",
  "class" : "WLAN",
  "name" : "connect",
  "generate" : "jswrap_wlan_connect",
  "params" : [
    ["ap","JsVar","Access point name"],
    ["key","JsVar","WPA2 key (or undefined for unsecured connection)"],
    ["callback","JsVar","Function to call back with connection status. It has one argument which is one of 'connect'/'disconnect'/'dhcp'"]
  ],
  "return" : ["bool","True if connection succeeded, false if it didn't."]
}
Connect to a wireless network
*/
bool jswrap_wlan_connect(JsVar *wlanObj, JsVar *vAP, JsVar *vKey, JsVar *callback) {
  if (!(jsvIsUndefined(callback) || jsvIsFunction(callback))) {
    jsError("Expecting callback Function but got %t", callback);
    return 0;
  }

  JsNetwork net;
  if (!networkGetFromVar(&net)) return false;

  // if previously completely disconnected, try and reconnect
  if (jsvGetBoolAndUnLock(jsvObjectGetChild(wlanObj,JS_HIDDEN_CHAR_STR"DIS",0))) {
    cc3000_initialise(wlanObj);
    jsvObjectSetChildAndUnLock(wlanObj,JS_HIDDEN_CHAR_STR"DIS", jsvNewFromBool(false));
  }

  if (jsvIsFunction(callback)) {
    jsvObjectSetChild(wlanObj, CC3000_ON_STATE_CHANGE, callback);
  }

  jsvObjectSetChild(wlanObj,JS_HIDDEN_CHAR_STR"AP", vAP); // no unlock intended
  jsvObjectSetChild(wlanObj,JS_HIDDEN_CHAR_STR"KEY", vKey); // no unlock intended

  char ap[32];
  char key[32];
  unsigned long security = WLAN_SEC_UNSEC;
  jsvGetString(vAP, ap, sizeof(ap));
  if (jsvIsString(vKey)) {
    security = WLAN_SEC_WPA2;
    jsvGetString(vKey, key, sizeof(key));
  }
  // might want to set wlan_ioctl_set_connection_policy
  bool connected =  wlan_connect(security, ap, (long)strlen(ap), NULL, (unsigned char*)key, (long)strlen(key))==0;

  networkFree(&net);
  // note that we're only online (for networkState) when DHCP succeeds
  return connected;
}
예제 #13
0
JsVar *httpServerNew(JsVar *callback) {
  SOCKET sckt = socket(AF_INET,           // Go over TCP/IP
                       SOCK_STREAM,       // This is a stream-oriented socket
                       IPPROTO_TCP);      // Use TCP rather than UDP
  if (sckt == INVALID_SOCKET) {
    httpError("socket creation failed");
    return 0;
  }

  JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_SERVERS, true);
  if (!arr) return 0; // out of memory

  JsVar *server = jspNewObject(jsiGetParser(),0,"httpSrv");
  if (!server) {
    jsvUnLock(arr);
    return 0; // out of memory
  }

  jsvObjectSetChild(server, HTTP_NAME_ON_CONNECT, callback); // no unlock needed
  jsvUnLock(jsvObjectSetChild(server, HTTP_NAME_SOCKET, jsvNewFromInteger(sckt+1)));

#ifndef USE_CC3000
  int optval = 1;
  if (setsockopt(sckt,SOL_SOCKET,SO_REUSEADDR,(const char *)&optval,sizeof(optval)) < 0)
#else
  int optval = SOCK_ON;
  if (setsockopt(sckt,SOL_SOCKET,SOCKOPT_ACCEPT_NONBLOCK,(const char *)&optval,sizeof(optval)) < 0)
#endif
    jsWarn("setsockopt failed\n");

  // add to list of servers
  jsvArrayPush(arr, server);
  jsvUnLock(arr);

  return server;
}
예제 #14
0
static bool handlePipe(JsVar *arr, JsvObjectIterator *it, JsVar* pipe) {
  bool paused = jsvGetBoolAndUnLock(jsvObjectGetChild(pipe,"drainWait",0));
  if (paused) return false;

  JsVar *position = jsvObjectGetChild(pipe,"position",0);
  JsVar *chunkSize = jsvObjectGetChild(pipe,"chunkSize",0);
  JsVar *source = jsvObjectGetChild(pipe,"source",0);
  JsVar *destination = jsvObjectGetChild(pipe,"destination",0);

  bool dataTransferred = false;
  if(source && destination && chunkSize && position) {
    JsVar *readFunc = jspGetNamedField(source, "read", false);
    JsVar *writeFunc = jspGetNamedField(destination, "write", false);
    if (jsvIsFunction(readFunc) && jsvIsFunction(writeFunc)) { // do the objects have the necessary methods on them?
      JsVar *buffer = jspExecuteFunction(readFunc, source, 1, &chunkSize);
      if(buffer) {
        JsVarInt bufferSize = jsvGetLength(buffer);
        if (bufferSize>0) {
          JsVar *response = jspExecuteFunction(writeFunc, destination, 1, &buffer);
          if (jsvIsBoolean(response) && jsvGetBool(response)==false) {
            // If boolean false was returned, wait for drain event (http://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback)
            jsvUnLock(jsvObjectSetChild(pipe,"drainWait",jsvNewFromBool(true)));
          }
          jsvUnLock(response);
          jsvSetInteger(position, jsvGetInteger(position) + bufferSize);
        }
        jsvUnLock(buffer);
        dataTransferred = true; // so we don't close the pipe if we get an empty string
      }
    } else {
      if(!jsvIsFunction(readFunc))
        jsExceptionHere(JSET_ERROR, "Source Stream does not implement the required read(length) method.");
      if(!jsvIsFunction(writeFunc))
        jsExceptionHere(JSET_ERROR, "Destination Stream does not implement the required write(buffer) method.");
    }
    jsvUnLock(readFunc);
    jsvUnLock(writeFunc);
  }

  if(!dataTransferred) { // when no more chunks are possible, execute the callback
    handlePipeClose(arr, it, pipe);
  }
  jsvUnLock(source);
  jsvUnLock(destination);
  jsvUnLock(chunkSize);
  jsvUnLock(position);
  return dataTransferred;
}
예제 #15
0
void clientRequestWrite(JsVar *httpClientReqVar, JsVar *data) {
    SocketType socketType = socketGetType(httpClientReqVar);
    // Append data to sendData
    JsVar *sendData = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_SEND_DATA, 0);
    if (!sendData) {
        JsVar *options = 0;
        // Only append a header if we're doing HTTP
        if (socketType == ST_HTTP)
            options = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_OPTIONS_VAR, 0);
        if (options) {
            JsVar *method = jsvObjectGetChild(options, "method", 0);
            JsVar *path = jsvObjectGetChild(options, "path", 0);
            sendData = jsvVarPrintf("%v %v HTTP/1.0\r\nUser-Agent: Espruino "JS_VERSION"\r\nConnection: close\r\n", method, path);
            jsvUnLock(method);
            jsvUnLock(path);
            JsVar *headers = jsvObjectGetChild(options, "headers", 0);
            bool hasHostHeader = false;
            if (jsvIsObject(headers)) {
                JsVar *hostHeader = jsvObjectGetChild(headers, "Host", 0);
                hasHostHeader = hostHeader!=0;
                jsvUnLock(hostHeader);
                httpAppendHeaders(sendData, headers);
            }
            jsvUnLock(headers);
            if (!hasHostHeader) {
                JsVar *host = jsvObjectGetChild(options, "host", 0);
                int port = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "port", 0));
                if (port>0 && port!=80)
                    jsvAppendPrintf(sendData, "Host: %v:%d\r\n", host, port);
                else
                    jsvAppendPrintf(sendData, "Host: %v\r\n", host);
                jsvUnLock(host);
            }
            // finally add ending newline
            jsvAppendString(sendData, "\r\n");
        } else {
            sendData = jsvNewFromString("");
        }
        jsvObjectSetChild(httpClientReqVar, HTTP_NAME_SEND_DATA, sendData);
        jsvUnLock(options);
    }
    if (data && sendData) {
        JsVar *s = jsvAsString(data, false);
        if (s) jsvAppendStringVarComplete(sendData,s);
        jsvUnLock(s);
    }
    jsvUnLock(sendData);
}
예제 #16
0
/*JSON{
  "type"     : "staticmethod",
  "class"    : "ESP8266WiFi",
  "name"     : "getConnectedStations",
  "generate" : "jswrap_ESP8266WiFi_getConnectedStations",
  "return"   : ["JsVar","An array of connected stations."]
}*/
JsVar *jswrap_ESP8266WiFi_getConnectedStations() {
  uint8 stationCount = wifi_softap_get_station_num();
  struct station_info *stationInfo = wifi_softap_get_station_info();
  JsVar *jsArray = jsvNewArray(NULL, 0);
  if (stationInfo != NULL) {
    while (stationInfo != NULL) {
      os_printf("Station IP: %d.%d.%d.%d\n", IP2STR(&(stationInfo->ip)));
      JsVar *jsStation = jsvNewWithFlags(JSV_OBJECT);
      jsvUnLock(jsvObjectSetChild(jsStation, "ip", jsvNewFromInteger(stationInfo->ip.addr)));
      jsvArrayPush(jsArray, jsStation);
      stationInfo = STAILQ_NEXT(stationInfo, next);
    }
    wifi_softap_free_station_info();
  }
  return jsArray;
}
예제 #17
0
/**
 * Handle receiving a response from a ping reply.
 * If a callback function has been supplied we invoked that callback by queuing it for future
 * execution.  A parameter is supplied to the callback which is a JavaScript object that contains:
 *  - totalCount
 *  - totalBytes
 *  - totalTime
 *  - respTime
 *  - seqNo
 *  - timeoutCount
 *  - bytes
 *  - error
 */
static void pingRecvCB(void *pingOpt, void *pingResponse) {
  struct ping_resp *pingResp = (struct ping_resp *)pingResponse;
  os_printf("Received a ping response!\n");
  if (g_jsPingCallback != NULL) {
    JsVar *jsPingResponse = jspNewObject(NULL, "PingResponse");
    jsvUnLock(jsvObjectSetChild(jsPingResponse, "totalCount",   jsvNewFromInteger(pingResp->total_count)));
    jsvUnLock(jsvObjectSetChild(jsPingResponse, "totalBytes",   jsvNewFromInteger(pingResp->total_bytes)));
    jsvUnLock(jsvObjectSetChild(jsPingResponse, "totalTime",    jsvNewFromInteger(pingResp->total_time)));
    jsvUnLock(jsvObjectSetChild(jsPingResponse, "respTime",     jsvNewFromInteger(pingResp->resp_time)));
    jsvUnLock(jsvObjectSetChild(jsPingResponse, "seqNo",        jsvNewFromInteger(pingResp->seqno)));
    jsvUnLock(jsvObjectSetChild(jsPingResponse, "timeoutCount", jsvNewFromInteger(pingResp->timeout_count)));
    jsvUnLock(jsvObjectSetChild(jsPingResponse, "bytes",        jsvNewFromInteger(pingResp->bytes)));
    jsvUnLock(jsvObjectSetChild(jsPingResponse, "error",        jsvNewFromInteger(pingResp->ping_err)));
    JsVar *params[1];
    params[0] = jsPingResponse;
    jsiQueueEvents(NULL, g_jsPingCallback, params, 1);
  }
}
예제 #18
0
static JsVar *matchfound(JsvStringIterator *txtIt, matchInfo info) {
  JsVar *rmatch = jsvNewEmptyArray();
  size_t endIndex = jsvStringIteratorGetIndex(txtIt);
  JsVar *matchStr = jsvNewFromStringVar(info.sourceStr, info.startIndex, endIndex-info.startIndex);
  jsvSetArrayItem(rmatch, 0, matchStr);
  jsvUnLock(matchStr);
  int i;
  for (i=0;i<info.groups;i++) {
    matchStr = jsvNewFromStringVar(info.sourceStr, info.groupStart[i], info.groupEnd[i]-info.groupStart[i]);
    jsvSetArrayItem(rmatch, i+1, matchStr);
    jsvUnLock(matchStr);
  }
  jsvObjectSetChildAndUnLock(rmatch, "index", jsvNewFromInteger((JsVarInt)info.startIndex));
  jsvObjectSetChild(rmatch, "input", info.sourceStr);

  return rmatch;
}
예제 #19
0
void bytePortInit(JsVar *parent,JsBytePort *bp){
  int i,j,value;
  uint32_t mask;
  JsVar *buf = jswrap_typedarray_constructor(ARRAYBUFFERVIEW_UINT32, jsvNewFromInteger(256),0,0);
  uint32_t *maskPnt = (uint32_t *)jswrap_espruino_getAddressOf(buf,true);
  for(int i = 0; i < 256;i++){
    mask = 0;
	value = i;
    for(j = 0; j < jswrap_byteport_pins; j++){
	  if((value & 1)>0) mask += bp->data.mask[j];
      value = value>>1;
    }
    maskPnt[i] = mask;	
  }
  jsvObjectSetChild(parent,"PortMask",buf);
  jsvUnLock(buf);  
}
예제 #20
0
파일: board_spi.c 프로젝트: gbraad/Espruino
void cc3000_initialise(JsVar *wlanObj) {
  jsvObjectSetChild(jsiGetParser()->root, CC3000_OBJ_NAME, wlanObj);

  cc3000_spi_open();
  wlan_init(cc3000_usynch_callback,
            sendNoPatch/*sendWLFWPatch*/,
            sendNoPatch/*sendDriverPatch*/,
            sendNoPatch/*sendBootLoaderPatch*/,
            cc3000_read_irq_pin, cc3000_irq_enable, cc3000_irq_disable, cc3000_write_en_pin);
  wlan_start(0/* No patches */);
  // Mask out all non-required events from CC3000
  wlan_set_event_mask(
      HCI_EVNT_WLAN_KEEPALIVE |
      HCI_EVNT_WLAN_UNSOL_INIT);

  // TODO: check return value !=0
  wlan_ioctl_set_connection_policy(0, 0, 0); // don't auto-connect
  wlan_ioctl_del_profile(255); // delete stored eeprom data
예제 #21
0
/** This gets called when a pipe destination drains itself */
static void jswrap_pipe_drain_listener(JsVar *destination) {
  if (!jsvIsObject(destination)) return;
  // try and find it...
  JsVar *arr = pipeGetArray(false);
  if (arr) {
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, arr);
    while (jsvObjectIteratorHasValue(&it)) {
      JsVar *pipe = jsvObjectIteratorGetValue(&it);
      JsVar *dst = jsvObjectGetChild(pipe,"destination",0);
      if (dst == destination) {
        // found it! said wait to false
        jsvUnLock(jsvObjectSetChild(pipe,"drainWait",jsvNewFromBool(false)));
      }
      jsvUnLock(dst);
      jsvUnLock(pipe);
      jsvObjectIteratorNext(&it);
    }
    jsvObjectIteratorFree(&it);
    jsvUnLock(arr);
  }
}
예제 #22
0
// Return a string containing 'chars' bytes. If chars<=0 the string will be all available data
JsVar *jswrap_stream_read(JsVar *parent, JsVarInt chars) {
  if (!jsvIsObject(parent)) return 0;
  JsVar *buf = jsvObjectGetChild(parent, STREAM_BUFFER_NAME, 0);
  JsVar *data = 0;
  if (jsvIsString(buf)) {
    size_t len = jsvGetStringLength(buf);
    if (chars <= 0 || (size_t)chars>=len) {
      // return the whole buffer and remove it
      data = buf;
      buf = 0;
      jsvRemoveNamedChild(parent, STREAM_BUFFER_NAME);
    } else {
      // return just part of the buffer, and shorten it accordingly
      data = jsvNewFromStringVar(buf, 0, (size_t)chars);
      JsVar *newBuf = jsvNewFromStringVar(buf, (size_t)chars, JSVAPPENDSTRINGVAR_MAXLENGTH);
      jsvUnLock(jsvObjectSetChild(parent, STREAM_BUFFER_NAME, newBuf));
    }
  } else
    data = jsvNewFromEmptyString();
  jsvUnLock(buf);
  return data;
}
예제 #23
0
/*JSON{
    "type" : "staticmethod",
    "class" : "NRF",
    "name" : "setScan",
    "generate" : "jswrap_nrf_bluetooth_setScan",
    "params" : [
      ["callback","JsVar","The callback to call with information about received, or undefined to stop"]
    ]
}

Start/stop listening for BLE advertising packets within range.

```
// Start scanning
NRF.setScan(function(d) {
  console.log(JSON.stringify(d,null,2));
});
// prints {"rssi":-72, "addr":"##:##:##:##:##:##", "data":new ArrayBuffer([2,1,6,...])}

// Stop Scanning
NRF.setScan(false);
```
*/
void jswrap_nrf_bluetooth_setScan(JsVar *callback) {
  uint32_t              err_code;
  // set the callback event variable
  if (!jsvIsFunction(callback)) callback=0;
  jsvObjectSetChild(execInfo.root, BLE_SCAN_EVENT, callback);
  // either start or stop scanning
  if (callback) {
    ble_gap_scan_params_t     m_scan_param;
    // non-selective scan
    m_scan_param.active       = 0;            // Active scanning set.
    m_scan_param.selective    = 0;            // Selective scanning not set.
    m_scan_param.interval     = SCAN_INTERVAL;// Scan interval.
    m_scan_param.window       = SCAN_WINDOW;  // Scan window.
    m_scan_param.p_whitelist  = NULL;         // No whitelist provided.
    m_scan_param.timeout      = 0x0000;       // No timeout.

    err_code = sd_ble_gap_scan_start(&m_scan_param);
  } else {
    err_code = sd_ble_gap_scan_stop();
  }
  if (err_code)
    jsExceptionHere(JSET_ERROR, "Got BLE error code %d", err_code);
}
예제 #24
0
/*JSON{
  "type" : "method",
  "class" : "Function",
  "name" : "bind",
  "generate" : "jswrap_function_bind",
  "params" : [
    ["this","JsVar","The value to use as the 'this' argument when executing the function"],
    ["params","JsVarArray","Optional Default parameters that are prepended to the call"]
  ],
  "return" : ["JsVar","The 'bound' function"]
}
This executes the function with the supplied 'this' argument and parameters
 */
JsVar *jswrap_function_bind(JsVar *parent, JsVar *thisArg, JsVar *argsArray) {
  if (!jsvIsFunction(parent)) {
    jsExceptionHere(JSET_TYPEERROR, "Function.bind expects to be called on function, got %t", parent);
    return 0;
  }
  JsVar *fn;
  if (jsvIsNativeFunction(parent))
    fn = jsvNewNativeFunction(parent->varData.native.ptr, parent->varData.native.argTypes);
  else
    fn = jsvNewWithFlags(jsvIsFunctionReturn(parent) ? JSV_FUNCTION_RETURN : JSV_FUNCTION);
  if (!fn) return 0;

  // Old function info
  JsvObjectIterator fnIt;
  jsvObjectIteratorNew(&fnIt, parent);
  // add previously bound arguments
  while (jsvObjectIteratorHasValue(&fnIt)) {
    JsVar *param = jsvObjectIteratorGetKey(&fnIt);
    JsVar *defaultValue = jsvObjectIteratorGetValue(&fnIt);
    bool wasBound = jsvIsFunctionParameter(param) && defaultValue;
    if (wasBound) {
      JsVar *newParam = jsvCopy(param);
      if (newParam) { // could be out of memory
        jsvAddName(fn, newParam);
        jsvUnLock(newParam);
      }
    }
    jsvUnLock2(param, defaultValue);
    if (!wasBound) break;
    jsvObjectIteratorNext(&fnIt);
  }

  // add bound arguments
  JsvObjectIterator argIt;
  jsvObjectIteratorNew(&argIt, argsArray);
  while (jsvObjectIteratorHasValue(&argIt)) {
    JsVar *defaultValue = jsvObjectIteratorGetValue(&argIt);
    bool addedParam = false;
    while (!addedParam && jsvObjectIteratorHasValue(&fnIt)) {
      JsVar *param = jsvObjectIteratorGetKey(&fnIt);
      if (!jsvIsFunctionParameter(param)) {
        jsvUnLock(param);
        break;
      }
      JsVar *newParam = jsvCopyNameOnly(param, false,  true);
      jsvSetValueOfName(newParam, defaultValue);
      jsvAddName(fn, newParam);
      addedParam = true;
      jsvUnLock2(param, newParam);
      jsvObjectIteratorNext(&fnIt);
    }

    if (!addedParam) {
      JsVar *paramName = jsvNewFromEmptyString();
      if (paramName) {
        jsvMakeFunctionParameter(paramName); // force this to be called a function parameter
        jsvSetValueOfName(paramName, defaultValue);
        jsvAddName(fn, paramName);
        jsvUnLock(paramName);
      }
    }
    jsvUnLock(defaultValue);
    jsvObjectIteratorNext(&argIt);
  }
  jsvObjectIteratorFree(&argIt);

  // Copy the rest of the old function's info
  while (jsvObjectIteratorHasValue(&fnIt)) {
    JsVar *param = jsvObjectIteratorGetKey(&fnIt);
    JsVar *newParam = jsvCopyNameOnly(param, true, true);
    if (newParam) { // could be out of memory
      jsvAddName(fn, newParam);
      jsvUnLock(newParam);
    }
    jsvUnLock(param);
    jsvObjectIteratorNext(&fnIt);
  }
  jsvObjectIteratorFree(&fnIt);
  // Add 'this'
  jsvObjectSetChild(fn, JSPARSE_FUNCTION_THIS_NAME, thisArg); // no unlock needed

  return fn;
}
예제 #25
0
JsVar *jswrap_date_from_milliseconds(JsVarFloat time) {
  JsVar *d = jspNewObject(0,"Date");
  if (!d) return 0;
  jsvUnLock(jsvObjectSetChild(d, "ms", jsvNewFromFloat(time)));
  return d;
}
예제 #26
0
파일: main.c 프로젝트: Janesak1977/Espruino
void addNativeFunction(const char *name, void (*callbackPtr)(void)) {
  jsvUnLock(jsvObjectSetChild(execInfo.root, name, jsvNewNativeFunction(callbackPtr, JSWAT_VOID)));
}
예제 #27
0
/*JSON{ "type":"staticproperty",
         "class" : "process", "name" : "env",
         "description" : "Returns an Object containing various pre-defined variables. standard ones are BOARD, VERSION",
         "generate" : "jswrap_process_env",
         "return" : ["JsVar", "An object"]
}*/
JsVar *jswrap_process_env() {
  JsVar *obj = jsvNewWithFlags(JSV_OBJECT);
  jsvUnLock(jsvObjectSetChild(obj, "VERSION", jsvNewFromString(JS_VERSION)));
  jsvUnLock(jsvObjectSetChild(obj, "BUILD_DATE", jsvNewFromString(__DATE__)));
  jsvUnLock(jsvObjectSetChild(obj, "BUILD_TIME", jsvNewFromString(__TIME__)));
#ifdef GIT_COMMIT
  jsvUnLock(jsvObjectSetChild(obj, "GIT_COMMIT", jsvNewFromString(STRINGIFY(GIT_COMMIT))));
#endif
  jsvUnLock(jsvObjectSetChild(obj, "BOARD", jsvNewFromString(PC_BOARD_ID)));
  jsvUnLock(jsvObjectSetChild(obj, "CHIP", jsvNewFromString(PC_BOARD_CHIP)));
  jsvUnLock(jsvObjectSetChild(obj, "CHIP_FAMILY", jsvNewFromString(PC_BOARD_CHIP_FAMILY)));
  jsvUnLock(jsvObjectSetChild(obj, "FLASH", jsvNewFromInteger(FLASH_TOTAL)));
  jsvUnLock(jsvObjectSetChild(obj, "RAM", jsvNewFromInteger(RAM_TOTAL)));
  jsvUnLock(jsvObjectSetChild(obj, "SERIAL", jswrap_interface_getSerial()));
  jsvUnLock(jsvObjectSetChild(obj, "CONSOLE", jsvNewFromString(jshGetDeviceString(jsiGetConsoleDevice()))));

  return obj;
}
예제 #28
0
bool socketIdle(JsNetwork *net) {
    if (networkState != NETWORKSTATE_ONLINE) {
        // clear all clients and servers
        _socketCloseAllConnections(net);
        return false;
    }
    bool hadSockets = false;
    JsVar *arr = socketGetArray(HTTP_ARRAY_HTTP_SERVERS,false);
    if (arr) {
        JsvObjectIterator it;
        jsvObjectIteratorNew(&it, arr);
        while (jsvObjectIteratorHasValue(&it)) {
            hadSockets = true;

            JsVar *server = jsvObjectIteratorGetValue(&it);
            int sckt = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(server,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined

            int theClient = netAccept(net, sckt);
            if (theClient >= 0) {
                SocketType socketType = socketGetType(server);
                if ((socketType&ST_TYPE_MASK) == ST_HTTP) {
                    JsVar *req = jspNewObject(0, "httpSRq");
                    JsVar *res = jspNewObject(0, "httpSRs");
                    if (res && req) { // out of memory?
                        socketSetType(req, ST_HTTP);
                        JsVar *arr = socketGetArray(HTTP_ARRAY_HTTP_SERVER_CONNECTIONS, true);
                        if (arr) {
                            jsvArrayPush(arr, req);
                            jsvUnLock(arr);
                        }
                        jsvObjectSetChild(req, HTTP_NAME_RESPONSE_VAR, res);
                        jsvObjectSetChild(req, HTTP_NAME_SERVER_VAR, server);
                        jsvObjectSetChildAndUnLock(req, HTTP_NAME_SOCKET, jsvNewFromInteger(theClient+1));
                    }
                    jsvUnLock2(req, res);
                } else {
                    // Normal sockets
                    JsVar *sock = jspNewObject(0, "Socket");
                    if (sock) { // out of memory?
                        socketSetType(sock, ST_NORMAL);
                        JsVar *arr = socketGetArray(HTTP_ARRAY_HTTP_CLIENT_CONNECTIONS, true);
                        if (arr) {
                            jsvArrayPush(arr, sock);
                            jsvUnLock(arr);
                        }
                        jsvObjectSetChildAndUnLock(sock, HTTP_NAME_SOCKET, jsvNewFromInteger(theClient+1));
                        jsiQueueObjectCallbacks(server, HTTP_NAME_ON_CONNECT, &sock, 1);
                        jsvUnLock(sock);
                    }
                }
            }

            jsvUnLock(server);
            jsvObjectIteratorNext(&it);
        }
        jsvObjectIteratorFree(&it);
        jsvUnLock(arr);
    }

    if (socketServerConnectionsIdle(net)) hadSockets = true;
    if (socketClientConnectionsIdle(net)) hadSockets = true;
    netCheckError(net);
    return hadSockets;
}
예제 #29
0
void clientRequestWrite(JsNetwork *net, JsVar *httpClientReqVar, JsVar *data) {
    SocketType socketType = socketGetType(httpClientReqVar);
    // Append data to sendData
    JsVar *sendData = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_SEND_DATA, 0);
    if (!sendData) {
        JsVar *options = 0;
        // Only append a header if we're doing HTTP AND we haven't already connected
        if ((socketType&ST_TYPE_MASK) == ST_HTTP)
            if (jsvGetIntegerAndUnLock(jsvObjectGetChild(httpClientReqVar, HTTP_NAME_SOCKET, 0))==0)
                options = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_OPTIONS_VAR, 0);
        if (options) {
            // We're an HTTP client - make a header
            JsVar *method = jsvObjectGetChild(options, "method", 0);
            JsVar *path = jsvObjectGetChild(options, "path", 0);
            sendData = jsvVarPrintf("%v %v HTTP/1.0\r\nUser-Agent: Espruino "JS_VERSION"\r\nConnection: close\r\n", method, path);
            jsvUnLock2(method, path);
            JsVar *headers = jsvObjectGetChild(options, "headers", 0);
            bool hasHostHeader = false;
            if (jsvIsObject(headers)) {
                JsVar *hostHeader = jsvObjectGetChild(headers, "Host", 0);
                hasHostHeader = hostHeader!=0;
                jsvUnLock(hostHeader);
                httpAppendHeaders(sendData, headers);
                // if Transfer-Encoding:chunked was set, subsequent writes need to 'chunk' the data that is sent
                if (jsvIsStringEqualAndUnLock(jsvObjectGetChild(headers, "Transfer-Encoding", 0), "chunked")) {
                    jsvObjectSetChildAndUnLock(httpClientReqVar, HTTP_NAME_CHUNKED, jsvNewFromBool(true));
                }
            }
            jsvUnLock(headers);
            if (!hasHostHeader) {
                JsVar *host = jsvObjectGetChild(options, "host", 0);
                int port = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "port", 0));
                if (port>0 && port!=80)
                    jsvAppendPrintf(sendData, "Host: %v:%d\r\n", host, port);
                else
                    jsvAppendPrintf(sendData, "Host: %v\r\n", host);
                jsvUnLock(host);
            }
            // finally add ending newline
            jsvAppendString(sendData, "\r\n");
        } else { // !options
            // We're not HTTP (or were already connected), so don't send any header
            sendData = jsvNewFromString("");
        }
        jsvObjectSetChild(httpClientReqVar, HTTP_NAME_SEND_DATA, sendData);
        jsvUnLock(options);
    }
    // We have data and aren't out of memory...
    if (data && sendData) {
        // append the data to what we want to send
        JsVar *s = jsvAsString(data, false);
        if (s) {
            if ((socketType&ST_TYPE_MASK) == ST_HTTP &&
                    jsvGetBoolAndUnLock(jsvObjectGetChild(httpClientReqVar, HTTP_NAME_CHUNKED, 0))) {
                // If we asked to send 'chunked' data, we need to wrap it up,
                // prefixed with the length
                jsvAppendPrintf(sendData, "%x\r\n%v\r\n", jsvGetStringLength(s), s);
            } else {
                jsvAppendStringVarComplete(sendData,s);
            }
            jsvUnLock(s);
        }
    }
    jsvUnLock(sendData);
    if ((socketType&ST_TYPE_MASK) == ST_HTTP) {
        // on HTTP we connect after the first write
        clientRequestConnect(net, httpClientReqVar);
    }
}
예제 #30
0
/**
 * Callback function that is invoked at the culmination of a scan.
 */
static void scanCB(void *arg, STATUS status) {
  /**
   * Create a JsVar that is an array of JS objects where each JS object represents a
   * retrieved access point set of information.   The structure of a record will be:
   * o authMode
   * o isHidden
   * o rssi
   * o channel
   * o ssid
   * When the array has been built, invoke the callback function passing in the array
   * of records.
   */

  os_printf(">> scanCB\n");
  // Create the Empty JS array that will be passed as a parameter to the callback.
  JsVar *accessPointArray = jsvNewArray(NULL, 0);
  struct bss_info *bssInfo;

  bssInfo = (struct bss_info *)arg;
  while(bssInfo != NULL) {
    // Add a new object to the JS array that will be passed as a parameter to
    // the callback.  The ESP8266 bssInfo structure contains the following:
    // ---
    // uint8 bssid[6]
    // uint8 ssid[32]
    // uint8 channel
    // sint8 rssi \96 The received signal strength indication
    // AUTH_MODE authmode
    //  Open = 0
    //  WEP = 1
    //  WPA_PSK = 2
    //  WPA2_PSK = 3
    //  WPA_WPA2_PSK = 4
    // uint8 is_hidden
    // sint16 freq_offset
    // ---
    // Create, populate and add a child ...
    JsVar *currentAccessPoint = jspNewObject(NULL, "AccessPoint");
    jsvUnLock(jsvObjectSetChild(currentAccessPoint, "rssi", jsvNewFromInteger(bssInfo->rssi)));
    jsvUnLock(jsvObjectSetChild(currentAccessPoint, "channel", jsvNewFromInteger(bssInfo->channel)));
    jsvUnLock(jsvObjectSetChild(currentAccessPoint, "authMode", jsvNewFromInteger(bssInfo->authmode)));
    jsvUnLock(jsvObjectSetChild(currentAccessPoint, "isHidden", jsvNewFromBool(bssInfo->is_hidden)));
    // The SSID may **NOT** be NULL terminated ... so handle that.
    char ssid[sizeof(bssInfo->ssid) + 1];
    os_strncpy((char *)ssid, (char *)bssInfo->ssid, sizeof(bssInfo->ssid));
    ssid[sizeof(ssid)-1] = '\0';
    jsvUnLock(jsvObjectSetChild(currentAccessPoint, "ssid", jsvNewFromString(ssid)));

    // Add the new record to the array
    jsvArrayPush(accessPointArray, currentAccessPoint);

    os_printf(" - ssid: %s\n", bssInfo->ssid);
    bssInfo = STAILQ_NEXT(bssInfo, next);
  }

  // We have now completed the scan callback, so now we can invoke the JS callback.
  JsVar *params[1];
  params[0] = accessPointArray;
  jsiQueueEvents(NULL, g_jsScanCallback, params, 1);
  jsvUnLock(g_jsScanCallback);
  os_printf("<< scanCB\n");
}