Dashboard live
SELOtec GNSS · Monitoring Ecosystem complet · Actualisation 30s
—
Devices en ligne
—
— %
Positions / minute
—
— / heure
CPU / RAM
—
RAM —
Backup nightly
—
—
📈 CPU / RAM (24h)
CPU
RAM
📡 Activité GPS (24h)
pos/min
devices actifs
🔔 Alertes système
⏱ Countdown — Jour J Migration CloudDB
06/05/2026 02h30 · Bascule HyTalkPro → CloudDB · NAT switch ~30s coupure radios
--Jours
:
--Heures
:
--Min
:
--Sec
Accès rapides
Naviguer vers les sections
Flotte GPS
Parc complet en temps réel
—
Devices — Parc GPS complet
800 radios · 50 groupes entreprises · données en temps réel
—
🟢 En ligne
—
⚫ Hors ligne
—
Total
Liste des devices
—
| # | Device ID | Alias | Groupe | Statut |
|---|
Monitoring serveur
CPU · RAM · Disque · Base de données · Alertes
—
CPU
—
utilisation processeur
RAM
—
—
Disque
—
—
Load avg 1min
—
charge système
Swap
—
utilisation swap
PostgreSQL
—
base traccar
📈 Historique CPU / RAM (24h)
CPU
RAM
Load
📡 Activité GPS — positions/min et devices actifs (24h)
pos/min
devices actifs
🔔 Alertes Prometheus
—
Sécurité & fail2ban
Protection SSH · SELOtec GNSS auth · Nginx · Actualisé 5min
—
IP bannies actives
—
Tentatives SSH détectées
—
Jails actives
3
Ban durée
48h
Backup & PostgreSQL FDW
Backup nightly · Sync PUC → tc_positions
—
—
—
—
positions / minute
—
positions (dernière heure)
—
devices actifs (1h)
Dernier point GPS reçu
—
—
Nginx & CI/CD GitHub
Proxy · Headers sécurité · GitHub Actions
Configuration Nginx
# /etc/nginx/sites-available/selotec
server {
listen 80; server_name 197.31.9.21; server_tokens off;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy no-referrer-when-downgrade;
location / { proxy_pass http://127.0.0.1:8082; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
location /grafana/ { proxy_pass http://127.0.0.1:3000/; }
location /docs/ { alias /var/www/selotec-docs/; auth_basic "SELOtec GNSS"; auth_basic_user_file /etc/nginx/.htpasswd; }
location /mrps/ { proxy_pass http://127.0.0.1:5000/mrps/; }
location /scp/ { proxy_pass http://127.0.0.1:5000/scp/; }
}
GitHub Actions CI/CD
✓
validate-xml
Valide traccar.xml avec xmllint à chaque push
passing
✓
validate-sql
Vérifie la syntaxe des scripts .sql via psql --dry-run
passing
📸
schema-snapshot
pg_dump --schema-only → artifact GitHub (90 jours)
passing
SCP — SELOtec Control Panel
Dashboard superadmin · Contrôle FDW · Orchestration de l'écosystème GPS
Rôle dans l'écosystème
Le SCP est l'interface de contrôle unique de l'écosystème SELOtec GNSS.
Il remplace toutes les manipulations SQL/shell directes et permet de gérer le parc GPS, les organisations clientes,
la synchronisation FDW et l'infrastructure serveur depuis un dashboard React sécurisé.
Chaque action SCP impacte directement
Chaque action SCP impacte directement
tc_device_mapping, puc_enterprise_mapping
et les groupes SELOtec GNSS — les trois tables pivot de tout l'écosystème.
Version SCP
v2.4
SCP v1.0.0 release
API version
2.4.0
Catégories actives
A–C
D–E roadmap
Stack
FastAPI
+ React Vite
Architecture technique
# Flux SCP
/scp/ → React Vite (scp-frontend) → FastAPI :8090
↓
mrps_db (PostgreSQL) ← organisations, users, devices, audit
↓
traccar DB (via psycopg2) ← tc_devices, tc_groups, tc_device_mapping
↓
PUC FDW (gps_location_data_remote) ← Scan live devices non mappés
# Accès production
URL http://197.31.9.21/scp/
Homeid 00000 (superadmin)
Dépôt vxixv/SELOtec-MRPS (privé) tag v1.1.0
Cat A — Gestion clients & onboarding
Wizard 3 étapes · Utilisateurs · JWT auth
| Endpoint | Méthode | Description |
|---|---|---|
/api/admin/login | POST | Auth superadmin → JWT token |
/api/admin/clients | GET | Liste tous les clients avec KPIs (CDR, devices, dernière position) |
/api/admin/clients/{homeid} | GET | Fiche client complète |
/api/admin/clients/{homeid}/devices | GET/POST | Devices SELOtec GNSS du client (GPS + CDR 30j) · Ajout device |
/api/admin/onboard | POST | Wizard 3 étapes : Identifier → Provisionner → Résumé |
/api/admin/users | GET/POST | Gestion utilisateurs MRPS (JWT, rôles client/admin/superadmin) |
/api/admin/verify-password | POST | Vérification bcrypt avant action destructive |
Cat B — Organisations & groupes SELOtec GNSS
CRUD atomique · Création simultanée tc_groups + puc_enterprise_mapping + mrps_enterprises
| Endpoint | Méthode | Description |
|---|---|---|
/api/admin/organisations | GET | Liste orgs avec stats (devices actifs, CDR, homeid) |
/api/admin/organisations | POST | Création atomique : tc_groups + puc_enterprise_mapping + mrps_enterprises en une transaction |
/api/admin/organisations/{homeid} | PUT | Modification nom / homeid / mapping SELOtec GNSS |
/api/admin/organisations/{homeid} | DELETE | Suppression bloquée si devices actifs associés |
/api/groups | GET | Groupes SELOtec GNSS (avec parent, devices actifs) |
/api/groups | POST | Création groupe SELOtec GNSS |
/api/groups/{id} | PUT/DELETE | Renommage / changement parent / suppression |
/api/admin/organisations/{homeid}/scan | GET | Scan devices PUC non mappés (SSE, mode fast/live, auth token) |
Scanner PUC FDW — Modes fast & live
Cœur du SCP · Orchestration enregistrement devices
⚡ Mode fast (défaut)
Source :
Résultat instantané (<1s)
Données : devices connus depuis dernier scan live
Usage : consultation quotidienne
puc_known_devices localRésultat instantané (<1s)
Données : devices connus depuis dernier scan live
Usage : consultation quotidienne
⬡ Mode live (FDW réel)
Source :
Fenêtre 90 jours de données PUC
SSE avec messages
Timeout Nginx dédié 600s
Interface DOS/Matrix rain pendant le scan
gps_location_data_remote via FDWFenêtre 90 jours de données PUC
SSE avec messages
__step__ intermédiairesTimeout Nginx dédié 600s
Interface DOS/Matrix rain pendant le scan
Résultats : devices NEW (badge 7j) · devices avec alias à renommer (≤4 chiffres) · bouton
[+ADD] / [F2] TOUT AJOUTER
Cat C — Contrôle infrastructure
Crons · Services systemd · Disque · Sans accès SSH
| Endpoint | Méthode | Description |
|---|---|---|
/api/infra/status | GET | État sync PUC, purge osmand, disque, services systemd |
/api/infra/sync/toggle | POST | Activer / désactiver le cron sync_puc.sh (30s) |
/api/infra/sync/run | POST | Force run synchronisation PUC immédiate |
/api/infra/purge-osmand/toggle | POST | Activer / désactiver la purge nightly osmand |
/api/infra/purge-osmand/run | POST | Force run purge osmand immédiate |
Audit & Synchronisation
Cohérence PUC ↔ GNSS ↔ MRPS · Journal actions
| Endpoint | Description |
|---|---|
/api/admin/sync-audit?days=7|30|90 | Audit cohérence 3 systèmes — 100% local (<1s), 800 lignes tc_devices.lastupdate |
/api/admin/audit | Journal actions superadmin (filtrable par type, date, homeid) |
SYNC — PUC actif + mappé GNSS + CDR MRPS
PARTIEL — actif PUC + mappé + sans CDR période
NON_MAPPE — actif PUC, non enregistré GNSS
GNSS_ONLY — mappé GNSS, inactif PUC
ORPHELIN — device GNSS sans client MRPS
Roadmap Cat D–E
Cat D — Gestion utilisateurs MRPS depuis SCP
Création/modification/suppression comptes clients depuis le panel superadmin — en attente migration clouddb
Cat E — Rapports & exports
CDR export CSV/PDF, rapports activité, heatmaps positions par client
MRPS — Relations Clients SELOtec
Interface client · CDR · GPS · Statistiques · Authentification multi-tenant
—
Rôle dans l'écosystème
MRPS est l'interface client finale de l'écosystème : chaque entreprise cliente
accède à son espace dédié (homeid), visualise ses radios GPS sur carte, consulte l'historique CDR,
et reçoit des alertes (urgences, positions anormales).
MRPS consomme les données produites par le FDW (positions GPS), enrichies par Nominatim (géocodage), et injectées via
MRPS consomme les données produites par le FDW (positions GPS), enrichies par Nominatim (géocodage), et injectées via
ingest.py + enrich_gps.py.
Devices enregistrés
—
Nouveaux (7 jours)
—
Nouveaux (24h)
—
Clients actifs
38
sur 50 entreprises
CDR total
214K+
Positions géolocalisées
151K+
Urgences détectées
21
Version API
2.3.0
Architecture technique
# Flux MRPS
/mrps/ → React Vite (frontend) → FastAPI :8090
↓
mrps_db (PostgreSQL)
├── mrps_enterprises ← 50 entreprises (homeid, nom, actif)
├── mrps_users ← comptes JWT (client/admin/superadmin)
├── mrps_call_records ← 214K CDR (device_id, durée, coords, priorité)
└── mrps_audit_log ← journal actions superadmin (JSONB)
# Pipeline données GPS
tc_positions → ingest.py → mrps_call_records
→ enrich_gps.py → Nominatim → coordonnées nommées
# Accès production
URL http://197.31.9.21/mrps/
Homeid 00004 (admin client démo)
Dépôt vxixv/SELOtec-MRPS (privé) tag v1.1.0
API endpoints clients
| Endpoint | Méthode | Description |
|---|---|---|
/api/login | POST | Auth client → JWT (homeid, username, rôle) |
/api/devices | GET | Devices du client (GPS live, statut, dernière position) |
/api/cdr | GET | Journal d'appels (durée, coordonnées, priorité, urgence) |
/api/stats | GET | Statistiques : appels/jour, durée moyenne, urgences, couverture GPS |
/api/positions | GET | Historique positions GPS (filtre device, période) |
/api/map | GET | Données carte : positions actuelles + tracé trajet |
Derniers devices enregistrés
Les plus récents en premier
Workflow Hytera complet
# Flux Hytera → SELOtec
SOP Interface → org_id 5 chiffres (= homeid MRPS)
→ Radio allumée → Hytalk app → Internet
→ Hytalk Pro (serveur)
├── PUC (GPS) : device_id 7 chiffres → FDW → tc_positions → MRPS
└── clouddb (CDR) : enterprise_id interne ⚠ ≠ homeid (lien non résolu)
# État 98 devices Hytalk incompatibles
state=10 → PTT OK mais GPS non transmis
Cause : version app Hytalk incompatible serveur PUC
Correction : upgrade serveur PUC (prévu migration clouddb)
Architecture — Migration CloudDB
Philosophie SQL · Architecture · Infrastructure · Données · Séquence · Jour J — 06/05/2026 02h30
⏰ Jour J : 06/05/2026 02h30
Du relationnel au dimensionnel — un changement de paradigme
Le PUC Hytera fonctionnait sur un modèle relationnel classique (OLTP) : 1 table plate, toutes les radios mélangées, aucun partitionnement.
CloudDB adopte un modèle dimensionnel orienté time-series (OLAP) : hypertable TimescaleDB partitionnée sur l'axe temporel, isolation par realm (dimension client), distribution Citus.
Ce n'est pas qu'un changement de serveur — c'est un changement de paradigme de stockage.
PUC — Modèle Relationnel (OLTP)
Modèle de stockage
1 table plate
Toutes les radios mélangées — aucune isolation client
dbo.gps_location_dataToutes les radios mélangées — aucune isolation client
Identifiant device
device_id 12 chars — encodage compositeorg(5) + device(7) — pas une vraie dimensionPartitionnement
Aucun — 1 bloc de données, croissance linéaire
Index btree sur
Index btree sur
device_id + gps_datetimeIndicateur GPS valide
gps_av = 'A' → valide · 'V' → invalideConvention NMEA inversée propre à HyTalkPro
Timezone
UTC+2 Brussels → décalage +1h vs Tunis
Correction obligatoire à chaque sync
Correction obligatoire à chaque sync
CloudDB — Dimensionnel / Time-Series (OLAP)
Modèle de stockage
51 schémas isolés — 1 par client (realm)
Chaque realm = dimension organisation indépendante
Chaque realm = dimension organisation indépendante
Dimensions
device_id 7 chars — dimension device purerealm — dimension client (clé de routage inter-schéma)Axe temporel — TimescaleDB
Hypertable sur
Chunks automatiques 7j · Compression chunks froids · Rétention · Range scans ultra-rapides
gps_datetimeChunks automatiques 7j · Compression chunks froids · Rétention · Range scans ultra-rapides
Indicateur GPS valide
gps_av = 'V' → valide (inversé vs PUC)Notre sync gère les deux conventions simultanément
Distribution — Citus
Données réparties sur nœuds workers · Scalabilité horizontale
Africa/Tunis — offset 0 vs notre serveur
Africa/Tunis — offset 0 vs notre serveur
Adaptation SELOtec — pont entre les deux modèles
| Concept SQL | PUC (relationnel) | CloudDB (dimensionnel) | Adaptation sync |
|---|---|---|---|
| Identifiant device | 12 chars 000041000053 | 7 chars 1000053 | RIGHT(remote_uniqueid, 7) |
| Validité GPS | gps_av = 'A' | gps_av = 'V' | Condition OR dans sync |
| Namespace client | Absent (1 schéma dbo) | db_[client].selotec.com | puc_enterprise_mapping.clouddb_realm |
| Accès données | 1 foreign table FDW | 51 foreign tables | Vue UNION ALL gps_location_data_clouddb |
| Décalage horaire | UTC+2 → correction -1h | Africa/Tunis → offset 0 | Aucune correction dans sync clouddb |
| Partitionnement | Aucun (table plate) | Hypertable chunks 7j | Transparent pour la sync (SELECT standard) |
Stack logicielle complète — SELOtec GNSS
6 couches · Terrain → PTT → DB → Sync → Services → UI
Architecture infrastructure — avant / après migration
Réseau · NAT · Serveurs · Ports · Jour J
Architecture des données — modèle entité-relation
Tables · Clés · JOIN · FDW · Relations inter-systèmes
Diagramme de séquence — flux GPS complet
Radio → HyTalkPro → FDW → GNSS → Applications · 13 étapes
Rapport & Documentation
Architecture · Chronologie · Problèmes · Changelog · Roadmap · Synthèse
Paramètres du projet
| Paramètre | Valeur |
|---|
Flux de données
Objets SQL
Chronologie du projet
Composants installés
Mises à jour techniques
État opérationnel des composants
🇫🇷 Synthèse finale
🇬🇧 Executive Summary
Réalisations
🏗 Architecture CloudDB
Architecture PUC → CloudDB · Jour J — 06/05/2026 02h30
Documentation complète de la migration vers CloudDB (51 schémas, Citus + TimescaleDB) :
- Architecture PUC (ancien) vs CloudDB (nouveau)
- Concept Realm : identification du schéma client dans clouddb
- Adaptation FDW : foreign server + 51 tables + vue UNION ALL
- Ports : 8063/8064/46000-48005/14005
- Séquence Jour J — bascule automatique en 5 étapes