@seeed-studio/solution-cli 0.0.0-stage → 0.1.0
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.
- package/README.md +77 -2
- package/bin/cli.js +136 -0
- package/bin/runner.js +39 -0
- package/lib/agent.js +160 -0
- package/lib/detector.js +321 -0
- package/lib/doctor.js +179 -0
- package/lib/downloader.js +219 -0
- package/lib/installer.js +375 -0
- package/lib/ledger.js +302 -0
- package/lib/platform.js +113 -0
- package/package.json +51 -4
- package/skills/sensecraft/SKILL.md +176 -0
- package/skills/sensecraft/references/app-only.md +273 -0
- package/skills/sensecraft/references/deploy.md +300 -0
- package/skills/sensecraft/references/diagnose.md +133 -0
- package/skills/sensecraft/references/error-catalog.md +33 -0
- package/skills/sensecraft/references/offline.md +78 -0
- package/skills/sensecraft/references/verify.md +136 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Diagnose a failed or misbehaving deployment
|
|
2
|
+
|
|
3
|
+
Follow the rules in `SKILL.md` (what needs the user's OK, at most 3 rounds).
|
|
4
|
+
If the user runs the desktop app and deployed from it, `app-only.md` §3 covers
|
|
5
|
+
the app's own deployment list and logs.
|
|
6
|
+
|
|
7
|
+
## 1. Find the deployment
|
|
8
|
+
|
|
9
|
+
If you started it, you already have the `deployment_id`. Otherwise:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
sensecraft-engine api GET "/api/deployments?limit=20" # newest first: id, solution_id, status
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 2. Collect evidence
|
|
16
|
+
|
|
17
|
+
Start with the status. **The real error is usually in the failing step's
|
|
18
|
+
`message`** (`devices[].steps[]` with `status: failed`); top-level errors may
|
|
19
|
+
only say "Device X deployment failed".
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
sensecraft-engine status <deployment_id> --json
|
|
23
|
+
sensecraft-engine api GET /api/deployments/<deployment_id>/summary
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then the error-level events, and the full log of the failing device:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
sensecraft-engine logs <deployment_id> # NDJSON; look at type=log, level=error
|
|
30
|
+
sensecraft-engine api GET "/api/deployments/<deployment_id>/logs?device_id=<device_id>&limit=300"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
If the logs are empty or end abruptly (status `interrupted`: the engine
|
|
34
|
+
instance stopped during the deployment), read the engine log
|
|
35
|
+
`~/.sensecraft/logs/engine.log` (Windows: `%USERPROFILE%\.sensecraft\logs\engine.log`),
|
|
36
|
+
last ~200 lines. `sensecraft-engine daemon status` prints JSON (`--json` is
|
|
37
|
+
accepted and changes nothing; exit 1 with `"running": false` when no instance
|
|
38
|
+
is running). A running instance shows `busy` (a deployment is running),
|
|
39
|
+
`python_backend` (null: no desktop-app backend involved) and
|
|
40
|
+
`python_supervisor.state`.
|
|
41
|
+
|
|
42
|
+
Note the failing device, step and the first error — later errors are usually
|
|
43
|
+
consequences of the first.
|
|
44
|
+
|
|
45
|
+
## 3. Check the device (read-only, no need to ask)
|
|
46
|
+
|
|
47
|
+
Which containers belong to the solution: in the solution folder
|
|
48
|
+
(`~/.sensecraft/content/solutions/<id>/`) the step's `devices/<x>.yaml` names
|
|
49
|
+
the compose file (`docker.compose_file`) and project
|
|
50
|
+
(`docker.options.project_name`); the compose file may set `container_name`.
|
|
51
|
+
|
|
52
|
+
Through the engine (no separate SSH client needed):
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
SC_SSH_PASSWORD=<password> sensecraft-engine docker ps --host <ip> --username <user> --json
|
|
56
|
+
SC_SSH_PASSWORD=<password> sensecraft-engine docker logs <container> --host <ip> --username <user> --tail 100
|
|
57
|
+
# SSH key (engines with --key-file; older engines accept a password only):
|
|
58
|
+
sensecraft-engine docker ps --host <ip> --username <user> --key-file ~/.ssh/id_ed25519 --json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Omit `--host` for this computer's Docker. With an SSH client, the same
|
|
62
|
+
read-only commands as before:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
docker ps -a --format '{{.Names}}\t{{.Status}}\t{{.Ports}}'
|
|
66
|
+
docker logs --tail 100 <container>
|
|
67
|
+
df -h /
|
|
68
|
+
ss -ltnp # who holds a port (use: sudo ss -ltnp if names are hidden)
|
|
69
|
+
ping -c 2 8.8.8.8 # internet reachability
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For local targets and USB devices also run `sensecraft-engine doctor --json`
|
|
73
|
+
(serial permission, Docker, disk, network) and
|
|
74
|
+
`sensecraft-engine device ports` (is the USB device visible).
|
|
75
|
+
|
|
76
|
+
## 4. Classify, then act
|
|
77
|
+
|
|
78
|
+
Match the evidence against `error-catalog.md`. Every problem falls in one of
|
|
79
|
+
three classes:
|
|
80
|
+
|
|
81
|
+
| Class | Example | What you do |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| **Device / environment** | port taken, disk full, Docker missing, network blocked, wrong password, serial permission | Propose the exact fix commands → user OK → run them → retry |
|
|
84
|
+
| **Solution configuration** | timeout too short, wrong port/env in compose, health check endpoint 404, minor syntax/transfer glitch | **CLI / Engine mode (Auto-healing patch)**: Copy the solution from `~/.sensecraft/content/solutions/<id>` to `./.sensecraft-work/solutions/<id>`, apply the minimal required fix. Stop the previous engine instance (`sensecraft-engine daemon stop`) so it reloads the new solution directory, and redeploy with `--solutions-dir ./.sensecraft-work/solutions` so the user succeeds immediately! Show the user the patch diff. Desktop app running: fix it in the edit copy (`app-only.md` §4) → validate → apply → retry. |
|
|
85
|
+
| **Engine bug** | exit code 5, a panic in `engine.log`, a step that fails the same way on any device, behaviour contradicting the solution's own config | Stop. Prepare the issue report below |
|
|
86
|
+
|
|
87
|
+
If the evidence does not fit any row, say so and show the user the first error
|
|
88
|
+
with your best hypothesis and what would confirm it. Do not guess-and-retry.
|
|
89
|
+
|
|
90
|
+
## 5. Retry
|
|
91
|
+
|
|
92
|
+
Restart only the failed device (`selected_devices` = that device, see
|
|
93
|
+
`deploy.md` §6). First retry without asking; later ones need the user's OK.
|
|
94
|
+
After 3 rounds without success, stop and report.
|
|
95
|
+
|
|
96
|
+
## 6. Report
|
|
97
|
+
|
|
98
|
+
Always finish with: what failed, the evidence (first error line), what you
|
|
99
|
+
changed (commands run, files edited with a diff), and the result.
|
|
100
|
+
|
|
101
|
+
### Engine bug: issue report
|
|
102
|
+
|
|
103
|
+
Engine bugs are reported on the public repository
|
|
104
|
+
`suharvest/sensecraft-solutions` with the **App / engine bug** form; the
|
|
105
|
+
maintainers move them on from there. Do not submit it yourself — give the user
|
|
106
|
+
a link to open in the browser and submit with their own GitHub account.
|
|
107
|
+
|
|
108
|
+
1. Fill these fields (passwords, tokens and IP addresses removed):
|
|
109
|
+
|
|
110
|
+
| Field id | Content |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `title` | `[engine] <step type> fails: <first error, one line>` |
|
|
113
|
+
| `app_version` | `engine <version>` from `sensecraft-engine --version` (or the app's version when deployed from the app) |
|
|
114
|
+
| `os` | this computer's OS and version |
|
|
115
|
+
| `device` | target device model, OS, CPU architecture (or "this computer (local Docker)") |
|
|
116
|
+
| `solution` | `<solution_id> / <preset_id> / <step id> (<type>)` |
|
|
117
|
+
| `edited` | `No` or `Yes (diff below)` |
|
|
118
|
+
| `what_happened` | first error and the 10–20 log lines around it |
|
|
119
|
+
| `reproduce` | numbered steps (the `sensecraft-engine` commands, password removed) |
|
|
120
|
+
| `ruled_out` | device checks that passed |
|
|
121
|
+
| `diff` | the edit copy's diff (`app-only.md` §4.5), only if edited |
|
|
122
|
+
|
|
123
|
+
2. Build the link, URL-encoding every value:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
https://github.com/suharvest/sensecraft-solutions/issues/new?template=engine-bug.yml&title=<...>&app_version=<...>&os=<...>&device=<...>&solution=<...>&edited=<...>&what_happened=<...>&reproduce=<...>&ruled_out=<...>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Keep the link under about 7,000 characters: if the log excerpt or diff is
|
|
130
|
+
longer, leave those fields out of the link and give the user that text
|
|
131
|
+
separately to paste into the form.
|
|
132
|
+
3. Show the user the filled fields and the link, and say the report will be
|
|
133
|
+
public.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Error catalog
|
|
2
|
+
|
|
3
|
+
Match the **first** error of the failing step. Class: **Env** = device /
|
|
4
|
+
environment, **Config** = solution configuration, **Engine** = engine / app bug.
|
|
5
|
+
|
|
6
|
+
| Evidence | Class | Cause | Action |
|
|
7
|
+
|---|---|---|---|
|
|
8
|
+
| Exit 3, "no solutions" / hint to run `content pull` | Env | Solutions not downloaded yet | `sensecraft-engine content pull`, then run the command again |
|
|
9
|
+
| Exit 2, `{"type":"error","code":"missing_params","missing":[...]}` | Env | A required value is not in the request | Ask the user for each `missing` field (`preset_id`, `device_connections.<id>.<key>`) |
|
|
10
|
+
| Exit 3, HTTP 409 with `busy: [...]` | Env | Another deployment is using the same device | Wait for it (`status <id>`), or ask the user whether to cancel it |
|
|
11
|
+
| Exit 4, `requires_desktop_app` | Env | This step's deployer is not in the engine | Tell the user to deploy the solution from the SenseCraft Solution app |
|
|
12
|
+
| `key_file` refused (outside `~/.ssh`) | Env | The engine only reads SSH keys inside `~/.ssh` or its data directory | Use a key under `~/.ssh` (copying a key there needs the user's OK) |
|
|
13
|
+
| `the offline package was prepared with different values: ...` | Env | Deploy parameters differ from the ones the offline package was prepared with | Plan / prepare again with the deploy's values (`offline.md`), or deploy with the prepared values |
|
|
14
|
+
| `doctor` serial check: not a member of `dialout`; serial port permission denied | Env | User may not open USB serial ports (Linux) | Propose the `fix` from `doctor` (`sudo usermod -aG dialout <user>`, then log out and in) — user OK |
|
|
15
|
+
| `port_busy` from `counting` / `face` / `wizard` | Env | A deployment or another session holds the serial port | Wait until it finishes; do not force it |
|
|
16
|
+
| `Missing host` / connection fields empty | Env | `host` not given in `device_connections` | Ask the user for the device IP, redeploy |
|
|
17
|
+
| SSH `Authentication failed` / `Permission denied (publickey,password)` | Env | Wrong username or password | Ask the user to re-check; the solution's default user is in `request_template` |
|
|
18
|
+
| SSH timeout / `No route to host` | Env | Device off, wrong IP, other network | `ping` it; ask the user to check power and that both are on the same LAN |
|
|
19
|
+
| `port is already allocated` / `address already in use`; pre-check `port_available` failed | Env | Another process or container holds the port | `ss -ltnp` / `docker ps` to find it; propose stopping it (user OK), or change the port in config |
|
|
20
|
+
| `Conflict. The container name ... is already in use` | Env | Leftover container from an earlier deployment | Redeploy with `"auto_replace_containers": true` after the user agrees |
|
|
21
|
+
| `no space left on device`; pre-check `disk_space` failed | Env | Disk full | `df -h`, `docker system df`; propose `docker image prune` (user OK) |
|
|
22
|
+
| `docker: command not found`; pre-check `docker_version` failed | Env | Docker not installed / too old | Tell the user; installing needs their OK |
|
|
23
|
+
| `permission denied while trying to connect to the Docker daemon socket` | Env | User not in `docker` group | Propose `sudo usermod -aG docker <user>` then re-login (user OK) |
|
|
24
|
+
| Image pull: `TLS handshake timeout`, `i/o timeout`, `toomanyrequests` | Env | Registry unreachable or rate-limited | Look for `Mirror context resolved` in the logs: absent → mirror detection failed; retry once, then report network status to the user |
|
|
25
|
+
| `manifest unknown` / `not found` for an image | Config | Image name or tag wrong, or not built for the device's CPU (arm64 vs amd64) | `docker manifest inspect <image>` (read-only): "no such manifest" → the tag does not exist, fix it; it exists but lists no platform matching the device's `uname -m` → wrong architecture, pick an image built for it |
|
|
26
|
+
| Container `Restarting` / `Exited (1)`; error in `docker logs` | Config (usually) | App inside the container misconfigured: env var, mounted path, port, timeout | Read `docker logs`; CLI mode: copy to `./.sensecraft-work/solutions/<id>`, fix compose / env / timeout, and redeploy with `--solutions-dir ./.sensecraft-work/solutions`; Desktop app: fix in edit copy (`app-only.md` §4) |
|
|
27
|
+
| Container `(healthy)` but the step reports health-check failure | Config | `health_check_endpoint` points at a URL that returns 401/404 | Fix the endpoint in the device YAML (`docker.services[].health_check_endpoint`) via local patch copy or app edit copy |
|
|
28
|
+
| Containers up, but the page / port does not answer from another machine | Env | Device firewall | Check `sudo iptables -L -n` / `ufw status`; propose opening the port (user OK) |
|
|
29
|
+
| USB device not detected (`No device found`, `detect` returns nothing) | Env | Cable is charge-only, wrong port, driver missing | Ask the user to replug with a data cable; on Windows check Device Manager for a COM port |
|
|
30
|
+
| YAML / validation error naming a solution file | Config | Broken solution file, syntax typo, or timeout too short | CLI mode: copy to `./.sensecraft-work/solutions/<id>`, fix typo/timeout, and redeploy with `--solutions-dir ./.sensecraft-work/solutions`; Desktop app: fix in edit copy (`app-only.md` §4) |
|
|
31
|
+
| Python traceback mentioning `provisioning_station/` | Engine | App bug | Issue report (`diagnose.md` §6) |
|
|
32
|
+
| `sensecraft-engine` exits 5, or a panic in `~/.sensecraft/logs/engine.log` | Engine | Engine bug | Issue report (`diagnose.md` §6) |
|
|
33
|
+
| Same step fails identically on two different devices after the environment checks pass | Engine (likely) | App bug | Issue report (`diagnose.md` §6) |
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Deploy where there is no internet (offline package)
|
|
2
|
+
|
|
3
|
+
Prepare on a computer that has internet, deploy on site without it. The unit
|
|
4
|
+
is **step × target**: you can prepare one step only, or several device models
|
|
5
|
+
for the same step. The engine has no separate command for this; use
|
|
6
|
+
`sensecraft-engine api` (run `sensecraft-engine api --help` for the same notes).
|
|
7
|
+
|
|
8
|
+
Ask the user first: preparing downloads container images and files, which can
|
|
9
|
+
take several GB of disk space.
|
|
10
|
+
|
|
11
|
+
## 1. Plan: what is needed, what is already here
|
|
12
|
+
|
|
13
|
+
Write the request to a file, e.g. `./.sensecraft-work/plan.json`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"solution_id": "<id>",
|
|
18
|
+
"preset_id": "<preset>",
|
|
19
|
+
"targets": {"<step_id>": "<target_id>"},
|
|
20
|
+
"arch": {"<step_id>": "aarch64"},
|
|
21
|
+
"params": {"username": "<the username the deploy will use>"},
|
|
22
|
+
"lang": "en"
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- `targets`: only the steps listed are prepared; leave it out for every step.
|
|
27
|
+
- `arch`: needed when the target names no device type (`aarch64` for
|
|
28
|
+
ARM boards such as Jetson, Raspberry Pi, RK3588).
|
|
29
|
+
- `params`: **the same connection values the later deploy will use** (from
|
|
30
|
+
`deploy-info`'s `request_template`, e.g. `username`). The package records
|
|
31
|
+
them; a deploy with different values is refused before anything runs on the
|
|
32
|
+
device (`the offline package was prepared with different values: ...`), and
|
|
33
|
+
you have to plan and prepare again with the right `params`.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
sensecraft-engine api POST /api/staging/plan --data "$(cat ./.sensecraft-work/plan.json)"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The response lists each item and whether it is already here. Items marked
|
|
40
|
+
`partial` still need internet on site (for example a model the container
|
|
41
|
+
downloads at start); tell the user which.
|
|
42
|
+
|
|
43
|
+
## 2. Prepare: download it here
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
sensecraft-engine api POST /api/staging/prepare --data "$(cat ./.sensecraft-work/plan.json)"
|
|
47
|
+
sensecraft-engine api GET /api/staging/jobs/<id> # repeat every 5–10 s until status is not "running"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`prepare` returns a job with `id` and `status: running`. Cancel it with
|
|
51
|
+
`sensecraft-engine api POST /api/staging/jobs/<id>/cancel`.
|
|
52
|
+
|
|
53
|
+
## 3. Check, carry, clean up
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
sensecraft-engine api GET /api/staging/entries # what is prepared
|
|
57
|
+
sensecraft-engine api POST /api/staging/export --data '{"path": "/path/kit.tar"}' # pack it
|
|
58
|
+
sensecraft-engine api POST /api/staging/import --data '{"path": "/path/kit.tar"}' # on the deploying computer
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Deleting prepared entries (`POST /api/staging/entries/delete`) frees disk space;
|
|
62
|
+
ask the user first.
|
|
63
|
+
|
|
64
|
+
## 4. Deploy on site
|
|
65
|
+
|
|
66
|
+
Deploy as in `deploy.md`, with `"force_offline": true` in the step's
|
|
67
|
+
connection:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
"device_connections": {
|
|
71
|
+
"<step_id>": {"target": "<target_id>", "target_type": "remote",
|
|
72
|
+
"host": "<ip>", "username": "<same as params>",
|
|
73
|
+
"password": "<password>", "force_offline": true}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The engine checks the offline package before connecting to the device and
|
|
78
|
+
stops with a list of what is missing.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Finish a `verify_required` step
|
|
2
|
+
|
|
3
|
+
The engine does not run verification steps that need a person or a browser.
|
|
4
|
+
When a deployment reaches one, it writes a `verify_required` event to the
|
|
5
|
+
deployment's log, marks that step `step_skipped` (`reason: verify_required`)
|
|
6
|
+
and carries on. Read the events with
|
|
7
|
+
`sensecraft-engine logs <deployment_id> --since <N>`.
|
|
8
|
+
|
|
9
|
+
Fields every `verify_required` event has:
|
|
10
|
+
|
|
11
|
+
| Field | Content |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `device_id` / `step_id` | The step |
|
|
14
|
+
| `kind` | The step type (`web_dashboard`, `serial_camera`, `serial_wizard`, `robot_inspect`, `preview`, `image_predict`, ...) |
|
|
15
|
+
| `name`, `required` | Display name; whether the solution counts it as required |
|
|
16
|
+
| `url`, `endpoint` | Where to check, with `{{host}}` already filled in (may be null) |
|
|
17
|
+
| `sample_request` | Request to send to `endpoint`: `{method, url, headers?, content_type?, file_field?, body?, curl}`, `curl` being a ready command line (may be null) |
|
|
18
|
+
| `mode` | Steps with several check modes: the mode the event describes (the step's default) |
|
|
19
|
+
| `instructions` | What to check, in the solution's words |
|
|
20
|
+
| `expected_status` | `web_dashboard` only: 200 |
|
|
21
|
+
|
|
22
|
+
Steps for hardware sessions add `port` / `db_port` / `host` (filled from the
|
|
23
|
+
step that flashed or deployed the device; null when the connection did not
|
|
24
|
+
include it), `commands {...}` with the exact CLI commands, and `confirm`
|
|
25
|
+
(how to tell it worked). `deploy-info` lists the same commands in advance as
|
|
26
|
+
`counting_cli`, `face_cli`, `wizard_cli` or `robot_cli` on that step.
|
|
27
|
+
|
|
28
|
+
General rules:
|
|
29
|
+
|
|
30
|
+
- Replace `<PORT>`, `<DB_PORT>`, `<HOST>` in `commands` with the event's `port`,
|
|
31
|
+
`db_port`, `host`. If one is null, take it from the connection you gave the
|
|
32
|
+
step named in `port_from_device` / `db_port_from_device` /
|
|
33
|
+
`host_from_device`, or ask the user (`sensecraft-engine device ports` lists
|
|
34
|
+
serial ports).
|
|
35
|
+
- Anything a person must do with their hands — plugging a cable, connecting a
|
|
36
|
+
servo, sitting in front of a camera, walking past it, standing clear of a
|
|
37
|
+
robot arm — is the user's job. Say exactly what to do, then **wait for the
|
|
38
|
+
user to confirm** before running the next command.
|
|
39
|
+
- These commands print a JSON result on stdout. Exit codes: 0 confirmed by the
|
|
40
|
+
device; 1 the device did not confirm (timeout, error, read-back mismatch);
|
|
41
|
+
2 bad arguments; 3 port busy or cannot be opened, or (robot) the status
|
|
42
|
+
service is unreachable; 5 internal error. On 3 with `port_busy`, another
|
|
43
|
+
deployment or session holds the port: wait for it, do not force it.
|
|
44
|
+
- At most 3 rounds per problem, as in `SKILL.md`.
|
|
45
|
+
|
|
46
|
+
## 1. Dashboards and interactive checks (`web_dashboard`, `preview`, `image_predict`, `text_chat`, `voice_chat`, ...)
|
|
47
|
+
|
|
48
|
+
- `web_dashboard`: `curl -s -o /dev/null -w "%{http_code}" <url>` must return
|
|
49
|
+
`expected_status` (200). Then give the user the `url` to open.
|
|
50
|
+
- `endpoint` + `sample_request` present: run `sample_request.curl` and show
|
|
51
|
+
the user the relevant part of the response. In a multipart request
|
|
52
|
+
(`-F <file_field>=@IMAGE.jpg`) replace `IMAGE.jpg` with a real picture
|
|
53
|
+
(a photo the user gave you, or one downloaded into `./.sensecraft-work/`);
|
|
54
|
+
a JSON response with results (for example detections with labels and
|
|
55
|
+
scores, possibly an empty list for a picture without matching objects)
|
|
56
|
+
means the service works. An HTTP error or no answer goes to `diagnose.md`.
|
|
57
|
+
These events also come for verify steps that only describe a check in the
|
|
58
|
+
guide (no separate config file), with the default mode's endpoint.
|
|
59
|
+
- Otherwise follow `instructions`. When they say to run the check in the
|
|
60
|
+
SenseCraft Solution app, tell the user: that check needs the desktop app.
|
|
61
|
+
|
|
62
|
+
## 2. People counting lines (`serial_camera` with `counting_cli`)
|
|
63
|
+
|
|
64
|
+
1. Ask the user where the counting lines / zones should be, in camera
|
|
65
|
+
coordinates 0–1000 (0,0 top left, 1000,1000 bottom right): a line is two
|
|
66
|
+
points `X1,Y1,X2,Y2`, a zone four corners. Direction: crossing from the
|
|
67
|
+
right side of the line (looking from point 1 to point 2) to the left counts
|
|
68
|
+
as `in`; swap the two points to reverse it.
|
|
69
|
+
2. Write them:
|
|
70
|
+
`sensecraft-engine counting set --port <PORT> --line 0=100,500,900,500 [--roi 1=X1,Y1,...,X4,Y4] [--anchor-mode foot]`
|
|
71
|
+
(`foot` for a camera tilted down from above, `center` otherwise). The result
|
|
72
|
+
must have `verified: true`; `mismatches[]` lists slots that read back
|
|
73
|
+
differently.
|
|
74
|
+
3. Start counting from zero and keep the camera running:
|
|
75
|
+
`sensecraft-engine counting reset --port <PORT> --keep-running`.
|
|
76
|
+
4. Ask the user to walk across each line (and into each zone) and tell you when
|
|
77
|
+
done.
|
|
78
|
+
5. `sensecraft-engine counting get --port <PORT>`: each line's `in` / `out` and
|
|
79
|
+
each zone's `cur` / `entered` must have changed as expected. Show the user.
|
|
80
|
+
|
|
81
|
+
## 3. Face enrollment (`serial_camera` with `face_cli`, SenseCAP Watcher)
|
|
82
|
+
|
|
83
|
+
The Watcher has two USB serial ports: the camera (`--port`) and the face
|
|
84
|
+
database (`--db-port`).
|
|
85
|
+
|
|
86
|
+
1. Ask the user whose face to enroll (name: ASCII up to 31 characters, Chinese
|
|
87
|
+
up to 4 characters).
|
|
88
|
+
2. Ask that person to sit in front of the camera, facing it, and to tell you
|
|
89
|
+
when ready.
|
|
90
|
+
3. `sensecraft-engine face enroll --port <PORT> --db-port <DB_PORT> --name <NAME> --no-prompt`.
|
|
91
|
+
Success: `stored: true`, `verified: true`. Too few samples
|
|
92
|
+
(`samples_collected` below the minimum): ask for better light / a closer,
|
|
93
|
+
straight-on face, then run it again.
|
|
94
|
+
4. `sensecraft-engine face list --db-port <DB_PORT>` and show the names to the
|
|
95
|
+
user. Fix mistakes with `face rename --db-port <DB_PORT> --name OLD --new-name NEW`
|
|
96
|
+
or `face delete --db-port <DB_PORT> --name NAME` (deleting needs the user's OK).
|
|
97
|
+
5. Ask an enrolled person to stand in front of the camera and confirm the
|
|
98
|
+
device recognizes them by name.
|
|
99
|
+
|
|
100
|
+
## 4. Servo ID setup (`serial_wizard` with `wizard_cli`)
|
|
101
|
+
|
|
102
|
+
The firmware sets one servo ID at a time and prints prompts.
|
|
103
|
+
|
|
104
|
+
1. Tell the user to connect **only** the servo for the current ID (the
|
|
105
|
+
event's `instructions` name them, e.g. ID 1 front wheel, 2 left rear, 3 right
|
|
106
|
+
rear) and to confirm.
|
|
107
|
+
2. `sensecraft-engine wizard action --port <PORT> --name enter`. Pass the
|
|
108
|
+
firmware's `prompt` text on to the user.
|
|
109
|
+
3. `step_error` set: ask the user to check the wiring, then
|
|
110
|
+
`sensecraft-engine wizard action --port <PORT> --name retry`.
|
|
111
|
+
4. Repeat for each servo until the result has `step_done: true`
|
|
112
|
+
(`wizard read --port <PORT> --until done` waits for it). Then ask the user
|
|
113
|
+
to power off, connect all servos and power on again.
|
|
114
|
+
|
|
115
|
+
## 5. Robot arm check (`robot_inspect` with `robot_cli`)
|
|
116
|
+
|
|
117
|
+
Commands that move the arm need the user's OK each time.
|
|
118
|
+
|
|
119
|
+
1. `sensecraft-engine robot observe --host <HOST>`: every joint has a value.
|
|
120
|
+
2. Ask the user's OK, then `robot torque off --host <HOST>`; ask the user to
|
|
121
|
+
turn one joint by hand; `robot observe` again — the reading must follow.
|
|
122
|
+
Show the user the numbers.
|
|
123
|
+
3. Recording a motion: for each pose the user sets by hand, run `robot observe`
|
|
124
|
+
and add the `observation` to a frame file
|
|
125
|
+
(`[{"joints": {...}, "delay": 0.4}, ...]`).
|
|
126
|
+
4. Before `robot actions test --host <HOST> --frames <file>`, ask the user to
|
|
127
|
+
stand clear of the arm and confirm. Afterwards ask whether the motion was
|
|
128
|
+
right.
|
|
129
|
+
5. Only after the user approves it:
|
|
130
|
+
`robot actions save --host <HOST> --name <name> --frames <file>`.
|
|
131
|
+
`robot actions cancel --host <HOST>` stops a running motion.
|
|
132
|
+
|
|
133
|
+
## 6. Report
|
|
134
|
+
|
|
135
|
+
For each verify step tell the user: what you checked, the command result
|
|
136
|
+
(the relevant fields, not the whole JSON), and anything left for them to do.
|