plc-checkweigher 1.16.0 → 1.17.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/bin/plc_checkweigher +455 -53
- package/package.json +1 -1
- package/setup.sh +55 -16
package/bin/plc_checkweigher
CHANGED
|
@@ -151,7 +151,16 @@ case "$CMD" in
|
|
|
151
151
|
|
|
152
152
|
# ── System diagnostic ─────────────────────────────────────────────────────────
|
|
153
153
|
status|check|diag)
|
|
154
|
-
|
|
154
|
+
set +e
|
|
155
|
+
"${PYTHON}" "${INSTALL_DIR}/debugger.py" "$@"
|
|
156
|
+
_STATUS_EXIT=$?
|
|
157
|
+
set -e
|
|
158
|
+
if [[ $_STATUS_EXIT -ne 0 ]]; then
|
|
159
|
+
echo ""
|
|
160
|
+
warn "Errors detected — starting auto-fix ..."
|
|
161
|
+
sleep 1
|
|
162
|
+
"$0" fix
|
|
163
|
+
fi
|
|
155
164
|
;;
|
|
156
165
|
|
|
157
166
|
# ── Live logs ─────────────────────────────────────────────────────────────────
|
|
@@ -577,7 +586,326 @@ smb-config)
|
|
|
577
586
|
;;
|
|
578
587
|
|
|
579
588
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
580
|
-
#
|
|
589
|
+
# FIX — auto-detect and repair common issues
|
|
590
|
+
# Usage: fix [-wifi] [-health] [-programs] (no flags = run all)
|
|
591
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
592
|
+
fix)
|
|
593
|
+
FIX_WIFI=0; FIX_HEALTH=0; FIX_PROGRAMS=0
|
|
594
|
+
if [[ $# -eq 0 ]]; then
|
|
595
|
+
FIX_WIFI=1; FIX_HEALTH=1; FIX_PROGRAMS=1
|
|
596
|
+
else
|
|
597
|
+
for _flag in "$@"; do
|
|
598
|
+
case "$_flag" in
|
|
599
|
+
-wifi) FIX_WIFI=1 ;;
|
|
600
|
+
-health) FIX_HEALTH=1 ;;
|
|
601
|
+
-programs) FIX_PROGRAMS=1 ;;
|
|
602
|
+
*) warn "Unknown flag: $_flag (valid: -wifi -health -programs)" ;;
|
|
603
|
+
esac
|
|
604
|
+
done
|
|
605
|
+
fi
|
|
606
|
+
|
|
607
|
+
LOG_DIR="/home/pi/reports/logs"
|
|
608
|
+
mkdir -p "$LOG_DIR" 2>/dev/null || true
|
|
609
|
+
# Build mode tag: "all" or hyphen-joined active scopes
|
|
610
|
+
_LOG_MODES=""
|
|
611
|
+
[[ $FIX_WIFI -eq 1 ]] && _LOG_MODES="${_LOG_MODES:+${_LOG_MODES}-}wifi"
|
|
612
|
+
[[ $FIX_HEALTH -eq 1 ]] && _LOG_MODES="${_LOG_MODES:+${_LOG_MODES}-}health"
|
|
613
|
+
[[ $FIX_PROGRAMS -eq 1 ]] && _LOG_MODES="${_LOG_MODES:+${_LOG_MODES}-}programs"
|
|
614
|
+
[[ "$_LOG_MODES" == "wifi-health-programs" ]] && _LOG_MODES="all"
|
|
615
|
+
LOG_FILE="${LOG_DIR}/fix_${_LOG_MODES}_$(date '+%Y%m%d_%H%M%S').log"
|
|
616
|
+
flog() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"; }
|
|
617
|
+
ffix_ok() { spin_ok "$*"; flog "FIXED : $*"; FIX_COUNT=$((FIX_COUNT+1)); }
|
|
618
|
+
ffix_info() { spin_ok "$*"; flog "INFO : $*"; }
|
|
619
|
+
ffix_warn() { spin_warn "$*"; flog "WARN : $*"; }
|
|
620
|
+
ffix_err() { spin_err "$*"; flog "ERROR : $*"; }
|
|
621
|
+
|
|
622
|
+
FIX_COUNT=0
|
|
623
|
+
flog "=== Run started | wifi=${FIX_WIFI} health=${FIX_HEALTH} programs=${FIX_PROGRAMS} ==="
|
|
624
|
+
|
|
625
|
+
banner "Auto Fix"
|
|
626
|
+
echo ""
|
|
627
|
+
need_sudo
|
|
628
|
+
|
|
629
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
630
|
+
# WIFI
|
|
631
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
632
|
+
if [[ $FIX_WIFI -eq 1 ]]; then
|
|
633
|
+
echo -e " ${B}▸ WiFi${NC}"; hr; echo ""
|
|
634
|
+
|
|
635
|
+
spin_start "NetworkManager"
|
|
636
|
+
if ! systemctl is-active --quiet NetworkManager 2>/dev/null; then
|
|
637
|
+
sudo systemctl start NetworkManager 2>/dev/null || true; sleep 2
|
|
638
|
+
if systemctl is-active --quiet NetworkManager 2>/dev/null; then
|
|
639
|
+
ffix_ok "NetworkManager was down — restarted"
|
|
640
|
+
else
|
|
641
|
+
ffix_err "NetworkManager failed to start"
|
|
642
|
+
fi
|
|
643
|
+
else
|
|
644
|
+
ffix_info "NetworkManager running"
|
|
645
|
+
fi
|
|
646
|
+
|
|
647
|
+
spin_start "WiFi hardware block"
|
|
648
|
+
if rfkill list wifi 2>/dev/null | grep -q "Hard blocked: yes"; then
|
|
649
|
+
ffix_warn "Hard blocked — check physical WiFi switch"
|
|
650
|
+
elif rfkill list wifi 2>/dev/null | grep -q "Soft blocked: yes"; then
|
|
651
|
+
rfkill unblock wifi 2>/dev/null || true
|
|
652
|
+
ffix_ok "WiFi soft-block removed"
|
|
653
|
+
else
|
|
654
|
+
ffix_info "rfkill OK"
|
|
655
|
+
fi
|
|
656
|
+
|
|
657
|
+
spin_start "wlan0 interface"
|
|
658
|
+
if ! ip link show wlan0 &>/dev/null; then
|
|
659
|
+
ffix_warn "wlan0 not found — adapter missing?"
|
|
660
|
+
elif ! ip link show wlan0 2>/dev/null | grep -q "UP"; then
|
|
661
|
+
sudo ip link set wlan0 up 2>/dev/null || true; sleep 1
|
|
662
|
+
if ip link show wlan0 2>/dev/null | grep -q "UP"; then
|
|
663
|
+
ffix_ok "wlan0 was down — brought up"
|
|
664
|
+
else
|
|
665
|
+
ffix_err "Could not bring up wlan0"
|
|
666
|
+
fi
|
|
667
|
+
else
|
|
668
|
+
ffix_info "wlan0 UP"
|
|
669
|
+
fi
|
|
670
|
+
|
|
671
|
+
spin_start "WiFi connection"
|
|
672
|
+
_WIFI_CON=$(nmcli -t -f NAME,DEVICE,TYPE con show --active 2>/dev/null \
|
|
673
|
+
| grep ":wlan0:802-11-wireless" | cut -d: -f1 | head -1 || echo "")
|
|
674
|
+
if [[ -z "$_WIFI_CON" ]]; then
|
|
675
|
+
_LAST_CON=$(nmcli -t -f NAME,TYPE con show 2>/dev/null \
|
|
676
|
+
| grep ":802-11-wireless" | head -1 | cut -d: -f1 || echo "")
|
|
677
|
+
if [[ -n "$_LAST_CON" ]]; then
|
|
678
|
+
_spin_kill
|
|
679
|
+
spin_start "Reconnecting to '${_LAST_CON}'"
|
|
680
|
+
sudo nmcli connection up "$_LAST_CON" 2>/dev/null || true; sleep 3
|
|
681
|
+
_WIFI_NOW=$(nmcli -t -f NAME,DEVICE,TYPE con show --active 2>/dev/null \
|
|
682
|
+
| grep ":wlan0:802-11-wireless" | cut -d: -f1 | head -1 || echo "")
|
|
683
|
+
if [[ -n "$_WIFI_NOW" ]]; then
|
|
684
|
+
_NEW_IP=$(ip -4 addr show wlan0 2>/dev/null \
|
|
685
|
+
| grep -oP '(?<=inet )\d+\.\d+\.\d+\.\d+' || echo "")
|
|
686
|
+
ffix_ok "Reconnected to '${_WIFI_NOW}' (IP: ${_NEW_IP:-?})"
|
|
687
|
+
else
|
|
688
|
+
ffix_warn "Could not reconnect — run: plc_checkweigher wifi"
|
|
689
|
+
fi
|
|
690
|
+
else
|
|
691
|
+
ffix_warn "No saved connections — run: plc_checkweigher wifi"
|
|
692
|
+
fi
|
|
693
|
+
else
|
|
694
|
+
_WIFI_IP=$(ip -4 addr show wlan0 2>/dev/null \
|
|
695
|
+
| grep -oP '(?<=inet )\d+\.\d+\.\d+\.\d+' || echo "?")
|
|
696
|
+
ffix_info "'${_WIFI_CON}' (${_WIFI_IP})"
|
|
697
|
+
fi
|
|
698
|
+
|
|
699
|
+
spin_start "Internet connectivity"
|
|
700
|
+
if ping -c 2 -W 2 8.8.8.8 &>/dev/null; then
|
|
701
|
+
ffix_info "Internet reachable"
|
|
702
|
+
else
|
|
703
|
+
ffix_warn "No internet — local LAN may still work"
|
|
704
|
+
fi
|
|
705
|
+
|
|
706
|
+
echo ""
|
|
707
|
+
fi
|
|
708
|
+
|
|
709
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
710
|
+
# HEALTH
|
|
711
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
712
|
+
if [[ $FIX_HEALTH -eq 1 ]]; then
|
|
713
|
+
echo -e " ${B}▸ System Health${NC}"; hr; echo ""
|
|
714
|
+
|
|
715
|
+
spin_start "Disk space"
|
|
716
|
+
_DISK_PCT=$(df / --output=pcent 2>/dev/null | tail -1 | tr -d ' %' || echo "0")
|
|
717
|
+
if [[ "${_DISK_PCT:-0}" -ge 95 ]]; then
|
|
718
|
+
sudo journalctl --vacuum-size=100M 2>/dev/null || true
|
|
719
|
+
_DISK_AFTER=$(df / --output=pcent 2>/dev/null | tail -1 | tr -d ' %' || echo "?")
|
|
720
|
+
ffix_ok "Disk ${_DISK_PCT}% → ${_DISK_AFTER}% after journal clean"
|
|
721
|
+
elif [[ "${_DISK_PCT:-0}" -ge 85 ]]; then
|
|
722
|
+
ffix_warn "Disk ${_DISK_PCT}% — consider removing old reports"
|
|
723
|
+
else
|
|
724
|
+
ffix_info "Disk ${_DISK_PCT}%"
|
|
725
|
+
fi
|
|
726
|
+
|
|
727
|
+
spin_start "CPU temperature"
|
|
728
|
+
if command -v vcgencmd &>/dev/null; then
|
|
729
|
+
_TEMP=$(vcgencmd measure_temp 2>/dev/null | grep -oP '[\d.]+' | head -1 || echo "0")
|
|
730
|
+
_TEMP_INT=${_TEMP%.*}
|
|
731
|
+
if [[ "${_TEMP_INT:-0}" -ge 80 ]]; then
|
|
732
|
+
ffix_warn "${_TEMP}°C — check ventilation"
|
|
733
|
+
else
|
|
734
|
+
ffix_info "${_TEMP}°C"
|
|
735
|
+
fi
|
|
736
|
+
else
|
|
737
|
+
ffix_info "Temperature check not available"
|
|
738
|
+
fi
|
|
739
|
+
|
|
740
|
+
spin_start "Memory"
|
|
741
|
+
_MEM_FREE=$(free -m 2>/dev/null | awk '/^Mem:/{print $7}' || echo "999")
|
|
742
|
+
_MEM_TOTAL=$(free -m 2>/dev/null | awk '/^Mem:/{print $2}' || echo "1")
|
|
743
|
+
if [[ "${_MEM_FREE:-999}" -lt 50 ]]; then
|
|
744
|
+
echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null 2>&1 || true
|
|
745
|
+
_MEM_AFTER=$(free -m 2>/dev/null | awk '/^Mem:/{print $7}' || echo "?")
|
|
746
|
+
ffix_ok "Low memory ${_MEM_FREE}MB → ${_MEM_AFTER}MB after cache drop"
|
|
747
|
+
else
|
|
748
|
+
ffix_info "${_MEM_FREE}MB / ${_MEM_TOTAL}MB free"
|
|
749
|
+
fi
|
|
750
|
+
|
|
751
|
+
spin_start "System time"
|
|
752
|
+
if timedatectl status 2>/dev/null | grep -q "synchronized: yes"; then
|
|
753
|
+
ffix_info "NTP synchronized"
|
|
754
|
+
else
|
|
755
|
+
sudo timedatectl set-ntp true 2>/dev/null || true
|
|
756
|
+
command -v chronyc &>/dev/null && sudo chronyc makestep 2>/dev/null || true
|
|
757
|
+
sleep 2
|
|
758
|
+
if timedatectl status 2>/dev/null | grep -q "synchronized: yes"; then
|
|
759
|
+
ffix_ok "NTP sync restored"
|
|
760
|
+
else
|
|
761
|
+
ffix_warn "Time not synced — no internet?"
|
|
762
|
+
fi
|
|
763
|
+
fi
|
|
764
|
+
|
|
765
|
+
spin_start "Reports directory"
|
|
766
|
+
_REPORTS_DIR="/home/pi/reports"
|
|
767
|
+
if [[ ! -d "$_REPORTS_DIR" ]]; then
|
|
768
|
+
mkdir -p "$_REPORTS_DIR" 2>/dev/null && ffix_ok "Created ${_REPORTS_DIR}" \
|
|
769
|
+
|| ffix_warn "Could not create ${_REPORTS_DIR}"
|
|
770
|
+
else
|
|
771
|
+
ffix_info "${_REPORTS_DIR} OK"
|
|
772
|
+
fi
|
|
773
|
+
|
|
774
|
+
spin_start "SMB config file"
|
|
775
|
+
if [[ ! -f "$SMB_CFG" ]]; then
|
|
776
|
+
printf 'SMB_ENABLED = False\nSMB_HOST = ""\nSMB_SHARE = "Reports"\nSMB_USERNAME = ""\nSMB_PASSWORD = ""\nSMB_SUBDIR = ""\n' \
|
|
777
|
+
> "$SMB_CFG" 2>/dev/null
|
|
778
|
+
ffix_ok "Created default smb_config.py (disabled — run: plc_checkweigher smb-config)"
|
|
779
|
+
else
|
|
780
|
+
ffix_info "smb_config.py present"
|
|
781
|
+
fi
|
|
782
|
+
|
|
783
|
+
echo ""
|
|
784
|
+
fi
|
|
785
|
+
|
|
786
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
787
|
+
# PROGRAMS
|
|
788
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
789
|
+
if [[ $FIX_PROGRAMS -eq 1 ]]; then
|
|
790
|
+
echo -e " ${B}▸ Programs & Services${NC}"; hr; echo ""
|
|
791
|
+
|
|
792
|
+
for _SVC in plc_watcher plc_web; do
|
|
793
|
+
spin_start "${_SVC}"
|
|
794
|
+
_SVC_STATE=$(systemctl is-active "$_SVC" 2>/dev/null || echo "inactive")
|
|
795
|
+
if [[ "$_SVC_STATE" != "active" ]]; then
|
|
796
|
+
sudo systemctl enable "$_SVC" 2>/dev/null || true
|
|
797
|
+
sudo systemctl restart "$_SVC" 2>/dev/null || true; sleep 2
|
|
798
|
+
_SVC_NOW=$(systemctl is-active "$_SVC" 2>/dev/null || echo "inactive")
|
|
799
|
+
if [[ "$_SVC_NOW" == "active" ]]; then
|
|
800
|
+
ffix_ok "${_SVC} restarted (was: ${_SVC_STATE})"
|
|
801
|
+
else
|
|
802
|
+
ffix_err "${_SVC} failed — check: journalctl -u ${_SVC} -n 30"
|
|
803
|
+
fi
|
|
804
|
+
else
|
|
805
|
+
ffix_info "${_SVC} active"
|
|
806
|
+
fi
|
|
807
|
+
done
|
|
808
|
+
|
|
809
|
+
spin_start "Python venv"
|
|
810
|
+
if [[ ! -x "$PYTHON" ]]; then
|
|
811
|
+
ffix_err "Venv missing at ${PYTHON} — re-run installer"
|
|
812
|
+
else
|
|
813
|
+
ffix_info "Venv OK"
|
|
814
|
+
fi
|
|
815
|
+
|
|
816
|
+
spin_start "Python packages"
|
|
817
|
+
_PKG_MISSING=""
|
|
818
|
+
for _pkg in flask reportlab pymcprotocol impacket; do
|
|
819
|
+
"${PYTHON}" -c "import ${_pkg}" &>/dev/null 2>&1 || _PKG_MISSING="${_PKG_MISSING} ${_pkg}"
|
|
820
|
+
done
|
|
821
|
+
if [[ -n "$_PKG_MISSING" ]]; then
|
|
822
|
+
_spin_kill
|
|
823
|
+
spin_start "Installing:${_PKG_MISSING}"
|
|
824
|
+
"${PYTHON}" -m pip install ${_PKG_MISSING} --quiet 2>/dev/null || true
|
|
825
|
+
_PKG_STILL=""
|
|
826
|
+
for _pkg in ${_PKG_MISSING}; do
|
|
827
|
+
"${PYTHON}" -c "import ${_pkg}" &>/dev/null 2>&1 || _PKG_STILL="${_PKG_STILL} ${_pkg}"
|
|
828
|
+
done
|
|
829
|
+
if [[ -z "$_PKG_STILL" ]]; then
|
|
830
|
+
ffix_ok "Installed:${_PKG_MISSING}"
|
|
831
|
+
else
|
|
832
|
+
ffix_warn "Could not install:${_PKG_STILL}"
|
|
833
|
+
fi
|
|
834
|
+
else
|
|
835
|
+
ffix_info "All packages present"
|
|
836
|
+
fi
|
|
837
|
+
|
|
838
|
+
spin_start "Delivery queue"
|
|
839
|
+
_QUEUE="${INSTALL_DIR}/delivery_queue.json"
|
|
840
|
+
if [[ ! -f "$_QUEUE" ]]; then
|
|
841
|
+
echo "[]" > "$_QUEUE"
|
|
842
|
+
ffix_ok "Created missing delivery_queue.json"
|
|
843
|
+
elif ! "${PYTHON}" -c "import json; json.load(open('${_QUEUE}'))" &>/dev/null 2>&1; then
|
|
844
|
+
mv "$_QUEUE" "${_QUEUE}.broken.$(date +%s)" 2>/dev/null || true
|
|
845
|
+
echo "[]" > "$_QUEUE"
|
|
846
|
+
ffix_ok "Corrupt delivery queue reset (backup saved)"
|
|
847
|
+
else
|
|
848
|
+
ffix_info "delivery_queue.json valid"
|
|
849
|
+
fi
|
|
850
|
+
|
|
851
|
+
spin_start "systemd unit files"
|
|
852
|
+
_RESTORED=""
|
|
853
|
+
for _src in "${INSTALL_DIR}/plc_watcher.service" "${INSTALL_DIR}/web/plc_web.service"; do
|
|
854
|
+
[[ ! -f "$_src" ]] && continue
|
|
855
|
+
_dst="/etc/systemd/system/$(basename "$_src")"
|
|
856
|
+
if [[ ! -f "$_dst" ]]; then
|
|
857
|
+
sudo cp "$_src" "$_dst" 2>/dev/null || true
|
|
858
|
+
_RESTORED="${_RESTORED} $(basename "$_src")"
|
|
859
|
+
fi
|
|
860
|
+
done
|
|
861
|
+
if [[ -n "$_RESTORED" ]]; then
|
|
862
|
+
sudo systemctl daemon-reload 2>/dev/null || true
|
|
863
|
+
ffix_ok "Restored:${_RESTORED}"
|
|
864
|
+
else
|
|
865
|
+
ffix_info "Unit files present"
|
|
866
|
+
fi
|
|
867
|
+
|
|
868
|
+
echo ""
|
|
869
|
+
fi
|
|
870
|
+
|
|
871
|
+
# ── Summary ───────────────────────────────────────────────────────────────
|
|
872
|
+
flog "=== Complete: ${FIX_COUNT} fix(es) applied ==="
|
|
873
|
+
hr
|
|
874
|
+
echo ""
|
|
875
|
+
if [[ $FIX_COUNT -gt 0 ]]; then
|
|
876
|
+
ok "${FIX_COUNT} fix(es) applied"
|
|
877
|
+
else
|
|
878
|
+
ok "All checks passed — no fixes needed"
|
|
879
|
+
fi
|
|
880
|
+
info "Log: ${LOG_FILE}"
|
|
881
|
+
|
|
882
|
+
# ── Push log to SMB share ─────────────────────────────────────────────────
|
|
883
|
+
_SMB_HOST=$(smb_get "SMB_HOST")
|
|
884
|
+
_SMB_SHARE=$(smb_get "SMB_SHARE")
|
|
885
|
+
_SMB_USER=$(smb_get "SMB_USERNAME")
|
|
886
|
+
_SMB_PASS=$(smb_get "SMB_PASSWORD")
|
|
887
|
+
_SMB_EN=$(grep "^SMB_ENABLED" "${SMB_CFG}" 2>/dev/null | grep -qi "true" && echo "1" || echo "0")
|
|
888
|
+
|
|
889
|
+
if [[ "$_SMB_EN" == "1" && -n "$_SMB_HOST" && -n "$_SMB_USER" ]] \
|
|
890
|
+
&& command -v smbclient &>/dev/null; then
|
|
891
|
+
spin_start "Uploading log to SMB share"
|
|
892
|
+
_LOG_BASENAME="$(basename "$LOG_FILE")"
|
|
893
|
+
if smbclient "//${_SMB_HOST}/${_SMB_SHARE}" \
|
|
894
|
+
-U "${_SMB_USER}%${_SMB_PASS}" \
|
|
895
|
+
-c "mkdir logs; put ${LOG_FILE} logs/${_LOG_BASENAME}" &>/dev/null 2>&1; then
|
|
896
|
+
spin_ok "Log pushed → //${_SMB_HOST}/${_SMB_SHARE}/logs/${_LOG_BASENAME}"
|
|
897
|
+
flog "INFO : Log uploaded to SMB //${_SMB_HOST}/${_SMB_SHARE}/logs/${_LOG_BASENAME}"
|
|
898
|
+
else
|
|
899
|
+
spin_warn "SMB upload failed — log saved locally only"
|
|
900
|
+
flog "WARN : SMB log upload failed"
|
|
901
|
+
fi
|
|
902
|
+
fi
|
|
903
|
+
|
|
904
|
+
echo ""
|
|
905
|
+
;;
|
|
906
|
+
|
|
907
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
908
|
+
# UNINSTALL — two modes: software-only or full drive wipe
|
|
581
909
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
582
910
|
uninstall)
|
|
583
911
|
PI_USER="${PI_USER:-pi}"
|
|
@@ -591,46 +919,83 @@ uninstall)
|
|
|
591
919
|
echo -e "${R} ║ PLC CHECK-WEIGHER UNINSTALLER ║${NC}"
|
|
592
920
|
echo -e "${R} ╚══════════════════════════════════════════════════════════╝${NC}"
|
|
593
921
|
echo ""
|
|
594
|
-
echo -e "
|
|
922
|
+
echo -e " Choose uninstall mode:"
|
|
595
923
|
echo ""
|
|
596
|
-
echo -e " ${
|
|
597
|
-
echo -e "
|
|
598
|
-
echo -e "
|
|
599
|
-
echo -e " ${R}✗${NC} CLI tool /usr/local/bin/plc_checkweigher"
|
|
600
|
-
echo -e " ${R}✗${NC} Plymouth theme saismruth (reverts to default)"
|
|
601
|
-
echo -e " ${R}✗${NC} RT kernel config (reverts /boot/firmware/config.txt)"
|
|
602
|
-
echo -e " ${R}✗${NC} LightDM drop-in /etc/systemd/system/lightdm.service.d/"
|
|
603
|
-
echo -e " ${R}✗${NC} NetworkManager cfg /etc/systemd/system/NetworkManager-wait-online.service.d/"
|
|
604
|
-
echo -e " ${R}✗${NC} Hotspot connection plc-hotspot (nmcli)"
|
|
605
|
-
echo -e " ${Y}!${NC} reports folder ${REPORTS_DIR} (you will be asked)"
|
|
924
|
+
echo -e " ${Y}1)${NC} ${W}Software only${NC}"
|
|
925
|
+
echo -e " ${D}Remove PLC services, code, venv and kernel config.${NC}"
|
|
926
|
+
echo -e " ${D}OS, user files and WiFi credentials are kept intact.${NC}"
|
|
606
927
|
echo ""
|
|
607
|
-
echo -e " ${
|
|
928
|
+
echo -e " ${R}2)${NC} ${W}Clean drive${NC} — prepare for fresh OS flash"
|
|
929
|
+
echo -e " ${D}Everything above PLUS all user data and WiFi credentials,${NC}"
|
|
930
|
+
echo -e " ${D}then zeros the entire SD card.${NC}"
|
|
931
|
+
echo -e " ${R} ⚠ The Pi will NOT boot after this. Reflash required.${NC}"
|
|
608
932
|
echo ""
|
|
609
|
-
|
|
933
|
+
|
|
934
|
+
while true; do
|
|
935
|
+
read -r -p " Mode [1 / 2]: " UNINSTALL_MODE </dev/tty
|
|
936
|
+
[[ "$UNINSTALL_MODE" == "1" || "$UNINSTALL_MODE" == "2" ]] && break
|
|
937
|
+
echo -e " ${R}Enter 1 or 2${NC}"
|
|
938
|
+
done
|
|
610
939
|
echo ""
|
|
611
940
|
|
|
612
|
-
|
|
613
|
-
|
|
941
|
+
# ── Mode-specific confirmation ────────────────────────────────────────────
|
|
942
|
+
KEEP_REPORTS="Y"
|
|
943
|
+
if [[ "$UNINSTALL_MODE" == "1" ]]; then
|
|
944
|
+
hr
|
|
945
|
+
echo ""
|
|
946
|
+
echo -e " ${R}✗${NC} systemd services plc_watcher plc_web"
|
|
947
|
+
echo -e " ${R}✗${NC} project code ${INSTALL_DIR}"
|
|
948
|
+
echo -e " ${R}✗${NC} Python venv ${VENV_DIR}"
|
|
949
|
+
echo -e " ${R}✗${NC} CLI tool plc_checkweigher"
|
|
950
|
+
echo -e " ${R}✗${NC} Plymouth theme saismruth → default"
|
|
951
|
+
echo -e " ${R}✗${NC} RT kernel config /boot/firmware/config.txt"
|
|
952
|
+
echo -e " ${Y}!${NC} reports folder ${REPORTS_DIR} (you will be asked)"
|
|
953
|
+
echo ""
|
|
954
|
+
echo -e " ${D}System packages (git, python3-venv, samba-client) NOT removed.${NC}"
|
|
955
|
+
echo ""
|
|
956
|
+
hr; echo ""
|
|
957
|
+
read -r -p " Type YES to confirm: " _CONFIRM </dev/tty
|
|
958
|
+
[[ "$_CONFIRM" == "YES" ]] || { echo " Aborted."; exit 0; }
|
|
959
|
+
echo ""
|
|
960
|
+
read -r -p " Keep report PDFs in ${REPORTS_DIR}? [Y/n]: " KEEP_REPORTS </dev/tty
|
|
961
|
+
KEEP_REPORTS="${KEEP_REPORTS:-Y}"
|
|
962
|
+
else
|
|
963
|
+
# Detect the drive that holds the root filesystem
|
|
964
|
+
_ROOT_SRC=$(findmnt -n -o SOURCE / 2>/dev/null || echo "")
|
|
965
|
+
_ROOT_DEV=$(lsblk -no pkname "$_ROOT_SRC" 2>/dev/null || echo "")
|
|
966
|
+
_ROOT_DEV_PATH="/dev/${_ROOT_DEV}"
|
|
614
967
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
968
|
+
hr; echo ""
|
|
969
|
+
echo -e " ${R}⚠ DESTRUCTIVE — READ CAREFULLY${NC}"
|
|
970
|
+
echo ""
|
|
971
|
+
echo -e " ${R}✗${NC} All PLC software, services and kernel config"
|
|
972
|
+
echo -e " ${R}✗${NC} All reports, logs and SMB credentials"
|
|
973
|
+
echo -e " ${R}✗${NC} SSH keys, bash history, npm cache, user configs"
|
|
974
|
+
echo -e " ${R}✗${NC} All saved WiFi connections"
|
|
975
|
+
echo -e " ${R}✗${NC} Entire drive zeroed: ${W}${_ROOT_DEV_PATH}${NC}"
|
|
976
|
+
echo ""
|
|
977
|
+
echo -e " ${R}The Pi will become unresponsive during the wipe.${NC}"
|
|
978
|
+
echo -e " ${D}Power off after ~2 minutes, then reflash with Raspberry Pi Imager.${NC}"
|
|
979
|
+
echo ""
|
|
980
|
+
hr; echo ""
|
|
981
|
+
read -r -p " Type WIPE to confirm drive wipe: " _CONFIRM </dev/tty
|
|
982
|
+
[[ "$_CONFIRM" == "WIPE" ]] || { echo " Aborted."; exit 0; }
|
|
983
|
+
fi
|
|
618
984
|
|
|
619
985
|
echo ""
|
|
620
986
|
need_sudo
|
|
621
987
|
|
|
622
|
-
# Step counter
|
|
623
|
-
|
|
988
|
+
# ── Step counter (9 for software-only, 12 for clean drive) ───────────────
|
|
989
|
+
_UT=$([[ "$UNINSTALL_MODE" == "1" ]] && echo "9" || echo "12")
|
|
990
|
+
_US=0
|
|
624
991
|
ustep() { _US=$((_US + 1)); spin_start "[${_US}/${_UT}] $*"; }
|
|
625
992
|
|
|
626
993
|
# ── 1. Stop and disable services ─────────────────────────────────────────
|
|
627
994
|
echo ""
|
|
628
995
|
ustep "Stopping and disabling services"
|
|
629
996
|
for SVC in plc_watcher plc_web; do
|
|
630
|
-
systemctl is-active
|
|
631
|
-
|
|
632
|
-
systemctl is-enabled --quiet "$SVC" 2>/dev/null \
|
|
633
|
-
&& sudo systemctl disable "$SVC" 2>/dev/null || true
|
|
997
|
+
systemctl is-active --quiet "$SVC" 2>/dev/null && sudo systemctl stop "$SVC" 2>/dev/null || true
|
|
998
|
+
systemctl is-enabled --quiet "$SVC" 2>/dev/null && sudo systemctl disable "$SVC" 2>/dev/null || true
|
|
634
999
|
done
|
|
635
1000
|
sudo rm -f /etc/systemd/system/plc_watcher.service \
|
|
636
1001
|
/etc/systemd/system/plc_web.service
|
|
@@ -657,27 +1022,23 @@ uninstall)
|
|
|
657
1022
|
fi
|
|
658
1023
|
spin_ok "Reverted to '${DEFAULT_THEME:-default}'"
|
|
659
1024
|
|
|
660
|
-
# ── 4. Rebuild initramfs
|
|
1025
|
+
# ── 4. Rebuild initramfs ─────────────────────────────────────────────────
|
|
661
1026
|
ustep "Rebuilding initramfs ${D}(~30 s)${NC}"
|
|
662
1027
|
sudo update-initramfs -u > /tmp/uninstall_initramfs.log 2>&1 \
|
|
663
|
-
&& spin_ok
|
|
664
|
-
|| spin_warn "Warnings — see /tmp/uninstall_initramfs.log"
|
|
1028
|
+
&& spin_ok || spin_warn "Warnings — see /tmp/uninstall_initramfs.log"
|
|
665
1029
|
|
|
666
1030
|
# ── 5. RT kernel revert ──────────────────────────────────────────────────
|
|
667
1031
|
ustep "Reverting RT kernel config"
|
|
668
1032
|
if [[ -f "${BOOT_FW}/config.txt" ]]; then
|
|
669
|
-
sudo sed -i '/### PLC-RT-BLOCK-START ###/,/### PLC-RT-BLOCK-END ###/d'
|
|
670
|
-
"${BOOT_FW}/config.txt"
|
|
1033
|
+
sudo sed -i '/### PLC-RT-BLOCK-START ###/,/### PLC-RT-BLOCK-END ###/d' "${BOOT_FW}/config.txt"
|
|
671
1034
|
sudo sed -i '/^gpu_mem=128$/d' "${BOOT_FW}/config.txt"
|
|
672
|
-
sudo rm -f "${BOOT_FW}/kernel8-rt.img"
|
|
673
|
-
|
|
674
|
-
"${BOOT_FW}/kernel8-stock.img"
|
|
675
|
-
spin_ok "Stock kernel will boot after reboot"
|
|
1035
|
+
sudo rm -f "${BOOT_FW}/kernel8-rt.img" "${BOOT_FW}/initramfs8-rt" "${BOOT_FW}/kernel8-stock.img"
|
|
1036
|
+
spin_ok "Stock kernel restored"
|
|
676
1037
|
else
|
|
677
1038
|
spin_warn "config.txt not found — skipped"
|
|
678
1039
|
fi
|
|
679
1040
|
|
|
680
|
-
# ── 6.
|
|
1041
|
+
# ── 6. Network cleanup ───────────────────────────────────────────────────
|
|
681
1042
|
ustep "Cleaning up network connections"
|
|
682
1043
|
sudo nmcli connection delete "plc-hotspot" 2>/dev/null || true
|
|
683
1044
|
sudo systemctl daemon-reload
|
|
@@ -685,15 +1046,10 @@ uninstall)
|
|
|
685
1046
|
|
|
686
1047
|
# ── 7. Python venv ───────────────────────────────────────────────────────
|
|
687
1048
|
ustep "Removing Python environment"
|
|
688
|
-
|
|
689
|
-
rm -rf "$VENV_DIR"
|
|
690
|
-
spin_ok "Removed ${VENV_DIR}"
|
|
691
|
-
else
|
|
692
|
-
spin_ok "Already gone"
|
|
693
|
-
fi
|
|
1049
|
+
[[ -d "$VENV_DIR" ]] && rm -rf "$VENV_DIR" && spin_ok "Removed ${VENV_DIR}" || spin_ok "Already gone"
|
|
694
1050
|
|
|
695
|
-
# ── 8.
|
|
696
|
-
ustep "Cleaning up runtime files"
|
|
1051
|
+
# ── 8. Runtime files + CLI ───────────────────────────────────────────────
|
|
1052
|
+
ustep "Cleaning up runtime files and CLI"
|
|
697
1053
|
rm -f /tmp/plc_live.json 2>/dev/null || true
|
|
698
1054
|
BASHRC="${HOME_DIR}/.bashrc"
|
|
699
1055
|
[[ -f "$BASHRC" ]] && sed -i '/export PATH.*\.local\/bin/d' "$BASHRC" 2>/dev/null || true
|
|
@@ -704,16 +1060,61 @@ uninstall)
|
|
|
704
1060
|
fi
|
|
705
1061
|
spin_ok "CLI and temp files removed"
|
|
706
1062
|
|
|
707
|
-
# ── 9.
|
|
1063
|
+
# ── 9. Project code ──────────────────────────────────────────────────────
|
|
708
1064
|
ustep "Removing project code"
|
|
709
1065
|
if [[ -d "$INSTALL_DIR" ]]; then
|
|
710
|
-
rm -rf "$INSTALL_DIR"
|
|
711
|
-
spin_ok "Removed ${INSTALL_DIR}"
|
|
1066
|
+
rm -rf "$INSTALL_DIR" && spin_ok "Removed ${INSTALL_DIR}"
|
|
712
1067
|
else
|
|
713
1068
|
spin_ok "Already gone"
|
|
714
1069
|
fi
|
|
715
1070
|
|
|
716
|
-
#
|
|
1071
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
1072
|
+
# MODE 2 ONLY: wipe all user data then zero the drive
|
|
1073
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
1074
|
+
if [[ "$UNINSTALL_MODE" == "2" ]]; then
|
|
1075
|
+
|
|
1076
|
+
# ── 10. All WiFi connections ─────────────────────────────────────────
|
|
1077
|
+
ustep "Removing all WiFi connections"
|
|
1078
|
+
nmcli -t -f NAME con show 2>/dev/null | while IFS= read -r _CON; do
|
|
1079
|
+
[[ -n "$_CON" ]] && sudo nmcli connection delete "$_CON" 2>/dev/null || true
|
|
1080
|
+
done
|
|
1081
|
+
spin_ok "All network connections cleared"
|
|
1082
|
+
|
|
1083
|
+
# ── 11. User data ────────────────────────────────────────────────────
|
|
1084
|
+
ustep "Wiping user data"
|
|
1085
|
+
rm -rf "${REPORTS_DIR}" 2>/dev/null || true
|
|
1086
|
+
rm -rf "${HOME_DIR}/.ssh" 2>/dev/null || true
|
|
1087
|
+
rm -f "${HOME_DIR}/.bash_history" 2>/dev/null || true
|
|
1088
|
+
rm -rf "${HOME_DIR}/.npm" 2>/dev/null || true
|
|
1089
|
+
rm -rf "${HOME_DIR}/.config" 2>/dev/null || true
|
|
1090
|
+
rm -rf "${HOME_DIR}/.cache" 2>/dev/null || true
|
|
1091
|
+
rm -rf "${HOME_DIR}/.local" 2>/dev/null || true
|
|
1092
|
+
spin_ok "User data cleared"
|
|
1093
|
+
|
|
1094
|
+
# ── 12. Zero the drive ───────────────────────────────────────────────
|
|
1095
|
+
ustep "Zeroing drive — ${_ROOT_DEV_PATH}"
|
|
1096
|
+
_spin_kill
|
|
1097
|
+
echo ""
|
|
1098
|
+
echo -e " ${R}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
1099
|
+
echo -e " ${R} Starting drive wipe. The system will become unresponsive.${NC}"
|
|
1100
|
+
echo -e " ${R} Power off after 2 minutes and reflash with Pi Imager.${NC}"
|
|
1101
|
+
echo -e " ${R}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
1102
|
+
echo ""
|
|
1103
|
+
for _i in 10 9 8 7 6 5 4 3 2 1; do
|
|
1104
|
+
printf "\r Wiping in %2d s ... (Ctrl-C to abort) " "$_i"
|
|
1105
|
+
sleep 1
|
|
1106
|
+
done
|
|
1107
|
+
printf '\r\033[K'
|
|
1108
|
+
echo -e " ${R}Wiping ${_ROOT_DEV_PATH} ...${NC}"
|
|
1109
|
+
echo ""
|
|
1110
|
+
sudo dd if=/dev/zero of="${_ROOT_DEV_PATH}" bs=4M status=progress 2>&1 || true
|
|
1111
|
+
# The system will have crashed by here. This line is a safety net.
|
|
1112
|
+
echo ""
|
|
1113
|
+
warn "Wipe complete — power off and reflash."
|
|
1114
|
+
exit 0
|
|
1115
|
+
fi
|
|
1116
|
+
|
|
1117
|
+
# ── Done (mode 1 only) ────────────────────────────────────────────────────
|
|
717
1118
|
echo ""
|
|
718
1119
|
echo -e "${G}"
|
|
719
1120
|
echo " ╔══════════════════════════════════════════════════════════╗"
|
|
@@ -724,13 +1125,10 @@ uninstall)
|
|
|
724
1125
|
echo -e "${NC}"
|
|
725
1126
|
[[ "${KEEP_REPORTS^^}" == "Y" ]] && info "PDFs still at: ${REPORTS_DIR} (remove manually if needed)"
|
|
726
1127
|
echo ""
|
|
727
|
-
|
|
728
1128
|
read -r -p " Reboot now? [Y/n]: " DO_REBOOT </dev/tty
|
|
729
1129
|
DO_REBOOT="${DO_REBOOT:-Y}"
|
|
730
1130
|
if [[ "${DO_REBOOT^^}" == "Y" ]]; then
|
|
731
|
-
spin_start "Rebooting"
|
|
732
|
-
sleep 1
|
|
733
|
-
sudo reboot
|
|
1131
|
+
spin_start "Rebooting"; sleep 1; sudo reboot
|
|
734
1132
|
else
|
|
735
1133
|
warn "Remember to reboot for kernel changes to take effect."
|
|
736
1134
|
echo ""
|
|
@@ -745,7 +1143,11 @@ help|--help|-h)
|
|
|
745
1143
|
echo -e "${B} plc_checkweigher${NC} — PLC Check-Weigher system CLI"
|
|
746
1144
|
echo ""
|
|
747
1145
|
echo -e " ${W}Diagnostics${NC}"
|
|
748
|
-
echo " status Full system diagnostic
|
|
1146
|
+
echo " status Full system diagnostic (auto-runs fix on errors)"
|
|
1147
|
+
echo " fix Auto-detect and repair all issues + write log"
|
|
1148
|
+
echo " fix -wifi Fix WiFi connectivity only"
|
|
1149
|
+
echo " fix -health Fix disk, memory, time, dirs"
|
|
1150
|
+
echo " fix -programs Fix services, packages, queue, unit files"
|
|
749
1151
|
echo " logs Stream live logs (plc_watcher + plc_web)"
|
|
750
1152
|
echo " queue Show SMB pending queue and delivery ledger"
|
|
751
1153
|
echo ""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plc-checkweigher",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.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
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
# 3. Clone / update repo
|
|
13
13
|
# 4. Python venv + pip install
|
|
14
14
|
# 5. Create /home/<user>/reports
|
|
15
|
-
# 6. WiFi
|
|
16
|
-
# 7. SMB
|
|
15
|
+
# 6. WiFi — scan → pick from list → password
|
|
16
|
+
# 7. SMB — enter host IP, share name, credentials → smb_config.py
|
|
17
17
|
# 8. NetworkManager-wait-online
|
|
18
18
|
# 9. systemd services (plc_watcher + plc_web)
|
|
19
|
-
# 10. Boot logo
|
|
20
|
-
# 11. Display
|
|
19
|
+
# 10. Boot logo — Plymouth theme with logo.png + "SAI SAMARTH ENGG"
|
|
20
|
+
# 11. Display — LightDM priority, CPU isolation, utmpx
|
|
21
|
+
# 11b. VS Code — priority daemon: cores 0-2, Nice=-5
|
|
21
22
|
# 12. PREEMPT_RT kernel ← installed last so only one reboot is needed
|
|
22
23
|
# 13. REBOOT
|
|
23
24
|
# =============================================================================
|
|
@@ -494,7 +495,7 @@ Nice=-5
|
|
|
494
495
|
|
|
495
496
|
LimitNOFILE=65536
|
|
496
497
|
EOF
|
|
497
|
-
ok "LightDM: CPUAffinity=0-2, Nice=-5, network dep removed"
|
|
498
|
+
ok "LightDM: CPUAffinity=0-2, Nice=-5, restarts up to 20×, network dep removed"
|
|
498
499
|
|
|
499
500
|
# ── Fix utmpx — PAM needs /run/utmp to track sessions ───────────────────
|
|
500
501
|
cat > /etc/tmpfiles.d/utmp-fix.conf << 'EOF'
|
|
@@ -503,20 +504,57 @@ EOF
|
|
|
503
504
|
systemd-tmpfiles --create /etc/tmpfiles.d/utmp-fix.conf 2>/dev/null || true
|
|
504
505
|
ok "/run/utmp fixed (utmpx PAM session tracking)"
|
|
505
506
|
|
|
506
|
-
#
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
sed -i '/### PLC-RT-BLOCK-START ###/i gpu_mem=128' "${BOOT_FW}/config.txt"
|
|
510
|
-
else
|
|
511
|
-
echo "gpu_mem=128" >> "${BOOT_FW}/config.txt"
|
|
512
|
-
fi
|
|
513
|
-
ok "gpu_mem=128 set in config.txt (128 MB VRAM)"
|
|
507
|
+
# gpu_mem is intentionally left at Pi OS firmware default.
|
|
508
|
+
# display_auto_detect=1 (already in config.txt) handles VRAM and output
|
|
509
|
+
# automatically — whether the Pi is headless or a display is connected.
|
|
514
510
|
|
|
515
511
|
systemctl daemon-reload
|
|
516
512
|
systemctl enable lightdm.service 2>/dev/null || true
|
|
517
513
|
ok "LightDM enabled — starts on every boot when display is connected"
|
|
518
514
|
}
|
|
519
515
|
|
|
516
|
+
# ── 11b. VS Code server priority ──────────────────────────────────────────────
|
|
517
|
+
setup_vscode_priority() {
|
|
518
|
+
step "VS Code server priority ..."
|
|
519
|
+
|
|
520
|
+
cat > /usr/local/bin/vscode-priority-daemon << 'DAEMON'
|
|
521
|
+
#!/usr/bin/env bash
|
|
522
|
+
# Apply CPU affinity (cores 0-2) and Nice=-5 to VS Code server processes.
|
|
523
|
+
# Core 3 is reserved exclusively for the SCHED_FIFO PLC process.
|
|
524
|
+
# Runs every 60s so newly-spawned extension host processes are caught promptly.
|
|
525
|
+
while true; do
|
|
526
|
+
mapfile -t pids < <(pgrep -u pi -f '\.vscode-server' 2>/dev/null || true)
|
|
527
|
+
for pid in "${pids[@]}"; do
|
|
528
|
+
taskset -cp 0-2 "$pid" >/dev/null 2>&1 || true
|
|
529
|
+
renice -n -5 -p "$pid" >/dev/null 2>&1 || true
|
|
530
|
+
done
|
|
531
|
+
sleep 60
|
|
532
|
+
done
|
|
533
|
+
DAEMON
|
|
534
|
+
chmod +x /usr/local/bin/vscode-priority-daemon
|
|
535
|
+
|
|
536
|
+
cat > /etc/systemd/system/vscode-priority.service << 'EOF'
|
|
537
|
+
[Unit]
|
|
538
|
+
Description=VS Code Server priority manager (cores 0-2, Nice=-5)
|
|
539
|
+
After=multi-user.target
|
|
540
|
+
Wants=multi-user.target
|
|
541
|
+
|
|
542
|
+
[Service]
|
|
543
|
+
Type=simple
|
|
544
|
+
ExecStart=/usr/local/bin/vscode-priority-daemon
|
|
545
|
+
Restart=always
|
|
546
|
+
RestartSec=10
|
|
547
|
+
User=root
|
|
548
|
+
|
|
549
|
+
[Install]
|
|
550
|
+
WantedBy=multi-user.target
|
|
551
|
+
EOF
|
|
552
|
+
|
|
553
|
+
systemctl daemon-reload
|
|
554
|
+
systemctl enable vscode-priority.service
|
|
555
|
+
ok "vscode-priority.service (cores 0-2, Nice=-5) — starts on every boot"
|
|
556
|
+
}
|
|
557
|
+
|
|
520
558
|
# ── 12. RT kernel — installed LAST so only one reboot is needed ───────────────
|
|
521
559
|
install_rt_kernel() {
|
|
522
560
|
step "PREEMPT_RT kernel (final step before reboot) ..."
|
|
@@ -621,9 +659,10 @@ main() {
|
|
|
621
659
|
setup_smb # 7 — interactive SMB config → smb_config.py
|
|
622
660
|
setup_network_online # 8
|
|
623
661
|
install_services # 9
|
|
624
|
-
setup_boot_logo #
|
|
625
|
-
setup_display #
|
|
626
|
-
|
|
662
|
+
setup_boot_logo # 10 — Plymouth: logo + "SAI SAMARTH ENGG"
|
|
663
|
+
setup_display # 11 — LightDM priority, CPU isolation, utmpx
|
|
664
|
+
setup_vscode_priority # 11b — VS Code: cores 0-2, Nice=-5
|
|
665
|
+
install_rt_kernel # 12 — LAST, so only one reboot needed
|
|
627
666
|
do_reboot # 12 — single reboot applies everything
|
|
628
667
|
}
|
|
629
668
|
|