// '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))); } }
/*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; }
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; } } }
/*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; }
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); } }
/*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; }
/*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; }
/*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 }
/*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; }
/*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; }
/*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; }
/*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; }
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; }
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; }
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); }
/*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; }
/** * 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); } }
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; }
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); }
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
/** 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); } }
// 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; }
/*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); }
/*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; }
JsVar *jswrap_date_from_milliseconds(JsVarFloat time) { JsVar *d = jspNewObject(0,"Date"); if (!d) return 0; jsvUnLock(jsvObjectSetChild(d, "ms", jsvNewFromFloat(time))); return d; }
void addNativeFunction(const char *name, void (*callbackPtr)(void)) { jsvUnLock(jsvObjectSetChild(execInfo.root, name, jsvNewNativeFunction(callbackPtr, JSWAT_VOID))); }
/*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; }
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; }
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); } }
/** * 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"); }