One-command install + launchd agent for deploying to another Mac
Answers "do we have to start the server in terminal?" -- no. install.sh installs
deps and registers a launchd agent with RunAtLoad + KeepAlive, so the daemon
starts at login and comes back if it dies. Verified by killing the process: back
up and serving within seconds under a new pid. Deploying to the M3 Air is then:
git clone ssh://git@100.71.119.27:222/monster/yourovo.git
cd yourovo/mac && ./install.sh
Also revises the A/B/C recommendation. Grepping the extension shows it calls only
six endpoints: /status, /write-tag, /read-tag (all served here) plus /weight,
/scale/start, /scale/stop (the DYMO M10 postal scale, Node-only). So the gap to a
single service is the scale and nothing else -- which makes option B (Node on
:7791 with this one proxying) the wrong trade: one URL but two processes, two
dependency stacks and two things to keep alive, against a stated goal of one
button on a second machine.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6d9a49ea42
commit
d4b16c075b
@ -42,13 +42,29 @@ PRINT <set>, <copy> # note the space after the co
|
|||||||
All plain ASCII, one command per line, CRLF-terminated. `writeUHF("H",2,12,"E",epc)`
|
All plain ASCII, one command per line, CRLF-terminated. `writeUHF("H",2,12,"E",epc)`
|
||||||
emits exactly `UHF WRITE H,2,12,E,"<24 hex chars>"`.
|
emits exactly `UHF WRITE H,2,12,E,"<24 hex chars>"`.
|
||||||
|
|
||||||
## Setup
|
## Install on a new Mac (one command)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./setup.sh # brew install libusb + venv with pyusb/pillow/segno
|
git clone ssh://git@100.71.119.27:222/monster/yourovo.git
|
||||||
|
cd yourovo/mac && ./install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Then double-click **`start-daemon.command`** (leave it open while you work).
|
That installs libusb + the venv, then registers a **launchd agent** so the daemon starts
|
||||||
|
at login and restarts itself if it ever dies. **No Terminal window to keep open, and
|
||||||
|
nothing to click** — after this it is simply always running. Verified: `kill` the process
|
||||||
|
and launchd has it serving again within seconds.
|
||||||
|
|
||||||
|
Re-run `./install.sh` any time to pull the latest commit and reload. `./install.sh
|
||||||
|
uninstall` removes the agent.
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| logs | `tail -f ~/Library/Logs/pricegod-labeld.log` |
|
||||||
|
| restart | `launchctl kickstart -k gui/$(id -u)/com.pricegod.labeld` |
|
||||||
|
| check | `curl -s localhost:7790/devices` |
|
||||||
|
|
||||||
|
For a foreground run while developing (agent must be stopped first), use `./setup.sh`
|
||||||
|
then double-click **`start-daemon.command`**.
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
|
|
||||||
@ -106,9 +122,21 @@ handles this, and the resolution difference (203 vs 300 dpi) comes from `profile
|
|||||||
(`CF [ADDR] [CMD] [LEN] [DATA] [CRC16]` @115200) plus the postal-scale and inventory
|
(`CF [ADDR] [CMD] [LEN] [DATA] [CRC16]` @115200) plus the postal-scale and inventory
|
||||||
routes, none of which this service implements — so it is *not* a full replacement.
|
routes, none of which this service implements — so it is *not* a full replacement.
|
||||||
|
|
||||||
Pick one of: run this on `--port 7791`; keep the Chafon daemon for the gun and run this
|
The extension calls only six endpoints:
|
||||||
one elsewhere; or fold the Chafon protocol in here. Unresolved — decide before wiring the
|
|
||||||
extension.
|
| endpoint | owner today |
|
||||||
|
|---|---|
|
||||||
|
| `/status` `/write-tag` `/read-tag` | ✅ this service |
|
||||||
|
| `/weight` `/scale/start` `/scale/stop` | ❌ Node only — DYMO M10 postal scale over USB HID |
|
||||||
|
|
||||||
|
So the gap to a genuinely single service is **the postal scale, and nothing else**. Once
|
||||||
|
`/weight` and `/scale/*` are ported here (the M10 is USB HID `0922:8003/8004`; the parsing
|
||||||
|
is ~130 lines of `index.js`), the Node daemon can be retired for the extension's purposes
|
||||||
|
and there is one process, one venv, one launchd agent.
|
||||||
|
|
||||||
|
Until then the honest position is: two services, or no scale. Running this one on
|
||||||
|
`--port 7791` behind the Node daemon works but gives one URL and *two* processes, which
|
||||||
|
defeats the point of a single launchd agent.
|
||||||
|
|
||||||
## Media profiles
|
## Media profiles
|
||||||
|
|
||||||
|
|||||||
79
mac/install.sh
Executable file
79
mac/install.sh
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# One-command install on a fresh Apple Silicon Mac.
|
||||||
|
#
|
||||||
|
# git clone ssh://git@100.71.119.27:222/monster/yourovo.git
|
||||||
|
# cd yourovo/mac && ./install.sh
|
||||||
|
#
|
||||||
|
# Installs dependencies, then registers a launchd agent so the daemon starts at login
|
||||||
|
# and restarts itself if it dies. No Terminal needed after this, ever.
|
||||||
|
#
|
||||||
|
# Re-runnable: pulls the latest commit and reloads the agent.
|
||||||
|
set -e
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
HERE="$(pwd -P)"
|
||||||
|
LABEL="com.pricegod.labeld"
|
||||||
|
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
|
||||||
|
LOG="$HOME/Library/Logs/pricegod-labeld.log"
|
||||||
|
|
||||||
|
case "${1:-install}" in
|
||||||
|
uninstall)
|
||||||
|
launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true
|
||||||
|
rm -f "$PLIST"
|
||||||
|
echo "removed $LABEL"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "==> updating from git"
|
||||||
|
git -C "$HERE/.." pull --ff-only 2>/dev/null || echo " (skipped -- not a clean fast-forward)"
|
||||||
|
|
||||||
|
echo "==> dependencies"
|
||||||
|
./setup.sh
|
||||||
|
|
||||||
|
echo "==> launchd agent"
|
||||||
|
mkdir -p "$(dirname "$PLIST")" "$(dirname "$LOG")"
|
||||||
|
cat > "$PLIST" <<PLISTEOF
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||||
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key> <string>$LABEL</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>$HERE/venv/bin/python</string>
|
||||||
|
<string>$HERE/daemon.py</string>
|
||||||
|
</array>
|
||||||
|
<key>WorkingDirectory</key> <string>$HERE</string>
|
||||||
|
<key>RunAtLoad</key> <true/>
|
||||||
|
<key>KeepAlive</key> <true/>
|
||||||
|
<key>ProcessType</key> <string>Interactive</string>
|
||||||
|
<key>StandardOutPath</key> <string>$LOG</string>
|
||||||
|
<key>StandardErrorPath</key> <string>$LOG</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
PLISTEOF
|
||||||
|
|
||||||
|
launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true
|
||||||
|
launchctl bootstrap "gui/$(id -u)" "$PLIST"
|
||||||
|
launchctl kickstart -k "gui/$(id -u)/$LABEL"
|
||||||
|
|
||||||
|
echo "==> waiting for the daemon"
|
||||||
|
for i in $(seq 1 20); do
|
||||||
|
if curl -fsS -m 2 http://localhost:7790/ >/dev/null 2>&1; then
|
||||||
|
echo
|
||||||
|
curl -s http://localhost:7790/devices
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "OK -- running on http://localhost:7790/ and will start at every login."
|
||||||
|
echo " logs: tail -f $LOG"
|
||||||
|
echo " restart: launchctl kickstart -k gui/$(id -u)/$LABEL"
|
||||||
|
echo " uninstall: ./install.sh uninstall"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "daemon did not come up -- check $LOG" >&2
|
||||||
|
tail -20 "$LOG" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
Loading…
Reference in New Issue
Block a user