{"id":47922966,"url":"https://github.com/bleugreen/lnp2","last_synced_at":"2026-04-04T06:19:30.451Z","repository":{"id":342920453,"uuid":"1175034563","full_name":"bleugreen/lnp2","owner":"bleugreen","description":"Rust Server PNP ","archived":false,"fork":false,"pushed_at":"2026-03-08T02:29:23.000Z","size":131,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-08T06:32:56.639Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bleugreen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-07T06:13:03.000Z","updated_at":"2026-03-08T02:15:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bleugreen/lnp2","commit_stats":null,"previous_names":["bleugreen/lnp2"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/bleugreen/lnp2","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleugreen%2Flnp2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleugreen%2Flnp2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleugreen%2Flnp2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleugreen%2Flnp2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bleugreen","download_url":"https://codeload.github.com/bleugreen/lnp2/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleugreen%2Flnp2/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31389694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T04:26:24.776Z","status":"ssl_error","status_checked_at":"2026-04-04T04:23:34.147Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-04T06:19:29.975Z","updated_at":"2026-04-04T06:19:30.420Z","avatar_url":"https://github.com/bleugreen.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lnp2\n\n    Look N Pick N Look N Place\n\nSingle-binary pick-and-place machine controller for LumenPnP. Replaces OpenPnP with a Rust backend and Svelte frontend — owns serial, motion, cameras, vision, feeders, and serves everything over HTTP.\n\n## Quick Start\n\n```bash\n# Build\ncargo build --release\ncd web \u0026\u0026 npm install \u0026\u0026 npx vite build \u0026\u0026 cd ..\n\n# Run\n./target/release/lnp2 serve --config config/\n```\n\nServer starts on `0.0.0.0:3000` — open in a browser for the control UI.\n\n## Architecture\n\n```\nlnp2 binary\n├── Serial (GCode)  ─────→  Marlin firmware (Rambo board)\n│   ├── Motion         5-axis: XY gantry, Z, A/B rotation\n│   ├── Actuators      Vacuum, blow-off, LED, I2C sensors\n│   └── RS-485 bus     Photon Smart Feeder protocol\n│\n├── Cameras (V4L2)  ─────→  Top (down-looking) + Bottom (up-looking)\n│   ├── MJPEG capture    15fps, turbojpeg lossless flip\n│   ├── Auto-exposure    v4l2 brightness tracking\n│   └── WebSocket stream Binary frames to browser\n│\n├── Vision  ─────────────→  OpenCV + ONNX Runtime (YOLOv8)\n│   ├── Pocket detection   Locate feeder slots (ML or CV fallback)\n│   ├── Fiducial detection PCB alignment markers\n│   └── Part alignment     Pad-level rotation correction\n│\n└── Web UI (Svelte)  ────→  Served from web/dist/\n    ├── Live camera view   Canvas + crosshair + ML overlay\n    ├── Click-to-move      Pixel → mm via camera calibration\n    ├── Jog controls       Step/feedrate, keyboard shortcuts\n    └── Actuator panel     Vacuum, blow, LED\n```\n\n## CLI Commands\n\n```bash\nlnp2 serve --config config/          # Start server (default)\nlnp2 import --from ~/.openpnp2 --to config/  # Import OpenPnP XML → TOML\nlnp2 scan --config config/           # Discover feeders on RS-485 bus\nlnp2 feed --config config/ --slot 3  # Test-feed a single slot\n```\n\n## API\n\n### Motion \u0026 Actuators\n\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | `/api/gcode` | Send raw GCode command |\n| POST | `/api/gcode/batch` | Send multiple GCode commands |\n| POST | `/api/move` | Move to coordinates (x, y, z, a, b, feedrate) |\n| POST | `/api/move/safe` | Safe XY move (retracts Z first) |\n| POST | `/api/home` | Home all axes |\n| GET | `/api/position` | Get current position |\n| POST | `/api/acceleration` | Set acceleration |\n| POST | `/api/vacuum` | Vacuum on/off (nozzle, action) |\n| GET | `/api/vacuum/read` | Read vacuum sensor |\n| POST | `/api/blow` | Blow-off pulse (nozzle, duration_ms) |\n| POST | `/api/led` | LED control (r, g, b, brightness, off) |\n\n### Camera \u0026 Vision\n\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | `/api/camera/list` | List cameras and configs |\n| GET | `/api/camera/capture` | Single JPEG frame |\n| WS | `/api/camera/stream?name=top` | Live MJPEG WebSocket stream |\n| POST | `/api/vision/detect_all` | Run YOLOv8 inference, return detections |\n| POST | `/api/vision/detect_pocket` | Detect feeder pocket, return mm offset |\n| POST | `/api/vision/detect_fiducial` | Detect PCB fiducial marker |\n| POST | `/api/vision/align_part` | Pad-level part alignment |\n\n### Config \u0026 Data\n\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | `/api/config` | Get machine config |\n| PUT | `/api/config` | Update machine config (hot-reload) |\n| POST | `/api/dataset/capture` | Save labeled frame for ML training |\n| GET | `/api/dataset/count` | Count captured images |\n\n### WebSocket Events\n\n`/api/events` streams JSON position updates and state changes:\n```json\n{\"type\": \"Position\", \"x\": 10.5, \"y\": 20.3, \"z\": 15.0, \"a\": 0, \"b\": 0}\n```\n\n## Configuration\n\nAll machine parameters live in `config/*.toml`:\n\n| File | Contents |\n|------|----------|\n| `machine.toml` | Serial port, axes, nozzles, cameras, LEDs, vision models |\n| `feeders.toml` | Feeder definitions (Photon slots, tray positions) |\n| `parts.toml` | Part library (package, speed, value) |\n| `packages.toml` | Package footprints (pads, body dimensions) |\n| `nozzle_tips.toml` | Tip changer waypoint sequences |\n\nUse `lnp2 import` to convert an existing OpenPnP configuration.\n\n## Build Dependencies\n\nRust crate dependencies are handled by Cargo. System libraries needed on the target:\n\n- `libopencv-dev` — image processing and classical CV\n- `libturbojpeg0-dev` — lossless JPEG transforms\n- `nasm` + `cmake` — for building turbojpeg from source\n- ONNX Runtime — loaded dynamically via `ort` (set `ORT_DYLIB_PATH` if needed)\n\n## Deploy\n\nDeployment uses [just](https://github.com/casey/just) recipes to sync, build, and manage the service on `lumeneer.local`.\n\n```bash\njust setup       # One-time remote setup (install deps, create dirs, enable service)\njust check       # Verify remote environment (toolchain, libs, disk)\n\njust build       # Sync source + cargo build --release on remote\njust build-web   # Sync source + npm install + vite build on remote\njust deploy      # Build all + copy to production dir + restart systemd service\njust deploy-rust # Binary-only deploy (skip web build)\n\njust run         # Build + run server in foreground (for dev/debug)\njust logs        # Follow journalctl output\njust status      # Show systemd service status\n\njust watch       # Auto-sync on file save (requires fswatch)\njust ssh         # SSH into remote build dir\njust builds      # List remote build dirs with disk usage\njust clean       # Remove a remote build dir\n```\n\nThe remote uses per-branch build dirs (`~/lnp2/builds/\u003cbranch\u003e/`) and a single production dir (`~/lnp2/production/`) managed by a systemd service (`remote/lnp2.service`).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbleugreen%2Flnp2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbleugreen%2Flnp2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbleugreen%2Flnp2/lists"}