diff --git a/applications/system/js_app/js_modules.c b/applications/system/js_app/js_modules.c index bffa553a8..429c01090 100644 --- a/applications/system/js_app/js_modules.c +++ b/applications/system/js_app/js_modules.c @@ -267,6 +267,15 @@ void js_check_sdk_compatibility(struct mjs* mjs) { static const char* extra_features[] = { "baseline", // dummy "feature" + + // extra modules + "blebeacon", + "i2c", + "spi", + "subghz", + "usbdisk", + "vgm", + "widget", }; /** diff --git a/applications/system/js_app/modules/js_subghz/js_subghz.c b/applications/system/js_app/modules/js_subghz/js_subghz.c index 051566aec..f7065d38c 100644 --- a/applications/system/js_app/modules/js_subghz/js_subghz.c +++ b/applications/system/js_app/modules/js_subghz/js_subghz.c @@ -223,7 +223,7 @@ static void js_subghz_transmit_file(struct mjs* mjs) { // - "repeat" as variable and loop in this code applies to RAW files only // parsed files handle repeat in protocol layer instead // We keep 0 as default, or literal value if specified by user - // If user did not specify, -1 is detected below, and we use: + // If user did not specify, 0 is detected below, and we use: // - 1 repeat for RAW // - 10 repeats for parsed, which is passed to protocol, and we loop once here uint32_t repeat = 0; diff --git a/applications/system/js_app/packages/create-fz-app/README.md b/applications/system/js_app/packages/create-fz-app/README.md index cf6ddbc91..97f22a4cc 100644 --- a/applications/system/js_app/packages/create-fz-app/README.md +++ b/applications/system/js_app/packages/create-fz-app/README.md @@ -1,11 +1,15 @@ -# Flipper Zero JavaScript SDK Wizard +# Flipper Unleashed Firmware JavaScript SDK Wizard This package contains an interactive wizard that lets you scaffold a JavaScript -application for Flipper Zero. +application for Flipper Zero using the Custom Unleashed Firmware JS SDK. + +This is a fork of the [Official Flipper Zero JS SDK Wizard](https://www.npmjs.com/package/@flipperdevices/create-fz-app), +configured to use the [Unleashed FW JavaScript SDK]((https://www.npmjs.com/package/@darkflippers/fz-sdk-ul)) instead. +No other changes are included. ## Getting started Create your application using the interactive wizard: ```shell -npx @flipperdevices/create-fz-app@latest +npx @darkflippers/create-fz-app-ul@latest ``` Then, enter the directory with your application and launch it: diff --git a/applications/system/js_app/packages/create-fz-app/package.json b/applications/system/js_app/packages/create-fz-app/package.json index 216423396..068260de9 100644 --- a/applications/system/js_app/packages/create-fz-app/package.json +++ b/applications/system/js_app/packages/create-fz-app/package.json @@ -1,10 +1,15 @@ { - "name": "@flipperdevices/create-fz-app", - "version": "0.1.0", - "description": "Template package for JS apps Flipper Zero", + "name": "@darkflippers/create-fz-app-ul", + "version": "0.1.1", + "description": "Template package for JS apps for Flipper Zero using Unleashed Firmware JS SDK", "bin": "index.js", "type": "module", "keywords": [ + "unleashed", + "unleashed firmware", + "ul", + "darkflippers", + "flipper cfw js", "flipper", "flipper zero" ], @@ -12,7 +17,7 @@ "license": "GPL-3.0-only", "repository": { "type": "git", - "url": "git+https://github.com/flipperdevices/flipperzero-firmware.git", + "url": "git+https://github.com/DarkFlippers/unleashed-firmware.git", "directory": "applications/system/js_app/packages/create-fz-app" }, "dependencies": { diff --git a/applications/system/js_app/packages/create-fz-app/template/index.ts b/applications/system/js_app/packages/create-fz-app/template/index.ts index 6291e3e13..430705e75 100644 --- a/applications/system/js_app/packages/create-fz-app/template/index.ts +++ b/applications/system/js_app/packages/create-fz-app/template/index.ts @@ -1,9 +1,9 @@ // import modules // caution: `eventLoop` HAS to be imported before `gui`, and `gui` HAS to be // imported before any `gui` submodules. -import * as eventLoop from "@flipperdevices/fz-sdk/event_loop"; -import * as gui from "@flipperdevices/fz-sdk/gui"; -import * as dialog from "@flipperdevices/fz-sdk/gui/dialog"; +import * as eventLoop from "@darkflippers/fz-sdk-ul/event_loop"; +import * as gui from "@darkflippers/fz-sdk-ul/gui"; +import * as dialog from "@darkflippers/fz-sdk-ul/gui/dialog"; // a common pattern is to declare all the views that your app uses on one object const views = { diff --git a/applications/system/js_app/packages/create-fz-app/template/package.json b/applications/system/js_app/packages/create-fz-app/template/package.json index 7acdeccaa..211411c73 100644 --- a/applications/system/js_app/packages/create-fz-app/template/package.json +++ b/applications/system/js_app/packages/create-fz-app/template/package.json @@ -2,11 +2,11 @@ "name": "", "version": "1.0.0", "scripts": { - "build": "tsc && node node_modules/@flipperdevices/fz-sdk/sdk.js build", - "start": "npm run build && node node_modules/@flipperdevices/fz-sdk/sdk.js upload" + "build": "tsc && node node_modules/@darkflippers/fz-sdk-ul/sdk.js build", + "start": "npm run build && node node_modules/@darkflippers/fz-sdk-ul/sdk.js upload" }, "devDependencies": { - "@flipperdevices/fz-sdk": "^0.1", + "@darkflippers/fz-sdk-ul": "^0.1", "typescript": "^5.6.3" } } \ No newline at end of file diff --git a/applications/system/js_app/packages/create-fz-app/template/tsconfig.json b/applications/system/js_app/packages/create-fz-app/template/tsconfig.json index c7b83cd5d..a1db94c39 100644 --- a/applications/system/js_app/packages/create-fz-app/template/tsconfig.json +++ b/applications/system/js_app/packages/create-fz-app/template/tsconfig.json @@ -5,13 +5,14 @@ "module": "CommonJS", "noLib": true, "target": "ES2015", + "types": [], }, "files": [ - "./node_modules/@flipperdevices/fz-sdk/global.d.ts", + "./node_modules/@darkflippers/fz-sdk-ul/global.d.ts", ], "include": [ "./**/*.ts", - "./**/*.js" + "./**/*.js", ], "exclude": [ "./node_modules/**/*", diff --git a/applications/system/js_app/packages/fz-sdk/README.md b/applications/system/js_app/packages/fz-sdk/README.md index 3234f68aa..8bac450fb 100644 --- a/applications/system/js_app/packages/fz-sdk/README.md +++ b/applications/system/js_app/packages/fz-sdk/README.md @@ -1,11 +1,22 @@ -# Flipper Zero JavaScript SDK -This package contains official tooling and typings for developing Flipper Zero -applications in JavaScript. +# Flipper Unleashed FW JavaScript SDK +This package contains tooling and typings for developing Flipper Zero +applications in JavaScript for Unleashed Custom Firmware (based on official SDK). + +This is a fork of the [Official Flipper Zero JS SDK](https://www.npmjs.com/package/@flipperdevices/fz-sdk), +with added types for the extra features provided by the Unleashed firmware JavaScript API. + +Scripts made for Official Flipper Zero JS SDK will work on Unleashed Firmware too. +If you use extra features provided by Unleashed FW JS SDK, you are encouraged to use syntax like +`if (doesSdkSupport(["feature-name"])) { ... }` so that your JS app can work on Official +Firmware too, aswell as all other compliant Custom Firmwares. If some of those extra +features are essential to the functionality of your app, you can use `checkSdkFeatures(["feature1", "feature2"])` +near the beginning of your script, which will show a warning to the user that these features +are not available in their firmware distribution. ## Getting started Create your application using the interactive wizard: ```shell -npx @flipperdevices/create-fz-app@latest +npx @darkflippers/create-fz-app-ul@latest ``` Then, enter the directory with your application and launch it: diff --git a/applications/system/js_app/packages/fz-sdk/blebeacon/index.d.ts b/applications/system/js_app/packages/fz-sdk/blebeacon/index.d.ts new file mode 100644 index 000000000..b2b527a40 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/blebeacon/index.d.ts @@ -0,0 +1,41 @@ +/** + * Module for using the BLE extra beacon + * @version Available with JS feature `blebeacon` + * @module + */ + +/** + * @brief Check if the BLE beacon is active + */ +export declare function isActive(): boolean; + +/** + * @brief Set BLE beacon configuration + * @param mac The MAC address to use + * @param power The power level to use, in GapAdvPowerLevel scale: 0x00 (-40dBm) to 0x1F (+6dBm) + * @param minInterval Minimum advertisement interval + * @param maxInterval Maximum advertisement interval + */ +export declare function setConfig(mac: Uint8Array, power?: number, minInterval?: number, maxInterval?: number): void; + +/** + * @brief Set BLE beacon advertisement data + * @param data The advertisement data to use + */ +export declare function setData(data: Uint8Array): void; + +/** + * @brief Start BLE beacon + */ +export declare function start(): void; + +/** + * @brief Stop BLE beacon + */ +export declare function stop(): void; + +/** + * @brief Set whether the BLE beacon will remain active after the script exits + * @param keep True if BLE beacon should remain active after script exit + */ +export declare function keepAlive(keep: boolean): void; diff --git a/applications/system/js_app/packages/fz-sdk/flipper/index.d.ts b/applications/system/js_app/packages/fz-sdk/flipper/index.d.ts index 2dac4204b..f939f012b 100644 --- a/applications/system/js_app/packages/fz-sdk/flipper/index.d.ts +++ b/applications/system/js_app/packages/fz-sdk/flipper/index.d.ts @@ -26,7 +26,7 @@ export declare function getBatteryCharge(): number; * @warning Do **NOT** use this to check the presence or absence of features. If * you do, I'm gonna be sad :( Instead, refer to `checkSdkFeatures` and * other similar mechanisms. - * @note Original firmware reports `"flipperdevices"`. + * @note Unleashed firmware reports `"unleashed"`. / Official firmware reports `"flipperdevices"`. * @version Added in JS SDK 0.1 */ export declare const firmwareVendor: string; diff --git a/applications/system/js_app/packages/fz-sdk/global.d.ts b/applications/system/js_app/packages/fz-sdk/global.d.ts index d2e73f7de..ba6996f27 100644 --- a/applications/system/js_app/packages/fz-sdk/global.d.ts +++ b/applications/system/js_app/packages/fz-sdk/global.d.ts @@ -202,6 +202,13 @@ declare function chr(n: number): string | null; */ declare function require(module: string): any; +/** + * @brief Exit JavaScript with given message + * @param message The error message to show to user + * @version Added in JS SDK 0.1 + */ +declare function die(message: string): never; + /** * @brief mJS Foreign Pointer type * diff --git a/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts b/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts index ea0a640cb..7ce118fe5 100644 --- a/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts +++ b/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts @@ -1,3 +1,9 @@ +/** + * I2C bus communication + * @version Available with JS feature `i2c` + * @module + */ + /** * @brief Check if there is an I2C device ready on the bus * @param address The device address to check diff --git a/applications/system/js_app/packages/fz-sdk/package.json b/applications/system/js_app/packages/fz-sdk/package.json index 4d18f3f20..3dbfca258 100644 --- a/applications/system/js_app/packages/fz-sdk/package.json +++ b/applications/system/js_app/packages/fz-sdk/package.json @@ -1,8 +1,13 @@ { - "name": "@flipperdevices/fz-sdk", - "version": "0.1.1", - "description": "Type declarations and documentation for native JS modules available on Flipper Zero", + "name": "@darkflippers/fz-sdk-ul", + "version": "0.1.2", + "description": "Type declarations and documentation for native JS modules available on Unleashed Custom Firmware for Flipper Zero", "keywords": [ + "unleashed", + "unleashed firmware", + "ul", + "darkflippers", + "flipper unleashed fw sdk", "flipper", "flipper zero", "framework" @@ -11,7 +16,7 @@ "license": "GPL-3.0-only", "repository": { "type": "git", - "url": "git+https://github.com/flipperdevices/flipperzero-firmware.git", + "url": "git+https://github.com/DarkFlippers/unleashed-firmware.git", "directory": "applications/system/js_app/packages/fz-sdk" }, "type": "module", diff --git a/applications/system/js_app/packages/fz-sdk/sdk.js b/applications/system/js_app/packages/fz-sdk/sdk.js index 2eecf032d..4fa1a95a7 100644 --- a/applications/system/js_app/packages/fz-sdk/sdk.js +++ b/applications/system/js_app/packages/fz-sdk/sdk.js @@ -10,6 +10,9 @@ import json5 from "json5"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +const cfwSdkName = "@darkflippers/fz-sdk-ul/"; +const ofwSdkName = "@flipperdevices/fz-sdk/"; + async function build(config) { await esbuild.build({ entryPoints: ["./dist/index.js"], @@ -19,7 +22,7 @@ async function build(config) { bundle: true, minify: config.minify, external: [ - "@flipperdevices/fz-sdk/*" + "@darkflippers/fz-sdk-ul/*" ], supported: { "array-spread": false, @@ -74,6 +77,9 @@ async function build(config) { let outContents = fs.readFileSync(config.output, "utf8"); outContents = "let exports = {};\n" + outContents; + // Transform CFW SDK name to OFW SDK name so all firmwares understand it + outContents = outContents.replaceAll(`require("${cfwSdkName}`, `require("${ofwSdkName}`); + if (config.enforceSdkVersion) { const version = json5.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version; let [major, minor, _] = version.split("."); diff --git a/applications/system/js_app/packages/fz-sdk/spi/index.d.ts b/applications/system/js_app/packages/fz-sdk/spi/index.d.ts index 8d72bc29c..e4bb7774b 100644 --- a/applications/system/js_app/packages/fz-sdk/spi/index.d.ts +++ b/applications/system/js_app/packages/fz-sdk/spi/index.d.ts @@ -1,3 +1,9 @@ +/** + * SPI bus communication + * @version Available with JS feature `spi` + * @module + */ + /** * @brief Acquire SPI bus */ diff --git a/applications/system/js_app/packages/fz-sdk/subghz/index.d.ts b/applications/system/js_app/packages/fz-sdk/subghz/index.d.ts new file mode 100644 index 000000000..9af9e67a9 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/subghz/index.d.ts @@ -0,0 +1,64 @@ +/** + * Module for using Sub-GHz transciever + * @version Available with JS feature `subghz` + * @module + */ + +/** + * @brief Initialize Sub-GHz module + */ +export declare function setup(): void; + +/** + * @brief Deinitialize Sub-GHz module + */ +export declare function end(): void; + +/** + * @brief Set radio to receive mode + */ +export declare function setRx(): void; + +/** + * @brief Set radio to idle mode + */ +export declare function setIdle(): void; + +/** + * @brief Return current RSSI on current frequency, or undefined if radio is not in receive mode + */ +export declare function getRssi(): number | undefined; + +type RadioState = "RX" | "TX" | "IDLE" | ""; + +/** + * @brief Get current radio mode/state + */ +export declare function getState(): RadioState; + +/** + * @brief Get currently selected frequency + */ +export declare function getFrequency(): number; + +/** + * @brief Change current frequency, radio must be in idle mode + * + * Returns the effective frequency, since radio module cant use all precise + * values and instead chooses closest one available + * + * @param frequency What frequency to use + */ +export declare function setFrequency(frequency: number): number; + +/** + * @brief Check whether the radio module in use is internal or external + */ +export declare function isExternal(): boolean; + +/** + * @brief Transmit a .sub file, return true on success or error on failure + * @param path What .sub file to transmit + * @param repeat How many times to repeat the signal + */ +export declare function transmitFile(path: string, repeat?: number): true; diff --git a/applications/system/js_app/packages/fz-sdk/usbdisk/index.d.ts b/applications/system/js_app/packages/fz-sdk/usbdisk/index.d.ts new file mode 100644 index 000000000..b9c5da5f7 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/usbdisk/index.d.ts @@ -0,0 +1,24 @@ +/** + * Module for USB mass storage emulation + * @version Available with JS feature `usbdisk` + * @module + */ + +/** + * @brief Start emulating mass storage device + * @param path The disk image to emulate + */ +export declare function start(path: string): void; + +/** + * @brief Stop emulating mass storage device + */ +export declare function stop(): void; + +/** + * @brief Check if the mass storage device was exected + * + * Useful as a loop condition with a delay, so UsbDisk keeps running until ejected + * + */ +export declare function wasEjected(): boolean; diff --git a/applications/system/js_app/packages/fz-sdk/vgm/index.d.ts b/applications/system/js_app/packages/fz-sdk/vgm/index.d.ts new file mode 100644 index 000000000..a6bef6f16 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/vgm/index.d.ts @@ -0,0 +1,32 @@ +/** + * Module for interactive with Flipper Video Game Module (VGM) + * @version Available with JS feature `vgm` + * @module + */ + +/** + * @brief Get current VGM pitch, or undefined if VGM not present + */ +export declare function getPitch(): number | undefined; + +/** + * @brief Get current VGM roll, or undefined if VGM not present + */ +export declare function getRoll(): number | undefined; + +/** + * @brief Get current VGM yaw, or undefined if VGM not present + */ +export declare function getYaw(): number | undefined; + +/** + * @brief Wait until yaw changed by specified amount + * + * Returns how much the yaw changed from initial value if it exceeded the + * specified yaw angle, or returns 0 if it was not exceeded within the timeout + * Or returns undefined if VGM is not present + * + * @param angle How much the yaw needs to change + * @param timeout Maximum time in milliseconds to wait for specified yaw change, default 3000ms + */ +export declare function deltaYaw(angle: number, timeout?: number): number | undefined; diff --git a/applications/system/js_app/packages/fz-sdk/widget/index.d.ts b/applications/system/js_app/packages/fz-sdk/widget/index.d.ts new file mode 100644 index 000000000..6644b38b6 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/widget/index.d.ts @@ -0,0 +1,131 @@ +/** + * Displays a customizable Widget on screen + * @version Available with JS feature `widget` + * @module + */ + +type ComponentId = number; + +/** + * @brief Add a box component + * @param x Horizontal position + * @param y Vertical position + * @param w Width + * @param h Height + */ +export declare function addBox(x: number, y: number, w: number, h: number): ComponentId; + +/** + * @brief Add a circle component + * @param x Horizontal position + * @param y Vertical position + * @param r Radius + */ +export declare function addCircle(x: number, y: number, r: number): ComponentId; + +/** + * @brief Add a disc component + * @param x Horizontal position + * @param y Vertical position + * @param r Radius + */ +export declare function addDisc(x: number, y: number, r: number): ComponentId; + +/** + * @brief Add a dot component + * @param x Horizontal position + * @param y Vertical position + */ +export declare function addDot(x: number, y: number): ComponentId; + +/** + * @brief Add a frame component + * @param x Horizontal position + * @param y Vertical position + * @param w Width + * @param h Height + */ +export declare function addFrame(x: number, y: number, w: number, h: number): ComponentId; + +/** + * @brief Add a glyph component + * @param x Horizontal position + * @param y Vertical position + * @param ch ASCII character code (eg. `"C".charCodeAt(0)`) + */ +export declare function addGlyph(x: number, y: number, ch: number): ComponentId; + +/** + * @brief Add a line component + * @param x1 Horizontal position 1 + * @param y1 Vertical position 1 + * @param x2 Horizontal position 2 + * @param y2 Vertical position 2 + */ +export declare function addLine(x1: number, y1: number, x2: number, y2: number): ComponentId; + +/** + * @brief Add a rounded box component + * @param x Horizontal position + * @param y Vertical position + * @param w Width + * @param h Height + * @param r Radius + */ +export declare function addRbox(x: number, y: number, w: number, h: number, r: number): ComponentId; + +/** + * @brief Add a rounded frame component + * @param x Horizontal position + * @param y Vertical position + * @param w Width + * @param h Height + * @param r Radius + */ +export declare function addRframe(x: number, y: number, w: number, h: number, r: number): ComponentId; + +/** + * @brief Add a text component + * @param x Horizontal position + * @param y Vertical position + * @param font What font to use, Primary or Secondary + * @param text Text to display + */ +export declare function addText(x: number, y: number, font: "Primary" | "Secondary", text: string): ComponentId; + +type XbmId = number; + +/** + * @brief Add an xbm image component + * @param x Horizontal position + * @param y Vertical position + * @param index Loaded xbm id to use + */ +export declare function addXbm(x: number, y: number, index: XbmId): ComponentId; + +/** + * @brief Load an xbm image sprite + * @param path Xbm file to load + */ +export declare function loadImageXbm(path: string): XbmId; + +/** + * @brief Remove a component + * @param id Component id to remove + */ +export declare function remove(id: ComponentId): boolean; + +/** + * @brief Check if the widget view is shown + */ +export declare function isOpen(): boolean; + +/** + * @brief Show the widget view + */ +export declare function show(): void; + +/** + * @brief Close the widget view + */ +export declare function close(): void;