From 26b77feb4cf5416d4fbce26abebc5d2528156afb Mon Sep 17 00:00:00 2001 From: cursedsound Date: Tue, 13 Oct 2026 15:07:18 +0200 Subject: [PATCH] feat(js): add BLE GATT client to the ble module Adds a minimal GATT client to the bjs `ble` module so scripts can connect to a BLE peripheral and read/write its characteristics (NimBLE 2.x): ble.connect(nameOrAddress, timeoutSec?) -> bool ble.isConnected() -> bool ble.read(serviceUUID, charUUID) -> Uint8Array | null ble.write(serviceUUID, charUUID, Uint8Array|string, withResponse?) -> bool ble.disconnect() connect() scans for up to timeoutSec seconds and connects to the first device whose name starts with the given string (case-insensitive) or whose MAC matches. On NimBLE 1.x builds the new functions throw "not supported". Includes sd_files/interpreter/crafty.js, an example remote for the Storz & Bickel CRAFTY/CRAFTY+ (target/boost temperature, heater on/off, battery), and the regenerated mqjs headers. --- lib/mquickjs_headers/mqjs_stdlib.build.sha256 | 2 +- sd_files/interpreter/crafty.js | 258 ++++++++++++++ src/modules/bjs_interpreter/ble_js.cpp | 140 +++++++- src/modules/bjs_interpreter/ble_js.h | 5 + src/modules/bjs_interpreter/mqjs_stdlib.c | 5 + src/modules/bjs_interpreter/mqjs_stdlib.h | 320 ++++++++++-------- 6 files changed, 579 insertions(+), 151 deletions(-) create mode 100644 sd_files/interpreter/crafty.js diff --git a/lib/mquickjs_headers/mqjs_stdlib.build.sha256 b/lib/mquickjs_headers/mqjs_stdlib.build.sha256 index 7901afd69c..39608085d5 100644 --- a/lib/mquickjs_headers/mqjs_stdlib.build.sha256 +++ b/lib/mquickjs_headers/mqjs_stdlib.build.sha256 @@ -1 +1 @@ -01af20ef15490f6253823657a521e644b20cc49349232027f7da13b6a7d7b573 \ No newline at end of file +36f36068a7125c8078a2b10bc200a018c65b24165bfe3ebf85e93b291ab24a55 \ No newline at end of file diff --git a/sd_files/interpreter/crafty.js b/sd_files/interpreter/crafty.js new file mode 100644 index 0000000000..489428a229 --- /dev/null +++ b/sd_files/interpreter/crafty.js @@ -0,0 +1,258 @@ +// CURSEDSOUND // CRAFTY remote for Bruce (M5StickC Plus2) +// Controls a Storz & Bickel CRAFTY / CRAFTY+ over BLE. +// Needs the ble.connect/read/write GATT functions (Bruce fork "ble-gatt-client"). +// +// Buttons: M5 (front) = select TEMP / BOOST / HEAT +// B (right) = + (on HEAT: on) +// PWR (left) = - (on HEAT: off) +// B + PWR together = exit + +var display = require('display'); +var keyboard = require('keyboard'); +var ble = require('ble'); + +var BASE = '-4c45-4b43-4942-265a524f5453'; +var SVC1 = '00000001' + BASE; +var SVC2 = '00000002' + BASE; +var SVC3 = '00000003' + BASE; +var CUR_TEMP = '00000011' + BASE; +var TARGET = '00000021' + BASE; +var BOOST = '00000031' + BASE; +var BATTERY = '00000041' + BASE; +var HEAT_ON = '00000081' + BASE; +var HEAT_OFF = '00000091' + BASE; +var SERIAL = '00000052' + BASE; +var PRJ = '00000093' + BASE; +var PRJ2 = '000001c3' + BASE; + +var BLACK = display.color(4, 4, 8); +var PANEL = display.color(18, 18, 24); +var ACID = display.color(200, 255, 0); +var HOT = display.color(255, 46, 136); +var WHITE = display.color(255, 255, 255); +var DIM = display.color(110, 110, 120); + +var W = display.width(); +var H = display.height(); +var spr = display.createSprite(); + +function rd16(svc, chr) { + var v = ble.read(svc, chr); + if (!v || v.length < 2) return -1; + return v[0] | (v[1] << 8); +} + +function wr16(svc, chr, val) { + return ble.write(svc, chr, new Uint8Array([val & 255, (val >> 8) & 255])); +} + +function tenths(v) { + return Math.round(v / 10); +} + +// ---------------------------------------------------------------- drawing +function glitchTitle(x, y, size) { + spr.setTextSize(size); + spr.setTextAlign('left', 'top'); + var g = Math.floor(now() / 120) % 19 === 0; + var dx = g ? 3 : 1; + spr.setTextColor(HOT); + spr.drawText('CURSEDSOUND', x - dx, y + (g ? 1 : 0)); + spr.setTextColor(ACID); + spr.drawText('CURSEDSOUND', x + dx, y); + spr.setTextColor(WHITE); + spr.drawText('CURSEDSOUND', x, y); +} + +function message(line1, line2, color) { + spr.fill(BLACK); + glitchTitle(8, 8, 2); + spr.setTextAlign('center', 'middle'); + spr.setTextSize(2); + spr.setTextColor(color || WHITE); + spr.drawText(line1, W / 2, H / 2 + 6); + if (line2) { + spr.setTextSize(1); + spr.setTextColor(DIM); + spr.drawText(line2, W / 2, H / 2 + 30); + } + spr.pushSprite(); +} + +function box(x, y, w, h, label, value, selected, accent) { + if (selected) { + spr.drawFillRect(x, y, w, h, accent); + } else { + spr.drawFillRect(x, y, w, h, PANEL); + spr.drawRect(x, y, w, h, accent); + } + spr.setTextAlign('center', 'top'); + spr.setTextSize(1); + spr.setTextColor(selected ? BLACK : DIM); + spr.drawText(label, x + w / 2, y + 4); + spr.setTextSize(2); + spr.setTextColor(selected ? BLACK : WHITE); + spr.drawText(value, x + w / 2, y + 16); +} + +function draw(s) { + spr.fill(BLACK); + + // header + glitchTitle(6, 4, 1); + spr.setTextAlign('right', 'top'); + spr.setTextSize(1); + spr.setTextColor(s.battery < 20 ? HOT : ACID); + spr.drawText('BAT ' + s.battery + '%', W - 6, 4); + + // big current temperature + var hot = s.heater; + var big = s.cur > 0 ? String(s.cur) : '---'; + spr.setTextAlign('center', 'middle'); + spr.setTextSize(5); + spr.setTextColor(s.ready ? ACID : WHITE); + spr.drawText(big, W / 2 - 8, 42); + spr.drawCircle(W / 2 - 8 + big.length * 15 + 7, 27, 4, s.ready ? ACID : WHITE); + + // status + mode + spr.setTextSize(1); + spr.setTextColor(s.ready ? ACID : (hot ? HOT : DIM)); + var status = s.ready ? 'READY' : (hot ? 'HEATING' : 'IDLE'); + if (s.mode !== 'NORMAL' && hot) status = status + ' / ' + s.mode; + spr.drawText(status, W / 2, 68); + + // progress bar current -> target + var bx = 10, by = 78, bw = W - 20; + spr.drawFillRect(bx, by, bw, 4, PANEL); + var frac = Math.max(0, Math.min(1, (s.cur - 40) / (s.target + s.boost - 40))); + if (s.cur > 0) spr.drawFillRect(bx, by, Math.round(bw * frac), 4, hot ? HOT : ACID); + + // three controls + var bwid = Math.floor((W - 24) / 3); + var y = 88; + box(6, y, bwid, 40, 'TEMP', s.target + 'C', s.sel === 0, ACID); + box(12 + bwid, y, bwid, 40, 'BOOST', '+' + s.boost, s.sel === 1, HOT); + box(18 + bwid * 2, y, bwid, 40, 'HEAT', hot ? 'ON' : 'OFF', s.sel === 2, hot ? HOT : ACID); + + spr.pushSprite(); +} + +// ---------------------------------------------------------------- device +function connect() { + while (true) { + message('SEARCHING...', 'turn CRAFTY on, close other apps', ACID); + if (ble.connect('STORZ&BICKEL', 6)) return true; + message('NOT FOUND', 'M5: retry B+PWR: exit', HOT); + while (true) { + if (keyboard.getEscPress()) return false; + if (keyboard.getSelPress()) break; + delay(40); + } + } +} + +function readState(s, full) { + var v; + v = rd16(SVC1, CUR_TEMP); + if (v >= 0) s.cur = tenths(v); + v = rd16(SVC1, BATTERY); + if (v >= 0) s.battery = v; + v = rd16(SVC3, PRJ); + if (v >= 0) { + s.heater = (v & 0x10) !== 0; + s.mode = (v & 0x40) ? 'SUPERBOOST' : ((v & 0x20) ? 'BOOST' : 'NORMAL'); + } + v = rd16(SVC3, PRJ2); + if (v >= 0) s.ready = (v & 0x04) !== 0 && s.heater; + if (full) { + v = rd16(SVC1, TARGET); + if (v >= 0) { + var t = tenths(v); + if (t > 210) t = Math.round((t - 32) / 1.8); + s.target = t; + } + v = rd16(SVC1, BOOST); + if (v >= 0) s.boost = tenths(v); + } +} + +function clampBoost(s) { + if (s.boost < 0) s.boost = 0; + if (s.boost > 99) s.boost = 99; + if (s.target + s.boost > 210) s.boost = 210 - s.target; +} + +function main() { + if (!connect()) return; + + var s = { + cur: 0, target: 180, boost: 10, battery: 0, + heater: false, ready: false, mode: 'NORMAL', sel: 0 + }; + readState(s, true); + + var lastPoll = 0; + var lastFull = now(); + var pendingAt = 0; // when a temp/boost change should be sent + var dirty = true; + + while (true) { + var t = now(); + + // ---- input + if (keyboard.getEscPress()) break; + if (keyboard.getSelPress()) { s.sel = (s.sel + 1) % 3; dirty = true; } + var up = keyboard.getNextPress(); + var down = keyboard.getPrevPress(); + if (up || down) { + var d = up ? 1 : -1; + if (s.sel === 0) { + s.target = Math.max(40, Math.min(210, s.target + d)); + clampBoost(s); + pendingAt = t + 700; + } else if (s.sel === 1) { + s.boost = s.boost + d; + clampBoost(s); + pendingAt = t + 700; + } else { + ble.write(SVC1, up ? HEAT_ON : HEAT_OFF, new Uint8Array([0, 0])); + s.heater = up; + } + dirty = true; + } + + // ---- send pending temperature / boost once buttons are released + if (pendingAt && t >= pendingAt) { + wr16(SVC1, TARGET, s.target * 10); + wr16(SVC1, BOOST, s.boost * 10); + pendingAt = 0; + lastFull = t; + } + + // ---- poll device + if (t - lastPoll > 1000 && !pendingAt) { + if (!ble.isConnected()) { + message('LINK LOST', 'reconnecting...', HOT); + if (!connect()) break; + readState(s, true); + } else { + var full = t - lastFull > 5000; + readState(s, full); + if (full) lastFull = t; + } + lastPoll = now(); + dirty = true; + } + + if (dirty) { + draw(s); + dirty = false; + } + delay(30); + } +} + +main(); +ble.disconnect(); +spr.deleteSprite(); +display.fill(0); diff --git a/src/modules/bjs_interpreter/ble_js.cpp b/src/modules/bjs_interpreter/ble_js.cpp index ee9d38a8f1..f81c1d384e 100644 --- a/src/modules/bjs_interpreter/ble_js.cpp +++ b/src/modules/bjs_interpreter/ble_js.cpp @@ -6,9 +6,7 @@ JSValue native_bleScan(JSContext *ctx, JSValue *this_val, int argc, JSValue *arg // usage: ble.scan(timeout_seconds) // returns: array of objects [{name, address, rssi}, ...] int timeout = 5; // default 5 seconds - if (argc > 0 && JS_IsNumber(ctx, argv[0])) { - JS_ToInt32(ctx, &timeout, argv[0]); - } + if (argc > 0 && JS_IsNumber(ctx, argv[0])) { JS_ToInt32(ctx, &timeout, argv[0]); } if (timeout < 1) timeout = 1; if (timeout > 30) timeout = 30; @@ -51,9 +49,7 @@ JSValue native_bleAdvertise(JSContext *ctx, JSValue *this_val, int argc, JSValue // usage: ble.advertise(name_string) const char *name = "Bruce-App"; JSCStringBuf name_buf; - if (argc > 0 && JS_IsString(ctx, argv[0])) { - name = JS_ToCString(ctx, argv[0], &name_buf); - } + if (argc > 0 && JS_IsString(ctx, argv[0])) { name = JS_ToCString(ctx, argv[0], &name_buf); } BLEDevice::init(name); NimBLEServer *pServer = BLEDevice::createServer(); @@ -68,4 +64,136 @@ JSValue native_bleStopAdvertise(JSContext *ctx, JSValue *this_val, int argc, JSV return JS_UNDEFINED; } +// --------------------------------------------------------------------------- +// GATT client: connect to a peripheral and read/write its characteristics. +// +// ble.connect(nameOrAddress, timeoutSec?) -> bool +// Scans and connects to the first device whose name starts with +// nameOrAddress (case-insensitive) or whose MAC equals it. +// ble.isConnected() -> bool +// ble.read(serviceUUID, charUUID) -> Uint8Array | null +// ble.write(serviceUUID, charUUID, Uint8Array|string, withResponse?) -> bool +// ble.disconnect() +// --------------------------------------------------------------------------- +#if __has_include() +static NimBLEClient *jsBleClient = nullptr; + +static bool jsBleIsConnected() { return jsBleClient != nullptr && jsBleClient->isConnected(); } + +JSValue native_bleConnect(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + if (argc < 1 || !JS_IsString(ctx, argv[0])) { + return JS_ThrowTypeError(ctx, "ble.connect: arg0 must be a device name prefix or MAC address"); + } + JSCStringBuf target_buf; + const char *target_c = JS_ToCString(ctx, argv[0], &target_buf); + String target = target_c ? target_c : ""; + int timeout = 5; + if (argc > 1 && JS_IsNumber(ctx, argv[1])) JS_ToInt32(ctx, &timeout, argv[1]); + if (timeout < 1) timeout = 1; + if (timeout > 30) timeout = 30; + + if (jsBleIsConnected()) jsBleClient->disconnect(); + + BLEDevice::init(""); + NimBLEScan *pScan = NimBLEDevice::getScan(); + pScan->setActiveScan(true); + pScan->setInterval(100); + pScan->setWindow(99); + NimBLEScanResults results = pScan->getResults(timeout * 1000, false); + + const NimBLEAdvertisedDevice *found = nullptr; + for (int i = 0; i < results.getCount(); i++) { + const NimBLEAdvertisedDevice *dev = results.getDevice(i); + String name = dev->getName().c_str(); + String addr = dev->getAddress().toString().c_str(); + if ((name.length() >= target.length() && + strncasecmp(name.c_str(), target.c_str(), target.length()) == 0) || + addr.equalsIgnoreCase(target)) { + found = dev; + break; + } + } + + bool ok = false; + if (found != nullptr) { + if (jsBleClient == nullptr) jsBleClient = NimBLEDevice::createClient(); + jsBleClient->setConnectTimeout(timeout * 1000); + ok = jsBleClient->connect(found); + } + pScan->clearResults(); + return JS_NewBool(ok); +} + +JSValue native_bleIsConnected(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + return JS_NewBool(jsBleIsConnected()); +} + +static NimBLERemoteCharacteristic *jsBleGetChr(JSContext *ctx, int argc, JSValue *argv) { + if (!jsBleIsConnected() || argc < 2 || !JS_IsString(ctx, argv[0]) || !JS_IsString(ctx, argv[1])) { + return nullptr; + } + JSCStringBuf svc_buf, chr_buf; + const char *svc_c = JS_ToCString(ctx, argv[0], &svc_buf); + std::string svc_uuid = svc_c ? svc_c : ""; + const char *chr_c = JS_ToCString(ctx, argv[1], &chr_buf); + std::string chr_uuid = chr_c ? chr_c : ""; + + NimBLERemoteService *svc = jsBleClient->getService(NimBLEUUID(svc_uuid)); + if (svc == nullptr) return nullptr; + return svc->getCharacteristic(NimBLEUUID(chr_uuid)); +} + +JSValue native_bleRead(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + NimBLERemoteCharacteristic *chr = jsBleGetChr(ctx, argc, argv); + if (chr == nullptr || !chr->canRead()) return JS_NULL; + NimBLEAttValue val = chr->readValue(); + return JS_NewUint8ArrayCopy(ctx, val.data(), val.size()); +} + +JSValue native_bleWrite(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + NimBLERemoteCharacteristic *chr = jsBleGetChr(ctx, argc, argv); + if (chr == nullptr || argc < 3) return JS_NewBool(false); + + const uint8_t *buf = nullptr; + size_t len = 0; + JSCStringBuf str_buf; + if (JS_IsString(ctx, argv[2])) { + buf = (const uint8_t *)JS_ToCStringLen(ctx, &len, argv[2], &str_buf); + } else if (JS_IsTypedArray(ctx, argv[2])) { + buf = (const uint8_t *)JS_GetTypedArrayBuffer(ctx, &len, argv[2]); + } else { + return JS_ThrowTypeError(ctx, "ble.write: arg2 must be Uint8Array or string"); + } + if (buf == nullptr) return JS_NewBool(false); + + bool response = chr->canWrite(); + if (argc > 3) response = JS_ToBool(ctx, argv[3]); + return JS_NewBool(chr->writeValue(buf, len, response)); +} + +JSValue native_bleDisconnect(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + if (jsBleIsConnected()) jsBleClient->disconnect(); + return JS_UNDEFINED; +} +#else +static JSValue jsBleGattUnsupported(JSContext *ctx) { + return JS_ThrowInternalError(ctx, "ble GATT client requires NimBLE-Arduino 2.x"); +} +JSValue native_bleConnect(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + return jsBleGattUnsupported(ctx); +} +JSValue native_bleIsConnected(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + return JS_NewBool(false); +} +JSValue native_bleRead(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + return jsBleGattUnsupported(ctx); +} +JSValue native_bleWrite(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + return jsBleGattUnsupported(ctx); +} +JSValue native_bleDisconnect(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) { + return JS_UNDEFINED; +} +#endif + #endif diff --git a/src/modules/bjs_interpreter/ble_js.h b/src/modules/bjs_interpreter/ble_js.h index 97fe89eca6..f1d01e7ebb 100644 --- a/src/modules/bjs_interpreter/ble_js.h +++ b/src/modules/bjs_interpreter/ble_js.h @@ -8,6 +8,11 @@ extern "C" { JSValue native_bleScan(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv); JSValue native_bleAdvertise(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv); JSValue native_bleStopAdvertise(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv); +JSValue native_bleConnect(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv); +JSValue native_bleIsConnected(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv); +JSValue native_bleRead(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv); +JSValue native_bleWrite(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv); +JSValue native_bleDisconnect(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv); } #endif diff --git a/src/modules/bjs_interpreter/mqjs_stdlib.c b/src/modules/bjs_interpreter/mqjs_stdlib.c index 06526802ec..a6c26f0df2 100644 --- a/src/modules/bjs_interpreter/mqjs_stdlib.c +++ b/src/modules/bjs_interpreter/mqjs_stdlib.c @@ -587,6 +587,11 @@ static const JSPropDef js_ble[] = { JS_CFUNC_DEF("scan", 1, native_bleScan), JS_CFUNC_DEF("advertise", 1, native_bleAdvertise), JS_CFUNC_DEF("stopAdvertise", 0, native_bleStopAdvertise), + JS_CFUNC_DEF("connect", 2, native_bleConnect), + JS_CFUNC_DEF("isConnected", 0, native_bleIsConnected), + JS_CFUNC_DEF("read", 2, native_bleRead), + JS_CFUNC_DEF("write", 4, native_bleWrite), + JS_CFUNC_DEF("disconnect", 0, native_bleDisconnect), JS_PROP_END, }; diff --git a/src/modules/bjs_interpreter/mqjs_stdlib.h b/src/modules/bjs_interpreter/mqjs_stdlib.h index f1ae9860eb..62582991ce 100644 --- a/src/modules/bjs_interpreter/mqjs_stdlib.h +++ b/src/modules/bjs_interpreter/mqjs_stdlib.h @@ -1514,23 +1514,23 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { 0x65766441, 0x73697472, 0x00000065, - (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (5 << (JS_MTAG_BITS + 3)), /* "nrf24" (offset=1483) */ + (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (11 << (JS_MTAG_BITS + 3)), /* "isConnected" (offset=1483) */ + 0x6f437369, + 0x63656e6e, + 0x00646574, + (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (5 << (JS_MTAG_BITS + 3)), /* "nrf24" (offset=1487) */ 0x3266726e, 0x00000034, - (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (4 << (JS_MTAG_BITS + 3)), /* "send" (offset=1486) */ + (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (4 << (JS_MTAG_BITS + 3)), /* "send" (offset=1490) */ 0x646e6573, 0x00000000, - (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (7 << (JS_MTAG_BITS + 3)), /* "receive" (offset=1489) */ + (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (7 << (JS_MTAG_BITS + 3)), /* "receive" (offset=1493) */ 0x65636572, 0x00657669, - (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (10 << (JS_MTAG_BITS + 3)), /* "setChannel" (offset=1492) */ + (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (10 << (JS_MTAG_BITS + 3)), /* "setChannel" (offset=1496) */ 0x43746573, 0x6e6e6168, 0x00006c65, - (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (11 << (JS_MTAG_BITS + 3)), /* "isConnected" (offset=1496) */ - 0x6f437369, - 0x63656e6e, - 0x00646574, (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (3 << (JS_MTAG_BITS + 3)), /* "led" (offset=1500) */ 0x0064656c, (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (1 << (JS_MTAG_BITS + 1)) | (0 << (JS_MTAG_BITS + 2)) | (8 << (JS_MTAG_BITS + 3)), /* "setColor" (offset=1502) */ @@ -1908,7 +1908,7 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(109), /* interface */ JS_ROM_VALUE(1234), /* ir */ JS_ROM_VALUE(436), /* isArray */ - JS_ROM_VALUE(1496), /* isConnected */ + JS_ROM_VALUE(1483), /* isConnected */ JS_ROM_VALUE(771), /* isFinite */ JS_ROM_VALUE(1366), /* isForeground */ JS_ROM_VALUE(768), /* isNaN */ @@ -1944,7 +1944,7 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(31), /* new */ JS_ROM_VALUE(1292), /* notification */ JS_ROM_VALUE(592), /* now */ - JS_ROM_VALUE(1483), /* nrf24 */ + JS_ROM_VALUE(1487), /* nrf24 */ JS_ROM_VALUE(0), /* null */ JS_ROM_VALUE(1252), /* numKeyboard */ JS_ROM_VALUE(143), /* number */ @@ -1982,7 +1982,7 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(1314), /* readUID */ JS_ROM_VALUE(1385), /* readdir */ JS_ROM_VALUE(1377), /* readln */ - JS_ROM_VALUE(1489), /* receive */ + JS_ROM_VALUE(1493), /* receive */ JS_ROM_VALUE(1302), /* recordWav */ JS_ROM_VALUE(476), /* reduce */ JS_ROM_VALUE(479), /* reduceRight */ @@ -2007,14 +2007,14 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(1571), /* scrollToLine */ JS_ROM_VALUE(1563), /* scrollUp */ JS_ROM_VALUE(409), /* search */ - JS_ROM_VALUE(1486), /* send */ + JS_ROM_VALUE(1490), /* send */ JS_ROM_VALUE(1374), /* serial */ JS_ROM_VALUE(177), /* set */ JS_ROM_VALUE(616), /* set lastIndex */ JS_ROM_VALUE(364), /* set length */ JS_ROM_VALUE(268), /* set prototype */ JS_ROM_VALUE(1086), /* setBrightness */ - JS_ROM_VALUE(1492), /* setChannel */ + JS_ROM_VALUE(1496), /* setChannel */ JS_ROM_VALUE(1502), /* setColor */ JS_ROM_VALUE(950), /* setCursor */ JS_ROM_VALUE(1412), /* setFrequency */ @@ -4289,11 +4289,13 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_NULL, /* properties (offset=4011) */ - JS_VALUE_ARRAY_HEADER(13), - 3 << 1, /* n_props */ - 1 << 1, /* hash_mask */ - 4 << 1, - 10 << 1, + JS_VALUE_ARRAY_HEADER(30), + 8 << 1, /* n_props */ + 3 << 1, /* hash_mask */ + 6 << 1, + 24 << 1, + 21 << 1, + 27 << 1, JS_ROM_VALUE(1221) /* scan */, JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 307), (0 << 1) | (JS_PROP_NORMAL << 30), @@ -4302,70 +4304,85 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1478) /* stopAdvertise */, JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 309), - (7 << 1) | (JS_PROP_NORMAL << 30), - /* class (offset=4025) */ + (9 << 1) | (JS_PROP_NORMAL << 30), + JS_ROM_VALUE(1451) /* connect */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 310), + (0 << 1) | (JS_PROP_NORMAL << 30), + JS_ROM_VALUE(1483) /* isConnected */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 311), + (15 << 1) | (JS_PROP_NORMAL << 30), + JS_ROM_VALUE(1227) /* read */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 312), + (18 << 1) | (JS_PROP_NORMAL << 30), + JS_ROM_VALUE(1224) /* write */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 313), + (0 << 1) | (JS_PROP_NORMAL << 30), + JS_ROM_VALUE(1454) /* disconnect */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 314), + (12 << 1) | (JS_PROP_NORMAL << 30), + /* class (offset=4042) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), JS_ROM_VALUE(4011), -1, JS_NULL, JS_NULL, - /* properties (offset=4030) */ + /* properties (offset=4047) */ JS_VALUE_ARRAY_HEADER(21), 5 << 1, /* n_props */ 3 << 1, /* hash_mask */ 12 << 1, + 15 << 1, 18 << 1, - 0 << 1, 9 << 1, JS_ROM_VALUE(1218) /* begin */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 310), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 315), (0 << 1) | (JS_PROP_NORMAL << 30), - JS_ROM_VALUE(1486) /* send */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 311), + JS_ROM_VALUE(1490) /* send */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 316), (6 << 1) | (JS_PROP_NORMAL << 30), - JS_ROM_VALUE(1489) /* receive */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 312), + JS_ROM_VALUE(1493) /* receive */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 317), (0 << 1) | (JS_PROP_NORMAL << 30), - JS_ROM_VALUE(1492) /* setChannel */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 313), + JS_ROM_VALUE(1496) /* setChannel */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 318), (0 << 1) | (JS_PROP_NORMAL << 30), - JS_ROM_VALUE(1496) /* isConnected */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 314), - (15 << 1) | (JS_PROP_NORMAL << 30), - /* class (offset=4052) */ + JS_ROM_VALUE(1483) /* isConnected */, + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 319), + (0 << 1) | (JS_PROP_NORMAL << 30), + /* class (offset=4069) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4030), + JS_ROM_VALUE(4047), -1, JS_NULL, JS_NULL, - /* properties (offset=4057) */ + /* properties (offset=4074) */ JS_VALUE_ARRAY_HEADER(16), 4 << 1, /* n_props */ 1 << 1, /* hash_mask */ 13 << 1, 10 << 1, JS_ROM_VALUE(1502) /* setColor */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 315), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 320), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1086) /* setBrightness */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 316), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 321), (4 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1506) /* off */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 317), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 322), (7 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1297) /* blink */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 318), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 323), (0 << 1) | (JS_PROP_NORMAL << 30), - /* class (offset=4074) */ + /* class (offset=4091) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4057), + JS_ROM_VALUE(4074), -1, JS_NULL, JS_NULL, - /* properties (offset=4079) */ + /* properties (offset=4096) */ JS_VALUE_ARRAY_HEADER(24), 6 << 1, /* n_props */ 3 << 1, /* hash_mask */ @@ -4374,31 +4391,31 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { 21 << 1, 18 << 1, JS_ROM_VALUE(1511) /* show */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 319), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 324), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1514) /* showMainBorder */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 320), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 325), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1519) /* showMainBorderWithTitle */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 321), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 326), (6 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1526) /* printTitle */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 322), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 327), (9 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1530) /* printSubtitle */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 323), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 328), (15 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1535) /* displayMessage */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 324), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 329), (12 << 1) | (JS_PROP_NORMAL << 30), - /* class (offset=4104) */ + /* class (offset=4121) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4079), + JS_ROM_VALUE(4096), -1, JS_NULL, JS_NULL, - /* properties (offset=4109) */ + /* properties (offset=4126) */ JS_VALUE_ARRAY_HEADER(6), 1 << 1, /* n_props */ 0 << 1, /* hash_mask */ @@ -4406,7 +4423,7 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(179) /* prototype */, JS_CLASS_TIMERS_STATE << 1, (0 << 1) | (JS_PROP_SPECIAL << 30), - /* properties (offset=4116) */ + /* properties (offset=4133) */ JS_VALUE_ARRAY_HEADER(6), 1 << 1, /* n_props */ 0 << 1, /* hash_mask */ @@ -4414,14 +4431,14 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(183) /* constructor */, (uint32_t)(-JS_CLASS_TIMERS_STATE - 1) << 1, (0 << 1) | (JS_PROP_SPECIAL << 30), - /* class (offset=4123) */ + /* class (offset=4140) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4109), - 325, - JS_ROM_VALUE(4116), + JS_ROM_VALUE(4126), + 330, + JS_ROM_VALUE(4133), JS_NULL, - /* properties (offset=4128) */ + /* properties (offset=4145) */ JS_VALUE_ARRAY_HEADER(6), 1 << 1, /* n_props */ 0 << 1, /* hash_mask */ @@ -4429,7 +4446,7 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(179) /* prototype */, JS_CLASS_SPRITE << 1, (0 << 1) | (JS_PROP_SPECIAL << 30), - /* properties (offset=4135) */ + /* properties (offset=4152) */ JS_VALUE_ARRAY_HEADER(111), 31 << 1, /* n_props */ 15 << 1, /* hash_mask */ @@ -4534,22 +4551,22 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 203), (87 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1547) /* pushSprite */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 327), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 332), (42 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1551) /* deleteSprite */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 328), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 333), (21 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(183) /* constructor */, (uint32_t)(-JS_CLASS_SPRITE - 1) << 1, (48 << 1) | (JS_PROP_SPECIAL << 30), - /* class (offset=4247) */ + /* class (offset=4264) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4128), - 326, - JS_ROM_VALUE(4135), + JS_ROM_VALUE(4145), + 331, + JS_ROM_VALUE(4152), JS_NULL, - /* properties (offset=4252) */ + /* properties (offset=4269) */ JS_VALUE_ARRAY_HEADER(6), 1 << 1, /* n_props */ 0 << 1, /* hash_mask */ @@ -4557,7 +4574,7 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(179) /* prototype */, JS_CLASS_TEXTVIEWER << 1, (0 << 1) | (JS_PROP_SPECIAL << 30), - /* properties (offset=4259) */ + /* properties (offset=4276) */ JS_VALUE_ARRAY_HEADER(43), 11 << 1, /* n_props */ 7 << 1, /* hash_mask */ @@ -4570,46 +4587,46 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { 40 << 1, 0 << 1, JS_ROM_VALUE(1560) /* draw */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 330), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 335), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1563) /* scrollUp */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 331), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 336), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1567) /* scrollDown */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 332), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 337), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1571) /* scrollToLine */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 333), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 338), (13 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1576) /* getLine */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 334), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 339), (10 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1579) /* getMaxLines */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 335), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 340), (19 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1583) /* getVisibleText */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 336), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 341), (16 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1320) /* clear */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 337), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 342), (22 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1588) /* setText */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 338), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 343), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1591) /* close */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 339), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 344), (28 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(183) /* constructor */, (uint32_t)(-JS_CLASS_TEXTVIEWER - 1) << 1, (37 << 1) | (JS_PROP_SPECIAL << 30), - /* class (offset=4303) */ + /* class (offset=4320) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4252), - 329, - JS_ROM_VALUE(4259), + JS_ROM_VALUE(4269), + 334, + JS_ROM_VALUE(4276), JS_NULL, - /* properties (offset=4308) */ + /* properties (offset=4325) */ JS_VALUE_ARRAY_HEADER(6), 1 << 1, /* n_props */ 0 << 1, /* hash_mask */ @@ -4617,7 +4634,7 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(179) /* prototype */, JS_CLASS_GIF << 1, (0 << 1) | (JS_PROP_SPECIAL << 30), - /* properties (offset=4315) */ + /* properties (offset=4332) */ JS_VALUE_ARRAY_HEADER(21), 5 << 1, /* n_props */ 3 << 1, /* hash_mask */ @@ -4626,72 +4643,72 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { 18 << 1, 15 << 1, JS_ROM_VALUE(1596) /* gifPlayFrame */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 341), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 346), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1601) /* gifDimensions */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 342), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 347), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1606) /* gifReset */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 343), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 348), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(1610) /* gifClose */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 344), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 349), (12 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(183) /* constructor */, (uint32_t)(-JS_CLASS_GIF - 1) << 1, (0 << 1) | (JS_PROP_SPECIAL << 30), - /* class (offset=4337) */ + /* class (offset=4354) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4308), - 340, - JS_ROM_VALUE(4315), + JS_ROM_VALUE(4325), + 345, + JS_ROM_VALUE(4332), JS_NULL, - /* properties (offset=4342) */ + /* properties (offset=4359) */ JS_VALUE_ARRAY_HEADER(9), 2 << 1, /* n_props */ 0 << 1, /* hash_mask */ 6 << 1, JS_ROM_VALUE(1617) /* from */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 346), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 351), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(179) /* prototype */, JS_CLASS_BUFFER << 1, (3 << 1) | (JS_PROP_SPECIAL << 30), - /* properties (offset=4352) */ + /* properties (offset=4369) */ JS_VALUE_ARRAY_HEADER(9), 2 << 1, /* n_props */ 0 << 1, /* hash_mask */ 6 << 1, JS_ROM_VALUE(136) /* toString */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 347), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 352), (0 << 1) | (JS_PROP_NORMAL << 30), JS_ROM_VALUE(183) /* constructor */, (uint32_t)(-JS_CLASS_BUFFER - 1) << 1, (3 << 1) | (JS_PROP_SPECIAL << 30), - /* class (offset=4362) */ + /* class (offset=4379) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4342), - 345, - JS_ROM_VALUE(4352), + JS_ROM_VALUE(4359), + 350, + JS_ROM_VALUE(4369), JS_NULL, - /* properties (offset=4367) */ + /* properties (offset=4384) */ JS_VALUE_ARRAY_HEADER(6), 1 << 1, /* n_props */ 0 << 1, /* hash_mask */ 3 << 1, JS_ROM_VALUE(1540) /* TimersState */, - JS_ROM_VALUE(4123), + JS_ROM_VALUE(4140), (0 << 1) | (JS_PROP_NORMAL << 30), - /* class (offset=4374) */ + /* class (offset=4391) */ JS_MB_HEADER_DEF(JS_MTAG_OBJECT), - JS_ROM_VALUE(4367), + JS_ROM_VALUE(4384), -1, JS_NULL, JS_NULL, - /* global object properties (offset=4379) */ + /* global object properties (offset=4396) */ JS_VALUE_ARRAY_HEADER(178), JS_ROM_VALUE(224) /* Object */, JS_ROM_VALUE(2118), @@ -4754,11 +4771,11 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(297) /* parseFloat */, JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 21), JS_ROM_VALUE(165) /* eval */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 348), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 353), JS_ROM_VALUE(768) /* isNaN */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 349), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 354), JS_ROM_VALUE(771) /* isFinite */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 350), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 355), JS_ROM_VALUE(197) /* Infinity */, JS_ROM_VALUE(3256), JS_ROM_VALUE(195) /* NaN */, @@ -4772,49 +4789,49 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(782) /* performance */, JS_ROM_VALUE(3281), JS_ROM_VALUE(786) /* gc */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 351), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 356), JS_ROM_VALUE(788) /* load */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 352), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 357), JS_ROM_VALUE(791) /* setTimeout */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 353), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 358), JS_ROM_VALUE(795) /* clearTimeout */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 354), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 359), JS_ROM_VALUE(800) /* setInterval */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 355), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 360), JS_ROM_VALUE(804) /* clearInterval */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 356), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 361), JS_ROM_VALUE(809) /* exports */, JS_ROM_VALUE(3290), JS_ROM_VALUE(812) /* assert */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 357), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 362), JS_ROM_VALUE(815) /* require */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 358), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 363), JS_ROM_VALUE(592) /* now */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 359), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 364), JS_ROM_VALUE(818) /* delay */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 360), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 365), JS_ROM_VALUE(555) /* random */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 361), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 366), JS_ROM_VALUE(821) /* parse_int */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 362), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 367), JS_ROM_VALUE(825) /* to_string */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 363), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 368), JS_ROM_VALUE(829) /* to_hex_string */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 364), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 369), JS_ROM_VALUE(834) /* to_lower_case */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 365), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 370), JS_ROM_VALUE(839) /* to_upper_case */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 366), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 371), JS_ROM_VALUE(844) /* atob */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 367), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 372), JS_ROM_VALUE(847) /* btoa */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 368), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 373), JS_ROM_VALUE(850) /* atob_bin */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 369), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 374), JS_ROM_VALUE(854) /* btoa_bin */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 370), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 375), JS_ROM_VALUE(858) /* exit */, - JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 371), + JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, 376), JS_ROM_VALUE(861) /* audio */, JS_ROM_VALUE(3305), JS_ROM_VALUE(871) /* badusb */, @@ -4852,25 +4869,25 @@ static const uint32_t __attribute((aligned(64))) js_stdlib_table[] = { JS_ROM_VALUE(1439) /* wifi */, JS_ROM_VALUE(4006), JS_ROM_VALUE(1472) /* ble */, - JS_ROM_VALUE(4025), - JS_ROM_VALUE(1483) /* nrf24 */, - JS_ROM_VALUE(4052), + JS_ROM_VALUE(4042), + JS_ROM_VALUE(1487) /* nrf24 */, + JS_ROM_VALUE(4069), JS_ROM_VALUE(1500) /* led */, - JS_ROM_VALUE(4074), + JS_ROM_VALUE(4091), JS_ROM_VALUE(1508) /* menu */, - JS_ROM_VALUE(4104), + JS_ROM_VALUE(4121), JS_ROM_VALUE(1540) /* TimersState */, - JS_ROM_VALUE(4123), + JS_ROM_VALUE(4140), JS_ROM_VALUE(1544) /* Sprite */, - JS_ROM_VALUE(4247), + JS_ROM_VALUE(4264), JS_ROM_VALUE(1556) /* TextViewer */, - JS_ROM_VALUE(4303), + JS_ROM_VALUE(4320), JS_ROM_VALUE(1594) /* Gif */, - JS_ROM_VALUE(4337), + JS_ROM_VALUE(4354), JS_ROM_VALUE(1614) /* Buffer */, - JS_ROM_VALUE(4362), + JS_ROM_VALUE(4379), JS_ROM_VALUE(1620) /* __internal_functions */, - JS_ROM_VALUE(4374), + JS_ROM_VALUE(4391), }; static const JSCFunctionDef js_c_function_table[] = { @@ -5804,20 +5821,35 @@ static const JSCFunctionDef js_c_function_table[] = { { { .generic = native_bleStopAdvertise }, JS_ROM_VALUE(1478) /* stopAdvertise */, JS_CFUNC_generic, 0, 0 }, + { { .generic = native_bleConnect }, + JS_ROM_VALUE(1451) /* connect */, + JS_CFUNC_generic, 2, 0 }, + { { .generic = native_bleIsConnected }, + JS_ROM_VALUE(1483) /* isConnected */, + JS_CFUNC_generic, 0, 0 }, + { { .generic = native_bleRead }, + JS_ROM_VALUE(1227) /* read */, + JS_CFUNC_generic, 2, 0 }, + { { .generic = native_bleWrite }, + JS_ROM_VALUE(1224) /* write */, + JS_CFUNC_generic, 4, 0 }, + { { .generic = native_bleDisconnect }, + JS_ROM_VALUE(1454) /* disconnect */, + JS_CFUNC_generic, 0, 0 }, { { .generic = native_nrf24Begin }, JS_ROM_VALUE(1218) /* begin */, JS_CFUNC_generic, 1, 0 }, { { .generic = native_nrf24Send }, - JS_ROM_VALUE(1486) /* send */, + JS_ROM_VALUE(1490) /* send */, JS_CFUNC_generic, 2, 0 }, { { .generic = native_nrf24Receive }, - JS_ROM_VALUE(1489) /* receive */, + JS_ROM_VALUE(1493) /* receive */, JS_CFUNC_generic, 1, 0 }, { { .generic = native_nrf24SetChannel }, - JS_ROM_VALUE(1492) /* setChannel */, + JS_ROM_VALUE(1496) /* setChannel */, JS_CFUNC_generic, 1, 0 }, { { .generic = native_nrf24IsConnected }, - JS_ROM_VALUE(1496) /* isConnected */, + JS_ROM_VALUE(1483) /* isConnected */, JS_CFUNC_generic, 0, 0 }, { { .generic = native_ledSetColor }, JS_ROM_VALUE(1502) /* setColor */, @@ -6007,10 +6039,10 @@ const JSSTDLibraryDef js_stdlib = { js_stdlib_table, js_c_function_table, js_c_finalizer_table, - 4558, + 4575, 64, 1627, - 4379, + 4396, JS_CLASS_COUNT, };