Add js sdk changes

With type declarations and various missing parts added by Willy-JL
This commit is contained in:
MX 2024-11-05 09:49:46 +03:00
parent 8a2cf4dc3d
commit 79caf7bf72
No known key found for this signature in database
GPG Key ID: 7CCC66B7DBDD1C83
19 changed files with 378 additions and 26 deletions

View File

@ -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",
};
/**

View File

@ -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;

View File

@ -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:

View File

@ -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": {

View File

@ -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 = {

View File

@ -2,11 +2,11 @@
"name": "<app_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"
}
}

View File

@ -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/**/*",

View File

@ -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:

View File

@ -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;

View File

@ -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;

View File

@ -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
*

View File

@ -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

View File

@ -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",

View File

@ -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(".");

View File

@ -1,3 +1,9 @@
/**
* SPI bus communication
* @version Available with JS feature `spi`
* @module
*/
/**
* @brief Acquire SPI bus
*/

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;