feat(uno-q): ship the arduino-uno-q expert skill on every node by default
Vendors the comprehensive UNO Q skill (SKILL.md + 7 references/*.md) and installs it into EVERY agent's workspace on each board, so agents know this board's specifics (dual-brain arch, Bridge/RPC, pin tables, LED matrix + the ArduinoGraphics-not-installed gotcha) instead of guessing generic Arduino. Why per-agent workspace: ZeroClaw's read_skill returns only SKILL.md; the agent reads references/*.md via the workspace-sandboxed file_read tool, so references are only reachable under ~/.zeroclaw/agents/<alias>/workspace/skills/. A shared/skills bundle surfaces the skill but its references get sandbox-blocked. - push-skill.sh installs a SKILL.md+references skill into every agent workspace (discovers aliases from the board); provision-fleet runs it per board. - config.template risk profile now allows + auto-approves read_skill + file_read so agents load skills without a human approver (webhook path is non-interactive). - Flattened the folded 'description: >-' to single-line (ZeroClaw's frontmatter parser is a flat scanner, not full YAML). Verified on board 65301572 with cloud/Sonnet-5: discovered arduino-uno-q → read_skill(SKILL.md) → file_read references/04-bridge-rpc.md → correct board-specific answer citing the file. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7233a4b1c0
commit
d2135a1938
@@ -0,0 +1,74 @@
|
||||
# UNO Q — Workshop Playbook
|
||||
|
||||
Practical guidance for running a hands-on session with the board. Assumes the reader already understands the two-processor model (see SKILL.md).
|
||||
|
||||
## Pre-flight checklist (per station)
|
||||
- [ ] Board + a **known-good USB-C cable** rated for **5 V / 3 A** (or a multiport dongle with external PD — **not Apple's**, it's incompatible).
|
||||
- [ ] For SBC stations: HDMI monitor, USB keyboard/mouse via dongle, power to the dongle.
|
||||
- [ ] Decide the mode up front: **SBC** (self-contained, needs 4 GB variant recommended) vs **Network Mode** (students drive it from their laptops).
|
||||
- [ ] Each board: set a **board name** (becomes `<name>.local`), a password, and Wi-Fi during first-run. SSH turns on automatically after this.
|
||||
- [ ] If any facilitator laptop runs **Linux**, install the **udev rules** first (see setup reference) — otherwise App Lab connects silently to nothing.
|
||||
- [ ] Network allows **mDNS / UDP 5353** (needed for Network Mode discovery). On locked-down campus Wi-Fi this is the usual blocker.
|
||||
- [ ] For enterprise/eduroam Wi-Fi, pre-stage the `nmcli` 802.1X command (see wireless reference).
|
||||
|
||||
## Common failure modes → fixes
|
||||
| Symptom | Likely cause | Fix |
|
||||
|---|---|---|
|
||||
| App Lab shows no board (Linux PC, USB) | Missing udev rules | Install rules, reconnect board, restart App Lab |
|
||||
| Board absent in Network Mode | mDNS blocked | Open UDP 5353; approve `mdns-discovery.exe` on Windows; confirm same subnet |
|
||||
| Flash/upload "permission denied" (Linux) | udev not applied | Re-run rules, `udevadm control --reload-rules && udevadm trigger`, replug |
|
||||
| Python can't reach the sketch | router down / wrong function name | `systemctl status arduino-router`; check the `provide()` name matches the `call()` string; verbose logs |
|
||||
| Handler crashes / hangs | Arduino API called from `provide()` (RPC thread) | Use `provide_safe()`; never `Serial.print`/`Bridge.call` inside a handler |
|
||||
| Nothing on a pin | wrong logic level or wrong processor | MCU I/O is 3.3 V; onboard RGB LEDs are active-low; confirm the sketch (not Python) owns the pin |
|
||||
| `Serial1` acting weird | confusing header UART with router link | `Serial1` on D0/D1 is fine for external UART; never open the internal reserved transport / `/dev/ttyHS1` |
|
||||
| Can't SSH | no IP / SSH not set up | `ip addr show` (wlan0) on the board; SSH is enabled once first-run setup completes |
|
||||
|
||||
## The canonical teaching example: "Python button decides, Arduino acts"
|
||||
This one App ties the entire board together and is the best first exercise because it forces students to touch **both** processors and the **Bridge**.
|
||||
|
||||
**Concept:** the sketch owns an LED (a physical pin); Python owns the *logic* and calls across the Bridge to actuate it. Swap the LED for a relay/motor driver and you have real device control; swap the Python timer for a camera/AI Brick and you have an intelligent actuator.
|
||||
|
||||
**MCU sketch (`sketch.ino`):**
|
||||
```cpp
|
||||
#include "Arduino_RouterBridge.h"
|
||||
void setup() {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
Bridge.begin();
|
||||
Bridge.provide_safe("set_led_state", set_led_state);
|
||||
}
|
||||
void loop() {}
|
||||
void set_led_state(bool state) {
|
||||
digitalWrite(LED_BUILTIN, state ? LOW : HIGH); // built-in LED active-low
|
||||
}
|
||||
```
|
||||
|
||||
**Linux Python (`main.py`):**
|
||||
```python
|
||||
from arduino.app_utils import *
|
||||
import time
|
||||
state = False
|
||||
def loop():
|
||||
global state
|
||||
time.sleep(1)
|
||||
state = not state
|
||||
Bridge.call("set_led_state", state)
|
||||
App.run(user_loop=loop)
|
||||
```
|
||||
|
||||
**Teaching beats:**
|
||||
1. Run it → LED blinks, but emphasize *the decision happened in Python on Linux, the action happened on the MCU.*
|
||||
2. Break it on purpose: rename `"set_led_state"` on one side → show the router log error → fix. Cements the RPC contract idea.
|
||||
3. Extend: have Python read something real (time of day, a web request, a camera Brick) and gate the LED on it.
|
||||
4. Reverse it: MCU reads a real sensor and `Bridge.call()`s a Python function that logs/uploads it.
|
||||
|
||||
## Progression for a full session
|
||||
1. **Blink** (App Lab example) — proves the MCU toolchain.
|
||||
2. **Read a sensor in a sketch**, print with `Serial` → App Lab console — proves I/O + debugging.
|
||||
3. **Bridge example above** — proves Linux↔MCU.
|
||||
4. **Add a Brick** (vision/audio) on the Python side — shows the payoff of the Linux half.
|
||||
5. **Deploy:** set the App to **Run at startup** and unplug the keyboard → it's now an appliance. Manage it over **SSH** + `arduino-app-cli`.
|
||||
|
||||
## Deploying student projects headlessly
|
||||
- Copy the App to the board: `scp -r * arduino@<IP>:~/ArduinoApps/<name>`.
|
||||
- Start/stop/log via `arduino-app-cli app start|stop|logs ~/ArduinoApps/<name>`.
|
||||
- Autostart the finished one: `arduino-app-cli properties set default user:<name>`.
|
||||
Reference in New Issue
Block a user