Exemplo n.º 1
0
/**
 * ESP8266 WiFi Event handler.
 * This function is called by the ESP8266
 * environment when significant events happen related to the WiFi environment.
 * The event handler is registered with a call to wifi_set_event_handler_cb()
 * that is provided by the ESP8266 SDK.
 */
static void wifiEventHandler(System_Event_t *evt) {
  switch(evt->event) {
  // We have connected to an access point.
  case EVENT_STAMODE_CONNECTED:
    os_printf("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid,
      evt->event_info.connected.channel);
    sendWifiEvent(evt->event, jsvNewNull());
    break;

  // We have disconnected or been disconnected from an access point.
  case EVENT_STAMODE_DISCONNECTED:
    os_printf("Wifi disconnected from ssid %s, reason %s (%d)\n",
      evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason);
    JsVar *details = jspNewObject(NULL, "EventDetails");
    jsvUnLock(jsvObjectSetChild(details, "reason", jsvNewFromInteger(evt->event_info.disconnected.reason)));
    char ssid[33];
    memcpy(ssid, evt->event_info.disconnected.ssid, evt->event_info.disconnected.ssid_len);
    ssid[ evt->event_info.disconnected.ssid_len] = '\0';
    sendWifiEvent(evt->event, details);
    break;

  // The authentication information at the access point has changed.
  case EVENT_STAMODE_AUTHMODE_CHANGE:
    os_printf("Wifi auth mode: %d -> %d\n",
      evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode);
    sendWifiEvent(evt->event, jsvNewNull());
    break;

  // We have been allocated an IP address.
  case EVENT_STAMODE_GOT_IP:
    os_printf("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n",
      IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask),
      IP2STR(&evt->event_info.got_ip.gw));
    sendWifiEvent(evt->event, jsvNewNull());
    break;
  case EVENT_STAMODE_DHCP_TIMEOUT:
    os_printf("Wifi DHCP timeout");
    sendWifiEvent(evt->event, jsvNewNull());
    break;
  case EVENT_SOFTAPMODE_STACONNECTED:
    os_printf("Wifi AP: station " MACSTR " joined, AID = %d\n",
      MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid);
    sendWifiEvent(evt->event, jsvNewNull());
    break;
  case EVENT_SOFTAPMODE_STADISCONNECTED:
    os_printf("Wifi AP: station " MACSTR " left, AID = %d\n",
      MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid);
    sendWifiEvent(evt->event, jsvNewNull());
    break;
  case EVENT_SOFTAPMODE_PROBEREQRECVED:
    os_printf("Wifi AP: probe request from station " MACSTR ", rssi = %d\n",
      MAC2STR(evt->event_info.ap_probereqrecved.mac), evt->event_info.ap_probereqrecved.rssi);
    sendWifiEvent(evt->event, jsvNewNull());
    break;
  default:
    os_printf("Wifi: unexpected event %d\n", evt->event);
    sendWifiEvent(evt->event, jsvNewNull());
    break;
  }
}
Exemplo n.º 2
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");
}
Exemplo n.º 3
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;
}