-
Notifications
You must be signed in to change notification settings - Fork 9
docs: add App specification #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
6ac221d
72a7e10
ac95a4d
2bc7f89
e9f058c
d762618
ff1ce52
6d99d10
e2c36ef
fdb56a7
45a54ba
ccf610a
65cc7c2
c8d001e
9aae752
4cb1699
0276dfa
7a8a45b
c4bf603
329f870
05699d7
d613f21
5b0b2d2
7de63cc
be1522c
7a9e5af
2634acf
7f13d17
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,195 @@ | ||||||||||||
| # Arduino App specification | ||||||||||||
|
|
||||||||||||
| This is the specification for the Arduino App format to be used with `arduino-app-cli` and `Arduino App Lab`. | ||||||||||||
|
|
||||||||||||
| Arduino Apps are designed to run on `dual-brain` Arduino Boards (e.g., [Arduino Uno Q](https://store.arduino.cc/pages/uno-q)). | ||||||||||||
| An Arduino App leverages the board's operating system and the integrated microcontroller to perform a wide range of tasks, from high-level logic, data processing, executing AI models and more. | ||||||||||||
|
|
||||||||||||
| An Arduino App is composed of two main software components that work together as a single application: | ||||||||||||
|
|
||||||||||||
| - [**Arduino Sketch**](https://docs.arduino.cc/arduino-cli/sketch-specification/). It runs on the integrated Microcontroller (MCU). It is responsible for low-level hardware interaction, sensors, and actuators. | ||||||||||||
| - **Python and containers**. They run on the board's Linux OS. | ||||||||||||
|
|
||||||||||||
| The Sketch and the Python communicate using an RPC-based messaging (see [arduino-router](https://github.com/arduino/arduino-router)). | ||||||||||||
|
|
||||||||||||
| An App can be extended through **Bricks**: modular software components that add ready-to-use functionality (e.g. databases, computer vision services). An App may include multiple Bricks. | ||||||||||||
|
|
||||||||||||
| ## Arduino App folders and files | ||||||||||||
|
|
||||||||||||
| An Arduino App is a self-contained folder that includes a descriptor file (app.yaml), other sub-folders and files. | ||||||||||||
|
|
||||||||||||
| ### Arduino App root folder | ||||||||||||
|
|
||||||||||||
| The root folder containing the Arduino App files and subfolders. | ||||||||||||
|
|
||||||||||||
| #### `app.yaml` file | ||||||||||||
|
|
||||||||||||
| The `app.yaml` file contains the metadata of the App. It is mandatory and must be located in the root folder. | ||||||||||||
| See the [App Descriptor (`app.yaml`)](#app-descriptor-appyaml) section for details. | ||||||||||||
|
|
||||||||||||
| #### `python` subfolder | ||||||||||||
|
|
||||||||||||
| Contains the python code of the App. | ||||||||||||
|
|
||||||||||||
| - **Status**: Mandatory. | ||||||||||||
| - **Required File**: `main.py` (The entry point of the application). | ||||||||||||
| - **Optional File**: `requirements.txt` (Standard Python dependency list). | ||||||||||||
| - **Constraint**: must be located specifically in the `root-app-folder/` path. | ||||||||||||
|
|
||||||||||||
| #### `sketch` subfolder | ||||||||||||
|
|
||||||||||||
| Contains the Arduino sketch to be flashed on the integrated microcontroller. | ||||||||||||
|
|
||||||||||||
| - **Status**: Optional, Reserved. | ||||||||||||
| - **Required Files**: If present, must include both `sketch.ino` and `sketch.yaml`. | ||||||||||||
| - **Constraint**: The folder content must comply with the official [Sketch specification](https://arduino.github.io/arduino-cli/1.3/sketch-specification/). | ||||||||||||
|
|
||||||||||||
| #### `README.md` file | ||||||||||||
|
|
||||||||||||
| A markdown file located in the root folder. | ||||||||||||
|
|
||||||||||||
| - **Status**: Optional. | ||||||||||||
| - **Arduino App Lab** renders this file to provide documentation to the user. | ||||||||||||
| - **Constraint**: If the `description` field in `app.yaml` is absent or empty, the system derives the app description from `README.md` by parsing the first non-title paragraph and stripping all markdown syntax. | ||||||||||||
|
|
||||||||||||
| #### Reserved Folders | ||||||||||||
|
|
||||||||||||
| The following folders are reserved for specific uses: | ||||||||||||
|
|
||||||||||||
| ##### `data` subfolder | ||||||||||||
|
|
||||||||||||
| - **Status**: Optional. | ||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could put: |
||||||||||||
| - **Constraints**: | ||||||||||||
| - It contains volumes and other data generated by the App and its dependencies (e.g., database storage). | ||||||||||||
| - The content is accessible to the user to allow backups or deletion to reset the App state. | ||||||||||||
| - This folder should be emptied before sharing the App to avoid leaking personal data. | ||||||||||||
| - Located in `root-app-folder/`. | ||||||||||||
|
|
||||||||||||
| ##### `.cache` subfolder | ||||||||||||
|
|
||||||||||||
| - **Status**: Optional. | ||||||||||||
| - **Constraints**: | ||||||||||||
| - It contains volatile data needed to run the App (e.g., the Python `venv` folder or Docker Compose support files). | ||||||||||||
| - The content is transient and might change in the future. | ||||||||||||
| - It can be safely deleted at any time when the App is not running. | ||||||||||||
| - Located in `root-app-folder/`. | ||||||||||||
|
|
||||||||||||
| #### Extra files/folders | ||||||||||||
|
|
||||||||||||
| **Extra Files**: Any other file or folder is allowed. The runtime preserves these files and makes them accessible to your Python logic, but performs no automated action on them. They are bundled with the App during Import and Export operations. | ||||||||||||
|
|
||||||||||||
| ### A complete example | ||||||||||||
|
|
||||||||||||
| A hypothetical App named "SmartGarden" that adheres to the specification follows. Note that the root folder name (my-garden-project) differs from the App name defined in YAML. | ||||||||||||
|
|
||||||||||||
| ``` | ||||||||||||
| my-garden-project/ | ||||||||||||
| ├── app.yaml # Mandatory metadata (strict naming) | ||||||||||||
| ├── README.md # Documentation (Optional) | ||||||||||||
| ├── python/ # Mandatory source folder | ||||||||||||
| │ ├── main.py # Mandatory entry point | ||||||||||||
| │ └── requirements.txt # Python dependencies (Optional) | ||||||||||||
| ├── sketch/ # Arduino sketch folder (Optional) | ||||||||||||
| │ ├── sketch.yaml # Arduino sketch dependency | ||||||||||||
| │ └── sketch.ino # Arduino sketch | ||||||||||||
| ├── .cache/ # Reserved | ||||||||||||
| └── data/ # Reserved | ||||||||||||
| ``` | ||||||||||||
|
|
||||||||||||
| ## App Descriptor (`app.yaml`) | ||||||||||||
|
|
||||||||||||
| The `app.yaml` file (also referred to as the **App Descriptor**) is the manifest of the Arduino App. It allows the host system to identify, configure, and orchestrate the App and its dependencies. | ||||||||||||
|
|
||||||||||||
| ### File Format | ||||||||||||
|
|
||||||||||||
| - **Filename**: must be exactly `app.yaml`(not `.yml`). | ||||||||||||
| - **Location**: Root of the App folder. | ||||||||||||
| - **Syntax**: Standard YAML. | ||||||||||||
|
|
||||||||||||
| ### Configuration Fields | ||||||||||||
|
|
||||||||||||
| - **`name`** (Optional): Human-readable name. | ||||||||||||
| - Constraints: alphanumeric, underscores, dashes, and spaces. Cannot start with a dash. | ||||||||||||
|
|
||||||||||||
| - **`icon`** (Optional): A single emoji character used in the App Lab UI. | ||||||||||||
| - **`description`** (Optional): A short summary of the app's purpose. If omitted, it is retrieved from the first paragraph of README.md (see the README.md file paragraph for details). | ||||||||||||
| - **`ports`** (Optional): A list of integers representing the network ports exposed by the Python logic (e.g., for a web dashboard). | ||||||||||||
| - **`bricks`** (Optional): A list of Brick Object. Additional bricks needed by the app to perform specific tasks (see the next section for details). | ||||||||||||
|
|
||||||||||||
| ### Brick Object Definition | ||||||||||||
|
|
||||||||||||
| Bricks are Python-first modular dependencies that encapsulate both application logic and infrastructure configurations (such as Docker Compose files) to extend an App's capabilities. | ||||||||||||
| While the App folder holds the application logic and local resources, the App may depend on Bricks. These dependencies are declared in the App's description, but the Bricks themselves are not stored inside the App folder. They are downloaded and managed externally by the host system. | ||||||||||||
|
|
||||||||||||
| This section describes the structure of a single item within the bricks list in `app.yaml`. | ||||||||||||
|
|
||||||||||||
| - **`id`** (Mandatory): The unique identifier string of the Brick (e.g., web_ui, image_classification). | ||||||||||||
| - TODO: Update the spec after custom bricks validation rules are defined. | ||||||||||||
| - **`model`** (Optional): The model id to load within the Brick. | ||||||||||||
| - **`variables`** (Optional): A map of key-value pairs (both must be strings) representing configuration parameters or environment variables passed to the Brick container. | ||||||||||||
| - **`ports`** (Optional): A list of integers representing the network ports that the Brick must expose to interact with the User(e.g., exposing web interfaces). | ||||||||||||
| - Default Behavior: If ports are not explicitly defined in the app.yaml file, the system automatically uses the default ports specified in the Brick's metadata (if any). | ||||||||||||
| - Collision: If two or more Bricks attempt to use the same port, a network collision occurs. This conflict will prevent one of the Bricks from starting, potentially causing the application to fail or remain in a partial state. | ||||||||||||
| - **`required_devices`** (Optional): A list of "class" of devices, required by the app (e.g., `camera`, `remote_camera`, `microphone`, `remote_microphone`). | ||||||||||||
|
|
||||||||||||
| #### Handling Secrets in Variables | ||||||||||||
|
|
||||||||||||
| The `app.yaml` supports the use of **Secrets** within the Brick `variables` map to handle sensitive information, such as database passwords. | ||||||||||||
|
|
||||||||||||
|
Comment on lines
+137
to
+138
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how to define a secret variable ? we could give example
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this struct just for the brick-list?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what do you think?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, to make it clear that the "secret" variable is defined in the brick definition. Based on this indo, the variable defined in the app-yaml is redacted
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I opened a PR to remove the |
||||||||||||
| - **Automatic Redaction**: When an App is **exported**, the values of these secrets are automatically **redacted**. This ensures that the App bundle can be safely shared without leaking personal credentials or private keys. | ||||||||||||
|
|
||||||||||||
| ### Example `app.yaml` | ||||||||||||
|
|
||||||||||||
| ```yaml | ||||||||||||
| name: Smart-Garden-Pro | ||||||||||||
| description: AI-powered irrigation and monitoring system | ||||||||||||
| icon: 🌿 | ||||||||||||
| ports: | ||||||||||||
| - 5000 | ||||||||||||
|
|
||||||||||||
| bricks: | ||||||||||||
| - id: arduino/dbstorage | ||||||||||||
| variables: | ||||||||||||
| PASSWORD: password | ||||||||||||
| ports: "8080" | ||||||||||||
|
Comment on lines
+152
to
+154
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not true, secret is a boolen field
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. from tests:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, it is misleading to have an example with the name of the variable equal to "secret" that is also the field used in the brick definition to mark the variable secret. I would use a more variable name like "MY_ROOT_PASSWORD" and also show the snippet of the bricks that define the variable as secret |
||||||||||||
| - id: arduino/objectdetection | ||||||||||||
| model: yolo-v8 | ||||||||||||
| ports: | ||||||||||||
| - 8001 | ||||||||||||
| ``` | ||||||||||||
|
|
||||||||||||
| ## Broken App Definition | ||||||||||||
|
|
||||||||||||
| A **Broken App** is a directory that the system has successfully identified as an Arduino App but which fails to meet the operational requirements. Unlike a generic folder, a Broken App is an entity recognized by the `arduino-app-cli` and `Arduino App Lab`, but it is flagged as non-functional. | ||||||||||||
|
|
||||||||||||
| ### The Primary Identifier | ||||||||||||
|
|
||||||||||||
| The presence of the `app.yaml` file is the **sole requirement** for a directory to be promoted from a "generic folder" to an "Arduino App" entity. | ||||||||||||
|
|
||||||||||||
| - If `app.yaml` is present: The system must attempt to parse it and register the App. | ||||||||||||
| - If `app.yaml` is missing: The directory is ignored and must not be treated as an App. | ||||||||||||
|
|
||||||||||||
| ### Broken State Criteria | ||||||||||||
|
|
||||||||||||
| An Arduino App entity is classified as **Broken** if it falls into one of the following categories: | ||||||||||||
|
|
||||||||||||
| - **Invalid Descriptor**: The `app.yaml` file exists but contains syntax errors (invalid YAML) or violates the schema constraints (e.g., invalid characters in the `name` field). | ||||||||||||
| - **Structural Incompleteness**: The App lacks the mandatory internal components defined in the Project Structure: | ||||||||||||
| - Missing `python/` directory. | ||||||||||||
| - Missing `python/main.py` file. | ||||||||||||
|
|
||||||||||||
| - **Incomplete Sketch folder**: The `sketch/` folder exists, but it is missing the mandatory `sketch.ino` or `sketch.yaml` files. | ||||||||||||
|
|
||||||||||||
| ### System Behavior for Broken Apps | ||||||||||||
|
|
||||||||||||
| The existence of a Broken App entity allows the system to provide feedback rather than silent failure: | ||||||||||||
|
|
||||||||||||
| - **Discovery**: The `arduino-app-cli` must include Broken Apps in its list, clearly marking their status. | ||||||||||||
|
|
||||||||||||
| ### Static Validation vs. Runtime Errors | ||||||||||||
|
|
||||||||||||
| The classification of an App (as Valid or Broken) is determined solely through **Static Validation**. This process checks the presence and organization of files and the integrity of the `app.yaml` descriptor. | ||||||||||||
|
|
||||||||||||
| - **Scope of Static Validation**: The system only verifies that the required folders and files exist and that the manifest is readable. | ||||||||||||
| - **Exclusion of Execution Errors**: Static validation **does not** include code analysis. For example, a `main.py` file that contains Python syntax errors, or a `sketch.ino` that fails to compile due to logic errors, will **not** cause the App to be flagged as "Broken" during the discovery phase. | ||||||||||||
| - **Failure Mode**: Such issues will only emerge during the **Orchestration & Deployment** phase (Runtime), at which point the system will report an execution or compilation failure. | ||||||||||||
Uh oh!
There was an error while loading. Please reload this page.