Compare commits
12 Commits
91b9295974
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 01b9e0bca9 | |||
| 07b0b8c1b5 | |||
| d32ad8c94e | |||
| c5cba6a318 | |||
| f978bf31dd | |||
| 84527b9820 | |||
| b7625a883c | |||
| 43ef4d47fc | |||
| 6276c1dac5 | |||
| 405d524f59 | |||
| 7afd9aaa28 | |||
| e3241c21f7 |
31
CLAUDE.md
31
CLAUDE.md
@ -11,6 +11,31 @@ un LLM les interprète et génère des commandes MAVLink vers ArduPilot.
|
||||
- **Pi Zero 2W** : IP 192.168.1.132 — flux vidéo H.264 UDP → Jetson (câblé, arrêté pour l'instant)
|
||||
- **Matek H743** : à venir — contrôleur de vol ArduPilot réel
|
||||
|
||||
## Renommage du dossier (20 juillet 2026)
|
||||
|
||||
Ce dossier s'appelait `~/wireclaw`, renommé en `~/wireclaw-jetson` pour clarté : le repo `wireclaw-pizero` (config du drone) est maintenant aussi cloné localement sur le Jetson (voir ci-dessous), donc les deux noms de dossier doivent être distincts.
|
||||
|
||||
**Le dépôt distant Gitea reste `wireclaw.git`** (inchangé) — seul le nom du dossier local sur le Jetson a changé. Ne pas confondre les deux : `git remote -v` continuera d'afficher `wireclaw.git`, c'est normal.
|
||||
|
||||
Services systemd mis à jour en conséquence (`WorkingDirectory`/`ExecStart` pointent vers `/home/nicoboy/wireclaw-jetson`) :
|
||||
- `wireclaw.service` (tests SITL ArduPilot, carte MAV+GPS)
|
||||
- `receive-cam.service` (réception vidéo/YOLO/MJPEG)
|
||||
|
||||
## Organisation des deux repos sur le Jetson
|
||||
|
||||
Depuis le 20 juillet 2026, les deux dépôts du projet sont clonés localement sur le Jetson, pour permettre au script `switch_band.sh` (voir ci-dessous) de lire les deux profils de config radio sans dépendre du réseau vers un PC distant :
|
||||
|
||||
- `~/wireclaw-jetson/` — ce repo, code Jetson (réception vidéo, config radio ground station)
|
||||
- `~/wireclaw-pizero/` — code Pi Zero (émission caméra, config radio drone). **Ce repo reste normalement édité depuis le PC habituel** — le clone Jetson sert uniquement de source pour le déploiement des profils radio, pas de zone d'édition principale. Toujours faire `git pull` avant toute édition, où que ce soit, pour éviter une divergence entre les deux clones.
|
||||
|
||||
## Profils radio versionnés (5GHz / 2.4GHz)
|
||||
|
||||
Deux profils complets et testés existent dans `config/` de chaque repo :
|
||||
- `wifibroadcast_gs_5ghz.cfg` / `wifibroadcast_drone_5ghz.cfg` — canal 149, bande opérationnelle par défaut du projet
|
||||
- `wifibroadcast_gs_24ghz.cfg` / `wifibroadcast_drone_24ghz.cfg` — canal 6, **usage diagnostic/comparatif uniquement** : confirmé sujet à interférence domestique sévère (freeze disparaît en mode auto Freebox, revient sur canal chevauchant — cf 20260720_wireclaw_avancement_v17.md §6)
|
||||
|
||||
Bascule via `scripts/switch_band.sh 5ghz` ou `scripts/switch_band.sh 2.4ghz` (voir le script pour le détail — copie directe des profils, pas de patch, backup unique `.bak_last` écrasé à chaque bascule).
|
||||
|
||||
## Stack logicielle
|
||||
- Python 3.10, asyncio
|
||||
- MAVSDK Python (udp://:14551)
|
||||
@ -45,7 +70,7 @@ un LLM les interprète et génère des commandes MAVLink vers ArduPilot.
|
||||
|
||||
## Règles importantes
|
||||
- Ne jamais modifier `.env` ni `credentials.h` (secrets WiFi/API)
|
||||
- Toujours tester via `~/wireclaw/start.sh` avant de commiter
|
||||
- Toujours tester via `~/wireclaw-jetson/start.sh` avant de commiter
|
||||
- Les commandes MAVLink passent toutes par `execute_command()` dans wireclaw_core.py
|
||||
- L'état armement est synchronisé en temps réel via `monitor_armed()` (tâche de fond)
|
||||
- `MAV_CMD_DO_ORBIT` (commande 34) non supportée en SITL → fallback waypoints circulaires 16 points
|
||||
@ -54,7 +79,7 @@ un LLM les interprète et génère des commandes MAVLink vers ArduPilot.
|
||||
## Commandes de session
|
||||
```bash
|
||||
# Démarrer tout
|
||||
~/wireclaw/start.sh
|
||||
~/wireclaw-jetson/start.sh
|
||||
|
||||
# Vérifier SITL actif
|
||||
ps aux | grep -E "arducopter|mavproxy" | grep -v grep
|
||||
@ -66,7 +91,7 @@ nmcli dev status | grep wifi
|
||||
pkill -f hermes
|
||||
|
||||
# Lancer la réception caméra Pi Zero (quand Pi Zero actif)
|
||||
python3 ~/wireclaw/receive_cam.py
|
||||
python3 ~/wireclaw-jetson/receive_cam.py
|
||||
|
||||
# Vérifier MJPEG stream caméra
|
||||
curl -s --max-time 2 http://localhost:5601/ | head -1
|
||||
|
||||
33
config/wifibroadcast_gs_24ghz.cfg
Normal file
33
config/wifibroadcast_gs_24ghz.cfg
Normal file
@ -0,0 +1,33 @@
|
||||
# Fichier de RÉFÉRENCE versionné pour /etc/wifibroadcast.cfg (Jetson,
|
||||
# ground station). Le vrai fichier système n'est PAS versionné
|
||||
# directement (fichier hors dépôt git). Workflow :
|
||||
# 1. Modifier CE fichier ici, commit/push
|
||||
# 2. Appliquer manuellement sur le système :
|
||||
# sudo cp config/wifibroadcast_gs.cfg /etc/wifibroadcast.cfg
|
||||
# sudo systemctl restart wfb-server-gs.service
|
||||
# 3. Toujours faire un .bak du fichier système avant d'écraser
|
||||
# Historique de campagne : voir 20260719_wireclaw_avancement_v16.md et
|
||||
# suivants pour le contexte de chaque changement (canal, bandwidth, MCS,
|
||||
# fec_delay).
|
||||
#
|
||||
|
||||
[common]
|
||||
wifi_channel = 6 # 149 = 5GHz (DFS/UNII) | 6 = 2.4GHz (2437MHz, HT40 marge)
|
||||
wifi_region = 'FR' # Réglementation CRDA — FR par défaut ici,
|
||||
# PAS 'BO'/'GY' (max tx power, hors cadre FR)
|
||||
|
||||
[gs_mavlink]
|
||||
fec_delay = 20000 # us -- meme mecanisme que gs_tunnel, valeur adaptee a MCS3. Validation formelle en attente (trafic MAVLink vivant requis). Cf v16.
|
||||
peer = 'connect://127.0.0.1:14550' # outgoing connection
|
||||
|
||||
[gs_video]
|
||||
peer = 'connect://127.0.0.1:5600' # outgoing connection
|
||||
bandwidth = 40 # Test HT40, aligné avec drone_video
|
||||
mcs_index = 0 # Valeur par défaut (override master.cfg defaut=1)
|
||||
|
||||
[gs_tunnel]
|
||||
fec_delay = 35000 # µs — décorrèle les 2 copies FEC (k=1/n=2) pour
|
||||
# échapper aux fenêtres de surdité half-duplex.
|
||||
# Cf. 20260718_wireclaw_avancement_v15.md / méthode Fable.
|
||||
# Plafonne le débit tunnel à ~300 kbps (OK ping/
|
||||
# sideband/SSH interactif, PAS pour scp/gros transferts).
|
||||
20
config/wifibroadcast_gs_5ghz.cfg
Normal file
20
config/wifibroadcast_gs_5ghz.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
[common]
|
||||
wifi_channel = 149 # 149 = 5GHz (DFS/UNII) | 1 = 2.4GHz
|
||||
wifi_region = 'FR' # Réglementation CRDA — FR par défaut ici,
|
||||
# PAS 'BO'/'GY' (max tx power, hors cadre FR)
|
||||
|
||||
[gs_mavlink]
|
||||
fec_delay = 20000 # us -- meme mecanisme que gs_tunnel, valeur adaptee a MCS3. Validation formelle en attente (trafic MAVLink vivant requis). Cf v16.
|
||||
peer = 'connect://127.0.0.1:14550' # outgoing connection
|
||||
|
||||
[gs_video]
|
||||
peer = 'connect://127.0.0.1:5600' # outgoing connection
|
||||
bandwidth = 40 # HT40, jamais testé sur 5GHz avant ce profil
|
||||
mcs_index = 0 # Valeur par défaut (override master.cfg defaut=1)
|
||||
|
||||
[gs_tunnel]
|
||||
fec_delay = 35000 # µs — décorrèle les 2 copies FEC (k=1/n=2) pour
|
||||
# échapper aux fenêtres de surdité half-duplex.
|
||||
# Cf. 20260718_wireclaw_avancement_v15.md / méthode Fable.
|
||||
# Plafonne le débit tunnel à ~300 kbps (OK ping/
|
||||
# sideband/SSH interactif, PAS pour scp/gros transferts).
|
||||
@ -62,6 +62,7 @@ _pi_stats: dict | None = None
|
||||
# RSSI du flux vidéo dédié WFB-NG reçu via API JSON 127.0.0.1:8103
|
||||
_rssi_lock = threading.Lock()
|
||||
_rssi_data: dict | None = None # {"rssi_avg": -63, "snr_avg": 17}
|
||||
_band_label: str = "?" # "2.4GHz" ou "5GHz", déterminé au démarrage
|
||||
RSSI_API_PORT = 8103
|
||||
|
||||
|
||||
@ -90,6 +91,29 @@ def sideband_loop() -> None:
|
||||
print("[SIDEBAND] Arrêt.")
|
||||
|
||||
|
||||
def band_label_loop() -> None:
|
||||
"""Relit /etc/wifibroadcast.cfg toutes les 10s pour détecter un
|
||||
changement de bande (ex: après switch_band.sh) sans jamais avoir
|
||||
besoin de redémarrer ce service."""
|
||||
global _band_label
|
||||
while _running:
|
||||
try:
|
||||
with open("/etc/wifibroadcast.cfg") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith("wifi_channel"):
|
||||
val = line.split("=", 1)[1].split("#")[0].strip()
|
||||
ch = int(val)
|
||||
new_label = "2.4GHz" if ch <= 14 else "5GHz"
|
||||
if new_label != _band_label:
|
||||
print(f"[BAND] Changement détecté : {_band_label} -> {new_label}")
|
||||
_band_label = new_label
|
||||
break
|
||||
except (FileNotFoundError, ValueError, IndexError) as e:
|
||||
print(f"[BAND] Impossible de lire wifi_channel : {e}")
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
def rssi_loop() -> None:
|
||||
"""Écoute l'API JSON wfb-ng locale (127.0.0.1:8103), extrait le RSSI
|
||||
du flux vidéo dédié (id="video rx") et le stocke pour l'overlay.
|
||||
@ -200,6 +224,7 @@ def draw_rssi_pyramid(frame: np.ndarray) -> np.ndarray:
|
||||
|
||||
def draw_overlay(frame: np.ndarray) -> np.ndarray:
|
||||
"""Dessine l'overlay stats Pi Zero (fond noir semi-transparent) sur le frame."""
|
||||
global _band_label
|
||||
with _stats_lock:
|
||||
stats = _pi_stats
|
||||
if stats is None:
|
||||
@ -212,10 +237,11 @@ def draw_overlay(frame: np.ndarray) -> np.ndarray:
|
||||
temp = stats.get("temp_c", "?")
|
||||
cpu = stats.get("cpu_pct", "?")
|
||||
throttled = stats.get("throttled", False)
|
||||
throttle_str = "THROTTLED" if throttled else "ok"
|
||||
|
||||
line1 = f"{w_res}x{h_res} | {fps}fps | {enc} | {temp}C"
|
||||
line2 = f"CPU {cpu}% | {throttle_str}"
|
||||
line2 = f"CPU {cpu}% | {_band_label}"
|
||||
if throttled:
|
||||
line2 += " | THROTTLED"
|
||||
|
||||
font = cv2.FONT_HERSHEY_SIMPLEX
|
||||
scale = 0.55
|
||||
@ -399,6 +425,10 @@ def main():
|
||||
tr = threading.Thread(target=rssi_loop, daemon=True)
|
||||
tr.start()
|
||||
|
||||
# Thread bande : relit wifi_channel toutes les 10s pour détecter les changements
|
||||
tb = threading.Thread(target=band_label_loop, daemon=True)
|
||||
tb.start()
|
||||
|
||||
# Thread de fond : connexion/reconnexion continue au flux GStreamer réel
|
||||
tg = threading.Thread(target=gstreamer_watcher, daemon=True)
|
||||
tg.start()
|
||||
|
||||
@ -1,151 +0,0 @@
|
||||
# WireClaw TX Power Control Scripts
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
Deux scripts bash pour contrôler la puissance d'émission (TX) du système WireClaw :
|
||||
|
||||
- **`set_TX_power_base.sh`** — Base (Jetson)
|
||||
- **`set_TX_power_drone.sh`** — Drone (Pi Zero)
|
||||
|
||||
## Utilisation
|
||||
|
||||
### Base (Jetson)
|
||||
|
||||
```bash
|
||||
./set_TX_power_base.sh <index>
|
||||
```
|
||||
|
||||
**Exemples :**
|
||||
```bash
|
||||
./set_TX_power_base.sh 10 # Puissance faible (~3 dBm)
|
||||
./set_TX_power_base.sh 31 # Puissance moyenne (~10 dBm)
|
||||
./set_TX_power_base.sh 52 # Puissance haute (~20 dBm)
|
||||
./set_TX_power_base.sh 63 # Puissance maximale (~23 dBm)
|
||||
```
|
||||
|
||||
**Interface :** `wlx54c9ff02f26e`
|
||||
**Méthode :** `iw dev ... set txpower fixed`
|
||||
**Requis :** `sudo`
|
||||
|
||||
---
|
||||
|
||||
### Drone (Pi Zero)
|
||||
|
||||
```bash
|
||||
./set_TX_power_drone.sh <index>
|
||||
```
|
||||
|
||||
**Exemples :**
|
||||
```bash
|
||||
./set_TX_power_drone.sh 10 # Puissance faible (~3 dBm)
|
||||
./set_TX_power_drone.sh 31 # Puissance moyenne (~10 dBm)
|
||||
./set_TX_power_drone.sh 52 # Puissance haute (~20 dBm)
|
||||
./set_TX_power_drone.sh 63 # Puissance maximale (~23 dBm)
|
||||
```
|
||||
|
||||
**Interface :** `wlan-drone` (via SSH)
|
||||
**Méthode :** `modprobe -r rtl88xxau_wfb && modprobe rtl88xxau_wfb rtw_tx_pwr_idx_override=<index>`
|
||||
**Requis :** SSH alias `jetson-pi` + `sudo` sur Pi Zero
|
||||
|
||||
---
|
||||
|
||||
## Table de conversion Index → dBm
|
||||
|
||||
| Index | dBm approximatif |
|
||||
|-------|------------------|
|
||||
| 0 | 0 dBm |
|
||||
| 10 | ~3 dBm |
|
||||
| 20 | ~6 dBm |
|
||||
| 31 | ~10 dBm |
|
||||
| 42 | ~15 dBm |
|
||||
| 52 | ~20 dBm |
|
||||
| 63 | ~23 dBm (max) |
|
||||
|
||||
## Prérequis
|
||||
|
||||
### Jetson (Base)
|
||||
- Commande `iw` disponible (`/usr/sbin/iw`)
|
||||
- Sudo sans mot de passe configuré
|
||||
- Interface `wlx54c9ff02f26e` active
|
||||
|
||||
### Pi Zero (Drone)
|
||||
- SSH alias `jetson-pi` fonctionnel dans `~/.ssh/config`
|
||||
- Session sudo "chaude" lancée sur Pi Zero
|
||||
- Module driver `rtl88xxau_wfb` chargé
|
||||
- Interface `wlan-drone` active
|
||||
|
||||
## Configuration de la session sudo "chaude"
|
||||
|
||||
Sur Pi Zero, au démarrage de session :
|
||||
```bash
|
||||
sudo -v
|
||||
```
|
||||
|
||||
Cela cache le mot de passe pendant 15 minutes (~5 min après dernière commande sudo).
|
||||
|
||||
## Aide
|
||||
|
||||
```bash
|
||||
./set_TX_power_base.sh --help
|
||||
./set_TX_power_drone.sh --help
|
||||
```
|
||||
|
||||
## Version
|
||||
|
||||
- **Base script :** 1.0.0
|
||||
- **Drone script :** 1.0.0
|
||||
|
||||
## Auteur
|
||||
|
||||
WireClaw TX Power Control System
|
||||
|
||||
## Notes
|
||||
|
||||
- La conversion Index → dBm est approximative et dépend du chipset/driver
|
||||
- Modifier la puissance affecte immédiatement le trafic en cours (peut déconnecter)
|
||||
- Les limites régionales (FCC/ETSI) peuvent être appliquées par le driver
|
||||
- Le Pi Zero demande un rechargement du module (interruption de service ~2s)
|
||||
|
||||
---
|
||||
|
||||
## Exemples d'utilisation
|
||||
|
||||
### Configuration complète (Base + Drone)
|
||||
|
||||
```bash
|
||||
# Tous deux à puissance moyenne (~10 dBm)
|
||||
./set_TX_power_base.sh 31
|
||||
./set_TX_power_drone.sh 31
|
||||
```
|
||||
|
||||
### Configuration asymétrique
|
||||
|
||||
```bash
|
||||
# Base en haute puissance, Drone en faible puissance
|
||||
./set_TX_power_base.sh 52
|
||||
./set_TX_power_drone.sh 10
|
||||
```
|
||||
|
||||
### Reset (minimum)
|
||||
|
||||
```bash
|
||||
./set_TX_power_base.sh 0
|
||||
./set_TX_power_drone.sh 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Erreur : "sudo requis"
|
||||
Sur Jetson : lancez `sudo -v` pour activer une session sudo "chaude"
|
||||
|
||||
### Erreur : "SSH non disponible"
|
||||
Vérifiez que l'alias `jetson-pi` est configuré dans `~/.ssh/config`
|
||||
|
||||
### Erreur : "Module not found"
|
||||
Vérifiez que le driver `rtl88xxau_wfb` est compilé et chargé sur Pi Zero
|
||||
|
||||
### Changement de puissance non visible
|
||||
Vérifiez avec : `iw dev <iface> info | grep txpower`
|
||||
|
||||
@ -1,156 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# WireClaw TX Power Control - Base (Jetson)
|
||||
# Version: 1.0.0
|
||||
# Description: Modifie la puissance d'émission (TX) du Jetson via iw
|
||||
# Usage: ./set_TX_power_base.sh <power_index>
|
||||
# Example: ./set_TX_power_base.sh 10
|
||||
|
||||
set -e
|
||||
|
||||
VERSION="1.0.0"
|
||||
SCRIPT_NAME=$(basename "$0")
|
||||
|
||||
# Configuration
|
||||
JETSON_IFACE="wlx54c9ff02f26e"
|
||||
IW_CMD="/usr/sbin/iw"
|
||||
|
||||
# Couleurs
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Fonctions
|
||||
print_header() {
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE} WireClaw TX Power Control - BASE (Jetson) v${VERSION}${NC}"
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[✓]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[✗]${NC} $1"
|
||||
}
|
||||
|
||||
show_help() {
|
||||
cat << EOF
|
||||
${BLUE}Usage:${NC}
|
||||
$SCRIPT_NAME <power_index>
|
||||
|
||||
${BLUE}Arguments:${NC}
|
||||
power_index Index de puissance TX (0-63)
|
||||
0 = 0 dBm (minimum)
|
||||
10 = ~3 dBm
|
||||
20 = ~6 dBm
|
||||
31 = ~10 dBm
|
||||
42 = ~15 dBm
|
||||
52 = ~20 dBm
|
||||
63 = ~23 dBm (maximum)
|
||||
|
||||
${BLUE}Exemples:${NC}
|
||||
$SCRIPT_NAME 10 # Puissance faible
|
||||
$SCRIPT_NAME 31 # Puissance moyenne
|
||||
$SCRIPT_NAME 52 # Puissance haute
|
||||
$SCRIPT_NAME 63 # Puissance maximale
|
||||
|
||||
${BLUE}Interface:${NC}
|
||||
${JETSON_IFACE}
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Validation
|
||||
validate_input() {
|
||||
if [ -z "$1" ]; then
|
||||
print_error "Aucun index spécifié"
|
||||
echo ""
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
|
||||
print_error "L'index doit être un nombre entier"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" -lt 0 ] || [ "$1" -gt 63 ]; then
|
||||
print_error "L'index doit être entre 0 et 63 (reçu: $1)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Conversion index (0-63) -> dBm (0-23)
|
||||
index_to_dbm() {
|
||||
echo $(( ($1 * 23) / 63 ))
|
||||
}
|
||||
|
||||
# Obtenir la puissance actuelle
|
||||
get_current_power() {
|
||||
$IW_CMD dev "$JETSON_IFACE" info 2>/dev/null | grep "txpower" | awk '{print $2, $3}' || echo "unknown"
|
||||
}
|
||||
|
||||
# Modifier la puissance
|
||||
set_power() {
|
||||
local index=$1
|
||||
local dbm=$(index_to_dbm "$index")
|
||||
local mbm=$(( dbm * 100 ))
|
||||
|
||||
print_info "Modification du Jetson (Base)..."
|
||||
echo -n " Puissance actuelle: "
|
||||
get_current_power
|
||||
|
||||
if sudo -n $IW_CMD dev "$JETSON_IFACE" set txpower fixed "$mbm" 2>/dev/null; then
|
||||
sleep 0.5
|
||||
echo -n " Puissance nouvelle: "
|
||||
get_current_power
|
||||
print_success "Jetson configuré (index=$index, ~$dbm dBm)"
|
||||
return 0
|
||||
else
|
||||
print_error "Impossible de configurer (sudo requis)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main
|
||||
main() {
|
||||
print_header
|
||||
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-v|--version)
|
||||
echo "WireClaw TX Power Control - Base v${VERSION}"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
validate_input "$1"
|
||||
|
||||
echo ""
|
||||
set_power "$1"
|
||||
STATUS=$?
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"
|
||||
|
||||
if [ $STATUS -eq 0 ]; then
|
||||
print_success "Puissance TX Base configurée (index=$1)"
|
||||
exit 0
|
||||
else
|
||||
print_error "Impossible de configurer la puissance TX"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@ -1,170 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# WireClaw TX Power Control - Drone (Pi Zero)
|
||||
# Version: 1.0.0
|
||||
# Description: Modifie la puissance d'émission (TX) du Pi Zero via modprobe rtw_tx_pwr_idx_override
|
||||
# Usage: ./set_TX_power_drone.sh <power_index>
|
||||
# Example: ./set_TX_power_drone.sh 10
|
||||
|
||||
set -e
|
||||
|
||||
VERSION="1.0.0"
|
||||
SCRIPT_NAME=$(basename "$0")
|
||||
|
||||
# Configuration
|
||||
PIZERO_SSH_ALIAS="jetson-pi"
|
||||
PIZERO_MODULE="rtl88xxau_wfb"
|
||||
PIZERO_IFACE="wlan-drone"
|
||||
IW_CMD="/usr/sbin/iw"
|
||||
|
||||
# Couleurs
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Fonctions
|
||||
print_header() {
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE} WireClaw TX Power Control - DRONE (Pi Zero) v${VERSION}${NC}"
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[✓]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[✗]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[!]${NC} $1"
|
||||
}
|
||||
|
||||
show_help() {
|
||||
cat << EOF
|
||||
${BLUE}Usage:${NC}
|
||||
$SCRIPT_NAME <power_index>
|
||||
|
||||
${BLUE}Arguments:${NC}
|
||||
power_index Index de puissance TX (0-63)
|
||||
0 = 0 dBm (minimum)
|
||||
10 = ~3 dBm
|
||||
20 = ~6 dBm
|
||||
31 = ~10 dBm
|
||||
42 = ~15 dBm
|
||||
52 = ~20 dBm
|
||||
63 = ~23 dBm (maximum)
|
||||
|
||||
${BLUE}Exemples:${NC}
|
||||
$SCRIPT_NAME 10 # Puissance faible
|
||||
$SCRIPT_NAME 31 # Puissance moyenne
|
||||
$SCRIPT_NAME 52 # Puissance haute
|
||||
$SCRIPT_NAME 63 # Puissance maximale
|
||||
|
||||
${BLUE}Interface:${NC}
|
||||
${PIZERO_IFACE} (via SSH: ${PIZERO_SSH_ALIAS})
|
||||
|
||||
${BLUE}Méthode:${NC}
|
||||
ssh jetson-pi "sudo modprobe -r ${PIZERO_MODULE} && sudo modprobe ${PIZERO_MODULE} rtw_tx_pwr_idx_override=<index>"
|
||||
|
||||
${BLUE}Notes:${NC}
|
||||
- Recharge le module du driver
|
||||
- Nécessite sudo sur Pi Zero
|
||||
- Session sudo "chaude" requise
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Validation
|
||||
validate_input() {
|
||||
if [ -z "$1" ]; then
|
||||
print_error "Aucun index spécifié"
|
||||
echo ""
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
|
||||
print_error "L'index doit être un nombre entier"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" -lt 0 ] || [ "$1" -gt 63 ]; then
|
||||
print_error "L'index doit être entre 0 et 63 (reçu: $1)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Obtenir la puissance actuelle
|
||||
get_current_power() {
|
||||
ssh "$PIZERO_SSH_ALIAS" "$IW_CMD dev $PIZERO_IFACE info 2>/dev/null | grep txpower | awk '{print \$2, \$3}'" 2>/dev/null || echo "unknown"
|
||||
}
|
||||
|
||||
# Modifier la puissance
|
||||
set_power() {
|
||||
local index=$1
|
||||
|
||||
print_info "Modification du Pi Zero (Drone)..."
|
||||
echo -n " Puissance actuelle: "
|
||||
get_current_power
|
||||
|
||||
print_info "Recharge du module ${PIZERO_MODULE}..."
|
||||
print_info " Commande: sudo modprobe -r ${PIZERO_MODULE} && sudo modprobe ${PIZERO_MODULE} rtw_tx_pwr_idx_override=$index"
|
||||
|
||||
if ssh "$PIZERO_SSH_ALIAS" "sudo -n modprobe -r $PIZERO_MODULE && sudo -n modprobe $PIZERO_MODULE rtw_tx_pwr_idx_override=$index" 2>/dev/null; then
|
||||
sleep 2 # Attendre le rechargement complet du module et la reconnexion
|
||||
echo -n " Puissance nouvelle: "
|
||||
get_current_power
|
||||
print_success "Pi Zero configuré (index=$index)"
|
||||
return 0
|
||||
else
|
||||
print_error "Impossible de recharger le module"
|
||||
print_error "Vérifiez que:"
|
||||
print_error " 1. SSH vers ${PIZERO_SSH_ALIAS} fonctionne"
|
||||
print_error " 2. Une session sudo 'chaude' est active sur Pi Zero"
|
||||
print_error " 3. Le module ${PIZERO_MODULE} existe"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main
|
||||
main() {
|
||||
print_header
|
||||
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-v|--version)
|
||||
echo "WireClaw TX Power Control - Drone v${VERSION}"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
validate_input "$1"
|
||||
|
||||
echo ""
|
||||
set_power "$1"
|
||||
STATUS=$?
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"
|
||||
|
||||
if [ $STATUS -eq 0 ]; then
|
||||
print_success "Puissance TX Drone configurée (index=$1)"
|
||||
exit 0
|
||||
else
|
||||
print_error "Impossible de configurer la puissance TX"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
83
scripts/switch_band.sh
Executable file
83
scripts/switch_band.sh
Executable file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# switch_band.sh — Bascule entre les deux profils radio complets et
|
||||
# testés (5GHz canal 149 / 2.4GHz canal 6), Jetson + Pi Zero synchronisés.
|
||||
#
|
||||
# Les deux profils vivent en dur dans les repos (config/wifibroadcast_gs_*.cfg
|
||||
# ici, config/wifibroadcast_drone_*.cfg dans wireclaw-pizero, cloné
|
||||
# localement sur le Jetson) — ce script les copie tels quels, il ne
|
||||
# patche rien. Pour modifier un profil, édite le fichier de référence
|
||||
# correspondant dans le repo concerné, commit/push, puis relance ce
|
||||
# script pour le déployer.
|
||||
#
|
||||
# 5GHz = bande opérationnelle par défaut (cf v17 §6 — 2.4GHz sujet à
|
||||
# interférence domestique confirmée, usage diagnostic/comparatif
|
||||
# uniquement).
|
||||
#
|
||||
# USAGE : ./switch_band.sh 5ghz | 2.4ghz
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
PIZERO_REPO="${HOME}/wireclaw-pizero"
|
||||
CFG_JETSON="/etc/wifibroadcast.cfg"
|
||||
SSH_PI="jetson-pi"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 {5ghz|2.4ghz}"
|
||||
exit 1
|
||||
}
|
||||
[ $# -eq 1 ] || usage
|
||||
|
||||
case "$1" in
|
||||
5ghz)
|
||||
GS_PROFILE="${REPO_DIR}/config/wifibroadcast_gs_5ghz.cfg"
|
||||
DRONE_PROFILE="${PIZERO_REPO}/config/wifibroadcast_drone_5ghz.cfg"
|
||||
BAND_LABEL="5GHz (canal 149) — bande opérationnelle"
|
||||
;;
|
||||
2.4ghz)
|
||||
GS_PROFILE="${REPO_DIR}/config/wifibroadcast_gs_24ghz.cfg"
|
||||
DRONE_PROFILE="${PIZERO_REPO}/config/wifibroadcast_drone_24ghz.cfg"
|
||||
BAND_LABEL="2.4GHz (canal 6) — ⚠️ interférence domestique possible, usage diagnostic uniquement"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -f "$GS_PROFILE" ] || { echo "Profil introuvable : $GS_PROFILE"; exit 1; }
|
||||
[ -f "$DRONE_PROFILE" ] || { echo "Profil introuvable : $DRONE_PROFILE (pense à faire git pull dans wireclaw-pizero)"; exit 1; }
|
||||
|
||||
echo "=== Bascule vers $BAND_LABEL ==="
|
||||
echo
|
||||
echo "--- Diff profil Jetson (système actuel vs cible) ---"
|
||||
diff -u "$CFG_JETSON" "$GS_PROFILE" || true
|
||||
echo
|
||||
read -r -p "Appliquer ce profil sur les deux machines ? [y/N] " confirm
|
||||
[[ "$confirm" =~ ^[yY]([eE][sS])?$ ]] || { echo "Annulé."; exit 0; }
|
||||
|
||||
# Backup unique (écrasé à chaque bascule, pas d'accumulation de .bak)
|
||||
sudo cp "$CFG_JETSON" "${CFG_JETSON}.bak_last"
|
||||
ssh "$SSH_PI" "sudo cp /etc/wifibroadcast.cfg /etc/wifibroadcast.cfg.bak_last"
|
||||
|
||||
# Application — copie directe du profil complet, pas de patch
|
||||
sudo cp "$GS_PROFILE" "$CFG_JETSON"
|
||||
scp "$DRONE_PROFILE" "${SSH_PI}:/tmp/wifibroadcast_new.cfg"
|
||||
ssh "$SSH_PI" "sudo cp /tmp/wifibroadcast_new.cfg /etc/wifibroadcast.cfg && rm /tmp/wifibroadcast_new.cfg"
|
||||
|
||||
echo
|
||||
echo "Redémarrage des services..."
|
||||
sudo systemctl restart wfb-server-gs.service
|
||||
ssh "$SSH_PI" "sudo systemctl restart wfb-server-drone.service"
|
||||
sleep 5
|
||||
|
||||
echo
|
||||
echo "--- Vérification PHY (Jetson) ---"
|
||||
iw dev wlx54c9ff02f26e info | grep -E "channel|width" || echo "⚠️ Lecture PHY échouée"
|
||||
|
||||
echo
|
||||
echo "--- Vérification config chargée (API JSON sol) ---"
|
||||
timeout 2 nc 127.0.0.1 8103 | head -1 | python3 -m json.tool | grep -A5 '"common"' || echo "⚠️ API 8103 non accessible"
|
||||
|
||||
echo
|
||||
echo "✅ Bascule vers $BAND_LABEL terminée."
|
||||
4
start.sh
4
start.sh
@ -24,7 +24,7 @@ echo "Lancement ArduCopter..."
|
||||
--model + \
|
||||
--speedup 1 \
|
||||
--sim-address=127.0.0.1 \
|
||||
--defaults /home/nicoboy/wireclaw/sitl_params.parm \
|
||||
--defaults /home/nicoboy/wireclaw-jetson/sitl_params.parm \
|
||||
> /tmp/arducopter.log 2>&1 &
|
||||
sleep 3
|
||||
|
||||
@ -65,5 +65,5 @@ sleep 2
|
||||
|
||||
# 5. Lancer WireClaw
|
||||
echo "Lancement WireClaw..."
|
||||
cd ~/wireclaw
|
||||
cd ~/wireclaw-jetson
|
||||
/home/nicoboy/.local/bin/uvicorn web_server:app --host 0.0.0.0 --port 8765
|
||||
|
||||
Reference in New Issue
Block a user