Initial import: WebAisMap
Closes TG-4 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=AIS Map Network Init (AP/WiFi with rollback)
|
||||
After=network-pre.target
|
||||
Before=network.target hostapd.service
|
||||
Wants=network-pre.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/opt/aismap/scripts/network_init.sh
|
||||
TimeoutStartSec=60
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Install AIS Map network scripts and systemd service.
|
||||
# Run as root on the target device.
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
INSTALL_DIR="/opt/aismap/scripts"
|
||||
CONFIG_DIR="/etc/aismap"
|
||||
CONFIG_FILE="$CONFIG_DIR/network.json"
|
||||
HOSTAPD_CONF="/etc/hostapd/hostapd.conf"
|
||||
|
||||
echo "=== AIS Map network scripts installer ==="
|
||||
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
mkdir -p "$CONFIG_DIR"
|
||||
|
||||
echo "[1] Copying scripts to $INSTALL_DIR ..."
|
||||
cp "$SCRIPT_DIR/to_wifi.sh" "$INSTALL_DIR/"
|
||||
cp "$SCRIPT_DIR/to_ap.sh" "$INSTALL_DIR/"
|
||||
cp "$SCRIPT_DIR/network_init.sh" "$INSTALL_DIR/"
|
||||
chmod +x "$INSTALL_DIR"/*.sh
|
||||
|
||||
echo "[2] Creating default config (if not exists) ..."
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
# Read current AP settings from hostapd.conf
|
||||
AP_SSID=""
|
||||
AP_PSK=""
|
||||
AP_IFACE="wlan0"
|
||||
if [ -f "$HOSTAPD_CONF" ]; then
|
||||
AP_SSID=$(grep -E '^ssid=' "$HOSTAPD_CONF" | head -1 | cut -d= -f2 || echo "")
|
||||
AP_PSK=$(grep -E '^wpa_passphrase=' "$HOSTAPD_CONF" | head -1 | cut -d= -f2 || echo "")
|
||||
AP_IFACE=$(grep -E '^interface=' "$HOSTAPD_CONF" | head -1 | cut -d= -f2 || echo "wlan0")
|
||||
echo " Read from hostapd.conf: SSID=$AP_SSID, iface=$AP_IFACE"
|
||||
fi
|
||||
|
||||
cat > "$CONFIG_FILE" <<EOF
|
||||
{
|
||||
"mode": "ap",
|
||||
"wifi_ssid": "",
|
||||
"wifi_psk": "",
|
||||
"wifi_ip": "192.168.22.50/24",
|
||||
"wifi_gw": "192.168.22.1",
|
||||
"wifi_dns": "8.8.8.8",
|
||||
"ap_ip": "192.168.4.1/24",
|
||||
"ap_ssid": "$AP_SSID",
|
||||
"ap_psk": "$AP_PSK",
|
||||
"iface": "$AP_IFACE"
|
||||
}
|
||||
EOF
|
||||
echo " Created $CONFIG_FILE"
|
||||
else
|
||||
echo " Config already exists, skipping"
|
||||
fi
|
||||
|
||||
echo "[3] Installing systemd service ..."
|
||||
cp "$SCRIPT_DIR/aismap-network.service" /etc/systemd/system/
|
||||
systemctl daemon-reload
|
||||
systemctl enable aismap-network.service
|
||||
echo " Service enabled: aismap-network.service"
|
||||
|
||||
echo "[4] Disabling conflicting services (optional) ..."
|
||||
# We manage hostapd manually — prevent it from auto-starting
|
||||
systemctl disable hostapd 2>/dev/null || true
|
||||
echo " hostapd auto-start disabled (we start it from to_ap.sh)"
|
||||
|
||||
echo ""
|
||||
echo "=== Installation complete ==="
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " - Web UI: open Settings tab -> 'Сеть / Режим работы'"
|
||||
echo " - Manual switch to WiFi: bash $INSTALL_DIR/to_wifi.sh"
|
||||
echo " - Manual switch to AP: bash $INSTALL_DIR/to_ap.sh"
|
||||
echo " - Config file: $CONFIG_FILE"
|
||||
echo " - Boot init logs: /var/log/aismap_network_init.log"
|
||||
echo " - Hostapd backup: ${HOSTAPD_CONF}.orig (created on first AP switch)"
|
||||
echo ""
|
||||
echo "On next reboot, network_init.sh will run automatically."
|
||||
echo "If WiFi fails, it will roll back to AP mode."
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# AIS Map network init — runs at boot.
|
||||
# Reads /etc/aismap/network.json, tries the configured mode.
|
||||
# If mode=wifi and connection fails — rolls back to AP.
|
||||
#
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
CONFIG="/etc/aismap/network.json"
|
||||
LOG="/var/log/aismap_network_init.log"
|
||||
exec >"$LOG" 2>&1
|
||||
|
||||
echo "=== $(date) network_init start ==="
|
||||
|
||||
if [ ! -f "$CONFIG" ]; then
|
||||
echo "Config not found ($CONFIG), defaulting to AP mode"
|
||||
bash "$SCRIPT_DIR/to_ap.sh"
|
||||
echo "=== $(date) network_init done (default AP) ==="
|
||||
exit 0
|
||||
fi
|
||||
|
||||
MODE=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('mode','ap'))" 2>/dev/null || echo "ap")
|
||||
echo "Configured mode: $MODE"
|
||||
|
||||
if [ "$MODE" = "wifi" ]; then
|
||||
echo "--- Attempting WiFi connection ---"
|
||||
bash "$SCRIPT_DIR/to_wifi.sh"
|
||||
WIFI_EXIT=$?
|
||||
|
||||
if [ $WIFI_EXIT -ne 0 ]; then
|
||||
echo "to_wifi.sh failed (exit $WIFI_EXIT) — rolling back to AP"
|
||||
bash "$SCRIPT_DIR/to_ap.sh"
|
||||
echo "=== $(date) network_init done (rollback to AP) ==="
|
||||
exit 0
|
||||
fi
|
||||
|
||||
GW=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('wifi_gw',''))" 2>/dev/null || echo "")
|
||||
IFACE=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('iface','wlan0'))" 2>/dev/null || echo "wlan0")
|
||||
|
||||
echo "Verifying WiFi connectivity (gateway: $GW) ..."
|
||||
CONNECTED=0
|
||||
for ATTEMPT in 1 2 3; do
|
||||
sleep 3
|
||||
if [ -n "$GW" ] && ping -c 2 -W 3 "$GW" >/dev/null 2>&1; then
|
||||
echo "Attempt $ATTEMPT: gateway reachable"
|
||||
CONNECTED=1
|
||||
break
|
||||
fi
|
||||
# Also check wpa_supplicant state
|
||||
if wpa_cli -i "$IFACE" status 2>/dev/null | grep -q "wpa_state=COMPLETED"; then
|
||||
echo "Attempt $ATTEMPT: wpa_supplicant COMPLETED"
|
||||
CONNECTED=1
|
||||
break
|
||||
fi
|
||||
echo "Attempt $ATTEMPT: not connected yet..."
|
||||
done
|
||||
|
||||
if [ $CONNECTED -eq 1 ]; then
|
||||
echo "WiFi connection confirmed"
|
||||
echo "=== $(date) network_init done (wifi) ==="
|
||||
exit 0
|
||||
else
|
||||
echo "WiFi NOT reachable after 3 attempts — rolling back to AP"
|
||||
bash "$SCRIPT_DIR/to_ap.sh"
|
||||
echo "=== $(date) network_init done (rollback to AP) ==="
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
echo "--- Starting AP mode ---"
|
||||
bash "$SCRIPT_DIR/to_ap.sh"
|
||||
echo "=== $(date) network_init done (ap) ==="
|
||||
exit 0
|
||||
fi
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Короткий импульс на GPIO (Linux + gpiod). Пример для Orange Pi: скопируйте на устройство и укажите путь в настройках транспондера."""
|
||||
import os
|
||||
import time
|
||||
|
||||
try:
|
||||
import gpiod
|
||||
except ImportError:
|
||||
raise SystemExit("Нужен пакет gpiod (python3-libgpiod)") from None
|
||||
|
||||
CHIP = os.environ.get("AIS_TX_GPIO_CHIP", "/dev/gpiochip1")
|
||||
LINE = int(os.environ.get("AIS_TX_GPIO_LINE", "0"))
|
||||
PULSE_US = int(os.environ.get("AIS_TX_PULSE_US", "1000"))
|
||||
|
||||
with gpiod.request_lines(
|
||||
CHIP,
|
||||
consumer="ais-tx-pulse",
|
||||
config={
|
||||
LINE: gpiod.LineSettings(
|
||||
direction=gpiod.line.Direction.OUTPUT,
|
||||
output_value=gpiod.line.Value.INACTIVE,
|
||||
)
|
||||
},
|
||||
) as req:
|
||||
req.set_value(LINE, gpiod.line.Value.ACTIVE)
|
||||
time.sleep(PULSE_US / 1_000_000.0)
|
||||
req.set_value(LINE, gpiod.line.Value.INACTIVE)
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
CONFIG="/etc/aismap/network.json"
|
||||
HOSTAPD_CONF="/etc/hostapd/hostapd.conf"
|
||||
LOG="/var/log/aismap_to_ap.log"
|
||||
exec >"$LOG" 2>&1
|
||||
|
||||
echo "=== $(date) start to_ap ==="
|
||||
|
||||
IFACE="wlan0"
|
||||
AP_IP="192.168.4.1/24"
|
||||
AP_SSID=""
|
||||
AP_PSK=""
|
||||
|
||||
if [ -f "$CONFIG" ]; then
|
||||
IFACE=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('iface','wlan0'))" 2>/dev/null || echo "wlan0")
|
||||
AP_IP=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('ap_ip','192.168.4.1/24'))" 2>/dev/null || echo "192.168.4.1/24")
|
||||
AP_SSID=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('ap_ssid',''))" 2>/dev/null || echo "")
|
||||
AP_PSK=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('ap_psk',''))" 2>/dev/null || echo "")
|
||||
fi
|
||||
|
||||
echo "[1] stop wifi client"
|
||||
killall wpa_supplicant 2>/dev/null || true
|
||||
sleep 1
|
||||
|
||||
echo "[2] reset iface $IFACE"
|
||||
ip addr flush dev "$IFACE" 2>/dev/null || true
|
||||
ip route del default 2>/dev/null || true
|
||||
ip link set "$IFACE" down 2>/dev/null || true
|
||||
sleep 1
|
||||
ip link set "$IFACE" up
|
||||
sleep 2
|
||||
|
||||
echo "[3] restore AP IP: $AP_IP"
|
||||
ip addr add "$AP_IP" dev "$IFACE"
|
||||
|
||||
echo "[4] update hostapd.conf (if new SSID/PSK provided)"
|
||||
if [ -n "$AP_SSID" ] && [ -f "$HOSTAPD_CONF" ]; then
|
||||
# Back up the original before first modification
|
||||
if [ ! -f "${HOSTAPD_CONF}.orig" ]; then
|
||||
cp "$HOSTAPD_CONF" "${HOSTAPD_CONF}.orig"
|
||||
echo " backed up original to ${HOSTAPD_CONF}.orig"
|
||||
fi
|
||||
sed -i "s/^ssid=.*/ssid=${AP_SSID}/" "$HOSTAPD_CONF"
|
||||
echo " ssid -> $AP_SSID"
|
||||
if [ -n "$AP_PSK" ]; then
|
||||
sed -i "s/^wpa_passphrase=.*/wpa_passphrase=${AP_PSK}/" "$HOSTAPD_CONF"
|
||||
echo " wpa_passphrase -> (updated)"
|
||||
fi
|
||||
# Keep interface in sync
|
||||
sed -i "s/^interface=.*/interface=${IFACE}/" "$HOSTAPD_CONF"
|
||||
else
|
||||
echo " no SSID in config or hostapd.conf missing — using existing hostapd.conf"
|
||||
fi
|
||||
|
||||
echo "[5] start hostapd"
|
||||
hostapd -B "$HOSTAPD_CONF"
|
||||
|
||||
echo "[6] restart dnsmasq (if used)"
|
||||
systemctl restart dnsmasq 2>/dev/null || true
|
||||
|
||||
echo "[7] status"
|
||||
ip addr show dev "$IFACE"
|
||||
iw dev 2>/dev/null || true
|
||||
|
||||
echo "=== $(date) done to_ap ==="
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
CONFIG="/etc/aismap/network.json"
|
||||
LOG="/var/log/aismap_to_wifi.log"
|
||||
exec >"$LOG" 2>&1
|
||||
|
||||
echo "=== $(date) start to_wifi ==="
|
||||
|
||||
if [ ! -f "$CONFIG" ]; then
|
||||
echo "ERROR: config not found: $CONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SSID=$(python3 -c "import json; print(json.load(open('$CONFIG'))['wifi_ssid'])")
|
||||
PSK=$(python3 -c "import json; print(json.load(open('$CONFIG'))['wifi_psk'])")
|
||||
WIFI_IP=$(python3 -c "import json; print(json.load(open('$CONFIG'))['wifi_ip'])")
|
||||
GW=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('wifi_gw',''))")
|
||||
DNS=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('wifi_dns','8.8.8.8'))")
|
||||
IFACE=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('iface','wlan0'))")
|
||||
|
||||
if [ -z "$SSID" ]; then
|
||||
echo "ERROR: wifi_ssid is empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[1] stop AP services"
|
||||
killall hostapd 2>/dev/null || true
|
||||
killall wpa_supplicant 2>/dev/null || true
|
||||
sleep 1
|
||||
|
||||
echo "[2] reset iface $IFACE"
|
||||
ip link set "$IFACE" down 2>/dev/null || true
|
||||
sleep 1
|
||||
ip link set "$IFACE" up
|
||||
sleep 2
|
||||
|
||||
echo "[3] scan for SSID: $SSID"
|
||||
iw dev "$IFACE" scan 2>/dev/null | grep -F "SSID: $SSID" || echo "WARN: SSID not found in scan, trying anyway"
|
||||
|
||||
echo "[4] build wpa config"
|
||||
wpa_passphrase "$SSID" "$PSK" > /tmp/aismap_wifi.conf
|
||||
|
||||
echo "[5] connect to wifi"
|
||||
wpa_supplicant -B -i "$IFACE" -c /tmp/aismap_wifi.conf
|
||||
sleep 5
|
||||
|
||||
echo "[6] flush old IPs"
|
||||
ip addr flush dev "$IFACE"
|
||||
|
||||
echo "[7] set static IP: $WIFI_IP"
|
||||
ip addr add "$WIFI_IP" dev "$IFACE"
|
||||
|
||||
echo "[8] set default route"
|
||||
ip route del default 2>/dev/null || true
|
||||
if [ -n "$GW" ]; then
|
||||
ip route add default via "${GW}" dev "$IFACE"
|
||||
fi
|
||||
|
||||
echo "[9] set DNS"
|
||||
if [ -n "$DNS" ]; then
|
||||
echo "nameserver $DNS" > /etc/resolv.conf
|
||||
fi
|
||||
|
||||
echo "[10] verify connectivity"
|
||||
sleep 2
|
||||
CURRENT_IP=$(ip -4 addr show "$IFACE" | grep -oP 'inet \K[0-9./]+' || echo "none")
|
||||
echo "IP on $IFACE: $CURRENT_IP"
|
||||
|
||||
if [ -n "$GW" ]; then
|
||||
if ping -c 2 -W 3 "${GW}" >/dev/null 2>&1; then
|
||||
echo "Gateway $GW reachable — WiFi OK"
|
||||
else
|
||||
echo "WARN: gateway $GW unreachable"
|
||||
fi
|
||||
else
|
||||
echo "No gateway configured, skipping ping check"
|
||||
fi
|
||||
|
||||
echo "[11] wpa_supplicant status"
|
||||
wpa_cli -i "$IFACE" status 2>/dev/null || true
|
||||
|
||||
ip addr show dev "$IFACE"
|
||||
iw dev "$IFACE" link 2>/dev/null || true
|
||||
|
||||
echo "=== $(date) done to_wifi ==="
|
||||
Reference in New Issue
Block a user