nff 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nff-0.2.2 → nff-0.2.4}/PKG-INFO +1 -1
- {nff-0.2.2 → nff-0.2.4}/nff/commands/flash.py +1 -1
- {nff-0.2.2 → nff-0.2.4}/nff/commands/init.py +35 -1
- nff-0.2.4/nff/skills/nff.md +213 -0
- nff-0.2.4/nff/skills/wokwi-diagram.md +213 -0
- {nff-0.2.2 → nff-0.2.4}/nff/tools/toolchain.py +1 -0
- {nff-0.2.2 → nff-0.2.4}/nff.egg-info/PKG-INFO +1 -1
- {nff-0.2.2 → nff-0.2.4}/nff.egg-info/SOURCES.txt +2 -0
- {nff-0.2.2 → nff-0.2.4}/pyproject.toml +4 -1
- {nff-0.2.2 → nff-0.2.4}/LICENSE +0 -0
- {nff-0.2.2 → nff-0.2.4}/README.md +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/__init__.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/cli.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/commands/__init__.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/commands/clean.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/commands/doctor.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/commands/monitor.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/commands/wokwi.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/config.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/mcp_server.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/tools/__init__.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/tools/boards.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/tools/installer.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/tools/serial.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/tools/wokwi.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff/tools/wokwi_installer.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff.egg-info/dependency_links.txt +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff.egg-info/entry_points.txt +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff.egg-info/requires.txt +0 -0
- {nff-0.2.2 → nff-0.2.4}/nff.egg-info/top_level.txt +0 -0
- {nff-0.2.2 → nff-0.2.4}/setup.cfg +0 -0
- {nff-0.2.2 → nff-0.2.4}/tests/test_boards.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/tests/test_config.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/tests/test_doctor.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/tests/test_mcp.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/tests/test_serial.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/tests/test_toolchain.py +0 -0
- {nff-0.2.2 → nff-0.2.4}/tests/test_wokwi.py +0 -0
{nff-0.2.2 → nff-0.2.4}/PKG-INFO
RENAMED
|
@@ -13,6 +13,7 @@ if __name__ == "__main__":
|
|
|
13
13
|
import json
|
|
14
14
|
import shutil
|
|
15
15
|
import subprocess
|
|
16
|
+
from importlib import resources
|
|
16
17
|
from pathlib import Path
|
|
17
18
|
|
|
18
19
|
import click
|
|
@@ -97,7 +98,7 @@ def _register_mcp_claude_code() -> bool:
|
|
|
97
98
|
|
|
98
99
|
try:
|
|
99
100
|
result = subprocess.run(
|
|
100
|
-
["claude", "mcp", "add", "nff", nff_exe, "mcp"],
|
|
101
|
+
["claude", "mcp", "add", "--scope", "user", "nff", nff_exe, "mcp"],
|
|
101
102
|
capture_output=True,
|
|
102
103
|
text=True,
|
|
103
104
|
timeout=15,
|
|
@@ -107,6 +108,33 @@ def _register_mcp_claude_code() -> bool:
|
|
|
107
108
|
return False
|
|
108
109
|
|
|
109
110
|
|
|
111
|
+
def _install_claude_skills() -> None:
|
|
112
|
+
"""Copy bundled skill files to ~/.claude/commands/ (user-level global skills).
|
|
113
|
+
|
|
114
|
+
Silently skips any file that cannot be written so it never aborts init.
|
|
115
|
+
"""
|
|
116
|
+
dest_dir = Path.home() / ".claude" / "commands"
|
|
117
|
+
dest_dir.mkdir(parents=True, exist_ok=True)
|
|
118
|
+
|
|
119
|
+
skills_pkg = resources.files("nff") / "skills"
|
|
120
|
+
installed: list[str] = []
|
|
121
|
+
for skill_file in skills_pkg.iterdir():
|
|
122
|
+
if not skill_file.name.endswith(".md"):
|
|
123
|
+
continue
|
|
124
|
+
try:
|
|
125
|
+
dest = dest_dir / skill_file.name
|
|
126
|
+
dest.write_text(skill_file.read_text(encoding="utf-8"), encoding="utf-8")
|
|
127
|
+
installed.append(skill_file.name)
|
|
128
|
+
except OSError:
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
if installed:
|
|
132
|
+
names = ", ".join(f"/{p.removesuffix('.md')}" for p in installed)
|
|
133
|
+
console.print(
|
|
134
|
+
f" [bold green]✓[/bold green] Claude skills installed: [bold]{names}[/bold]"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
110
138
|
def _update_claude_desktop_config() -> None:
|
|
111
139
|
"""Merge the nff MCP entry into ~/.claude/claude_desktop_config.json.
|
|
112
140
|
|
|
@@ -379,6 +407,12 @@ def _write_success(port: str, board: str, device: DetectedDevice | None) -> None
|
|
|
379
407
|
except OSError as exc:
|
|
380
408
|
console.print(f" [yellow]⚠[/yellow] Could not write CLAUDE.md: {exc}")
|
|
381
409
|
|
|
410
|
+
# Install Claude skills globally
|
|
411
|
+
try:
|
|
412
|
+
_install_claude_skills()
|
|
413
|
+
except Exception as exc:
|
|
414
|
+
console.print(f" [yellow]⚠[/yellow] Could not install Claude skills: {exc}")
|
|
415
|
+
|
|
382
416
|
# Claude Code CLI — preferred
|
|
383
417
|
if _register_mcp_claude_code():
|
|
384
418
|
console.print(
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# nff — IoT CLI Bridge for Claude Code
|
|
2
|
+
|
|
3
|
+
`nff` connects Claude Code to embedded hardware (Arduino, ESP32, ESP8266) via USB or Wokwi simulation.
|
|
4
|
+
Use this skill whenever you need to write, compile, simulate, or flash a sketch.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Core Rules
|
|
9
|
+
|
|
10
|
+
- **Always use `nff flash` to compile/flash** — never call `arduino-cli` directly.
|
|
11
|
+
- **Never install libraries with `arduino-cli lib install`** — write sketches that use built-in APIs only, or ask the user to install the library first.
|
|
12
|
+
- For ESP32 servo control use `ledcAttach` / `ledcWrite` (built-in LEDC, no library needed).
|
|
13
|
+
- The working directory for all `nff` commands is the project root (where `wokwi.toml` lives).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Prerequisites Check
|
|
18
|
+
|
|
19
|
+
Before any pipeline, run:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
nff doctor
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This verifies: arduino-cli, wokwi-cli, Wokwi token, connected device.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Full Simulation Pipeline (no hardware)
|
|
30
|
+
|
|
31
|
+
### Step 1 — Write the sketch
|
|
32
|
+
|
|
33
|
+
Place it in `sketches/<name>/<name>.ino`. The folder name must match the `.ino` filename (arduino-cli requirement).
|
|
34
|
+
|
|
35
|
+
### Step 2 — Initialize Wokwi project (first time only)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
nff wokwi init --board <fqbn>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Creates `wokwi.toml` and a minimal `diagram.json` in the project root.
|
|
42
|
+
To add components (LEDs, buttons, servos, sensors), edit `diagram.json` directly.
|
|
43
|
+
|
|
44
|
+
**Common FQBNs:**
|
|
45
|
+
| Board | FQBN |
|
|
46
|
+
|---|---|
|
|
47
|
+
| ESP32 DevKit V1 | `esp32:esp32:esp32` |
|
|
48
|
+
| Arduino Uno | `arduino:avr:uno` |
|
|
49
|
+
| Arduino Nano | `arduino:avr:nano` |
|
|
50
|
+
| ESP8266 | `esp8266:esp8266:generic` |
|
|
51
|
+
|
|
52
|
+
### Step 3 — Compile (flash to simulator)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
nff flash --sim sketches/<name> --board <fqbn>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This compiles the sketch and writes the ELF to:
|
|
59
|
+
`sketches/<name>/build/<fqbn_dotted>/<name>.elf/<name>.ino.elf`
|
|
60
|
+
|
|
61
|
+
The headless simulation will time out (expected — there's no button to click). What matters is that compilation succeeds.
|
|
62
|
+
|
|
63
|
+
### Step 4 — Update `wokwi.toml`
|
|
64
|
+
|
|
65
|
+
Make sure `wokwi.toml` points to the compiled ELF:
|
|
66
|
+
|
|
67
|
+
```toml
|
|
68
|
+
[wokwi]
|
|
69
|
+
version = 1
|
|
70
|
+
firmware = "sketches/<name>/build/<fqbn_dotted>/<name>.elf/<name>.ino.elf"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Where `<fqbn_dotted>` replaces `:` with `.` (e.g. `esp32.esp32.esp32`).
|
|
74
|
+
|
|
75
|
+
### Step 5 — Run visual simulation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
nff wokwi run --gui
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Opens `diagram.json` as a new tab in the existing VS Code window and auto-starts the Wokwi simulator after ~3 s.
|
|
82
|
+
|
|
83
|
+
### Step 6 — Run headless simulation (serial output only)
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
nff wokwi run
|
|
87
|
+
nff wokwi run --timeout 10000 --serial-log output.txt
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## diagram.json — Component Reference
|
|
93
|
+
|
|
94
|
+
Always keep the serial monitor wired:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
["esp:TX0", "$serialMonitor:RX", "", []],
|
|
98
|
+
["esp:RX0", "$serialMonitor:TX", "", []]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**ESP32 pin naming:** `esp:D<gpio>` (e.g. `esp:D18`), `esp:GND.1`, `esp:GND.2`, `esp:3V3`, `esp:VIN`
|
|
102
|
+
|
|
103
|
+
**Common components and their pins — use `/wokwi-diagram` for the full reference:**
|
|
104
|
+
|
|
105
|
+
| Type | Pins |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `wokwi-led` | `A` (anode), `C` (cathode — **not K**) |
|
|
108
|
+
| `wokwi-resistor` | `1`, `2` |
|
|
109
|
+
| `wokwi-pushbutton` | `1.l`, `1.r`, `2.l`, `2.r` |
|
|
110
|
+
| `wokwi-servo` | `PWM`, `V+`, `GND` |
|
|
111
|
+
| `wokwi-ntc-temperature-sensor` | `VCC`, `GND`, `OUT` |
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{ "type": "wokwi-led", "id": "led1", "attrs": { "color": "red" } }
|
|
115
|
+
{ "type": "wokwi-pushbutton", "id": "btn1", "attrs": { "color": "blue" } }
|
|
116
|
+
{ "type": "wokwi-servo", "id": "srv1", "attrs": { "minAngle": "-90", "maxAngle": "90" } }
|
|
117
|
+
{ "type": "wokwi-resistor", "id": "r1", "attrs": { "value": "220" } }
|
|
118
|
+
{ "type": "wokwi-ntc-temperature-sensor", "id": "tmp1", "attrs": {} }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Servo (ESP32 LEDC — no library)
|
|
124
|
+
|
|
125
|
+
Wokwi servo maps its full range to **500 µs – 2500 µs** pulses.
|
|
126
|
+
With 50 Hz / 16-bit LEDC resolution (period = 20 000 µs, max count = 65535):
|
|
127
|
+
|
|
128
|
+
| Angle | Pulse | Duty count |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| min (−90°) | 500 µs | 1638 |
|
|
131
|
+
| center (0°) | 1500 µs | 4915 |
|
|
132
|
+
| max (+90°) | 2500 µs | 8192 |
|
|
133
|
+
|
|
134
|
+
```cpp
|
|
135
|
+
ledcAttach(SERVO_PIN, 50, 16); // attach (ESP32 core 3.x API)
|
|
136
|
+
ledcWrite(SERVO_PIN, 4915); // move to center
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Always declare `minAngle: "-90"` and `maxAngle: "90"` in `diagram.json` for correct visual mapping.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Full Real Hardware Pipeline
|
|
144
|
+
|
|
145
|
+
### Step 1 — Detect device
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
nff init
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Scans USB ports, identifies the board, writes `~/.nff/config.json`.
|
|
152
|
+
|
|
153
|
+
### Step 2 — Compile and flash
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
nff flash sketches/<name>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Uses board and port from config. Override with `--board <fqbn> --port <port>`.
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
nff flash sketches/<name> --board esp32:esp32:esp32 --port COM3
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
If upload fails with "Wrong boot mode detected":
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
nff flash sketches/<name> --manual-reset
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Hold the BOOT button when prompted, release after upload starts.
|
|
172
|
+
|
|
173
|
+
### Step 3 — Monitor serial output
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
nff monitor
|
|
177
|
+
nff monitor --port COM3 --baud 115200
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Ctrl+C to exit.
|
|
181
|
+
|
|
182
|
+
**Baud rate:** always match `--baud` (and the value in `~/.nff/config.json`) to the rate passed to
|
|
183
|
+
`Serial.begin()` in the sketch. Mismatched baud rates cause garbled or silent output and break
|
|
184
|
+
all serial debugging.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Debugging Workflow
|
|
189
|
+
|
|
190
|
+
### Simulation issues
|
|
191
|
+
|
|
192
|
+
1. Compilation error → fix the sketch, re-run `nff flash --sim`
|
|
193
|
+
2. Serial output looks wrong → check `nff wokwi run --serial-log out.txt`, inspect `out.txt`
|
|
194
|
+
3. Component not responding → check `diagram.json` wiring (pin names, connection direction)
|
|
195
|
+
4. Servo wrong angle → verify duty cycle values match the 500–2500 µs Wokwi range
|
|
196
|
+
5. Button not registering → ensure `INPUT_PULLUP` is set and wiring goes `gpio → btn:1.l`, `GND → btn:2.l`
|
|
197
|
+
|
|
198
|
+
### Hardware issues
|
|
199
|
+
|
|
200
|
+
1. Port not found → run `nff init` to re-detect
|
|
201
|
+
2. Upload fails → try `--manual-reset`, check driver (CH340/CP210x)
|
|
202
|
+
3. Wrong output → use `nff monitor` to inspect live serial
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Key File Locations
|
|
207
|
+
|
|
208
|
+
| File | Purpose |
|
|
209
|
+
|---|---|
|
|
210
|
+
| `wokwi.toml` | Points to the compiled ELF for simulation |
|
|
211
|
+
| `diagram.json` | Circuit schematic for Wokwi |
|
|
212
|
+
| `sketches/<name>/<name>.ino` | Arduino sketch source |
|
|
213
|
+
| `~/.nff/config.json` | Default board, port, baud, Wokwi token |
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# wokwi-diagram — Wokwi diagram.json Authoring Reference
|
|
2
|
+
|
|
3
|
+
Use this skill whenever writing or editing a Wokwi `diagram.json` schematic.
|
|
4
|
+
It is the ground-truth pin reference for all Wokwi components.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## diagram.json Structure
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"version": 1,
|
|
13
|
+
"author": "nff",
|
|
14
|
+
"editor": "wokwi",
|
|
15
|
+
"parts": [ ... ],
|
|
16
|
+
"connections": [ ... ]
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Each connection: `["partId:pin", "partId:pin", "color", [waypoints]]`
|
|
21
|
+
- `color`: any CSS color string, or `""` for default
|
|
22
|
+
- `waypoints`: `[]` for auto-route, or relative offsets like `["h30", "v-20"]`
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Serial Monitor (always wire this for ESP32/Arduino)
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
["esp:TX0", "$serialMonitor:RX", "", []],
|
|
30
|
+
["esp:RX0", "$serialMonitor:TX", "", []]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## MCU Pin Reference
|
|
36
|
+
|
|
37
|
+
### wokwi-esp32-devkit-v1
|
|
38
|
+
|
|
39
|
+
| Pin group | Names |
|
|
40
|
+
|---|---|
|
|
41
|
+
| GPIO | `D0` `D1` `D2` `D4` `D5` `D12`–`D19` `D21`–`D23` `D25`–`D27` `D32`–`D35` |
|
|
42
|
+
| UART | `TX` (GPIO1), `RX` (GPIO3) |
|
|
43
|
+
| Analog-only | `VP` (GPIO36), `VN` (GPIO39), `D34`, `D35` |
|
|
44
|
+
| Power | `3V3`, `VIN`, `GND.1` (left-column GND), `GND.2` (right-column GND) |
|
|
45
|
+
| Other | `EN` |
|
|
46
|
+
|
|
47
|
+
> Use `GND.1` for most circuits — it is the left-column GND between D12 and D13.
|
|
48
|
+
|
|
49
|
+
### wokwi-arduino-uno
|
|
50
|
+
|
|
51
|
+
| Pin group | Names |
|
|
52
|
+
|---|---|
|
|
53
|
+
| Digital | `D0`–`D13` |
|
|
54
|
+
| Analog | `A0`–`A5` |
|
|
55
|
+
| Power | `5V`, `3V3`, `GND.1`, `GND.2` |
|
|
56
|
+
| Other | `AREF`, `IOREF`, `RESET` |
|
|
57
|
+
|
|
58
|
+
### wokwi-arduino-nano
|
|
59
|
+
|
|
60
|
+
Same as Uno plus `AREF`. Power: `5V`, `3V3`, `GND.1`, `GND.2`.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Component Pin Reference
|
|
65
|
+
|
|
66
|
+
### wokwi-led
|
|
67
|
+
|
|
68
|
+
| Pin | Role |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `A` | Anode (positive, connect toward GPIO via resistor) |
|
|
71
|
+
| `C` | Cathode (negative, connect to GND) — **NOT `K`** |
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{ "type": "wokwi-led", "id": "led1", "top": 100, "left": 200, "attrs": { "color": "red" } }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Colors: `"red"`, `"green"`, `"blue"`, `"yellow"`, `"white"`, `"orange"`
|
|
78
|
+
|
|
79
|
+
**Standard blink circuit (GPIO → R → LED → GND):**
|
|
80
|
+
```json
|
|
81
|
+
["esp:D2", "r1:1", "green", []],
|
|
82
|
+
["r1:2", "led1:A", "green", []],
|
|
83
|
+
["led1:C", "esp:GND.1", "black", []]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### wokwi-resistor
|
|
89
|
+
|
|
90
|
+
| Pin | Role |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `1` | Terminal 1 |
|
|
93
|
+
| `2` | Terminal 2 |
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{ "type": "wokwi-resistor", "id": "r1", "top": 100, "left": 150, "attrs": { "value": "220" } }
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Common values: `"220"` (LED current limit), `"1000"`, `"10000"` (pull-up/down)
|
|
100
|
+
|
|
101
|
+
Add `"rotate": 90` to orient vertically.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### wokwi-pushbutton
|
|
106
|
+
|
|
107
|
+
| Pin | Role |
|
|
108
|
+
|---|---|
|
|
109
|
+
| `1.l` | Side 1 left lead |
|
|
110
|
+
| `1.r` | Side 1 right lead |
|
|
111
|
+
| `2.l` | Side 2 left lead |
|
|
112
|
+
| `2.r` | Side 2 right lead |
|
|
113
|
+
|
|
114
|
+
`1.*` and `2.*` are shorted when button is pressed. Typical wiring with `INPUT_PULLUP`:
|
|
115
|
+
```json
|
|
116
|
+
["esp:D4", "btn1:1.l", "green", []],
|
|
117
|
+
["esp:GND.1", "btn1:2.l", "black", []]
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{ "type": "wokwi-pushbutton", "id": "btn1", "top": 100, "left": 200, "attrs": { "color": "blue" } }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### wokwi-servo
|
|
127
|
+
|
|
128
|
+
| Pin | Role |
|
|
129
|
+
|---|---|
|
|
130
|
+
| `PWM` | Signal (connect to GPIO) |
|
|
131
|
+
| `V+` | Power (connect to 5V or 3V3) |
|
|
132
|
+
| `GND` | Ground |
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{ "type": "wokwi-servo", "id": "srv1", "top": 100, "left": 200, "attrs": { "minAngle": "-90", "maxAngle": "90" } }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
["esp:D18", "srv1:PWM", "orange", []],
|
|
140
|
+
["esp:3V3", "srv1:V+", "red", []],
|
|
141
|
+
["esp:GND.1", "srv1:GND", "black", []]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### wokwi-ntc-temperature-sensor
|
|
147
|
+
|
|
148
|
+
| Pin | Role |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `VCC` | Power (3.3V or 5V) |
|
|
151
|
+
| `GND` | Ground |
|
|
152
|
+
| `OUT` | Analog output (connect to ADC pin) |
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
["esp:3V3", "tmp1:VCC", "red", []],
|
|
156
|
+
["esp:GND.1", "tmp1:GND", "black", []],
|
|
157
|
+
["esp:D34", "tmp1:OUT", "green", []]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### wokwi-dht22
|
|
163
|
+
|
|
164
|
+
| Pin | Role |
|
|
165
|
+
|---|---|
|
|
166
|
+
| `VCC` | Power |
|
|
167
|
+
| `GND` | Ground |
|
|
168
|
+
| `SDA` | Data (connect to GPIO, no extra resistor needed in Wokwi) |
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### wokwi-ssd1306
|
|
173
|
+
|
|
174
|
+
| Pin | Role |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `VCC` | Power (3.3V) |
|
|
177
|
+
| `GND` | Ground |
|
|
178
|
+
| `SCL` | I2C clock |
|
|
179
|
+
| `SDA` | I2C data |
|
|
180
|
+
|
|
181
|
+
Default I2C on ESP32: `SCL = D22`, `SDA = D21`.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### wokwi-hc-sr04 (ultrasonic)
|
|
186
|
+
|
|
187
|
+
| Pin | Role |
|
|
188
|
+
|---|---|
|
|
189
|
+
| `VCC` | 5V |
|
|
190
|
+
| `GND` | Ground |
|
|
191
|
+
| `TRIG` | Trigger pulse (GPIO output) |
|
|
192
|
+
| `ECHO` | Echo return (GPIO input) |
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Positioning Tips
|
|
197
|
+
|
|
198
|
+
- `top` / `left` are canvas pixels; `0,0` is top-left of the first placed part.
|
|
199
|
+
- ESP32 DevKit V1 occupies roughly 160 × 400 px.
|
|
200
|
+
- Place external components to the **right** of the ESP32 (left ≈ 200+) to align with the right-column pins (D2, GND.2, etc.).
|
|
201
|
+
- Place components to the **left** (left ≈ -150) to align with left-column pins (D32, GND.1, etc.).
|
|
202
|
+
- `"rotate": 90` rotates a component 90° clockwise.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Common Mistakes
|
|
207
|
+
|
|
208
|
+
| Mistake | Correct |
|
|
209
|
+
|---|---|
|
|
210
|
+
| `led1:K` | `led1:C` — Wokwi uses `C` for cathode, not the standard `K` |
|
|
211
|
+
| `esp:GND` | `esp:GND.1` or `esp:GND.2` — always use the numbered suffix |
|
|
212
|
+
| `esp:GPIO2` | `esp:D2` — Wokwi prefixes GPIO numbers with `D` |
|
|
213
|
+
| `esp:TX0` in connections | `esp:TX` — omit the `0` suffix for UART pins |
|
|
@@ -368,6 +368,7 @@ def stream_compile(sketch_dir: pathlib.Path, fqbn: str) -> ProcessStream:
|
|
|
368
368
|
ToolchainError: If arduino-cli is missing or fails to start.
|
|
369
369
|
"""
|
|
370
370
|
exe = _require_arduino_cli()
|
|
371
|
+
#print(elf_path_for(sketch_dir, fqbn))
|
|
371
372
|
return _stream_process([exe, "compile", "--fqbn", fqbn, str(sketch_dir), "--build-path", str(elf_path_for(sketch_dir, fqbn))])
|
|
372
373
|
|
|
373
374
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nff"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "Claude Code IoT Bridge — connect Claude to hardware via USB"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -55,6 +55,9 @@ where = ["."]
|
|
|
55
55
|
include = ["nff*"]
|
|
56
56
|
exclude = ["tests*", "scripts*"]
|
|
57
57
|
|
|
58
|
+
[tool.setuptools.package-data]
|
|
59
|
+
"nff" = ["skills/*.md"]
|
|
60
|
+
|
|
58
61
|
[tool.black]
|
|
59
62
|
line-length = 100
|
|
60
63
|
|
{nff-0.2.2 → nff-0.2.4}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|