plc-checkweigher 1.24.0 → 1.28.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.
@@ -1186,22 +1186,23 @@ update)
1186
1186
  _NEW_HASH=$(${_GIT} rev-parse HEAD 2>/dev/null || echo "unknown")
1187
1187
  _NEW_SHORT="${_NEW_HASH:0:7}"
1188
1188
 
1189
+ _CODE_CHANGED=1
1189
1190
  if [[ "$_PREV_HASH" == "$_NEW_HASH" ]]; then
1191
+ _CODE_CHANGED=0
1190
1192
  spin_ok "Already up to date (${_PREV_SHORT})"
1193
+ info "Code current — verifying system configuration anyway ..."
1194
+ ulog "GIT: already up to date (${_PREV_SHORT})"
1191
1195
  echo ""
1192
- info "No changes pulled — services not restarted."
1196
+ else
1197
+ spin_ok "Pulled ${_PREV_SHORT} → ${_NEW_SHORT}"
1198
+ ulog "GIT: pulled ${_PREV_SHORT} -> ${_NEW_SHORT}"
1199
+ # ── Show what changed ─────────────────────────────────────────────────
1200
+ echo ""
1201
+ info "Changes:"
1202
+ ${_GIT} log --oneline "${_PREV_HASH}..HEAD" 2>/dev/null \
1203
+ | sed 's/^/ /' | head -15
1193
1204
  echo ""
1194
- exit 0
1195
1205
  fi
1196
- spin_ok "Pulled ${_PREV_SHORT} → ${_NEW_SHORT}"
1197
- ulog "GIT: pulled ${_PREV_SHORT} -> ${_NEW_SHORT}"
1198
-
1199
- # ── Show what changed ─────────────────────────────────────────────────────
1200
- echo ""
1201
- info "Changes:"
1202
- ${_GIT} log --oneline "${_PREV_HASH}..HEAD" 2>/dev/null \
1203
- | sed 's/^/ /' | head -15
1204
- echo ""
1205
1206
 
1206
1207
  # ── Re-lock source files (root:root 644) ──────────────────────────────────
1207
1208
  spin_start "Re-locking source file permissions"
@@ -1408,11 +1409,95 @@ PYEOF
1408
1409
  ulog "CONFIG: services OK"
1409
1410
  fi
1410
1411
 
1411
- # ── Restart services ──────────────────────────────────────────────────────
1412
- spin_start "Restarting services"
1413
- sudo systemctl restart plc_watcher plc_web 2>/dev/null
1414
- sleep 2
1415
- spin_ok "Services restarted"
1412
+ # 6. setserial masked (hangs on RT kernel, blocks boot completion)
1413
+ spin_start "setserial mask"
1414
+ if [[ "$(systemctl is-enabled setserial 2>/dev/null)" != "masked" ]] \
1415
+ && systemctl list-unit-files setserial.service 2>/dev/null | grep -q setserial; then
1416
+ sudo systemctl mask --now setserial.service &>/dev/null \
1417
+ && spin_ok "setserial was unmasked — masked now" \
1418
+ || spin_warn "Could not mask setserial"
1419
+ ulog "FIXED: setserial masked"
1420
+ else
1421
+ spin_ok "setserial masked / absent"
1422
+ ulog "CONFIG: setserial OK"
1423
+ fi
1424
+
1425
+ # 7. Shutdown timeout cap (10 s per unit)
1426
+ spin_start "Shutdown timeout cap"
1427
+ _SHUT_CONF="/etc/systemd/system.conf.d/plc-shutdown.conf"
1428
+ if ! grep -q "DefaultTimeoutStopSec=10s" "$_SHUT_CONF" 2>/dev/null; then
1429
+ sudo mkdir -p /etc/systemd/system.conf.d
1430
+ printf '[Manager]\nDefaultTimeoutStopSec=10s\n' | sudo tee "$_SHUT_CONF" >/dev/null
1431
+ sudo systemctl daemon-reload
1432
+ spin_ok "Shutdown cap installed (10 s)"
1433
+ ulog "FIXED: shutdown timeout cap installed"
1434
+ else
1435
+ spin_ok "10 s cap active"
1436
+ ulog "CONFIG: shutdown cap OK"
1437
+ fi
1438
+
1439
+ # 8. Persistent journal (capped 64 MB)
1440
+ spin_start "Persistent journal"
1441
+ _JRN_CONF="/etc/systemd/journald.conf.d/plc-journal.conf"
1442
+ if ! grep -q "Storage=persistent" "$_JRN_CONF" 2>/dev/null; then
1443
+ sudo mkdir -p /etc/systemd/journald.conf.d /var/log/journal
1444
+ printf '[Journal]\nStorage=persistent\nSystemMaxUse=64M\n' | sudo tee "$_JRN_CONF" >/dev/null
1445
+ sudo systemctl restart systemd-journald 2>/dev/null || true
1446
+ spin_ok "Persistent journal enabled (64 MB cap)"
1447
+ ulog "FIXED: persistent journal enabled"
1448
+ else
1449
+ spin_ok "Persistent journal active"
1450
+ ulog "CONFIG: journal OK"
1451
+ fi
1452
+
1453
+ # 9b. Web maintenance sudoers rule (dashboard FIX button)
1454
+ spin_start "Web maintenance sudoers rule"
1455
+ _SUDOERS_F="/etc/sudoers.d/010_plc-web-fix"
1456
+ if [[ ! -f "$_SUDOERS_F" ]]; then
1457
+ cat > /tmp/010_plc-web-fix << 'SUDOEOF'
1458
+ # Web dashboard maintenance console — allows the locked, root-owned CLI
1459
+ # to run its fix command from plc_web (User=pi). Scope: fix only.
1460
+ pi ALL=(root) NOPASSWD: /usr/local/bin/plc_checkweigher fix, /usr/local/bin/plc_checkweigher fix *
1461
+ SUDOEOF
1462
+ if sudo visudo -c -f /tmp/010_plc-web-fix &>/dev/null; then
1463
+ sudo cp /tmp/010_plc-web-fix "$_SUDOERS_F"
1464
+ sudo chmod 440 "$_SUDOERS_F"
1465
+ spin_ok "Sudoers rule installed (web FIX button enabled)"
1466
+ ulog "FIXED: web maintenance sudoers rule installed"
1467
+ else
1468
+ spin_warn "Sudoers rule failed validation — skipped"
1469
+ ulog "WARN: sudoers rule validation failed"
1470
+ fi
1471
+ rm -f /tmp/010_plc-web-fix
1472
+ else
1473
+ spin_ok "Sudoers rule present"
1474
+ ulog "CONFIG: web sudoers OK"
1475
+ fi
1476
+
1477
+ # 9. lightdm must not wait on deprecated udev-settle (~2.4 s saved)
1478
+ spin_start "lightdm boot dependency"
1479
+ _LDM_DROPIN="/etc/systemd/system/lightdm.service.d/display-priority.conf"
1480
+ if [[ -f "$_LDM_DROPIN" ]] && grep -q "udev-settle" "$_LDM_DROPIN"; then
1481
+ sudo sed -i 's/^After=systemd-udev-settle.service /After=/' "$_LDM_DROPIN"
1482
+ sudo sed -i '/^Wants=systemd-udev-settle.service/d' "$_LDM_DROPIN"
1483
+ sudo systemctl daemon-reload
1484
+ spin_ok "udev-settle wait removed from lightdm"
1485
+ ulog "FIXED: lightdm udev-settle dependency removed"
1486
+ else
1487
+ spin_ok "lightdm dependencies clean"
1488
+ ulog "CONFIG: lightdm OK"
1489
+ fi
1490
+
1491
+ # ── Restart services (only when code or unit files actually changed) ─────
1492
+ if [[ $_CODE_CHANGED -eq 1 || $_UNITS_UPDATED -eq 1 ]]; then
1493
+ spin_start "Restarting services"
1494
+ sudo systemctl restart plc_watcher plc_web 2>/dev/null
1495
+ sleep 2
1496
+ spin_ok "Services restarted"
1497
+ else
1498
+ info "No code/unit changes — services left running undisturbed"
1499
+ ulog "SERVICES: not restarted (no changes)"
1500
+ fi
1416
1501
 
1417
1502
  # ── Final status ──────────────────────────────────────────────────────────
1418
1503
  echo ""
@@ -1601,6 +1686,7 @@ uninstall)
1601
1686
  BASHRC="${HOME_DIR}/.bashrc"
1602
1687
  [[ -f "$BASHRC" ]] && sed -i '/export PATH.*\.local\/bin/d' "$BASHRC" 2>/dev/null || true
1603
1688
  sudo rm -f /usr/local/bin/plc_checkweigher
1689
+ sudo rm -f /etc/sudoers.d/010_plc-web-fix
1604
1690
  rm -f "${HOME_DIR}/.local/bin/plc_checkweigher" 2>/dev/null || true
1605
1691
  if [[ "${KEEP_REPORTS^^}" != "Y" && -d "$REPORTS_DIR" ]]; then
1606
1692
  rm -rf "$REPORTS_DIR"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plc-checkweigher",
3
- "version": "1.24.0",
3
+ "version": "1.28.0",
4
4
  "description": "One-command installer for the PLC Check-Weigher system on Raspberry Pi (PREEMPT_RT kernel, Python stack, WiFi, SMB, systemd RT services)",
5
5
  "scripts": {
6
6
  "postinstall": "node bin/cli.js"
package/setup.sh CHANGED
@@ -168,6 +168,22 @@ install_cli() {
168
168
  else
169
169
  warn "bin/plc_checkweigher not found — skipping CLI install"
170
170
  fi
171
+
172
+ # Scoped sudoers rule: web dashboard maintenance console can run the
173
+ # locked root-owned CLI's fix command (and nothing else) without password.
174
+ cat > /tmp/010_plc-web-fix << 'EOF'
175
+ # Web dashboard maintenance console — allows the locked, root-owned CLI
176
+ # to run its fix command from plc_web (User=pi). Scope: fix only.
177
+ pi ALL=(root) NOPASSWD: /usr/local/bin/plc_checkweigher fix, /usr/local/bin/plc_checkweigher fix *
178
+ EOF
179
+ if visudo -c -f /tmp/010_plc-web-fix &>/dev/null; then
180
+ cp /tmp/010_plc-web-fix /etc/sudoers.d/010_plc-web-fix
181
+ chmod 440 /etc/sudoers.d/010_plc-web-fix
182
+ ok "Web maintenance sudoers rule installed (fix only, validated)"
183
+ else
184
+ warn "sudoers rule failed validation — web FIX button will not work"
185
+ fi
186
+ rm -f /tmp/010_plc-web-fix
171
187
  }
172
188
 
173
189
  # ── 5. WiFi — scan → pick → password ─────────────────────────────────────────
@@ -545,8 +561,7 @@ setup_display() {
545
561
  cat > /etc/systemd/system/lightdm.service.d/display-priority.conf << 'EOF'
546
562
  [Unit]
547
563
  # Start after hardware udev settles (HDMI/DSI detected) — not after network.
548
- After=systemd-udev-settle.service local-fs.target acpid.socket dbus.service
549
- Wants=systemd-udev-settle.service
564
+ After=local-fs.target acpid.socket dbus.service
550
565
  # StartLimit* MUST be in [Unit] — ignored in [Service].
551
566
  StartLimitBurst=10
552
567
  StartLimitIntervalSec=60
@@ -730,6 +745,34 @@ setup_system_optimize() {
730
745
  || echo "dtoverlay=disable-bt" >> "${BOOT_FW}/config.txt"
731
746
  ok "Bluetooth radio disabled at boot (dtoverlay=disable-bt)"
732
747
 
748
+ # setserial hangs at boot on the RT kernel ("Loading the saved-state of
749
+ # the serial devices...") and blocks multi-user.target forever. Mask it —
750
+ # PLC comms are TCP; nothing here needs serial port tuning.
751
+ systemctl mask --now setserial.service &>/dev/null || true
752
+ ok "setserial masked (hangs on RT kernel, blocks boot completion)"
753
+
754
+ # Fast, bounded shutdown — no unit may hold a reboot longer than 10 s
755
+ # (systemd default is 90 s per unit; one hung service = very slow poweroff).
756
+ # plc_watcher keeps its own TimeoutStopSec=10 for batch finalization;
757
+ # going below 10 s globally risks cutting off journald/fs sync on SD card.
758
+ mkdir -p /etc/systemd/system.conf.d
759
+ cat > /etc/systemd/system.conf.d/plc-shutdown.conf << 'EOF'
760
+ [Manager]
761
+ DefaultTimeoutStopSec=10s
762
+ EOF
763
+ ok "Shutdown timeout capped at 10 s per unit"
764
+
765
+ # Persistent journal (capped at 64 MB) — boot/shutdown logs survive
766
+ # reboots so hangs and crashes can actually be diagnosed afterwards
767
+ mkdir -p /etc/systemd/journald.conf.d /var/log/journal
768
+ cat > /etc/systemd/journald.conf.d/plc-journal.conf << 'EOF'
769
+ [Journal]
770
+ Storage=persistent
771
+ SystemMaxUse=64M
772
+ EOF
773
+ systemd-tmpfiles --create --prefix /var/log/journal 2>/dev/null || true
774
+ ok "Persistent journal enabled (max 64 MB)"
775
+
733
776
  ok "System optimized — PLC stack, WiFi, SSH, Pi Connect untouched"
734
777
  }
735
778