1. Introduction
Le serveur est essentiellement constitué du logiciel r3Server qui gère une API REST pour le calcul de routes.
Il existe aussi des pages statiques (html, css, js...) utiles à l'application. Le logiciel r3Server est aussi un serveur Web, même si il est
recommandé d'utiliser Nginx pour :
- décharger le logiciel
r3serverafin qu'il ne se consacre qu'à la gestion de l'API et au calcul de routes, - autoriser du load balancing,
- gérer HTTPS et le chiffrement associé.
Un utilitaire r3gribget doit être lancé périodiquement pour récupérer les grib (NOAA, ECMWF, autres).
La "crontable" permet d'automatiser ces lancements, toutes les 6 ou toutes les 12 heures selon les Grib.
En annexe, on trouvera aussi la description d'un autre serveur, utilisé sur poste client qui peut ainsi collecter les information GPS et AIS
2. Procédure d'installation coté serveur
De façon générale, l'installation du serveur suppose :
- La disponibilité d'un serveur accessible d'Internet,
- l'installation de l'environnement (gcc, eccodes, curl) sur le serveur,
- le téléchargement des fichiers sources dans un répertoire
csources, - la compilation et l'édition de lien de ces sources,
- l'adaptation du fichier de configuration
routing.parpour notamment les chemins d'accès (wd, www), - la construction de l'arborescence avec les répertoires nécessaires,
- la présence d'au moins un fichier polaire dans le répertoire
pol, - la présence d'au moins un fichier grib dans le répertoire
grib. Utilisation recommandée de l'utilitairer3gribgetpour cela, - la présence des fichiers statiques html, js, css dans le répertoire
www, - l'assurance que le fichier javascript
r3param.jscontient la clef d'accès à Windy et le nom ou l'adresse IP du serveur avec le ou les numéros de ports choisis côté serveur (8080 et suivants en général), - le lancement du serveur,
- quelques tests en mode client avec curl,
- un test avec un navigateur est maintenant possible ;-)
Les commandes qui suivent sont données pour un environnement Debian (Ubuntu ou autre).
Préliminaires
Vérifier que gcc est installé. Si ce n’est pas le cas, l’installer.
sudo apt install gcc
Installer les bibliothèques
Installez les paquets nécessaires pour curl, eccodes :
sudo apt-get install -y libcurl4 libcurl4-openssl-dev
sudo apt-get install -y libeccodes0 libeccodes-dev
sudo apt-get install libeccodes-tools # pour les outils ligne de commande
JSdoc
Il n'est pas nécessaire d'installer JSdoc côté serveur.
Ce peut être néanmoins utile pour générer automatiquement la documentation des fichiers .js hébergés sur le serveur.
Dans ce cas installer d'abord nodejs.
sudo apt update sudo apt install nodejs npm
Puis JSsoc.
sudo npm install -g jsdoc
Vérifier l'installation avec
jsdoc --version
Basic Authentication avec NGINX
sudo apt install apache2-utilsPermet d'accéder à la commande
htpasswd.
wgrib2
Voir section relative à r3gribget.
Construction du code
Construction de l'arborescence.
mkdir csources gribget currentgrib geo grib par pol wavepol www
cd www
mkdir doc
Dans le répertoire d’exécution, on doit trouver les répertoires suivants :
csources gribget currentgrib geo grib par pol wavepol www
csources
csources contient les programmes sources et le Makefile ainsi que ccs.
La production du fichier exécutable nécessite les fichiers sources .c et .h suivants :
engine.c polar.c r3grib.c r3server.c r3util.c readgriballeccodes.c readgriballwithouteccodes.c r3gribget.c (programme indépendant utilisant quand même glibwrapper.h) engine.h glibwrapper.h grib.h inline.h polar.h r3types.h r3util.h readgriball.hAinsi que les fichiers :
ccg ccs ccs0 : idem ccs mais ne nécessite pas ECCODES MakeFile
Pour la construction du logiciel r3server, la commande de compilation et d’édition des liens est assurée par le
fichier shell exécutable :
./ccsou./ccs0
geo
Le répertoire geo contient les fichiers géographiques.
Le fichier issea.txt permet de savoir si un point de la carte est «en mer» ou «à terre».
Le fichier portprinc.csv donne la latitude et la longitude des ports principaux pour retrouver les marées du SHOM.
grib
Ce répertoire contient les fichiers Grib, téléchargés avec r3gribget.
Il est utile que ce répertoire contienne au moins un fichier. C'est pourquoi il est conseillé de ne pas détruire le petit fichier Grib : reference.grb2, ou de lancer r3gribget pour avoir au moins un fichier dans le répertoire.
gribget
gribget contient le programme source r3gribget.c ainsi que ccg.
currentgrib
Ce répertoire contient les fichiers Grib pour les courants.
www
Ce répertoire contient les fichiers html, css, js textes statiques.
par
Ce répertoire contient les fichiers de paramètres (scénarios) suffixés par “.par”.
Le fichier “.par” par défaut est : routing.par.
La description des paramètres se trouve dans le répertoire helpdir, fichier docpar.txt
pol
Ce répertoire contient les fichiers polaires au format ".pol" ou ".csv".
Les fichiers csv ont pour séparateurs le caractère ";".
Les fichiers pol ont pour séparateurs le caractère tabulation.
wavepol
Ce répertoire contient les fichiers polaires de vagues suffixées par "polwave.csv".
3. Documentation
La documentation est constituée :
- Des fichiers html, css que vous lisez et qui sont dans le répertoire
www, - du document
docpar.txtdans le même répertoire, - de la documentation produite par doxygen,
- github héberge aussi les sources du projet et un certain nombre de commentaires.
4. Lancement de l'application
Le lancement de l’application se fait via la commande :
./r3server <port> [parameter file]
Le numéro de port est obligatoire. Recommandé: 8080
Si le nom du fichier de paramètre est absent, le serveur utilise "routing.par".
5. API
Présentation
L'API est une API REST. Les requêtes sont des requêtes HTTP POST sur le port spécifié lors du lancement du serveur.
Exemple de requête :
curl http://localhost:8080 -d "type=1&boat=hoho,47.0,-3.0&waypoints=47.5,-3.0;47.0,-5.0&timeStep=3600&isoc=false"
Derrière un serveur NGINX répondant en HTTPS et configuré en reverse Proxy :
curl https://rcube.ddns.net/post-api/ -d "type=1&boat=hoho,47.0,-3.0&waypoints=47.5,-3.0;47.0,-5.0&timeStep=3600&isoc=false"
La commande curl envoie sur le port 8080 (ici au serveur local) la requête HTTP POST dont le contenu est spécifié après -d.
Le résultat de la requête est une réponse JSON.
Détail de la requête
L'ordre dans le quel les paramètres sont indiqués n'a pas d'importance.
Il sont séparés par l'esperluète &.
Exemple :
type=1&boat=hoho, 47.0, -3.0&waypoints=47.5,-3.0;47.0,-5.0&timeStep=3600&isoc=false
Type de la requête
| Val | Sémantique | Commentaire |
|---|---|---|
| 0 | Test | Pour vérifier réponse serveur. |
| 1 | Demande de routage pour un seul bateau | La principale requête. |
| 2 | Demande d'informations géographiques et météorologiques sur un point. | Coordonnées lat, lon du point et optionnellement nom du grib. |
| 3 | Demande les polygones d'interdiction | Sans paramètres. |
| 4 | Demande de polaire. | Le nom de la polaire doit être donné. |
| 5 | Demande des informations Grib. | Le nom du fichier doit être donné. |
| 6 | Liste un répertoire sur le serveur. | Le nom du répertoire doit être donné. |
| 7 | Demande le jeu de paramètres courant au serveur. Réponse au format brut (RAW) | Pas d'élément à ajouter. |
| 8 | Demande le jeu de paramètres courant au serveur. Réponse au format Json. | Pas d'élément à ajouter. |
| 9 | Réinitialise le serveur | Pas d'élément à ajouter. |
| 10 | Envoie feedback vers le serveur | Le feedback doit être donné. |
| 11 | Dump fichier texte | Le nom du fichier doit être donné.. |
| 12 | Demande le port le plus proche | A éviter. Préférer la gestion à partir du client. La latitude et la longitude du point doivent être donnés. |
| 13 | Marques | Pas de paramètre. |
| 14 | Vérification de grib | Le nom du grib vent et du grib courant doivent être donnés. |
| 15 | Route au format GPX | Pas de paramètre. |
| 17 | Dump Grib au format interne float array de uv[gw] | Model ou grib. onlyUV |
Paramètres de la requêtes
La latitude (lat) est un nombre décimal sur l'intervalle [-90..90].
:%sLa longitude (lon) est un nombre décimal sur l'intervalle [-180..180] ou sur l'intervalle [0..360].
Le tableau suivant indique pour chaque paramètre les dépendance par rapport au type.
| Key | Type/unités | Value | Dépendances | Valeur par défaut |
|---|---|---|---|---|
| type | Entier (0..10) | Type de la requête. | NA | Pas de défaut. Champ obligatoire. |
| boat | Liste de triplets name, lat, lon; | Liste les bateaux. | Pour requête 1 | Pas de défaut. Champ obligatoire. |
| waypoints | Liste de couples lat, lon; | Liste les Waypoints. | Pour requête 1 | Pas de défaut. Champ obligatoire. |
| timeStep | Entier (secondes) | Valeur du temps entre chaque isochrone. | Pour requête 1 | 3600 |
| epochStart | Entier (secondes) | Date de départ en temps Epoch Unix. | Pour requête 1 | Valeur actuelle (now) du temps Epoch (Unix). |
| polar | Chaîne de caractères | Nom de la polaire. | Pour requête 1, 4. | Par défaut fourni par le serveur. |
| wavePolar | Chaîne de caractères | Nom de la polaire de vaques. | Pour requête 1, 4. | Par défaut fourni par le serveur. |
| model | Chaîne de caractères | Model du grib | Pour requête 1, 5 | GFS, ECMWF, ARPEGE, METEOCONSULT |
| grib | Chaîne de caractères | Nom du fichier grib. | Pour requête 1, 2, 5. | Par défaut fourni par le serveur. |
| currentGrib | Chaîne de caractères | Nom du fichier grib courant. | Pour requête 1, 5. | Par défaut fourni par le serveur. |
| file | Chaîne de caractères | Nom de fichier | Pour requête 11. | vide |
| dir | Chaîne de caractères | Nom de répertoire. (soit "grib" soit "pol" soit vide). | Pour requête 6. | vide |
| forbid | Booléen: true | false | Prend en compte terre et zones interdites. | Pour requête 1 | false |
| isoc | Booléen: true | false | Demande les isochrones. | Pour requête 1 | false |
| isodesc | Booléen: true | false | Demande les descripteurs d'isochrones. | Pour requête 1 | false |
| withWaves | Booléen: true | false | Vagues prises en compte. | Pour requête 1 | false |
| withCurrent | Booléen: true | false | Courant pris en compte . | Pour requête 1 | false |
| sortByName | Booléen: true | false | Tri des fichiers par noms si vrai, par date si faux. | Pour requête 6. | false |
| cogstep | Entier | Pas de cap en degrés pour calcul isochrones | Pour requête 1 | 5 |
| cogRange | Entier | Range en degrés pour calcul isochrone | Pour requête 1 | 90 |
| jFactor | Entier | 0 ou valeur positive quelconque. | Pour requête 1 | 0 |
| kFactor | Entier | 0, 1, 2, 3 | Pour requête 1 | 1 |
| nSectors | Entier | Nombre de secteurs | Pour requête 1 | 720 |
| penalty0 | Entier (secondes) | Temps pour un virement de bord (tack) | Pour requête 1 | 0 |
| penalty1 | Entier (secondes) | Temps pour un empannage (gybe) | Pour requête 1 | 0 |
| penalty2 | Entier (secondes) | Temps pour changement de voile (sail) | Pour requête 1 | 0 |
| staminaVR | Décimal 0 à 110 | Stamina (énergie) pour Virtual Regatta | Pour requête 1 | 100 |
| initialAmure | Entier 0 ou 1 | Amure initiale. 0 Tribord, 1 Babord. Pour Virtual Regatta | Pour requête 1 | 100 |
| motorSpeed | Décimal | Vitesse en noeuds au moteur | Pour requête 1 | 6 |
| threshold | Décimal | Déclenchement du moteur si vitesse voile inférieure | Pour requête 1 | 0 |
| nightEfficiency | Décimal 0 à 1 | Facteur d'efficacité la nuit | Pour requête 1 | 1 |
| dayEfficiency | Décimal 0 à 1 | Facteur d'efficacité le jour | Pour requête 1 | 1 |
| xWind | Décimal | Coeff. Multiplicateur de la vitesse du vent | Pour requête 1 | 1 |
| maxWind | Décimal | Vitesse maximale du vent | Pour requête 1 | 100 |
| constWindTws | Décimal | Vitesse constante du vents en noeuds | Pour requête 1 | 0 |
| constWindTwd | Décimal | Direction constante du vents en degrés | Pour requête 1 | 0 |
| constWave | Décimal | Hauteur constante des vagues en mètres | Pour requête 1 | 0 |
| constCurrentS | Décimal | Vitesse constante du courant en noeuds | Pour requête 1 | 0 |
| constCurrentD | Décimal | Direction constante du courant en degrés | Pour requête 1 | 0 |
| feedback | Chaîne de caractères | Texte rédigé par l'utilisateur. | Pour requête 10 | vide |
| onlyUV | Booléen: true | false | Vrai si seulement vent (U, V) demandé | Pour requête 16 | false |
Utilisation
Requête test type= 0
Permet de vérifier la présence du serveur.
Exemple de Requête :
curl https://rcube.ddns.net/post-api/ -d "type=0"
{
"Prog-version": "RCube, 0.1, René Rigault",
"API server port": 8080,
"Grib Reader": "ECCODES 2.34.1",
"Memory for Grib Wind": "171 445 680",
"Memory for Grib Current": "0",
"Compilation-date": "Oct 6 2025",
"PID": 9520,
"Memory usage in KB": "195 484",
"Client IP Address": "90.12.244.150",
"User Agent": "curl/8.5.0",
"Authorization-Level": 0
}
Autre requête possible :
curl http://localhost:8080 -d "type=0"
Requête de routage pour un seul bateau type=1
Lance un routage.
Exemple de Requête :
curl https://rcube.ddns.net/post-api/ -u admin:admin -d "type=1&boat=banane,41.24,-16.78; &waypoints=43.068888,-40.957031;43.707594,-56.953125 &model=ECMWF &timeStep=7200 &polar=pol/class40VR.csv
Réponse du serveur :
{
"banane": {
"duration": 710255,
"totDist": 1982.56,
"routingRet": 97,
"isocTimeStep": 7200.00,
"calculationTime": 0.2669,
"destinationReached": true,
"lastStepDuration": [7618.6958, 11437.0309],
"motorDist": 0.00, "starboardDist": 1066.88, "portDist": 915.68,
"nSailChange": 26, "nAmureChange": 7,
"bottomLat": -60.00, "leftLon": -60.00, "topLat": 60.00, "rightLon": 20.00,
"polar": "class40VR.csv",
"wavePolar": "polwave.csv",
"grib": "ECMWF_20251005_12Z_240.grb",
"currentGrib": ".",
"track": [
[0, 41.244772, -16.787108, 0.000000, 10.712832, 5.356416, 146.477188, 5.366323, 279.003272, -132.448718, 0.000000, 0.000000, 100.000000, "LG", false, -1, -1],
[0, 41.272475, -17.021744, 7200.000000, 12.523172, 6.261586, 162.450041, 6.299242, 293.914355, -131.380405, 0.000000, 0.000000, 100.000000, "LG", false, 18, -1],
[0, 41.356804, -17.275940, 14400.000000, 13.085164, 6.542582, 165.576586, 6.768942, 298.634402, -132.973345, 0.000000, 0.000000, 100.000000, "LG", false, 683, 18],
...
]}}
Une route en JSON est générée pour le bateau.
Si le paramètre "isoc" était positionné à true dans la requête, l'isochrone de la route est envoyée.
Si le paramètre "isocdesc" était positionné à true dans la requête, un descripteur d'isochrones de la route est envoyée.
La route "track" elle même est un tableau Json (array).
Chaque élément du tableau est un tableau:
[wp, lat, lon, time, dist, sog, twd, tws, hdg, twa, g, w, stamina, sail, motor, id, father]
| Elément | Type/unités | Valeur |
|---|---|---|
| wp | Entier -1, 0...n | No de way point. -1 = destination |
| lat | Décimal | Latitude |
| lon | Décimal | Longitude |
| time | Entier | Nombre de seconde à partir du début de la route |
| dist | Décimal | Distance en miles marin. |
| sog | Décimal | Speed over Ground. Vitesse en noeuds. |
| twd | Décimal [0..360] | True Wind Direction. Direction du vent par rapport au Nord en degrés. |
| tws | Décimal | True Wind Speed. Vitesse du vent en noeuds. |
| hdg | Décimal [0..360] | Heading. Direction du bateau en degrés.. |
| twa | Décimal [0..360] | True Wind Angle. Angle du bateau par rapport au vent en degrés. |
| g | Décimal. | Gust. Vitesse du vent dans les rafales. |
| w | Décimal. | Waves. Hauteur des vagues en mètres. |
| stamina | Décimal | Energie (concept Virtual Regatta). |
| sail | Chaîne de caractères | Voile utilisé. |
| motor | Booléen: true / false | Moteur ou non. |
| id | Entier | Id du point |
| father | Entier | Id du father |
Element sur un point type=2
Requête donnant des informations sur un point. La requête a un paramètre qui est un triplet (nom du point, latitude, longitude) avec éventuellement le grib pour les information météo utiles pour un météogramme. Le nom du point n'est pas interprété, mais doit être présent.
Les informations renvoyées indiquent si le point est en mer en zone non interdite, et si il est a l'intérieur des zones Grib vent et courant, le nom du grib courant et le tableau des info météo.
Chaque ligne du tableau correspond à une heure. La première ligne correspond au temps de départ du grib.
Chaque élément du tableau est un tableau de 4 valeurs u, v, g, w.
u, v sont les composantes Nord Sud et Est Ouest du vent en surface en m/s.
g est la vitesses des rafales en m/s.
w est la hauteur des vagues en mètres.
curl https://rcube.ddns.net/post-api/ -u admin:admin -d "type=2&boat=bidon, 41.24, -16.0"
{
"isSea": true,
"isSeaTolerant": true,
"inWind": true,
"inCurrent": false,
"epochGribStart": 1743141600,
"grib": "METEOCONSULT06Z_VENT_0328_Nord_Atlantique.grb",
"meteoArray":
[
[0.0000, 0.0000, 0.0000, 0.0000],
[0.0000, 0.0000, 0.0000, 0.0000],
...
]
}
Liste les polygones d'interdiction type=3
Requête sans paramètre, renvoie un tableau de polygones.
Chaque polygones est un tableau de coordonnées.
Une coordonnée est un tableau avec deux éléments : [lat, lon]
Exemple avec deux polygones :
curl https://rcube.ddns.net/post-api/ -d "type=3" [ [[-43.5000, -2.7500], [-46.0000, 17.3000], [-48.0000, 35.0000], [-51.0000, 69.5000], [-49.0000, 96.0000]], [[-46.0000, 17.3000], [-48.0000, 35.0000], [-51.0000, 69.5000]] ]
Chargement de la polaire type=4
Exemples de Requête :
curl https://rcube.ddns.net/post-api/ -d "type=4" curl http://localhost:8080 -d "type=4&polar=dufour.csv"
Réponse du serveur :
Le serveur envoie en Json la polaire en Json sous forme de méta-données et d'un tableau array
à deux dimensions.
Si la polaire est une composition de polaire, trois tableaux sont générés
array: le contenu de la polaire,arraySail: le numéro de la voile utilisée,array: la légende des voiles. Indice 0: "NA", indice 1: nom de la première voile, etc.
Méta information sur un fichier Grib type=5
La requête contient soit :- Le nom du modèle. C'est alors le fichier le plus récent correspondant à ce modèle qui est sélectionné, model: GFS | ECMWF | ARPEGE | METEOCONSULT | SYN,
- Le nom du fichier grib. Il faut l'avoir préalablement identifié à partir d'une requête de type 6 par exemple.
Exemple de Requête :
curl https://rcube.ddns.net/post-api/ -d "type=5&model=GFS" ou curl https://rcube.ddns.net/post-api/ -d "type=5&model=GFS"
Réponse du serveur :
Les méta informations sur le grib et non pas le fichier Grib lui même.
Répertoire type=6
Liste le répertoire donné en paramètre dir=. Ce peut être :
polpour la liste des fichiers polaires,wavepolpour la liste des fichiers polaires de vagues,gribpour la liste des fichiers grib relatifs au vent,currentgribpour la liste des fichiers grib relatifs au courant.
Le paramètre complémentaire sortByName permet d'obtenir la liste des fichiers triés par nom.
Par défaut, les fichiers sont envoyés du plus récent au plus ancien selon leurs dates de modification.
Exemple de Requête :
curl https://rcube.ddns.net/post-api/ -d "type=6&dir=pol&sortByName=true" ou curl https://rcube.ddns.net/post-api/ -d "type=6&dir=grib"
Réponse du serveur :
Chaque ligne de tableau est de la forme :[nom fichier, taille fichier, date de modification] [ ["2024-VR-VG-RR.csv", 2162, "2025-01-11 01:52:20"], ["2025-Imoca.csv", 4188, "2025-01-03 19:07:14"], ["Dufou500GV+FocOriginal.pol", 665, "2024-05-04 15:57:52"] ] ou [ ["GFS_20251006_00Z_384.grb", 137104881, "2025-10-06 07:16:21"], ["GFS_20251005_18Z_384.grb", 137297882, "2025-10-06 01:16:19"], ["GFS_20251005_12Z_384.grb", 138417282, "2025-10-05 19:16:20"] ]
Paramètres (RAW) type=7
Permet de dumper les paramètres courants du serveur au format brut (RAW).
Voir section suivante pour comprendre les paramètres de configuration du serveur
curl https://rcube.ddns.net/post-api/ -u admin:admin -d "type=7"
Réponse du serveur :
DESC: Routing parameters. See also docpar.txt for documentation WD: /home/rr/routing/ ALLWAYS_SEA: 0 ...
Paramètres (Json) type=8
Permet de dumper les paramètres courants du serveur au format Json.
Voir section suivante pour comprendre les paramètres de configuration du serveur
curl https://rcube.ddns.net/post-api/ -d "type=8"
Réponse du serveur :
{
"wd": "/home/rr/routing/",
"grib": "GFS_20250429_00Z_384.grb",
"bottomLat": -20.00, "leftLon": -80.00, "topLat": 60.00, "rightLon": 10.00,
"currentGrib": ".",
"polar": "moteur.pol",
"wavePolar": "polwave.csv",
"issea": "issea.txt"
}
Réinit type=9
Utilisé notamment pour faire en sorte que le serveur charge le grib le plus récent.
Le script suivant r3init réinitialise l'ensemble des instances.
#!/bin/bash for port in $(seq 8080 8081); do curl http://localhost:$port -d type=8 done
Feedback type=10
Utilisé pour permettre à l'utilisateur de donner un feedback.
curl https://rcube.ddns.net/post-api/ -d "type=10&feedback=bug report..."
Dump type=11
Utilisé pour télécharger un fichier texte. Mode "RAW".
curl https://rcube.ddns.net/post-api/ -d "type=11&file=routing.log"
Port le plus proche type=12
Utilisé pour trouver le port le plus proche (SHOM) et l'identifiant Marée Info.
Peut être aussi générée à partir du client.
curl https://rcube.ddns.net/post-api/ -d "type=12&waypoints=47.2,-2.5"
{"nearestPort": "LE_POULIGUEN", "idPort": 115}
Marques type=13
Pas de paramètre.
Donne au format Json les marques. Utilisation avec Vitual Regatta.
Vérification de Grib type=14
Paramètres obligatoires : nom du grib vent et du grib pour courant
Renvoie au format text des informations sur la cohérence des grib.
Route au format GPX type 15
Pas de paramètre.
Renvoie la route stockée dans le serveur au format GPX.
Attention en cas d'utilisateurs multiples, c'est la dernière route calculée qui est envoyée, pas nécessairement celle de l'utilisateur qui fait la demande...
Téléchargement du grib type 16
curl -v http://localhost:8080 -o data.bin "type=16&model=GFS"
Le paramètre onlyUV=true peut être ajouté pour indiquer au serveur de ne renvoyer que u et v
Le fichier généré n'est pas au format grib, mais dans un format ad-hoc pour communiquer entre le serveur et le client (Javascript).
C'est un fichier binaire contenant une succession de flottants (codés sur 32 bits).
Chaque point est décrit par un vecteur de shortnames (u, v, g, w)
u et v sont obligatoires
L'entête HTTP contient X-Shortnames:, la liste des shortnames.
g (gust ou rafale) et w (swh ou hauteur des vagues) sont optionnels.
Les possibilités sont donc : uv, uvg, uvw, uvgw.
Le nombre de valeur est déterminé par :
- Le nombre de time stamp (nTimeStamp),
- le nombre de latitudes (nLat),
- le nombre de longitudes (nLat)
- le nombre de shortnames (nShortName).
La nombre de float émis est N : nTimeStamp * nLat * nLon * nShortname.
La taille du fichier en octets est : 4 * N.
6. Fichier de configuration du serveur
Les fichiers suffixés par ".par" ou par ".yaml" sont situés dans le répertoire "par".
Le fichier par défaut est "routing.par" et est essentiel pour le bon fonctionnement de RCube.
Un autre nom de fichier peut être spécifié dans la ligne de commande au lancement du serveur.
Un fichier ".par" ou ".yaml" est un fichier texte comportant des lignes de la forme :
NOM: valeur
Des commentaires peuvent être ajoutés après le signe "#".
Le format est compatible avec YAML.
Exemple :
WD: /home/rr/.... # Working directory SERVER_PORT: 80 # TCP PORT FORBID_ZONES: - [[lat0, lon0], [lat1, lon], [latN, lonN]] - ... ...
Informations sur les paramètres : docpar.txt
Exemple de fichier par : ../par/routing.par
7. Code source
Présentation
Le logiciel côté serveur est écrit en langage C.
La librairie eccodes peut être utilisée pour le décodage des fichiers Grib. C'est optionnel, il existe également la possibilité des se passer de eccodes.
Le répertoire csources contient le code C.
| Fichier | Commentaire |
|---|---|
| r3types.h | Définition des constantes générales #defines, des
enum et des typedef. |
| inline.h | Définition de petites fonctions inline incluses dans les fichiers .c |
| glibwrapper.h | Définition de petites fonctions inline simulant les fonctions éponymes de la GLIB. |
| engine.c ou enginesimple.c | Cœur du programme avec calcul des isochrones. |
| engine.h | Interface de engine (prototypes des fonctions externes). |
| r3grib.c | Lecture des fichiers Grib et utilitaires Grib. |
| grib.h | Interface de grib (prototypes des fonctions externes). |
| option.c | Gère les différentes commandes du mode CLI (voir routing.c |
| r3util.c | Fonctions utiles. |
| r3util.h | Interface de r3util (prototypes des fonctions externes). |
| polar.c | Lectures des fichiers polaires et utilitaires associés. |
| polar.h | Interface de polar (prototypes des fonctions externes). |
| readgriballeccodes.c | Chargement de fichiers Grib en mémoire, utilisant l'API ECMWF ECCODES. |
| readgriballwithouteccodes.c | Chargement de fichiers Grib en mémoire, n'utilisant pas l'API ECMWF ECCODES. |
| readgriball.h | Interface commune à readgribeccodes.h et de readgribwithoutccodes.c |
| r3server.c | Le serveur. |
| routing.c | Programme en mode CLI uniquement. |
Style et documentation
Doxygen donc utilisé pour produire la documentation.
L’anglais américain est utilisé pour les identificateurs (constantes, variables, fonction, etc) et les commentaires.
Les commentaires préférés sont de type //.
Les fonctions et typedef sont précédés de commentaires interprétables par Doxygen et précisant la nature du typedef ou de la fonction.
/*! Description */
Les #define sont en majuscules avec _ comme séparateur
#define MAX_N_ISOC 512
Les noms des variables et fonction sont en minuscules, en utilisant la notation camel.
Exemple : ceciEstConformeNotationCamel
Les nom des définitions de types commencent par une majuscule, le reste est en majuscule.
Les décimaux sont en général de type double. Le type float n’est utilisé que pour le stockage des grib. Les constantes de type double sont suffixées par .0 au besoin, pour éviter les ambigüités avec les types entiers.
Le type bool est largement utilisé avec les valeurs associées
true, false.
myInt = 10;
double myDouble = 10.5;
double myOtherDouble = 10.0;
myBool = false;
const int xTop = 1;
Vérification du code
Des directives de compilation strictes sont utilisées pour vérifier le code voir ccs, ccs0.
cppcheck est utilisé pour compléter la vérification statique du code.
gcc analyser est également utilisé.
Voir le fichier ccheck.
Mesures de performances
Les option de compilation -g et -pg sont à ajouter
(compilation et édition de liens).
Un fichier gmon.out est généré.
Exploiter ce fichier par la commande :
gprof ./r3server gmon.out > profil.txt
Gestion du temps
La gestion du temps est assez complexe et mérite quelques éclaircissements.
Fichiers Grib
Les fichiers Grib contiennent des informations sur le temps, en heures UTC. Côté serveur, toutes les informations relatives au temps se réfèrent au temps UTC.Variables globales dans RCube
par.startTimeInHours stocke en heures le temps t comme la différence en heure entre le temps t et le début du grib.
startInfo est une variable globale struct tm qui stocke le temps.
Elle est initialisée à la valeur du temps de début de Grib par la fonction
initStart (&startInfo)
on peut traduire startInfo en heures par rapport au début du Grib avec la fonction suivante :
par.startTimeInHours = getDepartureTimeInHour (&startInfo)
vOffsetLocalUTC stocke la différence en secondes entre le temps UTC et le temps local.
Par exemple, en France la valeur est donc de 3600 ou de 7200, selon l'heure d'été ou d'hiver
Il s'obtient par l'appel à la fonction suivante :
vOffsetLocalUTC = offsetLocalUTC ()
theTime est un double qui stocke la valeur du temps exprimée en heures après le début du grib
pour l'affichage de la carte météo
8. Chargement des GRIB
L'utilitaire r3gribget permet télécharger les fichiers Grib de la NOAA et de l'ECMWF.
Utilisation
Synopsys :
r3gribget dir mode [maxStep topLat leftLon bottomLat rightLon]
dir: directory for grib file
mode: 1 NOAA, 2 ECMWF, 3 ARPEGE, 4 AROME
for METEO CONSULT WIND: mode = 50y with no other parameter,
for METEO CONSULT CURRENT: mode = 60y with no other parameter.
Example: ./r3getgrib grib 1 96 60 -20 10 1 # NOAA request up to 96 hours, and specified region
Example: ./r3getgrib grib 1 # NOAA request with default values
Example: ./r3getgrib grib 502 # METEO CONSULT Request for Wind Centre_Atlantique"
maxStep step maximal (384 pour NOAA)
topLat, letLon, bottomLat, rightLon : Zone géographique
Calcul du run (00Z, 06Z, 12Z, 18Z) automatique en fonction de l'heure UTC et d'un delay (constante dans le code).
Création de fichiers temporaires .tmp
le fichier résultant se trouve dans le répertoire Grib, créé si besoin.
Construction du code
r3gribget est écrit en langage C. Un seul fichier source : r3gribget.c
La bibliothèque curl est utilisée pour le téléchargement des fichiers Grib.
gcc -o r3gribget r3gribget.c -lcurl
La commande de compilation et d’édition des liens est dans le fichier shell exécutable :
./ccg
grib_copy
Cet utilitaire fourni par l'ECMWF avec la bibliothèque ECCODES permet de sélectionner dans un grib les shortnames utiles.
Il est nécessaire pour la gestion des Grib venant de l'ECMWF et de Météo France (AROME et ARPEGE).
wgrib2
wgrib2 : cet utilitaire permet notamment d'extraire un sous ensemble d'un fichier Grib. Il est utilisé dans le cas des téléchargement web sur les sites open data de l'ECMWF et de Météo France. Si non installé, le logiciel fonctionne soit avec la NOAA (fichiers GFS) et avec Meteo Consult..RCube utilise maintenant wgrib2 (abandon définitif de CDO qui n'est pas compatible Arpege) au travers de la commande extrayant une région.
wgrib2 input.grib -small_grib lonLeft:lonRight latMin:latMax output.grib
wgrib2 /home/rr/rcube/grib/inter0.tmp -small_grib -13:-1 43:48 /home/rr/rcube/grib/inter1.tmp
Si wgrib2 n'est pas installé, le téléchargement direct des fichiers ECMWF et ou Météo France n'est pas possible
Installation de wgrib2 :
Un peu compliquée. Si on dispose déjà d'un exécutable, notez la procédure suivante :
scp from_directory/wgrib2 user@serveur:/home/user/bin
chmod +x /home/user/bin/wgrib2
export PATH=$HOME/bin:$PATH
Installation des dépendances :
sudo apt update
sudo apt install libgfortran5 libgomp1 libgcc-s1
Vérification de l'installation :
wgrib2 -version
9. Génération de grib
Un utilitaire mkgrib.c permet de générer un grib.
Lancement :
./mkgrib spec.yaml
spec.yaml contient les spécifications du fichier en YAML.
Il est possible de définir plusieurs "area".
Chaque Area défini la zone géographique couverte (latFirst, latLast, lonFirst, lonLast)
et l'évolution temporelle du vent (twd en degré, tws en noeuds) et de la hauteur des vaques (w en mètres).)
# Wind specification for mkgrib.c
---
stepHours: 3
# dataDate: 20251008
# dataTime: 1200
areas:
# bug avec 51 pas avec 53
- name: 0
latFirst: 60
latLast: 0
lonFirst: -50
lonLast: 15
# t twd tws w
winds:
- [0, 0, 20, 0]
- [50, 0, 20, 0]
- [70, -90, 5, 0.5]
- [100, -90, 5, 0.5]
- [150, 45, 28, 1]
- [200, 45, 28, 1]
- [240, 90, 14, 2]
- name: 1
latFirst: 30
latLast: 10
lonFirst: -40
lonLast: -15
# t tmax twd tws w
winds:
- [0, 180, 0, 0]
- [240, 180, 0, 0]
Sur la durée d'un plateau, les valeurs twd, tws w sont constantes.
Entre plateaux, interpolation linéaire.
10. Hébergement
Prérequis
- Un hébergement dans le cloud ou sur un serveur dédié,
- openssh-server,
- nginx,
- l'installation faite telle que décrite au début de de document.
Pour fonctionner en HTTPS, installer certbot et générer le certificat SSL :
sudo apt update sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d rcube.ddns.net
Renouvellement automatique du certificat (3 mois)
sudo certbot renew --dry-run
Le serveur r3server
Architecture NGINX et r3server
NGINX écoute sur le port 443 (HTTPS), sert les pages statiques situées dans le répertoire www et joue le rôle de proxy pour le serveur API qui fonctionne en HTTP sur les ports 8080, 8081, gère l'authentification "basic" HTTP.
L'application r3server écoute sur les ports 808x. (en fait, une instance pour chaque port).
Configuration NGINX
Edition du fichier de configuration
/etc/nginx/sites-available/rcube
upstream api_servers {
# Load balancing entre les serveurs API internes (en HTTP)
#least_conn;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
# Mapping identité niveau
map $remote_user $user_level {
default 0; # anonyme ou non authentifié : niveau 0
alice 1;
bob 1;
admin 10;
}
server {
listen 443 ssl;
server_name rcube.ddns.net;
# Certificat SSL géré par Certbot
ssl_certificate /etc/letsencrypt/live/rcube.ddns.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/rcube.ddns.net/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Fichiers statiques
location / {
root /home/rr/rcube/www;
index index.html;
try_files $uri $uri/ =404;
expires -1; # Désactive le cache
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header X-Frame-Options "DENY";
}
# Load Balancer + Auth "optionnelle"
location /post-api/ {
# Auth Basic : si échec, on redirige en interne (niveau 0)
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
error_page 401 = @anonymous;
# Retire le préfixe /post-api/ avant d'envoyer au backend
rewrite ^/post-api/(.*)$ /$1 break;
# En-têtes vers le backend (auth OK ici)
proxy_set_header X-User $remote_user;
proxy_set_header X-User-Level $user_level;
proxy_set_header Authorization "";
# IMPORTANT: pas de partie URI ici non plus (on a déjà réécrit l'URI)
proxy_pass http://api_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Debug optionnel
# add_header X-User $remote_user always;
# add_header X-User-Level $user_level always;
}
location @anonymous {
# Même réécriture du chemin (pour garder le même upstream URI)
rewrite ^/post-api/(.*)$ /$1 break;
proxy_set_header X-User anonymous;
proxy_set_header X-User-Level 0;
proxy_set_header Authorization "";
# IMPORTANT: pas de partie URI dans une named location
proxy_pass http://api_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Debug optionnel
# add_header X-User anonymous always;
# add_header X-User-Level 0 always;
}
}
Vérification de la configuration
sudo nginx -t
redémarrage nginx
sudo systemctl restart nginx
Lancement du serveur
On peut lancer plusieurs instances en load balancing
./r3server 8080 & ./r3server 8081 &
Vérification
sudo netstat -tulnp | grep 808Charge
for i in {1..20}; do curl https://rcube.ddns.net/post-api/ -d "type=0"; sleep 0.5; done
Permet aussi de vérifier le round robin entre ports 8080, 8081...
Pour pouvoir se déconnecter du serveur, le lancer avec la commande r3launch qui contient :
#!/bin/bash nohup /home/rr/rcube/r3server 8080 /home/rr/rcube/par/routing.par > /home/rr/rcube/r3server_8080.log 2>&1 & nohup /home/rr/rcube/r3server 8081 /home/rr/rcube/par/routing.par > /home/rr/rcube/r3server_8081.log 2>&1 &
Note: chemins absolus requis
nohup empêche le processus d'être stoppé lors de la déconnexion.
& exécute le processus en arrière-plan.
> r3server.log 2>&1 redirige les sorties standard et d'erreur vers un fichier r3server.log.
Vérifier que le serveur marche
ps aux | grep r3server ou pgrep r3server
Arrêter le serveur
kill PID ou kill -9 PID PID est le process ID rendu par la commande ps ou pgrep vue au dessus.
Chargement des grib
Mettre dans la crontable la commande
r3gribget avec les bons paramètres.
15 1,7,13,19 * * * /home/rr/rcube/r3gribget /home/rr/rcube/grib 1 384 60 -60 -60 20 >> /home/rr/rcube/r3gribget.log 2>>&1 && /home/rr/rcube/r3init # NOAA 30 4,10,16,22 * * * /home/rr/rcube/r3gribget /home/rr/rcube/grib 500 >> /home/rr/rcube/r3gribget.log 2>&1 # Meteoconsult Wind 0 5,11,17,23 * * * /chemin/vers/r3gribget >paramètres< >> /chemin/vers/r3gribget.log 2>&1
Effacer régulièrement les fichiers Grib anciens.
0 0 * * * find /chemin/vers/grib -type f -name "*.grb" -mtime +4 -exec rm {} \;
Exemple de crontable
Chemins absolus requis.
15 1,7,13,19 * * * /home/rr/rcube/r3gribget /home/rr/rcube/grib 1 384 60 -60 -60 20 >> /home/rr/rcube/r3gribget.log 2>&1 && /home/rr/rcube/r3init # NOAA
30 4,10,16,22 * * * /home/rr/rcube/r3gribget /home/rr/rcube/grib 500 >> /home/rr/rcube/r3gribget.log 2>&1 # Meteoconsult Wind
32 4,10,16,22 * * * /home/rr/rcube/r3gribget /home/rr/rcube/grib 501 >> /home/rr/rcube/r3gribget.log 2>&1 # Meteoconsult Wind
34 4,16 * * * /home/rr/rcube/r3gribget /home/rr/rcube/currentgrib 600 >> /home/rr/rcube/r3gribget.log 2>&1 # Meteoconsult Current
36 4,16 * * * /home/rr/rcube/r3gribget /home/rr/rcube/currentgrib 601 >> /home/rr/rcube/r3gribget.log 2>&1 # Meteoconsult Current
35 1,7,13,19 * * * /home/rr/rcube/r3gribget /home/rr/rcube/grib 3 102 60 -60 -60 20 >> /home/rr/rcube/r3gribget.log 2>&1 # ARPEGE
46 1,13 * * * /home/rr/rcube/r3gribget /home/rr/rcube/grib 2 9 60 -60 -60 20 >> /home/rr/rcube/r3gribget.log 2>&1 # ECMWF
0 0 * * * find /home/rr/rcube/grib -type f -name "*.grb" -mtime +1 -exec rm {} \;
0 0 * * * find /home/rr/rcube/currentgrib -type f -name "*.grb" -mtime +1 -exec rm {} \;
@reboot sleep 60 && /home/rr/rcube/r3launch
Vérifier la planification
crontab -l
Réseau
WAN
NO IP
- rene.rigault@wanadoo.fr
- rcube.ddns.net
LAN
- 192.168.1.200
- port translation 443
11. Authentification
But
NGINX gère le HTTPS et l’authentification HTTP Basic (via htpasswd),
puis traduit l’utilisateur en un niveau d’accès (0, 1, ADMIN)
qu’il transmet au serveur C dans X-User-Level.
Le serveur C applique les droits à partir de ce header.
Flux
- Le client appelle l'API avec Basic Auth.
- NGINX vérifie les identifiants dans
/etc/nginx/.htpasswd. - NGINX associé l’utilisateur validé au niveau et envoie
X-User-Levelau serveur C. - Le serveur C autorise ou refuse selon
X-User-Level.
Création des users
Premier user : sudo htpasswd -cB -C 10 /etc/nginx/.htpasswd alice Puis : sudo htpasswd -B -C 10 /etc/nginx/.htpasswd bob
Commande de test
curl https://rcube.ddns.net/post-api/ -u alice:pistache \
-d "type=1&boat=hoho, 47.0,-3.0&waypoints=47.5,-3.0;47.0,-5.0&timeStep=3600&isodesc=true&isoc=false"
Notes sécurité
- Utiliser
htpasswden bcrypt :-B(ex.-C 10). - Protéger
/etc/nginx/.htpasswd(droits 640, groupewww-data). - Ne pas faire confiance à un
X-User-Levelenvoyé par le client : NGINX le force.
11. Comportements bizarres
Pour fonctionner sans NGINX (en local) et éviter les erreurs CORS :- Mettre dans
par/routing.parAUTHENT = 0 (ou enlever la ligne AUTHENT). - Eviter d'envoyer dans le fetch l'authentication header.
Pour cela dans
r3param.jsmettre userID = “ ” et password = “ ”.
Annexe 1, ServeurGPS et AIS
Introduction
Côté client, il est possible d'installer un petit module ou plugin permettant de disposer des informations AIS et GPS.
La lecture des données se fait directement sur l’interface USB, muni d'un ou plusieurs capteurs (AIS et/ou GPS). Cette méthode fonctionne sous Windows comme sous Unix et Mac OS.
Gestion des ports USB pour AIS et GPS
Identitication des ports
ls -l /dev/tty/USB* /dev/ttyACM*
S'ajouter au groupe Dialout
sudo usermod -aG dialout $USER
Ouvrir le port en mode commande
cat /dev/ttyUSB0
Redémarrer si les droits ne sont pas mis à jour.
Sous Unix et Mac OS, s’assurer que le port a les droits nécessaires. Pour ce faire, passer la commande :
sudo chmod 666 /dev/ttyACM0.
sudo chmod 666 /dev/ttyUSB0.
Attention : Le bon fonctionnement peut nécessiter la déconnexion physique de l’interface USB, sa reconnexion, le passage de la commande changeant les droits d’accès et le relancement de l’application.
Lancement du serveur
./aisgpsserver <port> [fichierParametres]
Utiliser un port non déjà occupé.
./aisgpsserver 8090
param.par est le nom du fichier paramètres par défaut.
Le fichier midcodes.csv permet de traduire les premiers chiffres du MMSI en nom de pays, code ISO et emoticon du drapeau.
Les ports utilisés doivent être spécifiés dans le fichier paramètres
Exemple de fichier paramètres sous Unix :
DESC: AIS GPS parameters. # optionnel MID_COUNTRY: /home/rr/routing/geo/midcodes.csv # optionnel pour traduction mid code en country NMEA: /dev/ttyACM0 13 # 13 pour 9600 bauds NMEA: /dev/ttyUSB0 15 # 15 pour 38400 bauds SPECIAL: 1 # optionnel, permet d'avoir des navires de test AIS
Sous Windows, la difficulté est de repérer les noms des ports série COM3, COM4…
La vitesse est donnée explicitement :
NMEA: COM3 9600 NMEA: COM4 38400
Utilisation côté client
Le logiciel client appelle de le serveur avec le mot clef "gps" ou "ais" selon les informations souhaitées
GPS
Les informations renvoyées sont :
- Le temps en secondes Epoch Unix,
- la latitude, la longitude en degrés décimaux et l'altitude en mètres,
- la vitesse en noeuds (speed over ground) et le cap en degrés [0..360],
- le nombre de satellites captés,
- l'état.
curl http://localhost:8090/gps
{
"time": "1744649357",
"lat": -0.016667,
"lon": -2.347094,
"alt m": 13.90,
"sog": 3.18,
"cog": 12.00,
"numSat": 4,
"status": "V"
}
AIS
Les informations renvoyées sont pour chaque navire :
- Le nom du navire ou "_Unsupported" si message ID associé non supporté,
- le dernier message ID associé au MMSI du bateau,
- le pays extrait à partir du MMSI et du fichier
midcodes.csv, - la distance minimale calculée avec le navire, en projetant sa trajectoire et le notre,
- le MMSI du navire,
- la latitude et la longitude en degrés décimaux,
- la vitesse en noeuds et le cap du bateau en degrés [0..360],
- la date (temps Epoch en secondes) de la dernière mise à jour.
curl http://localhost:8090/ais
[
{"name": "bobo", "messageId": 3, "country": "United Kingdom;GB;🇬🇧", "mindist": 0, "mmsi": 232191800, "lat": 45.3000, "lon": -2.2000, "sog": 15.00, "cog": 315, "lastupdate": 1744706554},
{"name": "hello", "messageId": 0, "country": "France (Inland);FR;🇫🇷", "mindist": 0, "mmsi": 227191400, "lat": 45.2000, "lon": -2.5000, "sog": 5.00, "cog": 45, "lastupdate": 1744707094},
{"name": "coco", "messageId": 3, "country": "Spain;ES;🇪🇸", "mindist": 140, "mmsi": 224193900, "lat": 45.4000, "lon": -3.0000, "sog": 0.00, "cog": 180, "lastupdate": 1744707154}
]
Noter que "country" comporte le nom du pays, le code ISO et le code Unicode de l'émoticon du drapeau si le fichier midcodes.csv est référencé dans le fichier paramètres.
Construction de aisgpsserver
La GLIB est ici nécessaire.
| Fichier | Commentaire |
|---|---|
| aisgpsserver.c | Module principal. |
| rtypes.h | Définition des constantes générales #defines, des
enum et des typedef. |
| r3util.c | Fonctions utiles. |
| r3util.h | Interface de r3util (prototypes des fonctions externes). |
| aisgps.c | Gestion ais et gps |
| aisgps.h | Interface de engine (prototypes des fonctions externes). |
Compilation
./ccag
Annexe 2, Composition de Polaires
Le script transpolar transforme le fichier Json fourni par le dashboard de Virtual Regatta en un fichier lisible par jq.
Le script saillist ou list liste les voiles décrites dans le fichier json en question.
Le script jstocsv basé sur jq transforme la structure Json fournie par le dashboard Virtual Regatta (après transformation avec transpolar)
en n fichiers CSV.
composepol
Le programme composepol.c lit n fichiers CSV et produit
- Le fichier polaire résultant (max des valeurs de toutes les polaires) : VRrespol.csv
- Le fichier polaires de voiles donnant l'index de la voile utilisée : VRrespol.sailpol
Lancement de composepol
./composepol -c file1 file2 file3 ...
L'ordre est important. Le fichier VRespol.sailpol contient une matrice dont chaque cellule a la valeur :
- 1 pour les valeurs extraites de file 1,
- 2 pour les valeurs extraites de file 2,
- ...
La convention généralement adoptée est :
| No | Abréviation | voile | Couleur |
| 0 | NA | Not applicable | black |
| 1 | C0 | Code 0 | green |
| 2 | HG | Heavy Gennaker | purple |
| 3 | Jib | Jib | gray |
| 4 | LG | Light Gennaker | blue |
| 5 | LJ | Light Jib | yellow |
| 6 | Spi | Spi | orange |
| 7 | SS | Stay Sail | red |
Construction du code
Il nécessite :
- r3types.h
- r3util.c et r3util.h
- polar.c et polar.h
Pour la construction du code, utiliser : ./ccc.
Enchainement des opérations
allcompose enchaine :
- Translation du fichier passé en paramètre en fichier Json,
- Création de n fichiers CSV avec jq,
- Composition finale de ces n fichiers csv en
VRespol.csvetVRespol.sailpol
Annexe 3, Transformations de Grib
Cas des fichiers Meteoconsult
La version sans ECCCODES nécessite de traiter les fichiers Meteoconsult de façon à obtenir un format non compressé
La commande wgrib adaptée est automatiquement gérée par r3gribget dans la fonction uncompress :
/*! Uncompress Grib file received from METOCONSULT to Template 5.0 */
static bool uncompress (const char *in, const char *out) {
char command [MAX_SIZE_LINE * 4];
snprintf (command, sizeof (command),
"wgrib2 %s -set_scaling same same -set_grib_type simple -grib_out %s >/dev/null", in, out);
return (system (command) == 0);
}
Cas des fichiers Saildoc
La version sans ECCCODES nécessite de traiter les fichiers Saildoc de façon à
- Les convertir du format Grib1 au format Grib2 (script Perl
grp1to2.pl) - Forcer le "simple packing" avec wgrib2.
Installation de grb1to2
Ce script NOAA convertit GRIB1→GRIB2 en s’appuyant sur wgrib (GRIB1) + wgrib2.
Installer/Compiler wgrib (GRIB1) : mkdir -p ~/bin && cd ~/bin wget -O wgrib.c https://ftp.cpc.ncep.noaa.gov/wd51we/wgrib/wgrib.c gcc -O2 -o wgrib wgrib.c chmod +x wgrib Récupérer le convertisseur et ses deux fichiers compagnons : # dans ~/bin par ex. wget https://ftp.cpc.ncep.noaa.gov/wd51we/grb1to2/grb1to2.pl wget https://ftp.cpc.ncep.noaa.gov/wd51we/grb1to2/grib1to2_metadata.pl wget https://ftp.cpc.ncep.noaa.gov/wd51we/grb1to2/global_template.g2 chmod +x grb1to2.p
Enchaînement avec simple packing
Le script bash grib1togrib2 prend un entrée un fichier saildoc et produit en sortie un fichier lisible
par la version sans ECCOES de Rcube.
#!/bin/bash
in="$1"
out1="${in%.grb}_g2.grb"
out2="${in%.grb}_g2_simple.grb"
# si GRIB1 (octet 8 == 1) → convertir
if [ "$(dd if="$in" bs=1 skip=7 count=1 2 <> /dev/null | od -An -tu1)" -eq 1 ]; then
~/bin/grb1to2.pl -packing c3 "$in" -o "$out1" || exit 1
else
out1="$in"
fi
# forcer simple packing
wgrib2 "$out1" -set_grib_type simple -grib_out "$out2" || exit 1
echo "Output: ${$out2}"
Annexe 4, Exemple de session MAJ server
rr@rr-Zenbook-UX3402ZA-UX3402ZA:~/rcube$ ./upload Mot de passe SSH : www files... www/doc files... csources files... gribget files... Done rr@rr-Zenbook-UX3402ZA-UX3402ZA:~/rcube$ ssh rcube rr@rcube's password: Last login: Mon Sep 1 09:35:49 2025 from 2a01:cb05:8f15:5a00:41ed:5ba5:9f25:482f rr@rcube:~$ cd rcube/csources/ rr@rcube:~/rcube/csources$ ./ccs rr@rcube:~/rcube/csources$ cd .. rr@rcube:~/rcube$ pgrep r3server 858891 rr@rcube:~/rcube$ kill 858891 rr@rcube:~/rcube$ ./launch ==== Lancement des serveurs ==== → Lancement du serveur sur le port 8080 PID = 866224, log = /home/rr/rcube/r3server_8080.log ✅ Tous les serveurs sont lancés.