diff --git a/Taskfile.yaml b/Taskfile.yaml
index 7d61e13..19e0143 100644
--- a/Taskfile.yaml
+++ b/Taskfile.yaml
@@ -27,10 +27,12 @@ tasks:
# copy the extension to the rigth place
- ln -s $PWD/scratch-prg-extensions/extensions/src/arduino_basics $PWD/prg-raise-playground/extensions/src/arduino_basics
- cd scratch-prg-extensions/extensions/src/arduino_basics && pnpm install
+ - ln -s $PWD/scratch-prg-extensions/extensions/src/arduino_modulino $PWD/prg-raise-playground/extensions/src/arduino_modulino
+ - cd scratch-prg-extensions/extensions/src/arduino_modulino && pnpm install
scratch:watch:
cmds:
- - cd prg-raise-playground && pnpm dev -i arduino_basics
+ - cd prg-raise-playground && pnpm dev -i arduino_basics arduino_modulino
app:build:
desc: "Copy app files (python, assets, app.yaml) to a build directory"
diff --git a/python/main.py b/python/main.py
index 40ffc89..04a8545 100644
--- a/python/main.py
+++ b/python/main.py
@@ -13,4 +13,11 @@ def on_matrix_draw(_, data):
ui.on_message("matrix_draw", on_matrix_draw)
+
+def on_modulino_button_pressed(btn):
+ ui.send_message("modulino_buttons_pressed", {"btn": btn})
+
+
+Bridge.provide("modulino_button_pressed", on_modulino_button_pressed)
+
App.run()
diff --git a/scratch-prg-extensions/extensions/src/arduino_basics/MatrixArgument.svelte b/scratch-prg-extensions/extensions/src/arduino_basics/MatrixArgument.svelte
index 768c919..c3452e6 100644
--- a/scratch-prg-extensions/extensions/src/arduino_basics/MatrixArgument.svelte
+++ b/scratch-prg-extensions/extensions/src/arduino_basics/MatrixArgument.svelte
@@ -71,8 +71,7 @@
@@ -147,8 +168,8 @@
0 ? `rgba(0, 123, 255)` : '#222'}
- style:box-shadow={ledValue > 0 ? `0 0 ${ledValue * 2}px rgba(0, 123, 255, 0.8)` : 'none'}
+ style:background-color={ledValue > 0 ? `#FFFFFF` : '#62AEB2'}
+ style:box-shadow={ledValue > 0 ? `0 0 ${ledValue}px rgba(255, 255, 255, 0.7)` : 'none'}
on:mousedown={(e) => handleMouseDown(e, rowIndex, colIndex)}
on:mouseenter={() => handleMouseEnter(rowIndex, colIndex)}
on:contextmenu={handleContextMenu}
@@ -162,7 +183,31 @@
-
-
+
+
\ No newline at end of file
diff --git a/scratch-prg-extensions/extensions/src/arduino_basics/index.ts b/scratch-prg-extensions/extensions/src/arduino_basics/index.ts
index bf8b9ad..027b5d8 100644
--- a/scratch-prg-extensions/extensions/src/arduino_basics/index.ts
+++ b/scratch-prg-extensions/extensions/src/arduino_basics/index.ts
@@ -3,13 +3,13 @@ import { io, Socket } from "socket.io-client";
import MatrixArgument from "./MatrixArgument.svelte";
const details: ExtensionMenuDisplayDetails = {
- name: "Arduino Basics",
- description: "Arduino Basics for Uno Q",
- iconURL: "ArduinoLogo_Blue.png",
- insetIconURL: "ArduinoLogo_Blue.jpg",
- tags: ["Arduino"],
+ name: "Basic",
+ description: "Play with UNO Q matrix, leds and pins",
+ iconURL: "matrix.png",
+ insetIconURL: "unoq.svg",
+ tags: ["Arduino UNO Q"],
blockColor: "#00878F",
- menuColor: "#62AEB2",
+ menuColor: "#8C7965",
menuSelectColor: "#62AEB2",
};
diff --git a/scratch-prg-extensions/extensions/src/arduino_basics/matrix.png b/scratch-prg-extensions/extensions/src/arduino_basics/matrix.png
new file mode 100644
index 0000000..dfbc054
Binary files /dev/null and b/scratch-prg-extensions/extensions/src/arduino_basics/matrix.png differ
diff --git a/scratch-prg-extensions/extensions/src/arduino_basics/unoq.svg b/scratch-prg-extensions/extensions/src/arduino_basics/unoq.svg
new file mode 100644
index 0000000..ac92aad
--- /dev/null
+++ b/scratch-prg-extensions/extensions/src/arduino_basics/unoq.svg
@@ -0,0 +1,1460 @@
+
diff --git a/scratch-prg-extensions/extensions/src/arduino_modulino/.gitignore b/scratch-prg-extensions/extensions/src/arduino_modulino/.gitignore
new file mode 100644
index 0000000..b512c09
--- /dev/null
+++ b/scratch-prg-extensions/extensions/src/arduino_modulino/.gitignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/scratch-prg-extensions/extensions/src/arduino_modulino/ButtonArgument.svelte b/scratch-prg-extensions/extensions/src/arduino_modulino/ButtonArgument.svelte
new file mode 100644
index 0000000..96101f3
--- /dev/null
+++ b/scratch-prg-extensions/extensions/src/arduino_modulino/ButtonArgument.svelte
@@ -0,0 +1,231 @@
+
+
+
+
+
diff --git a/scratch-prg-extensions/extensions/src/arduino_modulino/index.test.ts b/scratch-prg-extensions/extensions/src/arduino_modulino/index.test.ts
new file mode 100644
index 0000000..fccb213
--- /dev/null
+++ b/scratch-prg-extensions/extensions/src/arduino_modulino/index.test.ts
@@ -0,0 +1,7 @@
+import { createTestSuite } from "$testing";
+import Extension from ".";
+
+createTestSuite({ Extension, __dirname }, {
+ unitTests: undefined,
+ integrationTests: undefined,
+});
diff --git a/scratch-prg-extensions/extensions/src/arduino_modulino/index.ts b/scratch-prg-extensions/extensions/src/arduino_modulino/index.ts
new file mode 100644
index 0000000..8dc8d69
--- /dev/null
+++ b/scratch-prg-extensions/extensions/src/arduino_modulino/index.ts
@@ -0,0 +1,75 @@
+import {
+ type BlockUtilityWithID,
+ type Environment,
+ extension,
+ type ExtensionMenuDisplayDetails,
+ scratch,
+} from "$common";
+import { io, type Socket } from "socket.io-client";
+import ButtonArgument from "./ButtonArgument.svelte";
+
+// Get Arduino board IP or hostname from URL parameter
+const getArduinoBoardHost = () => {
+ const urlParams = new URLSearchParams(window.location.search);
+ const boardHost = urlParams.get("host");
+ if (boardHost) {
+ return boardHost;
+ }
+ return window.location.hostname;
+};
+
+export default class ModulinoButtons extends extension({
+ name: "Modulino",
+ description: "Control your Arduino Modulinos",
+ iconURL: "modulinos.png", // png
+ insetIconURL: "modulino-buttons.svg", // svg
+ tags: ["Arduino UNO Q"],
+ blockColor: "#00878F",
+ menuColor: "#8C7965",
+ menuSelectColor: "#62AEB2",
+}, "customArguments") {
+ private socket: Socket | null = null;
+ private button_pressed: string = "";
+
+ init(env: Environment) {
+ const arduinoBoardHost = getArduinoBoardHost();
+ var serverURL = `wss://${arduinoBoardHost}:7000`;
+
+ this.socket = io(serverURL, {
+ path: "/socket.io",
+ transports: ["polling", "websocket"],
+ autoConnect: true,
+ });
+
+ this.socket.on("connect", () => {
+ console.log(`Connected to Arduino UNO Q`, serverURL);
+ });
+
+ this.socket.on("disconnect", (reason) => {
+ console.log(`Disconnected from Arduino UNO Q: ${reason}`);
+ });
+
+ this.socket.on("modulino_buttons_pressed", (data) => {
+ console.log(`Modulino button pressed event received: ${data.btn}`);
+ this.button_pressed = data.btn.toUpperCase();
+ });
+ }
+
+ @scratch.hat(function(instance, tag) {
+ const arg = instance.makeCustomArgument({
+ component: ButtonArgument,
+ initial: {
+ value: "A",
+ text: "A",
+ },
+ });
+ return tag`When modulino button ${arg} pressed`;
+ })
+ whenModulinoButtonsPressed(button: string, util: BlockUtilityWithID) {
+ if (button.toUpperCase() === this.button_pressed) {
+ this.button_pressed = "";
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/scratch-prg-extensions/extensions/src/arduino_modulino/modulino-buttons.svg b/scratch-prg-extensions/extensions/src/arduino_modulino/modulino-buttons.svg
new file mode 100644
index 0000000..7b8cb18
--- /dev/null
+++ b/scratch-prg-extensions/extensions/src/arduino_modulino/modulino-buttons.svg
@@ -0,0 +1,1340 @@
+
+
+
+
diff --git a/scratch-prg-extensions/extensions/src/arduino_modulino/modulinos.png b/scratch-prg-extensions/extensions/src/arduino_modulino/modulinos.png
new file mode 100644
index 0000000..b317723
Binary files /dev/null and b/scratch-prg-extensions/extensions/src/arduino_modulino/modulinos.png differ
diff --git a/scratch-prg-extensions/extensions/src/arduino_modulino/package.json b/scratch-prg-extensions/extensions/src/arduino_modulino/package.json
new file mode 100644
index 0000000..1ff6031
--- /dev/null
+++ b/scratch-prg-extensions/extensions/src/arduino_modulino/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "arduino_modulino-extension",
+ "version": "1.0.0",
+ "description": "An extension created using the PRG AI Blocks framework",
+ "main": "index.ts",
+ "scripts": {
+ "directory": "echo arduino_modulino",
+ "test": "pnpm --filter prg-extension-root test arduino_modulino/index.test.ts",
+ "dev": "pnpm --filter prg-extension-root dev --include arduino_modulino",
+ "add:ui": "pnpm --filter prg-extension-root add:ui arduino_modulino",
+ "add:arg": "pnpm --filter prg-extension-root add:arg arduino_modulino"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "socket.io-client": "^4.8.1"
+ }
+}
diff --git a/scratch-prg-extensions/extensions/src/arduino_modulino/pnpm-lock.yaml b/scratch-prg-extensions/extensions/src/arduino_modulino/pnpm-lock.yaml
new file mode 100644
index 0000000..649d689
--- /dev/null
+++ b/scratch-prg-extensions/extensions/src/arduino_modulino/pnpm-lock.yaml
@@ -0,0 +1,122 @@
+lockfileVersion: "9.0"
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+ .:
+ dependencies:
+ socket.io-client:
+ specifier: ^4.8.1
+ version: 4.8.1
+
+packages:
+ "@socket.io/component-emitter@3.1.2":
+ resolution: {
+ integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==,
+ }
+
+ debug@4.3.7:
+ resolution: {
+ integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==,
+ }
+ engines: { node: ">=6.0" }
+ peerDependencies:
+ supports-color: "*"
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ engine.io-client@6.6.3:
+ resolution: {
+ integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==,
+ }
+
+ engine.io-parser@5.2.3:
+ resolution: {
+ integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==,
+ }
+ engines: { node: ">=10.0.0" }
+
+ ms@2.1.3:
+ resolution: {
+ integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==,
+ }
+
+ socket.io-client@4.8.1:
+ resolution: {
+ integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==,
+ }
+ engines: { node: ">=10.0.0" }
+
+ socket.io-parser@4.2.4:
+ resolution: {
+ integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==,
+ }
+ engines: { node: ">=10.0.0" }
+
+ ws@8.17.1:
+ resolution: {
+ integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==,
+ }
+ engines: { node: ">=10.0.0" }
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: ">=5.0.2"
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ xmlhttprequest-ssl@2.1.2:
+ resolution: {
+ integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==,
+ }
+ engines: { node: ">=0.4.0" }
+
+snapshots:
+ "@socket.io/component-emitter@3.1.2": {}
+
+ debug@4.3.7:
+ dependencies:
+ ms: 2.1.3
+
+ engine.io-client@6.6.3:
+ dependencies:
+ "@socket.io/component-emitter": 3.1.2
+ debug: 4.3.7
+ engine.io-parser: 5.2.3
+ ws: 8.17.1
+ xmlhttprequest-ssl: 2.1.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ engine.io-parser@5.2.3: {}
+
+ ms@2.1.3: {}
+
+ socket.io-client@4.8.1:
+ dependencies:
+ "@socket.io/component-emitter": 3.1.2
+ debug: 4.3.7
+ engine.io-client: 6.6.3
+ socket.io-parser: 4.2.4
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ socket.io-parser@4.2.4:
+ dependencies:
+ "@socket.io/component-emitter": 3.1.2
+ debug: 4.3.7
+ transitivePeerDependencies:
+ - supports-color
+
+ ws@8.17.1: {}
+
+ xmlhttprequest-ssl@2.1.2: {}