Merge remote-tracking branch 'ofw/dev' into mntm-dev

This commit is contained in:
Willy-JL
2024-10-14 23:44:44 +01:00
167 changed files with 6280 additions and 2155 deletions

View File

@@ -17,7 +17,7 @@ while (true) {
let pa7_value = gpio.readAnalog("PA7");
let pa6_value = gpio.readAnalog("PA6");
let pa4_value = gpio.readAnalog("PA4");
print("A7: " + to_string(pa7_value) + " A6: " + to_string(pa6_value) + " A4: " + to_string(pa4_value));
print("A7: " + toString(pa7_value) + " A6: " + toString(pa6_value) + " A4: " + toString(pa4_value));
delay(100);
if (pa7_value === pa6_value * 2) {
break;

View File

@@ -1,48 +1,73 @@
let badusb = require("badusb");
let notify = require("notification");
let flipper = require("flipper");
let dialog = require("dialog");
let eventLoop = require("event_loop");
let gui = require("gui");
let dialog = require("gui/dialog");
let views = {
dialog: dialog.makeWith({
header: "BadUSB demo",
text: "Press OK to start",
center: "Start",
}),
};
badusb.setup({
vid: 0xAAAA,
pid: 0xBBBB,
mfr_name: "Flipper",
prod_name: "Zero",
layout_path: "/ext/badusb/assets/layouts/en-US.kl"
mfrName: "Flipper",
prodName: "Zero",
layoutPath: "/ext/badusb/assets/layouts/en-US.kl"
});
dialog.message("BadUSB demo", "Press OK to start");
if (badusb.isConnected()) {
notify.blink("green", "short");
print("USB is connected");
eventLoop.subscribe(views.dialog.input, function (_sub, button, eventLoop, gui) {
if (button !== "center")
return;
badusb.println("Hello, world!");
gui.viewDispatcher.sendTo("back");
badusb.press("CTRL", "a");
badusb.press("CTRL", "c");
badusb.press("DOWN");
delay(1000);
badusb.press("CTRL", "v");
delay(1000);
badusb.press("CTRL", "v");
if (badusb.isConnected()) {
notify.blink("green", "short");
print("USB is connected");
badusb.println("1234", 200);
badusb.println("Hello, world!");
badusb.println("Flipper Model: " + flipper.getModel());
badusb.println("Flipper Name: " + flipper.getName());
badusb.println("Battery level: " + to_string(flipper.getBatteryCharge()) + "%");
badusb.press("CTRL", "a");
badusb.press("CTRL", "c");
badusb.press("DOWN");
delay(1000);
badusb.press("CTRL", "v");
delay(1000);
badusb.press("CTRL", "v");
// Alt+Numpad method works only on Windows!!!
badusb.altPrintln("This was printed with Alt+Numpad method!");
badusb.println("1234", 200);
// There's also badusb.print() and badusb.altPrint()
// which don't add the return at the end
badusb.println("Flipper Model: " + flipper.getModel());
badusb.println("Flipper Name: " + flipper.getName());
badusb.println("Battery level: " + toString(flipper.getBatteryCharge()) + "%");
notify.success();
} else {
print("USB not connected");
notify.error();
}
// Alt+Numpad method works only on Windows!!!
badusb.altPrintln("This was printed with Alt+Numpad method!");
// There's also badusb.print() and badusb.altPrint()
// which don't add the return at the end
notify.success();
} else {
print("USB not connected");
notify.error();
}
eventLoop.stop();
}, eventLoop, gui);
eventLoop.subscribe(gui.viewDispatcher.navigation, function (_sub, _item, eventLoop) {
eventLoop.stop();
}, eventLoop);
gui.viewDispatcher.switchTo(views.dialog);
eventLoop.run();
// Optional, but allows to interchange with usbdisk
badusb.quit();

View File

@@ -45,7 +45,7 @@ function sendRandomModelAdvertisement() {
blebeacon.start();
print("Sent data for model ID " + to_string(model));
print("Sent data for model ID " + toString(model));
currentIndex = (currentIndex + 1) % watchValues.length;

View File

@@ -6,4 +6,4 @@ print("2");
delay(1000)
print("3");
delay(1000)
print("end");
print("end");

View File

@@ -1,22 +0,0 @@
let dialog = require("dialog");
let result1 = dialog.message("Dialog demo", "Press OK to start");
print(result1);
let dialog_params = ({
header: "Test_header",
text: "Test_text",
button_left: "Left",
button_right: "Files",
button_center: "OK"
});
let result2 = dialog.custom(dialog_params);
if (result2 === "") {
print("Back is pressed");
} else if (result2 === "Files") {
let result3 = dialog.pickFile("/ext", "*");
print("Selected", result3);
} else {
print(result2, "is pressed");
}

View File

@@ -17,7 +17,7 @@ if (result !== undefined) {
result = "0x";
for (let i = 0; i < data.byteLength; i++) {
if (data[i] < 0x10) result += "0";
result += to_hex_string(data[i]);
result += toString(data[i], 16);
}
}
print("Got data:", result);

View File

@@ -1,3 +1,3 @@
let math = load("/ext/apps/Scripts/load_api.js");
let result = math.add(5, 10);
print(result);
print(result);

View File

@@ -1,3 +1,3 @@
({
add: function (a, b) { return a + b; },
})
})

View File

@@ -22,48 +22,3 @@ print("math.sign(-5):", math.sign(-5));
print("math.sin(math.PI/2):", math.sin(math.PI / 2));
print("math.sqrt(25):", math.sqrt(25));
print("math.trunc(5.7):", math.trunc(5.7));
// Unit tests. Please add more if you have time and knowledge.
// math.EPSILON on Flipper Zero is 2.22044604925031308085e-16
let succeeded = 0;
let failed = 0;
function test(text, result, expected, epsilon) {
let is_equal = math.is_equal(result, expected, epsilon);
if (is_equal) {
succeeded += 1;
} else {
failed += 1;
print(text, "expected", expected, "got", result);
}
}
test("math.abs(5)", math.abs(-5), 5, math.EPSILON);
test("math.abs(0.5)", math.abs(-0.5), 0.5, math.EPSILON);
test("math.abs(5)", math.abs(5), 5, math.EPSILON);
test("math.abs(-0.5)", math.abs(0.5), 0.5, math.EPSILON);
test("math.acos(0.5)", math.acos(0.5), 1.0471975511965976, math.EPSILON);
test("math.acosh(2)", math.acosh(2), 1.3169578969248166, math.EPSILON);
test("math.asin(0.5)", math.asin(0.5), 0.5235987755982988, math.EPSILON);
test("math.asinh(2)", math.asinh(2), 1.4436354751788103, math.EPSILON);
test("math.atan(1)", math.atan(1), 0.7853981633974483, math.EPSILON);
test("math.atan2(1, 1)", math.atan2(1, 1), 0.7853981633974483, math.EPSILON);
test("math.atanh(0.5)", math.atanh(0.5), 0.5493061443340549, math.EPSILON);
test("math.cbrt(27)", math.cbrt(27), 3, math.EPSILON);
test("math.ceil(5.3)", math.ceil(5.3), 6, math.EPSILON);
test("math.clz32(1)", math.clz32(1), 31, math.EPSILON);
test("math.floor(5.7)", math.floor(5.7), 5, math.EPSILON);
test("math.max(3, 5)", math.max(3, 5), 5, math.EPSILON);
test("math.min(3, 5)", math.min(3, 5), 3, math.EPSILON);
test("math.pow(2, 3)", math.pow(2, 3), 8, math.EPSILON);
test("math.sign(-5)", math.sign(-5), -1, math.EPSILON);
test("math.sqrt(25)", math.sqrt(25), 5, math.EPSILON);
test("math.trunc(5.7)", math.trunc(5.7), 5, math.EPSILON);
test("math.cos(math.PI)", math.cos(math.PI), -1, math.EPSILON * 18); // Error 3.77475828372553223744e-15
test("math.exp(1)", math.exp(1), 2.718281828459045, math.EPSILON * 2); // Error 4.44089209850062616169e-16
test("math.sin(math.PI / 2)", math.sin(math.PI / 2), 1, math.EPSILON * 4.5); // Error 9.99200722162640886381e-16
if (failed > 0) {
print("!!!", failed, "Unit tests failed !!!");
}

View File

@@ -6,4 +6,4 @@ delay(1000);
for (let i = 0; i < 10; i++) {
notify.blink("red", "short");
delay(500);
}
}

View File

@@ -1,6 +1,6 @@
let sampleText = "Hello, World!";
let lengthOfText = "Length of text: " + to_string(sampleText.length);
let lengthOfText = "Length of text: " + toString(sampleText.length);
print(lengthOfText);
let start = 7;
@@ -9,7 +9,7 @@ let substringResult = sampleText.slice(start, end);
print(substringResult);
let searchStr = "World";
let result2 = to_string(sampleText.indexOf(searchStr));
let result2 = toString(sampleText.indexOf(searchStr));
print(result2);
let upperCaseText = "Text in upper case: " + to_upper_case(sampleText);

View File

@@ -1,11 +0,0 @@
let submenu = require("submenu");
submenu.addItem("Item 1", 0);
submenu.addItem("Item 2", 1);
submenu.addItem("Item 3", 2);
submenu.setHeader("Select an option:");
let result = submenu.show();
// Returns undefined when pressing back
print("Result:", result);

View File

@@ -1,30 +0,0 @@
let textbox = require("textbox");
// You should set config before adding text
// Focus (start / end), Font (text / hex)
textbox.setConfig("end", "text");
// Can make sure it's cleared before showing, in case of reusing in same script
// (Closing textbox already clears the text, but maybe you added more in a loop for example)
textbox.clearText();
// Add default text
textbox.addText("Example dynamic updating textbox\n");
// Non-blocking, can keep updating text after, can close in JS or in GUI
textbox.show();
let i = 0;
while (textbox.isOpen() && i < 20) {
print("console", i++);
// Add text to textbox buffer
textbox.addText("textbox " + to_string(i) + "\n");
delay(500);
}
// If not closed by user (instead i < 20 is false above), close forcefully
if (textbox.isOpen()) {
textbox.close();
}

View File

@@ -6,7 +6,7 @@ while (1) {
if (rx_data !== undefined) {
serial.write(rx_data);
let data_view = Uint8Array(rx_data);
print("0x" + to_hex_string(data_view[0]));
print("0x" + toString(data_view[0], 16));
}
}

View File

@@ -0,0 +1,25 @@
let eventLoop = require("event_loop");
// print a string after 1337 milliseconds
eventLoop.subscribe(eventLoop.timer("oneshot", 1337), function (_subscription, _item) {
print("Hi after 1337 ms");
});
// count up to 5 with a delay of 100ms between increments
eventLoop.subscribe(eventLoop.timer("periodic", 100), function (subscription, _item, counter) {
print("Counter two:", counter);
if (counter === 5)
subscription.cancel();
return [counter + 1];
}, 0);
// count up to 15 with a delay of 100ms between increments
// and stop the program when the count reaches 15
eventLoop.subscribe(eventLoop.timer("periodic", 100), function (subscription, _item, event_loop, counter) {
print("Counter one:", counter);
if (counter === 15)
event_loop.stop();
return [event_loop, counter + 1];
}, eventLoop, 0);
eventLoop.run();

View File

@@ -0,0 +1,57 @@
let eventLoop = require("event_loop");
let gpio = require("gpio");
// initialize pins
let led = gpio.get("pc3"); // same as `gpio.get(7)`
let pot = gpio.get("pc0"); // same as `gpio.get(16)`
let button = gpio.get("pc1"); // same as `gpio.get(15)`
led.init({ direction: "out", outMode: "push_pull" });
pot.init({ direction: "in", inMode: "analog" });
button.init({ direction: "in", pull: "up", inMode: "interrupt", edge: "falling" });
// blink led
print("Commencing blinking (PC3)");
eventLoop.subscribe(eventLoop.timer("periodic", 1000), function (_, _item, led, state) {
led.write(state);
return [led, !state];
}, led, true);
// read potentiometer when button is pressed
print("Press the button (PC1)");
eventLoop.subscribe(button.interrupt(), function (_, _item, pot) {
print("PC0 is at", pot.read_analog(), "mV");
}, pot);
// the program will just exit unless this is here
eventLoop.run();
// possible pins https://docs.flipper.net/gpio-and-modules#miFsS
// "PA7" aka 2
// "PA6" aka 3
// "PA4" aka 4
// "PB3" aka 5
// "PB2" aka 6
// "PC3" aka 7
// "PA14" aka 10
// "PA13" aka 12
// "PB6" aka 13
// "PB7" aka 14
// "PC1" aka 15
// "PC0" aka 16
// "PB14" aka 17
// possible modes
// { direction: "out", outMode: "push_pull" }
// { direction: "out", outMode: "open_drain" }
// { direction: "out", outMode: "push_pull", altFn: true }
// { direction: "out", outMode: "open_drain", altFn: true }
// { direction: "in", inMode: "analog" }
// { direction: "in", inMode: "plain_digital" }
// { direction: "in", inMode: "interrupt", edge: "rising" }
// { direction: "in", inMode: "interrupt", edge: "falling" }
// { direction: "in", inMode: "interrupt", edge: "both" }
// { direction: "in", inMode: "event", edge: "rising" }
// { direction: "in", inMode: "event", edge: "falling" }
// { direction: "in", inMode: "event", edge: "both" }
// all variants support an optional `pull` field which can either be undefined,
// "up" or "down"

View File

@@ -0,0 +1,77 @@
// import modules
let eventLoop = require("event_loop");
let gui = require("gui");
let loadingView = require("gui/loading");
let submenuView = require("gui/submenu");
let emptyView = require("gui/empty_screen");
let textInputView = require("gui/text_input");
let textBoxView = require("gui/text_box");
let dialogView = require("gui/dialog");
// declare view instances
let views = {
loading: loadingView.make(),
empty: emptyView.make(),
keyboard: textInputView.makeWith({
header: "Enter your name",
minLength: 0,
maxLength: 32,
}),
helloDialog: dialogView.makeWith({
center: "Hi Flipper! :)",
}),
longText: textBoxView.makeWith({
text: "This is a very long string that demonstrates the TextBox view. Use the D-Pad to scroll backwards and forwards.\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse rhoncus est malesuada quam egestas ultrices. Maecenas non eros a nulla eleifend vulputate et ut risus. Quisque in mauris mattis, venenatis risus eget, aliquam diam. Fusce pretium feugiat mauris, ut faucibus ex volutpat in. Phasellus volutpat ex sed gravida consectetur. Aliquam sed lectus feugiat, tristique lectus et, bibendum lacus. Ut sit amet augue eu sapien elementum aliquam quis vitae tortor. Vestibulum quis commodo odio. In elementum fermentum massa, eu pellentesque nibh cursus at. Integer eleifend lacus nec purus elementum sodales. Nulla elementum neque urna, non vulputate massa semper sed. Fusce ut nisi vitae dui blandit congue pretium vitae turpis.",
}),
demos: submenuView.makeWith({
header: "Choose a demo",
items: [
"Hourglass screen",
"Empty screen",
"Text input & Dialog",
"Text box",
"Exit app",
],
}),
};
// demo selector
eventLoop.subscribe(views.demos.chosen, function (_sub, index, gui, eventLoop, views) {
if (index === 0) {
gui.viewDispatcher.switchTo(views.loading);
// the loading view captures all back events, preventing our navigation callback from firing
// switch to the demo chooser after a second
eventLoop.subscribe(eventLoop.timer("oneshot", 1000), function (_sub, _, gui, views) {
gui.viewDispatcher.switchTo(views.demos);
}, gui, views);
} else if (index === 1) {
gui.viewDispatcher.switchTo(views.empty);
} else if (index === 2) {
gui.viewDispatcher.switchTo(views.keyboard);
} else if (index === 3) {
gui.viewDispatcher.switchTo(views.longText);
} else if (index === 4) {
eventLoop.stop();
}
}, gui, eventLoop, views);
// say hi after keyboard input
eventLoop.subscribe(views.keyboard.input, function (_sub, name, gui, views) {
views.helloDialog.set("text", "Hi " + name + "! :)");
gui.viewDispatcher.switchTo(views.helloDialog);
}, gui, views);
// go back after the greeting dialog
eventLoop.subscribe(views.helloDialog.input, function (_sub, button, gui, views) {
if (button === "center")
gui.viewDispatcher.switchTo(views.demos);
}, gui, views);
// go to the demo chooser screen when the back key is pressed
eventLoop.subscribe(gui.viewDispatcher.navigation, function (_sub, _, gui, views) {
gui.viewDispatcher.switchTo(views.demos);
}, gui, views);
// run UI
gui.viewDispatcher.switchTo(views.demos);
eventLoop.run();