/*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); }
/*JSON{ "type" : "staticmethod", "class" : "ESP8266WiFi", "name" : "getAccessPoints", "generate" : "jswrap_ESP8266WiFi_getAccessPoints", "params" : [ ["callback","JsVar","Function to call back when access points retrieved."] ] }*/ void jswrap_ESP8266WiFi_getAccessPoints( JsVar *callback //!< Function to call back when access points retrieved. ) { os_printf("> ESP8266WiFi_getAccessPoints\n"); if (callback == NULL || !jsvIsFunction(callback)) { jsExceptionHere(JSET_ERROR, "No callback."); return; } // If we had saved a previous scan callback function, release it. if (g_jsScanCallback != NULL) { jsvUnLock(g_jsScanCallback); } // Save the callback for the scan in the global variable called jsScanCallback. g_jsScanCallback = jsvLockAgainSafe(callback); // Ask the ESP8266 to perform a network scan after first entering // station mode. The network scan will eventually result in a callback // being executed (scanCB) which will contain the results. // Ensure we are in station mode wifi_set_opmode_current(STATION_MODE); // Request a scan of the network calling "scanCB" on completion wifi_station_scan(NULL, scanCB); os_printf("< ESP8266WiFi_getAccessPoints\n"); }
/*JSON{ "type" : "staticmethod", "ifndef" : "SAVE_ON_FLASH", "class" : "Storage", "name" : "write", "generate" : "jswrap_storage_write", "params" : [ ["name","JsVar","The filename - max 8 characters (case sensitive)"], ["data","JsVar","The data to write"], ["offset","int","The offset within the file to write"], ["size","int","The size of the file (if a file is to be created that is bigger than the data)"] ], "return" : ["bool","True on success, false on failure"] } Write/create a file in the flash storage area. This is nonvolatile and will not disappear when the device resets or power is lost. Simply write `require("Storage").write("MyFile", "Some data")` to write a new file, and `require("Storage").read("MyFile")` to read it. If you supply: * A String, it will be written as-is * An array, will be written as a byte array (but read back as a String) * An object, it will automatically be converted to a JSON string before being written. You may also create a file and then populate data later **as long as you don't try and overwrite data that already exists**. For instance: ``` var f = require("Storage"); f.write("a","Hello",0,14); f.write("a"," ",5); f.write("a","World!!!",6); print(f.read("a")); ``` This can be useful if you've got more data to write than you have RAM available. */ bool jswrap_storage_write(JsVar *name, JsVar *data, JsVarInt offset, JsVarInt _size) { JsVar *d; if (jsvIsObject(data)) { d = jswrap_json_stringify(data,0,0); offset = 0; _size = 0; } else d = jsvLockAgainSafe(data); bool success = jsfWriteFile(jsfNameFromVar(name), d, JSFF_NONE, offset, _size); jsvUnLock(d); return success; }
/*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); }
/*JSON{ "type" : "method", "class" : "Array", "name" : "reduce", "ifndef" : "SAVE_ON_FLASH", "generate" : "jswrap_array_reduce", "params" : [ ["callback","JsVar","Function used to reduce the array"], ["initialValue","JsVar","if specified, the initial value to pass to the function"] ], "return" : ["JsVar","The value returned by the last function called"] } Execute `previousValue=initialValue` and then `previousValue = callback(previousValue, currentValue, index, array)` for each element in the array, and finally return previousValue. */ JsVar *jswrap_array_reduce(JsVar *parent, JsVar *funcVar, JsVar *initialValue) { const char *name = "reduce"; if (!jsvIsIterable(parent)) { jsExceptionHere(JSET_ERROR, "Array.%s can only be called on something iterable", name); return 0; } if (!jsvIsFunction(funcVar)) { jsExceptionHere(JSET_ERROR, "Array.%s's first argument should be a function", name); return 0; } JsVar *previousValue = jsvLockAgainSafe(initialValue); JsvIterator it; jsvIteratorNew(&it, parent); if (!previousValue) { bool isDone = false; while (!isDone && jsvIteratorHasElement(&it)) { JsVar *index = jsvIteratorGetKey(&it); if (jsvIsInt(index)) { previousValue = jsvIteratorGetValue(&it); isDone = true; } jsvUnLock(index); jsvIteratorNext(&it); } if (!previousValue) { jsExceptionHere(JSET_ERROR, "Array.%s without initial value required non-empty array", name); } } while (jsvIteratorHasElement(&it)) { JsVar *index = jsvIteratorGetKey(&it); if (jsvIsInt(index)) { JsVarInt idxValue = jsvGetInteger(index); JsVar *args[4]; args[0] = previousValue; args[1] = jsvIteratorGetValue(&it); args[2] = jsvNewFromInteger(idxValue); // child is a variable name, create a new variable for the index args[3] = parent; previousValue = jspeFunctionCall(funcVar, 0, 0, false, 4, args); jsvUnLockMany(3,args); } jsvUnLock(index); jsvIteratorNext(&it); } jsvIteratorFree(&it); return previousValue; }
/*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"); }