Пример #1
0
/*JSON{
  "type"     : "staticmethod",
  "class"    : "ESP8266WiFi",
  "name"     : "onWiFiEvent",
  "generate" : "jswrap_ESP8266WiFi_onWiFiEvent",
  "params"   : [
    ["callback","JsVar","WiFi event callback"]
  ]
}*/
void jswrap_ESP8266WiFi_onWiFiEvent(
    JsVar *callback //!< WiFi event callback.
  ) {
  // If the callback is null
  if (callback == NULL || jsvIsNull(callback)) {
    if (g_jsWiFiEventCallback != NULL) {
      jsvUnLock(g_jsWiFiEventCallback);
    }
    g_jsWiFiEventCallback = NULL;
    return;
  }

  if (!jsvIsFunction(callback)) {
      jsExceptionHere(JSET_ERROR, "No callback.");
    return;
  }

  // We are about to save a new global WiFi even callback handler.  If we have previously
  // had one, we need to unlock it so that we don't leak memory.
  if (g_jsWiFiEventCallback != NULL) {
    jsvUnLock(g_jsWiFiEventCallback);
  }

  // Save the global WiFi event callback handler.
  g_jsWiFiEventCallback = jsvLockAgainSafe(callback);
}
Пример #2
0
/*JSON{ "type":"method", "class": "Serial", "name" : "setup",
         "description" : "Setup this Serial port with the given baud rate and options",
         "generate" : "jswrap_serial_setup",
         "params" : [ [ "baudrate", "int", "The baud rate - the default is 9600"],
                      [ "options", "JsVar", ["An optional structure containing extra information on initialising the serial port.",
                                             "```{rx:pin,tx:pin}```",
                                             "Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite" ] ] ]
}*/
void jswrap_serial_setup(JsVar *parent, JsVarInt baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (baud>0) inf.baudRate = (int)baud;

  if (jsvIsObject(options)) {

    inf.pinRX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "rx", 0));
    inf.pinTX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "tx", 0));
    inf.bytesize = (unsigned char)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "bytesize", 0));

    JsVar *v;
    v = jsvObjectGetChild(options, "parity", 0);
    
    if(jsvIsNull(v)) {
      inf.parity = 0;
    }
    else if(jsvIsString(v)) {
      inf.parity = 0xFF;
      char s[8] = "";

      jsvGetString(v, s, sizeof(s) - 1);

      if(!strcmp(s, "o") || !strcmp(s, "odd")) {
        inf.parity = 1;
      }
      else if(!strcmp(s, "e") || !strcmp(s, "even")) {
        inf.parity = 2;
      }
    }
    else if(jsvIsInt(v)) {
      inf.parity = (unsigned char)jsvGetInteger(v);
    }

    jsvUnLock(v);

    v = jsvObjectGetChild(options, "stopbits", 0);
    inf.stopbits = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  if (baud != DEFAULT_BAUD_RATE) {
    JsVar *baudVar = jsvNewFromInteger(baud);
    jsvUnLock(jsvSetNamedChild(parent, baudVar, USART_BAUDRATE_NAME));
    jsvUnLock(baudVar);
  } else
    jsvRemoveNamedChild(parent, USART_BAUDRATE_NAME);
  // Do the same for options
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Пример #3
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "match",
  "generate" : "jswrap_string_match",
  "params" : [
    ["subStr","JsVar","Substring or RegExp to match"]
  ],
  "return" : ["JsVar","This match array"]
}
Matches `subStr` occurrence in the string.
 */
JsVar *jswrap_string_match(JsVar *parent, JsVar *subStr) {
  if (!jsvIsString(parent)) return 0;
  if (jsvIsUndefined(subStr)) return 0;

#ifndef SAVE_ON_FLASH
  // Use RegExp if one is passed in
  if (jsvIsInstanceOf(subStr, "RegExp")) {
    jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(0));
    JsVar *match;
    match = jswrap_regexp_exec(subStr, parent);
    if (!jswrap_regexp_hasFlag(subStr,'g')) {
      return match;
    }

    // global
    JsVar *array = jsvNewEmptyArray();
    if (!array) return 0; // out of memory
    while (match && !jsvIsNull(match)) {
      // get info about match
      JsVar *matchStr = jsvGetArrayItem(match,0);
      JsVarInt idx = jsvGetIntegerAndUnLock(jsvObjectGetChild(match,"index",0));
      JsVarInt len = (JsVarInt)jsvGetStringLength(matchStr);
      int last = idx+len;
      jsvArrayPushAndUnLock(array, matchStr);
      // search again
      jsvUnLock(match);
      jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(last));
      match = jswrap_regexp_exec(subStr, parent);
    }
    jsvUnLock(match);
    jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(0));
    return array;
  }
#endif

  subStr = jsvAsString(subStr);

  int idx = jswrap_string_indexOf(parent, subStr, 0, false);
  if (idx>=0) {
      JsVar *array = jsvNewEmptyArray();
      if (!array) {
        jsvUnLock(subStr);
        return 0; // out of memory
      }

      jsvArrayPush(array, subStr);
      jsvObjectSetChildAndUnLock(array, "index", jsvNewFromInteger(idx));
      jsvObjectSetChildAndUnLock(array, "input", subStr);
      return array;
  }
  jsvUnLock(subStr);
  return NULL;
}
Пример #4
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;
}
Пример #5
0
/*JSON{
  "type"     : "staticmethod",
  "class"    : "ESP8266WiFi",
  "name"     : "ping",
  "generate" : "jswrap_ESP8266WiFi_ping",
  "params"   : [
    ["ipAddr","JsVar","A string or integer representation of an IP address."],
    ["pingCallback", "JsVar", "Optional callback function."]
  ]
}*/
void jswrap_ESP8266WiFi_ping(
    JsVar *ipAddr,      //!< A string or integer representation of an IP address.
    JsVar *pingCallback //!< Optional callback function.
  ) {
  // If the parameter is a string, get the IP address from the string
  // representation.
  if (jsvIsString(ipAddr)) {
    char ipString[20];
    int len = jsvGetString(ipAddr, ipString, sizeof(ipString)-1);
    ipString[len] = '\0';
    pingOpt.ip = networkParseIPAddress(ipString);
    if (pingOpt.ip == 0) {
        jsExceptionHere(JSET_ERROR, "Not a valid IP address.");
      return;
    }
  } else
  // If the parameter is an integer, treat it as an IP address.
  if (jsvIsInt(ipAddr)) {
    pingOpt.ip = jsvGetInteger(ipAddr);
  } else
  // The parameter was neither a string nor an IP address and hence we don't
  // know how to get the IP address of the partner to ping so throw an
  // exception.
  {
      jsExceptionHere(JSET_ERROR, "IP address must be string or integer.");
    return;
  }

  if (jsvIsUndefined(pingCallback) || jsvIsNull(pingCallback)) {
    if (g_jsPingCallback != NULL) {
      jsvUnLock(g_jsPingCallback);
    }
    g_jsPingCallback = NULL;
  } else if (!jsvIsFunction(pingCallback)) {
      jsExceptionHere(JSET_ERROR, "Callback is not a function.");
    return;
  } else {
    if (g_jsPingCallback != NULL) {
      jsvUnLock(g_jsPingCallback);
    }
    g_jsPingCallback = pingCallback;
    jsvLockAgainSafe(g_jsPingCallback);
  }

  // We now have an IP address to ping ... so ping.
  memset(&pingOpt, 0, sizeof(pingOpt));
  pingOpt.count = 5;
  pingOpt.recv_function = pingRecvCB;
  ping_start(&pingOpt);
}
Пример #6
0
/*JSON{
  "type" : "staticmethod",
  "class" : "JSON",
  "name" : "stringify",
  "generate" : "jswrap_json_stringify",
  "params" : [
    ["data","JsVar","The data to be converted to a JSON string"],
    ["replacer","JsVar","This value is ignored"],
    ["space","JsVar","The number of spaces to use for padding, a string, or null/undefined for no whitespace "]
  ],
  "return" : ["JsVar","A JSON string"]
}
Convert the given object into a JSON string which can subsequently be parsed with JSON.parse or eval.

**Note:** This differs from JavaScript's standard `JSON.stringify` in that:

* The `replacer` argument is ignored
* Typed arrays like `new Uint8Array(5)` will be dumped as if they were arrays, not as if they were objects (since it is more compact)
 */
JsVar *jswrap_json_stringify(JsVar *v, JsVar *replacer, JsVar *space) {
  NOT_USED(replacer);
  JSONFlags flags = JSON_IGNORE_FUNCTIONS|JSON_NO_UNDEFINED|JSON_ARRAYBUFFER_AS_ARRAY;
  JsVar *result = jsvNewFromEmptyString();
  if (result) {// could be out of memory
    char whitespace[11] = "";
    if (jsvIsUndefined(space) || jsvIsNull(space)) {
      // nothing
    } else if (jsvIsNumeric(space)) {
      unsigned int s = (unsigned int)jsvGetInteger(space);
      if (s>10) s=10;
      whitespace[s] = 0;
      while (s) whitespace[--s]=' ';
    } else {
      jsvGetString(space, whitespace, sizeof(whitespace));
    }
    if (strlen(whitespace)) flags |= JSON_ALL_NEWLINES|JSON_PRETTY;
    jsfGetJSONWhitespace(v, result, flags, whitespace);
  }
  return result;
}
Пример #7
0
bool jsonNeedsNewLine(JsVar *v) {
  return !(jsvIsUndefined(v) || jsvIsNull(v) || jsvIsNumeric(v));
  // we're skipping strings here because they're usually long and want printing on multiple lines
}
Пример #8
0
/*JSON{
  "type" : "method",
  "class" : "Serial",
  "name" : "setup",
  "generate" : "jswrap_serial_setup",
  "params" : [
    ["baudrate","JsVar","The baud rate - the default is 9600"],
    ["options","JsVar",["An optional structure containing extra information on initialising the serial port.","```{rx:pin,tx:pin,bytesize:8,parity:null/'none'/'o'/'odd'/'e'/'even',stopbits:1,flow:null/undefined/'none'/'xon'}```","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `UART`/`USART` markers.","Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite"]]
  ]
}
Setup this Serial port with the given baud rate and options.

If not specified in options, the default pins are used (usually the lowest numbered pins on the lowest port that supports this peripheral)
 */
void jswrap_serial_setup(JsVar *parent, JsVar *baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_USART(device)) return;

  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (jsvIsUndefined(options)) {
    options = jsvObjectGetChild(parent, DEVICE_OPTIONS_NAME, 0);
  } else
    jsvLockAgain(options);

  JsVar *parity = 0;
  JsVar *flow = 0;
  jsvConfigObject configs[] = {
      {"rx", JSV_PIN, &inf.pinRX},
      {"tx", JSV_PIN, &inf.pinTX},
      {"ck", JSV_PIN, &inf.pinCK},
      {"bytesize", JSV_INTEGER, &inf.bytesize},
      {"stopbits", JSV_INTEGER, &inf.stopbits},
      {"parity", JSV_OBJECT /* a variable */, &parity},
      {"flow", JSV_OBJECT /* a variable */, &flow},
  };



  if (!jsvIsUndefined(baud)) {
    int b = (int)jsvGetInteger(baud);
    if (b<=100 || b > 10000000)
      jsExceptionHere(JSET_ERROR, "Invalid baud rate specified");
    else
      inf.baudRate = b;
  }

  bool ok = true;
  if (jsvReadConfigObject(options, configs, sizeof(configs) / sizeof(jsvConfigObject))) {
    // sort out parity
    inf.parity = 0;
    if(jsvIsString(parity)) {
      if (jsvIsStringEqual(parity, "o") || jsvIsStringEqual(parity, "odd"))
        inf.parity = 1;
      else if (jsvIsStringEqual(parity, "e") || jsvIsStringEqual(parity, "even"))
        inf.parity = 2;
    } else if (jsvIsInt(parity)) {
      inf.parity = (unsigned char)jsvGetInteger(parity);
    }
    if (inf.parity>2) {
      jsExceptionHere(JSET_ERROR, "Invalid parity %d", inf.parity);
      ok = false;
    }

    if (ok) {
      if (jsvIsUndefined(flow) || jsvIsNull(flow) || jsvIsStringEqual(flow, "none"))
        inf.xOnXOff = false;
      else if (jsvIsStringEqual(flow, "xon"))
        inf.xOnXOff = true;
      else {
        jsExceptionHere(JSET_ERROR, "Invalid flow control: %q", flow);
        ok = false;
      }
    }

#ifdef LINUX
    if (ok && jsvIsObject(options))
      jsvObjectSetChildAndUnLock(parent, "path", jsvObjectGetChild(options, "path", 0));
#endif
  }
  jsvUnLock(parity);
  jsvUnLock(flow);
  if (!ok) {
    jsvUnLock(options);
    return;
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  jsvObjectSetChildAndUnLock(parent, USART_BAUDRATE_NAME, jsvNewFromInteger(inf.baudRate));
  // Do the same for options
  if (options)
    jsvObjectSetChildAndUnLock(parent, DEVICE_OPTIONS_NAME, options);
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Пример #9
0
/*JSON{
  "type"     : "staticmethod",
  "class"    : "ESP8266WiFi",
  "name"     : "connect",
  "generate" : "jswrap_ESP8266WiFi_connect",
  "params"   : [
    ["ssid","JsVar","The network id of the access point."],
    ["password","JsVar","The password to the access point"],
    ["gotIpCallback", "JsVar", "An optional callback invoked when we have an IP"]
  ]
}
 *
 * Connect the station to an access point.
 */
void jswrap_ESP8266WiFi_connect(
    JsVar *jsv_ssid,     //!< The SSID of the access point to connect.
    JsVar *jsv_password, //!< The password for the access point.
    JsVar *gotIpCallback //!< The Callback function to be called when we are connected.
  ) {
    os_printf("> jswrap_ESP8266WiFi_connect\n");

  // Check that the ssid and password values aren't obviously in error.
  if (jsv_ssid == NULL || !jsvIsString(jsv_ssid)) {
      jsExceptionHere(JSET_ERROR, "No SSID.");
    return;
  }
  if (jsv_password == NULL || !jsvIsString(jsv_password)) {
      jsExceptionHere(JSET_ERROR, "No password.");
    return;
  }

  // Check that if a callback function was supplied that we actually have a callback function.
  if (gotIpCallback != NULL && !jsvIsUndefined(gotIpCallback) && !jsvIsFunction(gotIpCallback)) {
    gotIpCallback = NULL;
      jsExceptionHere(JSET_ERROR, "A callback function was supplied that is not a function.");
    return;
  }
  if (jsvIsUndefined(gotIpCallback) || jsvIsNull(gotIpCallback)) {
    gotIpCallback = NULL;
  }

  // Set the global which is the gotIP callback to null but first unlock it.
  if (g_jsGotIpCallback != NULL) {
    jsvUnLock(g_jsGotIpCallback);
    g_jsGotIpCallback = NULL;
  }

  // If we have a callback, save it for later invocation.
  if (gotIpCallback != NULL) {
    g_jsGotIpCallback = jsvLockAgainSafe(gotIpCallback);
  }

  // Debug
  // os_printf("jsGotIpCallback=%p\n", jsGotIpCallback);

  // Create strings from the JsVars for the ESP8266 API calls.
  char ssid[33];
  int len = jsvGetString(jsv_ssid, ssid, sizeof(ssid)-1);
  ssid[len]='\0';
  char password[65];
  len = jsvGetString(jsv_password, password, sizeof(password)-1);
  password[len]='\0';

  os_printf(">  - ssid=%s, password=%s\n", ssid, password);

  // Set the WiFi mode of the ESP8266
  wifi_set_opmode_current(STATION_MODE);

  struct station_config stationConfig;
  memset(&stationConfig, 0, sizeof(stationConfig));
  os_strncpy((char *)stationConfig.ssid, ssid, 32);
  if (password != NULL) {
    os_strncpy((char *)stationConfig.password, password, 64);
  } else {
    os_strcpy((char *)stationConfig.password, "");
  }

  // Set the WiFi configuration
  wifi_station_set_config(&stationConfig);

  uint8 wifiConnectStatus = wifi_station_get_connect_status();
  os_printf(" - Current connect status: %s\n", wifiConnectStatusToString(wifiConnectStatus));

  if (wifiConnectStatus == STATION_GOT_IP) {
    // See issue #618.  There are currently three schools of thought on what should happen
    // when a connect is issued and we are already connected.
    //
    // Option #1 - Always perform a disconnect.
    // Option #2 - Perform a disconnect if the SSID or PASSWORD are different from current
    // Option #3 - Fail the connect if we are already connected.
    //
#define ISSUE_618 1

#if ISSUE_618 == 1
    wifi_station_disconnect();
#elif ISSUE_618 == 2
    struct station_config existingConfig;
    wifi_station_get_config(&existingConfig);
    if (os_strncmp((char *)existingConfig.ssid, (char *)stationConfig.ssid, 32) == 0 &&
        os_strncmp((char *)existingConfig.password, (char *)stationConfig.password, 64) == 0) {
      if (jsGotIpCallback != NULL) {
        JsVar *params[2];
        params[0] = jsvNewFromInteger(STATION_GOT_IP);
         params[1] = jsvNewNull();
        jsiQueueEvents(NULL, jsGotIpCallback, params, 2);
      }
      return;

    } else {
      wifi_station_disconnect();
    }
#elif ISSUE_618 == 3
    // Add a return code to the function and return an already connected error.
#endif
  }
  // Perform the network level connection.
  wifi_station_connect();
  os_printf("< jswrap_ESP8266WiFi_connect\n");
}
Пример #10
0
/*JSON{
  "type" : "staticmethod",
  "class" : "url",
  "name" : "parse",
  "generate" : "jswrap_url_parse",
  "params" : [
    ["urlStr","JsVar","A URL to be parsed"],
    ["parseQuery","bool","Whether to parse the query string into an object not (default = false)"]
  ],
  "return" : ["JsVar","An object containing options for ```http.request``` or ```http.get```. Contains `method`, `host`, `path`, `pathname`, `search`, `port` and `query`"]
}
A utility function to split a URL into parts

This is useful in web servers for instance when handling a request.

For instance `url.parse("/a?b=c&d=e",true)` returns `{"method":"GET","host":"","path":"/a?b=c&d=e","pathname":"/a","search":"?b=c&d=e","port":80,"query":{"b":"c","d":"e"}}`
*/
JsVar *jswrap_url_parse(JsVar *url, bool parseQuery) {
  if (!jsvIsString(url)) return 0;
  JsVar *obj = jsvNewWithFlags(JSV_OBJECT);
  if (!obj) return 0; // out of memory

  // scan string to try and pick stuff out
  JsvStringIterator it;
  jsvStringIteratorNew(&it, url, 0);
  int slashes = 0;
  int colons = 0;
  int addrStart = -1;
  int portStart = -1;
  int pathStart = -1;
  int searchStart = -1;
  int charIdx = 0;
  int portNumber = 0;
  while (jsvStringIteratorHasChar(&it)) {
    char ch = jsvStringIteratorGetChar(&it);
    if (ch == '/') {
      slashes++;
      if (pathStart<0) pathStart = charIdx;
      if (colons==1 && slashes==2 && addrStart<0) {
        addrStart = charIdx;
        pathStart = -1;
        searchStart = -1;
      }
    }
    if (ch == ':') {
      colons++;
      if (addrStart>=0 && pathStart<0)
        portStart = charIdx;
    }

    if (portStart>=0 && charIdx>portStart && pathStart<0 && ch >= '0' && ch <= '9') {
      portNumber = portNumber*10 + (ch-'0');
    }

    if (ch == '?' && pathStart>=0) {
      searchStart = charIdx;
    }

    jsvStringIteratorNext(&it);
    charIdx++;
  }
  jsvStringIteratorFree(&it);
  // try and sort stuff out
  if (pathStart<0) pathStart = charIdx;
  if (pathStart<0) pathStart = charIdx;
  int addrEnd = (portStart>=0) ? portStart : pathStart;
  // pull out details
  if (addrStart>0)
    jsvObjectSetChildAndUnLock(obj, "protocol", jsvNewFromStringVar(url, 0, (size_t)addrStart-1));
  jsvObjectSetChildAndUnLock(obj, "method", jsvNewFromString("GET"));
  jsvObjectSetChildAndUnLock(obj, "host", jsvNewFromStringVar(url, (size_t)(addrStart+1), (size_t)(addrEnd-(addrStart+1))));

  JsVar *v;

  v = jsvNewFromStringVar(url, (size_t)pathStart, JSVAPPENDSTRINGVAR_MAXLENGTH);
  if (jsvGetStringLength(v)==0) jsvAppendString(v, "/");
  jsvObjectSetChildAndUnLock(obj, "path", v);

  v = jsvNewFromStringVar(url, (size_t)pathStart, (size_t)((searchStart>=0)?(searchStart-pathStart):JSVAPPENDSTRINGVAR_MAXLENGTH));
  if (jsvGetStringLength(v)==0) jsvAppendString(v, "/");
  jsvObjectSetChildAndUnLock(obj, "pathname", v);

  jsvObjectSetChildAndUnLock(obj, "search", (searchStart>=0)?jsvNewFromStringVar(url, (size_t)searchStart, JSVAPPENDSTRINGVAR_MAXLENGTH):jsvNewNull());

  jsvObjectSetChildAndUnLock(obj, "port", (portNumber<=0 || portNumber>65535) ? jsvNewWithFlags(JSV_NULL) : jsvNewFromInteger(portNumber));

  JsVar *query = (searchStart>=0)?jsvNewFromStringVar(url, (size_t)(searchStart+1), JSVAPPENDSTRINGVAR_MAXLENGTH):jsvNewNull();
  if (parseQuery && !jsvIsNull(query)) {
    JsVar *queryStr = query;
    jsvStringIteratorNew(&it, query, 0);
    query = jsvNewWithFlags(JSV_OBJECT);

    JsVar *key = jsvNewFromEmptyString();
    JsVar *val = jsvNewFromEmptyString();
    bool hadEquals = false;

    while (jsvStringIteratorHasChar(&it)) {
      char ch = jsvStringIteratorGetChar(&it);
      if (ch=='&') {
        if (jsvGetStringLength(key)>0 || jsvGetStringLength(val)>0) {
          key = jsvAsArrayIndexAndUnLock(key); // make sure "0" gets made into 0
          jsvMakeIntoVariableName(key, val);
          jsvAddName(query, key);
          jsvUnLock2(key, val);
          key = jsvNewFromEmptyString();
          val = jsvNewFromEmptyString();
          hadEquals = false;
        }
      } else if (!hadEquals && ch=='=') {
        hadEquals = true;
      } else {
        // decode percent escape chars
        if (ch=='%') {
          jsvStringIteratorNext(&it);
          ch = jsvStringIteratorGetChar(&it);
          jsvStringIteratorNext(&it);
          ch = (char)((chtod(ch)<<4) | chtod(jsvStringIteratorGetChar(&it)));
        }

        if (hadEquals) jsvAppendCharacter(val, ch);
        else jsvAppendCharacter(key, ch);
      }
      jsvStringIteratorNext(&it);
      charIdx++;
    }
    jsvStringIteratorFree(&it);
    jsvUnLock(queryStr);

    if (jsvGetStringLength(key)>0 || jsvGetStringLength(val)>0) {
      key = jsvAsArrayIndexAndUnLock(key); // make sure "0" gets made into 0
      jsvMakeIntoVariableName(key, val);
      jsvAddName(query, key);
    }
    jsvUnLock2(key, val);
  }
  jsvObjectSetChildAndUnLock(obj, "query", query);

  return obj;
}
Пример #11
0
/*JSON{
  "type" : "method",
  "class" : "Serial",
  "name" : "setup",
  "generate" : "jswrap_serial_setup",
  "params" : [
    ["baudrate","JsVar","The baud rate - the default is 9600"],
    ["options","JsVar",["An optional structure containing extra information on initialising the serial port.","```{rx:pin,tx:pin,bytesize:8,parity:null/'none'/'o'/'odd'/'e'/'even',stopbits:1,flow:null/undefined/'none'/'xon'}```","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `UART`/`USART` markers.","Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite"]]
  ]
}
Setup this Serial port with the given baud rate and options.

If not specified in options, the default pins are used (usually the lowest numbered pins on the lowest port that supports this peripheral)
*/
void jswrap_serial_setup(JsVar *parent, JsVar *baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_USART(device)) return;

  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (!jsvIsUndefined(baud)) {
    int b = (int)jsvGetInteger(baud);
    if (b<=100 || b > 10000000)
      jsExceptionHere(JSET_ERROR, "Invalid baud rate specified");
    else
      inf.baudRate = b;
  }


  if (jsvIsObject(options)) {
    inf.pinRX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "rx", 0));
    inf.pinTX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "tx", 0));    
    inf.pinCK = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "ck", 0));

    JsVar *v;
    v = jsvObjectGetChild(options, "bytesize", 0);
    if (jsvIsInt(v)) 
      inf.bytesize = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
    
    inf.parity = 0;
    v = jsvObjectGetChild(options, "parity", 0);
    if(jsvIsString(v)) {
      if(jsvIsStringEqual(v, "o") || jsvIsStringEqual(v, "odd"))
        inf.parity = 1;
      else if(jsvIsStringEqual(v, "e") || jsvIsStringEqual(v, "even"))
        inf.parity = 2;
    } else if(jsvIsInt(v)) {
      inf.parity = (unsigned char)jsvGetInteger(v);
    }
    jsvUnLock(v);
    if (inf.parity>2) {
      jsExceptionHere(JSET_ERROR, "Invalid parity %d", inf.parity);
      return;
    }

    v = jsvObjectGetChild(options, "stopbits", 0);
    if (jsvIsInt(v)) 
      inf.stopbits = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);

    v = jsvObjectGetChild(options, "flow", 0);
    if(jsvIsUndefined(v) || jsvIsNull(v) || jsvIsStringEqual(v, "none"))
      inf.xOnXOff = false;
    else if(jsvIsStringEqual(v, "xon"))
      inf.xOnXOff = true;
    else jsExceptionHere(JSET_ERROR, "Invalid flow control: %q", v);
    jsvUnLock(v);

#ifdef LINUX
    jsvUnLock(jsvObjectSetChild(parent, "path", jsvObjectGetChild(options, "path", 0)));
#endif
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  jsvUnLock(jsvObjectSetChild(parent, USART_BAUDRATE_NAME, jsvNewFromInteger(inf.baudRate)));
  // Do the same for options
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Пример #12
0
/*JSON{
  "type" : "method",
  "ifndef" : "SAVE_ON_FLASH",
  "class" : "RegExp",
  "name" : "test",
  "params" : [
    ["str","JsVar","A string to match on"]
  ],
  "generate" : "jswrap_regexp_test",
  "return" : ["bool","true for a match, or false"]
}
Test this regex on a string - returns `true` on a successful match, or `false` otherwise
 */
bool jswrap_regexp_test(JsVar *parent, JsVar *str) {
  JsVar *v = jswrap_regexp_exec(parent, str);
  bool r = v && !jsvIsNull(v);
  jsvUnLock(v);
  return r;
}
Пример #13
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "split",
  "generate" : "jswrap_string_split",
  "params" : [
    ["separator","JsVar","The separator `String` or `RegExp` to use"]
  ],
  "return" : ["JsVar","Part of this string from start for len characters"]
}
Return an array made by splitting this string up by the separator. eg. ```'1,2,3'.split(',')==['1', '2', '3']```

Regular Expressions can also be used to split strings, eg. `'1a2b3 4'.split(/[^0-9]/)==['1', '2', '3', '4']`.
 */
JsVar *jswrap_string_split(JsVar *parent, JsVar *split) {
  if (!jsvIsString(parent)) return 0;
  JsVar *array = jsvNewEmptyArray();
  if (!array) return 0; // out of memory

  if (jsvIsUndefined(split)) {
    jsvArrayPush(array, parent);
    return array;
  }


#ifndef SAVE_ON_FLASH
  // Use RegExp if one is passed in
  if (jsvIsInstanceOf(split, "RegExp")) {
    unsigned int last = 0;
    JsVar *match;
    jsvObjectSetChildAndUnLock(split, "lastIndex", jsvNewFromInteger(0));
    match = jswrap_regexp_exec(split, parent);
    while (match && !jsvIsNull(match)) {
      // get info about match
      JsVar *matchStr = jsvGetArrayItem(match,0);
      JsVarInt idx = jsvGetIntegerAndUnLock(jsvObjectGetChild(match,"index",0));
      JsVarInt len = (JsVarInt)jsvGetStringLength(matchStr);
      jsvUnLock(matchStr);
      // do the replacement
      jsvArrayPushAndUnLock(array, jsvNewFromStringVar(parent, (size_t)last, (size_t)(idx-last)));
      last = idx+len;
      // search again
      jsvUnLock(match);
      jsvObjectSetChildAndUnLock(split, "lastIndex", jsvNewFromInteger(last));
      match = jswrap_regexp_exec(split, parent);
    }
    jsvUnLock(match);
    jsvObjectSetChildAndUnLock(split, "lastIndex", jsvNewFromInteger(0));
    // add remaining string after last match
    if (last<=jsvGetStringLength(parent))
      jsvArrayPushAndUnLock(array, jsvNewFromStringVar(parent, (size_t)last, JSVAPPENDSTRINGVAR_MAXLENGTH));
    return array;
  }
#endif

  split = jsvAsString(split);

  int idx, last = 0;
  int splitlen = jsvIsUndefined(split) ? 0 : (int)jsvGetStringLength(split);
  int l = (int)jsvGetStringLength(parent) + 1 - splitlen;

  for (idx=0;idx<=l;idx++) {
    if (splitlen==0 && idx==0) continue; // special case for where split string is ""
    if (idx==l || splitlen==0 || jsvCompareString(parent, split, (size_t)idx, 0, true)==0) {
      if (idx==l) {
        idx=l+splitlen; // if the last element, do to the end of the string
        if (splitlen==0) break;
      }

      JsVar *part = jsvNewFromStringVar(parent, (size_t)last, (size_t)(idx-last));
      if (!part) break; // out of memory
      jsvArrayPush(array, part);
      jsvUnLock(part);
      last = idx+splitlen;
    }
  }
  jsvUnLock(split);
  return array;
}
Пример #14
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "replace",
  "generate" : "jswrap_string_replace",
  "params" : [
    ["subStr","JsVar","The string to search for"],
    ["newSubStr","JsVar","The string to replace it with"]
  ],
  "return" : ["JsVar","This string with `subStr` replaced"]
}
Search and replace ONE occurrance of `subStr` with `newSubStr` and return the result. This doesn't alter the original string. Regular expressions not supported.
 */
JsVar *jswrap_string_replace(JsVar *parent, JsVar *subStr, JsVar *newSubStr) {
  JsVar *str = jsvAsString(parent);
#ifndef SAVE_ON_FLASH
  // Use RegExp if one is passed in
  if (jsvIsInstanceOf(subStr, "RegExp")) {
    JsVar *replace;
    if (jsvIsFunction(newSubStr) || jsvIsString(newSubStr))
      replace = jsvLockAgain(newSubStr);
    else
      replace = jsvAsString(newSubStr);
    jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(0));
    bool global = jswrap_regexp_hasFlag(subStr,'g');
    JsVar *match;
    match = jswrap_regexp_exec(subStr, str);
    while (match && !jsvIsNull(match) && !jspIsInterrupted()) {
      // get info about match
      JsVar *matchStr = jsvGetArrayItem(match,0);
      JsVarInt idx = jsvGetIntegerAndUnLock(jsvObjectGetChild(match,"index",0));
      JsVarInt len = (JsVarInt)jsvGetStringLength(matchStr);
      // do the replacement
      JsVar *newStr = jsvNewFromStringVar(str, 0, (size_t)idx);
      JsvStringIterator dst;
      jsvStringIteratorNew(&dst, newStr, 0);
      jsvStringIteratorGotoEnd(&dst);
      if (jsvIsFunction(replace)) {
        unsigned int argCount = 0;
        JsVar *args[13];
        args[argCount++] = jsvLockAgain(matchStr);
        JsVar *v;
        while ((v = jsvGetArrayItem(match, (JsVarInt)argCount)))
          args[argCount++] = v;
        args[argCount++] = jsvObjectGetChild(match,"index",0);
        args[argCount++] = jsvObjectGetChild(match,"input",0);
        JsVar *result = jsvAsStringAndUnLock(jspeFunctionCall(replace, 0, 0, false, (JsVarInt)argCount, args));
        jsvUnLockMany(argCount, args);
        jsvStringIteratorAppendString(&dst, result, 0);
        jsvUnLock(result);
      } else {
        JsvStringIterator src;
        jsvStringIteratorNew(&src, replace, 0);
        while (jsvStringIteratorHasChar(&src)) {
          char ch = jsvStringIteratorGetChar(&src);
          if (ch=='$') {
            jsvStringIteratorNext(&src);
            ch = jsvStringIteratorGetChar(&src);
            JsVar *group = 0;
            if (ch>'0' && ch<='9')
              group = jsvGetArrayItem(match, ch-'0');
            if (group) {
              jsvStringIteratorAppendString(&dst, group, 0);
              jsvUnLock(group);
            } else {
              jsvStringIteratorAppend(&dst, '$');
              jsvStringIteratorAppend(&dst, ch);
            }
          } else {
            jsvStringIteratorAppend(&dst, ch);
          }
          jsvStringIteratorNext(&src);
        }
        jsvStringIteratorFree(&src);
      }
      JsVarInt lastIndex = 1+(JsVarInt)jsvStringIteratorGetIndex(&dst);
      jsvStringIteratorAppendString(&dst, str, (size_t)(idx+len));
      jsvStringIteratorFree(&dst);
      jsvUnLock2(str,matchStr);
      str = newStr;
      // search again if global
      jsvUnLock(match);
      match = 0;
      if (global) {
        jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(lastIndex));
        match = jswrap_regexp_exec(subStr, str);
      }
    }
    jsvUnLock(match);
    jsvUnLock(replace);
    // reset lastIndex if global
    if (global)
      jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(0));
    return str;
  }
#endif

  newSubStr = jsvAsString(newSubStr);
  subStr = jsvAsString(subStr);


  int idx = jswrap_string_indexOf(parent, subStr, 0, false);
  if (idx>=0) {
    JsVar *newStr = jsvNewFromStringVar(str, 0, (size_t)idx);
    jsvAppendStringVar(newStr, newSubStr, 0, JSVAPPENDSTRINGVAR_MAXLENGTH);
    jsvAppendStringVar(newStr, str, (size_t)idx+jsvGetStringLength(subStr), JSVAPPENDSTRINGVAR_MAXLENGTH);
    jsvUnLock(str);
    str = newStr;
  }

  jsvUnLock2(subStr, newSubStr);
  return str;
}