LoRa, MQTT and Oled
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
|
||||
# IP Adresses
|
||||
|
||||
- AP (dynamic) : `10.85.213.190`
|
||||
- AP (dynamic) : `10.110.0.190`
|
||||
- Generated Wifi : `192.168.50.1`
|
||||
@@ -4,7 +4,7 @@ services:
|
||||
environment:
|
||||
MQTT_TLS_ENABLED: ${MQTT_TLS_ENABLED:-true}
|
||||
ports:
|
||||
- "8884:8884"
|
||||
- "192.168.50.1:8884:8884"
|
||||
volumes:
|
||||
- ./mqtt/mosquitto-tls.conf:/mosquitto/config/mosquitto-tls.conf:ro
|
||||
- ./mqtt/mosquitto-plain.conf:/mosquitto/config/mosquitto-plain.conf:ro
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
+32
-7
@@ -8,18 +8,43 @@ PYTHON_SCRIPT="${1:-$SCRIPT_DIR/main.py}"
|
||||
REQUIREMENTS_FILE="$REPO_ROOT/requirements.txt"
|
||||
|
||||
if [ ! -f "$PYTHON_SCRIPT" ]; then
|
||||
echo "Python script not found: $PYTHON_SCRIPT" >&2
|
||||
exit 1
|
||||
echo "Python script not found: $PYTHON_SCRIPT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PYTHONPATH="$REPO_ROOT${PYTHONPATH:+:$PYTHONPATH}"
|
||||
# 1. On définit proprement le PYTHONPATH pour tout le script
|
||||
export PYTHONPATH="$REPO_ROOT"
|
||||
|
||||
cd "$SCRIPT_DIR"
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
|
||||
# 2. On lance Docker en arrière-plan
|
||||
echo "Démarrage des conteneurs Docker..."
|
||||
docker compose pull
|
||||
docker compose up -d --remove-orphans
|
||||
|
||||
# 3. Installation des dépendances (sans '--user' si on est déjà root sous systemd)
|
||||
if [ -f "$REQUIREMENTS_FILE" ]; then
|
||||
"$PYTHON_BIN" -m pip install --user -r "$REQUIREMENTS_FILE"
|
||||
echo "Vérification des dépendances Python..."
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
"$PYTHON_BIN" -m pip install -r "$REQUIREMENTS_FILE"
|
||||
else
|
||||
"$PYTHON_BIN" -m pip install --user -r "$REQUIREMENTS_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. Sécurité anti-conflit : On vérifie si Docker n'a pas verrouillé le port USB de la LA66
|
||||
PORT="/dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0"
|
||||
if [ -e "$PORT" ]; then
|
||||
echo "Vérification de la disponibilité du port série..."
|
||||
# Si le port est occupé, on force sa libération en tuant le processus docker/screen persistant
|
||||
if lsof "$PORT" >/dev/null 2>&1; then
|
||||
echo "Le port série est occupé ! Libération en cours..."
|
||||
fuser -k "$PORT" || true
|
||||
sleep 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 5. Lancement propre du script Python
|
||||
echo "Launching Python script: $PYTHON_SCRIPT"
|
||||
cd "$REPO_ROOT"
|
||||
exec "$PYTHON_BIN" "$PYTHON_SCRIPT"
|
||||
exec "$PYTHON_BIN" "$PYTHON_SCRIPT"
|
||||
@@ -0,0 +1,69 @@
|
||||
import threading
|
||||
import queue
|
||||
import time
|
||||
from shared import get_lora, deviceTypes
|
||||
|
||||
# --- Lecture de l'ID unique du Raspberry Pi ---
|
||||
try:
|
||||
with open("device_id.txt", "r") as f:
|
||||
DEVICE_ID = f.read().strip()
|
||||
except Exception:
|
||||
# Alternative si le script est lancé depuis un autre dossier
|
||||
try:
|
||||
with open("/home/pi/SmartWave/orchestrateur/device_id.txt", "r") as f:
|
||||
DEVICE_ID = f.read().strip()
|
||||
except Exception:
|
||||
DEVICE_ID = "RPI_Orchestrateur_Default"
|
||||
|
||||
# Création de la file d'attente pour les messages (thread-safe)
|
||||
data_queue = queue.Queue()
|
||||
|
||||
lora = get_lora()
|
||||
lora.configure()
|
||||
|
||||
def lora_listener():
|
||||
"""Thread de fond : écoute en permanence et répond aux Heartbeats."""
|
||||
print("Thread Écouteur démarré.")
|
||||
while True:
|
||||
# On attend un paquet (timeout court pour rester réactif)
|
||||
paquet = lora.receive_packet(timeout_ms=1000)
|
||||
|
||||
if paquet:
|
||||
donnees = paquet["data"]
|
||||
expediteur_type = donnees.get("type")
|
||||
|
||||
# --- Cas 1 : Gestion automatique du Heartbeat ---
|
||||
if expediteur_type == deviceTypes.DEVICE_TYPES["MICROWAVE"]:
|
||||
print(f"\n[Thread Fond] Heartbeat reçu de {donnees.get('id')}")
|
||||
|
||||
reponse = {
|
||||
"id": DEVICE_ID, # Ou lecture de ton fichier device_id.txt
|
||||
"type": deviceTypes.DEVICE_TYPES["ORCHESTRATOR"]
|
||||
}
|
||||
lora.send(reponse)
|
||||
|
||||
# --- Cas 2 : Donnée applicative, on l'envoie vers le thread principal ---
|
||||
else:
|
||||
data_queue.put(paquet)
|
||||
|
||||
# 2. Lancement du thread d'écoute
|
||||
listener_thread = threading.Thread(target=lora_listener, daemon=True)
|
||||
listener_thread.start()
|
||||
|
||||
# 3. Boucle principale (Main Thread) : tu es libre de faire autre chose !
|
||||
print("Orchestrateur prêt. Le main loop est libre.")
|
||||
while True:
|
||||
try:
|
||||
# On regarde si on a reçu des données applicatives (non-heartbeat)
|
||||
# On utilise block=False pour ne pas bloquer si la queue est vide
|
||||
try:
|
||||
msg = data_queue.get(block=False)
|
||||
print(f"\n[Main Loop] Données traitées : {msg['data']}")
|
||||
except queue.Empty:
|
||||
pass # Rien à traiter, on fait autre chose...
|
||||
|
||||
# Ici tu peux faire tes autres tâches
|
||||
time.sleep(1)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
@@ -8,5 +8,5 @@ log_type notice
|
||||
log_type information
|
||||
allow_anonymous true
|
||||
|
||||
listener 8884
|
||||
listener 8884 192.168.50.1
|
||||
protocol mqtt
|
||||
@@ -8,7 +8,7 @@ log_type notice
|
||||
log_type information
|
||||
allow_anonymous true
|
||||
|
||||
listener 8884
|
||||
listener 8884 192.168.50.1
|
||||
protocol mqtt
|
||||
cafile /mosquitto/certs/ca.crt
|
||||
certfile /mosquitto/certs/server.crt
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
from shared import get_lora
|
||||
import time
|
||||
|
||||
lora = get_lora()
|
||||
lora.configure()
|
||||
|
||||
print("Raspberry Pi : En attente active de JSON...")
|
||||
|
||||
while True:
|
||||
paquet = lora.receive_packet(timeout_ms=5000)
|
||||
if paquet:
|
||||
# Plus besoin de décoder du HEX ou de parser du JSON manuellement !
|
||||
groupe = paquet['group']
|
||||
donnees = paquet['data']
|
||||
|
||||
print(f"\nRPI : Reçu du Groupe {groupe} -> {donnees}")
|
||||
if not paquet['raw']: # C'est bien du JSON (un dictionnaire Python)
|
||||
print(f"RPI : Température du capteur = {donnees.get('temp')}°C")
|
||||
|
||||
# Préparation de la réponse (on passe directement un dictionnaire !)
|
||||
reponse = {
|
||||
"status": "ack",
|
||||
"msg": "Donnees bien recues, merci !",
|
||||
"time": int(time.time())
|
||||
}
|
||||
|
||||
time.sleep(0.5)
|
||||
print("RPI : Envoi de la réponse...")
|
||||
lora.send(reponse) # Le pilote sérialise et encode en HEX à ta place !
|
||||
else:
|
||||
print("RPI : Rien reçu.")
|
||||
Reference in New Issue
Block a user